Files
SnapOtter/tests/e2e/gui-tools-layout.spec.ts
T
SnapOtter 03f82567d0 test: expand API and GUI test coverage across all tools
Add ~500 new E2E tests and ~300 new integration tests covering:

- 24 new GUI E2E specs: navigation, responsive layout, keyboard shortcuts,
  tool UI for all 35 non-AI tools, batch/pipeline workflows, settings/RBAC,
  visual regression, accessibility, and performance budgets
- 3 new E2E-Docker specs: batch workflows, advanced pipelines, cross-format
- 1 new adversarial integration test: memory pressure, corrupted files,
  unicode filenames, extreme dimensions, pipeline/batch edge cases
- 29 expanded integration test files: HEIC/HEIF input, large files, parameter
  boundaries, batch processing, format edge cases across all tools
- Cross-format matrix expanded: 641 tests covering every tool x 18 formats
- AI bridge unit tests expanded: lifecycle, tool modules, error propagation
- Unit test gaps filled: analytics, tool-registry, web stores

Also fixes:
- vitest.config.ts: exclude e2e-docs and e2e-landing from Vitest runner
- AI E2E specs: add sidecar health check to skip gracefully when Python
  AI backend is not running instead of timing out
2026-04-29 01:39:25 +08:00

147 lines
5.8 KiB
TypeScript

import { expect, test, uploadTestImage, waitForProcessing } from "./helpers";
// ---------------------------------------------------------------------------
// GUI E2E: Layout & Composition Tools (collage, stitch, split)
// ---------------------------------------------------------------------------
test.describe("GUI Layout Tools", () => {
// ========================================================================
// COLLAGE
// ========================================================================
test.describe("Collage", () => {
test("renders tool page without standard dropzone", async ({ loggedInPage: page }) => {
await page.goto("/collage");
await expect(page.getByText("Collage").first()).toBeVisible();
// Collage uses custom upload UI, not standard dropzone
await expect(page.getByText(/upload/i).first()).toBeVisible();
});
test("shows aspect ratio options in Canvas section", async ({ loggedInPage: page }) => {
await page.goto("/collage");
// Canvas section is collapsed by default -- expand it
await page.getByText("Canvas").click();
await expect(page.getByRole("button", { name: "Free" }).first()).toBeVisible();
await expect(page.getByRole("button", { name: "1:1" }).first()).toBeVisible();
await expect(page.getByRole("button", { name: "4:3" }).first()).toBeVisible();
await expect(page.getByRole("button", { name: "16:9" }).first()).toBeVisible();
});
test("shows output format selector in Output section", async ({ loggedInPage: page }) => {
await page.goto("/collage");
// Output section is collapsed by default -- expand it
await page.getByText("Output").click();
await expect(page.getByRole("button", { name: "PNG" }).first()).toBeVisible();
await expect(page.getByRole("button", { name: "JPEG" }).first()).toBeVisible();
await expect(page.getByRole("button", { name: "WebP" }).first()).toBeVisible();
});
test("shows background color in Spacing section", async ({ loggedInPage: page }) => {
await page.goto("/collage");
// Spacing & Style section is open by default
await expect(page.getByText(/background/i).first()).toBeVisible();
});
});
// ========================================================================
// STITCH
// ========================================================================
test.describe("Stitch", () => {
test("renders tool page with dropzone", async ({ loggedInPage: page }) => {
await page.goto("/stitch");
await expect(page.getByText("Stitch").first()).toBeVisible();
await expect(page.getByText("Upload from computer")).toBeVisible();
});
test("shows direction options after upload", async ({ loggedInPage: page }) => {
await page.goto("/stitch");
await uploadTestImage(page);
// Direction buttons: horizontal, vertical, grid
await expect(page.getByText(/horizontal/i).first()).toBeVisible();
await expect(page.getByText(/vertical/i).first()).toBeVisible();
await expect(page.getByText(/grid/i).first()).toBeVisible();
});
test("shows resize mode options after upload", async ({ loggedInPage: page }) => {
await page.goto("/stitch");
await uploadTestImage(page);
await expect(page.getByText(/resize mode|fit|original/i).first()).toBeVisible();
});
test("shows alignment options after upload", async ({ loggedInPage: page }) => {
await page.goto("/stitch");
await uploadTestImage(page);
await expect(page.getByText(/alignment|align/i).first()).toBeVisible();
});
});
// ========================================================================
// SPLIT
// ========================================================================
test.describe("Split", () => {
test("renders tool page with dropzone", async ({ loggedInPage: page }) => {
await page.goto("/split");
await expect(page.getByText("Image Splitting").first()).toBeVisible();
await expect(page.getByText("Upload from computer")).toBeVisible();
});
test("shows mode selector (Grid / Tile Size) after upload", async ({ loggedInPage: page }) => {
await page.goto("/split");
await uploadTestImage(page);
await expect(page.getByRole("button", { name: "Grid" }).first()).toBeVisible();
await expect(page.getByRole("button", { name: "Tile Size" }).first()).toBeVisible();
});
test("shows grid presets after upload", async ({ loggedInPage: page }) => {
await page.goto("/split");
await uploadTestImage(page);
// Grid presets from split-settings.tsx
await expect(page.getByRole("button", { name: "2x2" }).first()).toBeVisible();
await expect(page.getByRole("button", { name: "3x3" }).first()).toBeVisible();
});
test("shows output format selector after upload", async ({ loggedInPage: page }) => {
await page.goto("/split");
await uploadTestImage(page);
// Output format options
await expect(page.getByText(/output format|format/i).first()).toBeVisible();
});
test("processes split and shows download", async ({ loggedInPage: page }) => {
await page.goto("/split");
await uploadTestImage(page);
await page.waitForTimeout(1000);
// Select a preset (2x2)
await page.getByRole("button", { name: "2x2" }).first().click();
// Click split button
const splitBtn = page
.getByRole("button", { name: /split/i })
.filter({ hasNotText: /image splitting/i })
.first();
await splitBtn.click();
await waitForProcessing(page);
// Should show download (zip) or tile results
await expect(
page
.getByRole("link", { name: /download/i })
.first()
.or(page.getByText(/tiles|download/i).first()),
).toBeVisible({ timeout: 15_000 });
});
});
});