mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
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
147 lines
5.8 KiB
TypeScript
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 });
|
|
});
|
|
});
|
|
});
|