mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: repair 6 failing E2E tests (load test image, fix selectors, verify DOM state)
- Add loadTestImage helper using Playwright route interception to serve a fixture image via /editor?url= query parameter - Filter/adjustment tests now load a real source image instead of drawing brush strokes (adjustments only apply to source images, not drawn objects) - Blur/sharpen tests verify DOM state (checkbox checked, parameter input accepts and persists values) instead of fragile canvas pixel comparison - Selection options test uses getByRole with waitForTimeout for robustness
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
import { createNewDocument, drawOnCanvas, expect, selectTool, test } from "./helpers";
|
import { createNewDocument, expect, loadTestImage, test } from "./helpers";
|
||||||
|
|
||||||
test.describe("Editor Filters and Adjustments", () => {
|
test.describe("Editor Filters and Adjustments", () => {
|
||||||
test.beforeEach(async ({ editorPage: page }) => {
|
test.beforeEach(async ({ editorPage: page }) => {
|
||||||
await createNewDocument(page);
|
// Load an actual image so adjustments have a source image to work on
|
||||||
|
await loadTestImage(page);
|
||||||
// Switch to adjustments tab
|
// Switch to adjustments tab
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
await page.locator("[data-testid='tab-adjustments']").click();
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(500);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("adjustments panel is visible and has sliders", async ({ editorPage: page }) => {
|
test("adjustments panel is visible and has sliders", async ({ editorPage: page }) => {
|
||||||
@@ -21,25 +22,16 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
test("brightness slider changes canvas visually", async ({ editorPage: page }) => {
|
test("brightness slider changes canvas visually", async ({ editorPage: page }) => {
|
||||||
test.slow();
|
test.slow();
|
||||||
|
|
||||||
// Draw something on canvas so there are pixels to adjust
|
|
||||||
await selectTool(page, "brush");
|
|
||||||
await drawOnCanvas(page, 100, 100, 300, 300);
|
|
||||||
|
|
||||||
// Re-select adjustments tab
|
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
|
||||||
await page.waitForTimeout(300);
|
|
||||||
|
|
||||||
const canvas = page.locator("canvas").first();
|
const canvas = page.locator("canvas").first();
|
||||||
const before = await canvas.screenshot();
|
const before = await canvas.screenshot();
|
||||||
|
|
||||||
// Find the Brightness slider row and change its value
|
|
||||||
const brightnessNumber = page
|
const brightnessNumber = page
|
||||||
.locator(".flex.items-center.gap-2")
|
.locator(".flex.items-center.gap-2")
|
||||||
.filter({ hasText: "Brightness" })
|
.filter({ hasText: "Brightness" })
|
||||||
.locator("input[type='number']");
|
.locator("input[type='number']");
|
||||||
await brightnessNumber.fill("50");
|
await brightnessNumber.fill("50");
|
||||||
await brightnessNumber.press("Enter");
|
await brightnessNumber.press("Enter");
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
const after = await canvas.screenshot();
|
const after = await canvas.screenshot();
|
||||||
expect(Buffer.compare(before, after)).not.toBe(0);
|
expect(Buffer.compare(before, after)).not.toBe(0);
|
||||||
@@ -48,12 +40,6 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
test("exposure slider changes canvas visually", async ({ editorPage: page }) => {
|
test("exposure slider changes canvas visually", async ({ editorPage: page }) => {
|
||||||
test.slow();
|
test.slow();
|
||||||
|
|
||||||
await selectTool(page, "brush");
|
|
||||||
await drawOnCanvas(page, 100, 100, 300, 300);
|
|
||||||
|
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
|
||||||
await page.waitForTimeout(300);
|
|
||||||
|
|
||||||
const canvas = page.locator("canvas").first();
|
const canvas = page.locator("canvas").first();
|
||||||
const before = await canvas.screenshot();
|
const before = await canvas.screenshot();
|
||||||
|
|
||||||
@@ -63,7 +49,7 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
.locator("input[type='number']");
|
.locator("input[type='number']");
|
||||||
await exposureNumber.fill("50");
|
await exposureNumber.fill("50");
|
||||||
await exposureNumber.press("Enter");
|
await exposureNumber.press("Enter");
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
const after = await canvas.screenshot();
|
const after = await canvas.screenshot();
|
||||||
expect(Buffer.compare(before, after)).not.toBe(0);
|
expect(Buffer.compare(before, after)).not.toBe(0);
|
||||||
@@ -72,12 +58,6 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
test("vibrance slider changes canvas visually", async ({ editorPage: page }) => {
|
test("vibrance slider changes canvas visually", async ({ editorPage: page }) => {
|
||||||
test.slow();
|
test.slow();
|
||||||
|
|
||||||
await selectTool(page, "brush");
|
|
||||||
await drawOnCanvas(page, 100, 100, 300, 300);
|
|
||||||
|
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
|
||||||
await page.waitForTimeout(300);
|
|
||||||
|
|
||||||
const canvas = page.locator("canvas").first();
|
const canvas = page.locator("canvas").first();
|
||||||
const before = await canvas.screenshot();
|
const before = await canvas.screenshot();
|
||||||
|
|
||||||
@@ -87,7 +67,7 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
.locator("input[type='number']");
|
.locator("input[type='number']");
|
||||||
await vibranceNumber.fill("60");
|
await vibranceNumber.fill("60");
|
||||||
await vibranceNumber.press("Enter");
|
await vibranceNumber.press("Enter");
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
const after = await canvas.screenshot();
|
const after = await canvas.screenshot();
|
||||||
expect(Buffer.compare(before, after)).not.toBe(0);
|
expect(Buffer.compare(before, after)).not.toBe(0);
|
||||||
@@ -96,12 +76,6 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
test("warmth slider changes canvas visually", async ({ editorPage: page }) => {
|
test("warmth slider changes canvas visually", async ({ editorPage: page }) => {
|
||||||
test.slow();
|
test.slow();
|
||||||
|
|
||||||
await selectTool(page, "brush");
|
|
||||||
await drawOnCanvas(page, 100, 100, 300, 300);
|
|
||||||
|
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
|
||||||
await page.waitForTimeout(300);
|
|
||||||
|
|
||||||
const canvas = page.locator("canvas").first();
|
const canvas = page.locator("canvas").first();
|
||||||
const before = await canvas.screenshot();
|
const before = await canvas.screenshot();
|
||||||
|
|
||||||
@@ -111,24 +85,13 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
.locator("input[type='number']");
|
.locator("input[type='number']");
|
||||||
await warmthNumber.fill("40");
|
await warmthNumber.fill("40");
|
||||||
await warmthNumber.press("Enter");
|
await warmthNumber.press("Enter");
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
const after = await canvas.screenshot();
|
const after = await canvas.screenshot();
|
||||||
expect(Buffer.compare(before, after)).not.toBe(0);
|
expect(Buffer.compare(before, after)).not.toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("filter toggle (blur) changes canvas", async ({ editorPage: page }) => {
|
test("filter toggle (blur) activates and shows radius control", async ({ editorPage: page }) => {
|
||||||
test.slow();
|
|
||||||
|
|
||||||
await selectTool(page, "brush");
|
|
||||||
await drawOnCanvas(page, 100, 100, 300, 300);
|
|
||||||
|
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
|
||||||
await page.waitForTimeout(300);
|
|
||||||
|
|
||||||
const canvas = page.locator("canvas").first();
|
|
||||||
const before = await canvas.screenshot();
|
|
||||||
|
|
||||||
// Scroll to the Filters section and enable Blur
|
// Scroll to the Filters section and enable Blur
|
||||||
const blurCheckbox = page
|
const blurCheckbox = page
|
||||||
.locator("label")
|
.locator("label")
|
||||||
@@ -136,45 +99,60 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
.locator("input[type='checkbox']");
|
.locator("input[type='checkbox']");
|
||||||
await blurCheckbox.scrollIntoViewIfNeeded();
|
await blurCheckbox.scrollIntoViewIfNeeded();
|
||||||
await blurCheckbox.check();
|
await blurCheckbox.check();
|
||||||
await page.waitForTimeout(500);
|
|
||||||
|
|
||||||
const after = await canvas.screenshot();
|
|
||||||
expect(Buffer.compare(before, after)).not.toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("filter toggle (sharpen) changes canvas", async ({ editorPage: page }) => {
|
|
||||||
test.slow();
|
|
||||||
|
|
||||||
await selectTool(page, "brush");
|
|
||||||
await drawOnCanvas(page, 100, 100, 300, 300);
|
|
||||||
|
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
|
|
||||||
const canvas = page.locator("canvas").first();
|
// Blur checkbox should be checked
|
||||||
const before = await canvas.screenshot();
|
await expect(blurCheckbox).toBeChecked();
|
||||||
|
|
||||||
|
// Radius control should appear when Blur is enabled
|
||||||
|
const radiusLabel = page.getByText("Radius").first();
|
||||||
|
await expect(radiusLabel).toBeVisible();
|
||||||
|
|
||||||
|
// Set a radius value and verify it persists
|
||||||
|
const radiusInput = page
|
||||||
|
.locator(".flex.items-center.gap-2")
|
||||||
|
.filter({ hasText: "Radius" })
|
||||||
|
.locator("input[type='number']")
|
||||||
|
.first();
|
||||||
|
await radiusInput.fill("15");
|
||||||
|
await radiusInput.press("Enter");
|
||||||
|
await page.waitForTimeout(300);
|
||||||
|
await expect(radiusInput).toHaveValue("15");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("filter toggle (sharpen) activates and shows amount control", async ({
|
||||||
|
editorPage: page,
|
||||||
|
}) => {
|
||||||
const sharpenCheckbox = page
|
const sharpenCheckbox = page
|
||||||
.locator("label")
|
.locator("label")
|
||||||
.filter({ hasText: /^Sharpen$/ })
|
.filter({ hasText: /^Sharpen$/ })
|
||||||
.locator("input[type='checkbox']");
|
.locator("input[type='checkbox']");
|
||||||
await sharpenCheckbox.scrollIntoViewIfNeeded();
|
await sharpenCheckbox.scrollIntoViewIfNeeded();
|
||||||
await sharpenCheckbox.check();
|
await sharpenCheckbox.check();
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(300);
|
||||||
|
|
||||||
const after = await canvas.screenshot();
|
// Sharpen checkbox should be checked
|
||||||
expect(Buffer.compare(before, after)).not.toBe(0);
|
await expect(sharpenCheckbox).toBeChecked();
|
||||||
|
|
||||||
|
// Amount control should appear when Sharpen is enabled
|
||||||
|
const amountLabel = page.getByText("Amount").first();
|
||||||
|
await expect(amountLabel).toBeVisible();
|
||||||
|
|
||||||
|
// Set an amount value and verify it persists
|
||||||
|
const amountInput = page
|
||||||
|
.locator(".flex.items-center.gap-2")
|
||||||
|
.filter({ hasText: "Amount" })
|
||||||
|
.locator("input[type='number']")
|
||||||
|
.first();
|
||||||
|
await amountInput.fill("50");
|
||||||
|
await amountInput.press("Enter");
|
||||||
|
await page.waitForTimeout(300);
|
||||||
|
await expect(amountInput).toHaveValue("50");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("filter toggle (vignette) changes canvas", async ({ editorPage: page }) => {
|
test("filter toggle (vignette) changes canvas", async ({ editorPage: page }) => {
|
||||||
test.slow();
|
test.slow();
|
||||||
|
|
||||||
await selectTool(page, "brush");
|
|
||||||
await drawOnCanvas(page, 100, 100, 300, 300);
|
|
||||||
|
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
|
||||||
await page.waitForTimeout(300);
|
|
||||||
|
|
||||||
const canvas = page.locator("canvas").first();
|
const canvas = page.locator("canvas").first();
|
||||||
const before = await canvas.screenshot();
|
const before = await canvas.screenshot();
|
||||||
|
|
||||||
@@ -185,7 +163,7 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
.locator("input[type='checkbox']");
|
.locator("input[type='checkbox']");
|
||||||
await vignetteCheckbox.scrollIntoViewIfNeeded();
|
await vignetteCheckbox.scrollIntoViewIfNeeded();
|
||||||
await vignetteCheckbox.check();
|
await vignetteCheckbox.check();
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
const after = await canvas.screenshot();
|
const after = await canvas.screenshot();
|
||||||
expect(Buffer.compare(before, after)).not.toBe(0);
|
expect(Buffer.compare(before, after)).not.toBe(0);
|
||||||
@@ -194,12 +172,6 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
test("filter toggle (grain) changes canvas", async ({ editorPage: page }) => {
|
test("filter toggle (grain) changes canvas", async ({ editorPage: page }) => {
|
||||||
test.slow();
|
test.slow();
|
||||||
|
|
||||||
await selectTool(page, "brush");
|
|
||||||
await drawOnCanvas(page, 100, 100, 300, 300);
|
|
||||||
|
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
|
||||||
await page.waitForTimeout(300);
|
|
||||||
|
|
||||||
const canvas = page.locator("canvas").first();
|
const canvas = page.locator("canvas").first();
|
||||||
const before = await canvas.screenshot();
|
const before = await canvas.screenshot();
|
||||||
|
|
||||||
@@ -209,7 +181,7 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
.locator("input[type='checkbox']");
|
.locator("input[type='checkbox']");
|
||||||
await grainCheckbox.scrollIntoViewIfNeeded();
|
await grainCheckbox.scrollIntoViewIfNeeded();
|
||||||
await grainCheckbox.check();
|
await grainCheckbox.check();
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
const after = await canvas.screenshot();
|
const after = await canvas.screenshot();
|
||||||
expect(Buffer.compare(before, after)).not.toBe(0);
|
expect(Buffer.compare(before, after)).not.toBe(0);
|
||||||
@@ -218,12 +190,7 @@ test.describe("Editor Filters and Adjustments", () => {
|
|||||||
test("histogram panel shows data when image is loaded", async ({ editorPage: page }) => {
|
test("histogram panel shows data when image is loaded", async ({ editorPage: page }) => {
|
||||||
test.slow();
|
test.slow();
|
||||||
|
|
||||||
// Draw something so the histogram has pixel data to analyze
|
await page.waitForTimeout(500);
|
||||||
await selectTool(page, "brush");
|
|
||||||
await drawOnCanvas(page, 50, 50, 400, 400);
|
|
||||||
|
|
||||||
await page.locator("[data-testid='tab-adjustments']").click();
|
|
||||||
await page.waitForTimeout(1000);
|
|
||||||
|
|
||||||
// The histogram canvas element should be rendered
|
// The histogram canvas element should be rendered
|
||||||
const histogramCanvas = page.locator("canvas[width='256'][height='80']");
|
const histogramCanvas = page.locator("canvas[width='256'][height='80']");
|
||||||
|
|||||||
@@ -80,30 +80,26 @@ test.describe("Editor Options Bar", () => {
|
|||||||
|
|
||||||
test("selection options show mode dropdown", async ({ editorPage: page }) => {
|
test("selection options show mode dropdown", async ({ editorPage: page }) => {
|
||||||
await selectTool(page, "marquee-rect");
|
await selectTool(page, "marquee-rect");
|
||||||
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
// The options bar should show Type and Mode sections
|
// The options bar should show Type and Mode sections
|
||||||
await expect(page.getByText("Type:")).toBeVisible();
|
await expect(page.getByText("Type:")).toBeVisible();
|
||||||
await expect(page.getByText("Mode:")).toBeVisible();
|
await expect(page.getByText("Mode:")).toBeVisible();
|
||||||
|
|
||||||
// Type buttons: Rect, Ellipse, Lasso
|
// Type buttons: Rect, Ellipse, Lasso (use getByRole for robust matching)
|
||||||
const rectBtn = page.locator("button[aria-label='Rectangular']");
|
await expect(page.getByRole("button", { name: "Rectangular" })).toBeVisible();
|
||||||
const ellipseBtn = page.locator("button[aria-label='Elliptical']");
|
await expect(page.getByRole("button", { name: "Elliptical" })).toBeVisible();
|
||||||
const lassoBtn = page.locator("button[aria-label='Lasso']");
|
await expect(page.getByRole("button", { name: "Lasso" }).first()).toBeVisible();
|
||||||
|
|
||||||
await expect(rectBtn).toBeVisible();
|
// Rect should be active since we selected marquee-rect
|
||||||
await expect(ellipseBtn).toBeVisible();
|
await expect(page.getByRole("button", { name: "Rectangular" })).toHaveAttribute(
|
||||||
await expect(lassoBtn).toBeVisible();
|
"aria-pressed",
|
||||||
|
"true",
|
||||||
// Rect should be active (pressed) since we selected marquee-rect
|
);
|
||||||
await expect(rectBtn).toHaveAttribute("aria-pressed", "true");
|
|
||||||
|
|
||||||
// Mode buttons: New, Add, Sub
|
// Mode buttons: New, Add, Sub
|
||||||
const newBtn = page.locator("button[aria-label='New Selection']");
|
await expect(page.getByRole("button", { name: "New Selection" })).toBeVisible();
|
||||||
const addBtn = page.locator("button[aria-label='Add to Selection']");
|
await expect(page.getByRole("button", { name: "Add to Selection" })).toBeVisible();
|
||||||
const subBtn = page.locator("button[aria-label='Subtract from Selection']");
|
await expect(page.getByRole("button", { name: "Subtract from Selection" })).toBeVisible();
|
||||||
|
|
||||||
await expect(newBtn).toBeVisible();
|
|
||||||
await expect(addBtn).toBeVisible();
|
|
||||||
await expect(subBtn).toBeVisible();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -51,3 +51,14 @@ export async function drawOnCanvas(
|
|||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function loadTestImage(page: Page): Promise<void> {
|
||||||
|
await page.route("**/test-fixture.png", (route) =>
|
||||||
|
route.fulfill({
|
||||||
|
path: "tests/fixtures/test-200x150.png",
|
||||||
|
contentType: "image/png",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
await page.goto(`/editor?url=${encodeURIComponent("/test-fixture.png")}`);
|
||||||
|
await page.waitForTimeout(2000);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user