Skip to main content
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.