Luca Brunner·
Playwright visual regression with masked timestamps and a 1% tolerance so fonts stop false-flagging
Build visual regression testing suites with snapshot comparison, baseline management, and CI-integrated approval workflows.
Snapshot / Visual Regression Test Builder
You are a frontend testing specialist focused on visual regression testing. Build a complete visual regression testing setup.
**Application Type:**
{{application_type}}
**Frontend Tech Stack:**
{{frontend_stack}}
**Testing Tool:**
{{testing_tool}}
**Components / Pages to Test:**
{{components_pages}}
**Breakpoints to Cover:**
{{breakpoints}}
**Browsers:**
{{browsers}}
Generate:
1. **Test Configuration**: Complete config for {{testing_tool}} with browser, viewport, and threshold settings
2. **Visual Test Suite**: Complete test files covering:
- Full page screenshots at each breakpoint
- Component-level isolated screenshots
- Interaction state captures (hover, focus, active, disabled)
- Cross-browser comparison tests
3. **Baseline Management**: Strategy for updating baselines and storing them
4. **Diff Thresholds**: Per-component tolerance configuration for acceptable changes
5. **Masked Regions**: Hide dynamic content (timestamps, ads) from comparison
6. **Storybook Integration**: If using Storybook, visual tests for each story
7. **CI Pipeline**: Automated visual diff in pull requests with pass/fail gates
8. **Approval Workflow**: Process for approving intentional visual changes
9. **Anti-Flakiness**: Strategies to prevent false positives (font loading, animation waits)
10. **Reporting**: HTML diff report generation with side-by-side comparison
Output complete working configuration and test files.
Ergebnisse
Visual regression setup for a Next.js component library using Playwright's built-in screenshot comparison. Covers three breakpoints, masks dynamic content, and gates PRs.
```typescript
// playwright.config.ts
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
expect: {
toHaveScreenshot: { maxDiffPixelRatio: 0.01 }, // 1% tolerance for AA noise
},
projects: [
{ name: "desktop", use: { ...devices["Desktop Chrome"], viewport: { width: 1440, height: 900 } } },
{ name: "tablet", use: { viewport: { width: 768, height: 1024 } } },
{ name: "mobile", use: { ...devices["iPhone 13"] } },
],
});
```
```typescript
// tests/visual/button.spec.ts
import { test, expect } from "@playwright/test";
test("Button — all states", async ({ page }) => {
await page.goto("/storybook/button");
await page.waitForLoadState("networkidle"); // fonts loaded
await expect(page.getByTestId("btn-primary")).toHaveScreenshot("primary.png");
await page.getByTestId("btn-primary").hover();
await expect(page.getByTestId("btn-primary")).toHaveScreenshot("primary-hover.png");
});
test("Pricing page — full, dynamic content masked", async ({ page }) => {
await page.goto("/pricing");
await expect(page).toHaveScreenshot("pricing.png", {
mask: [page.getByTestId("live-timestamp"), page.locator(".ad-slot")],
animations: "disabled",
});
});
```
**Anti-flakiness:** `waitForLoadState("networkidle")` prevents shooting before web fonts swap; `animations: "disabled"` freezes transitions; the `mask` hides the timestamp so it never false-positives. **Baselines** live in `__screenshots__/` committed to git; update intentional changes with `npx playwright test --update-snapshots`. **CI gate:** the diff job fails the PR on any pixel delta over threshold and uploads a side-by-side HTML report for approval.
Modell: Claude Sonnet 4
19 Likes9 SavesScore: 15
1 Kommentar
Lena Fischer·
The Big-O note at the end sold me.