diff --git a/playwright.config.ts b/playwright.config.ts index be73910..25a37b4 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -63,6 +63,18 @@ export default defineConfig({ viewport: { width: 1440, height: 900 }, }, }, + { + // Visual regression baselines. Regenerate with --update-snapshots after + // intentional UI changes; otherwise pnpm exec playwright test --project=visual + // diffs against the committed PNGs. + name: 'visual', + testMatch: /visual\/.*\.spec\.ts/, + dependencies: ['setup'], + use: { + ...devices['Desktop Chrome'], + viewport: { width: 1440, height: 900 }, + }, + }, ], // Don't start the dev server — we expect it to already be running diff --git a/tests/e2e/visual/snapshots.spec.ts b/tests/e2e/visual/snapshots.spec.ts new file mode 100644 index 0000000..c6280c8 --- /dev/null +++ b/tests/e2e/visual/snapshots.spec.ts @@ -0,0 +1,67 @@ +import { test, expect, type Page } from '@playwright/test'; + +import { login, navigateTo } from '../smoke/helpers'; + +/** + * Visual regression baselines for stable list/landing pages. + * + * On first run (or after intentional UI changes), regenerate: + * pnpm exec playwright test --project=visual --update-snapshots + * + * Subsequent runs diff against the committed PNGs under + * tests/e2e/visual/snapshots.spec.ts-snapshots/. + * + * Pages chosen are list/landing screens that don't depend on per-row + * fixture data — they tolerate seed drift between runs. Detail screens + * (yacht detail, EOI dialog, invoice form review) are intentionally + * deferred until we have stable fixtures wired up. + */ + +const PAGES = [ + { name: 'portal-login', path: '/portal/login', requireAuth: false }, + { name: 'dashboard', path: '/dashboard', requireAuth: true }, + { name: 'clients-list', path: '/clients', requireAuth: true }, + { name: 'yachts-list', path: '/yachts', requireAuth: true }, + { name: 'berths-list', path: '/berths', requireAuth: true }, + { name: 'invoices-list', path: '/invoices', requireAuth: true }, +] as const; + +async function settle(page: Page) { + // Quiet the page so dynamic content (timers, spinners, blinking cursors) + // doesn't cause flaky pixel diffs. + await page.addStyleTag({ + content: ` + *, *::before, *::after { + animation-duration: 0s !important; + animation-delay: 0s !important; + transition-duration: 0s !important; + transition-delay: 0s !important; + caret-color: transparent !important; + } + `, + }); + await page.waitForLoadState('networkidle'); + // Tiny pause to let TanStack Query flush + await page.waitForTimeout(500); +} + +test.describe('Visual regression', () => { + for (const p of PAGES) { + test(`${p.name} matches baseline`, async ({ page }) => { + if (p.requireAuth) { + await login(page, 'super_admin'); + await navigateTo(page, p.path); + } else { + await page.goto(p.path); + } + + await settle(page); + + await expect(page).toHaveScreenshot(`${p.name}.png`, { + fullPage: true, + // Tolerate small text-rendering differences across machines/runs. + maxDiffPixelRatio: 0.02, + }); + }); + } +}); diff --git a/tests/e2e/visual/snapshots.spec.ts-snapshots/berths-list-visual-darwin.png b/tests/e2e/visual/snapshots.spec.ts-snapshots/berths-list-visual-darwin.png new file mode 100644 index 0000000..09af300 Binary files /dev/null and b/tests/e2e/visual/snapshots.spec.ts-snapshots/berths-list-visual-darwin.png differ diff --git a/tests/e2e/visual/snapshots.spec.ts-snapshots/clients-list-visual-darwin.png b/tests/e2e/visual/snapshots.spec.ts-snapshots/clients-list-visual-darwin.png new file mode 100644 index 0000000..6649dbb Binary files /dev/null and b/tests/e2e/visual/snapshots.spec.ts-snapshots/clients-list-visual-darwin.png differ diff --git a/tests/e2e/visual/snapshots.spec.ts-snapshots/dashboard-visual-darwin.png b/tests/e2e/visual/snapshots.spec.ts-snapshots/dashboard-visual-darwin.png new file mode 100644 index 0000000..9950b55 Binary files /dev/null and b/tests/e2e/visual/snapshots.spec.ts-snapshots/dashboard-visual-darwin.png differ diff --git a/tests/e2e/visual/snapshots.spec.ts-snapshots/invoices-list-visual-darwin.png b/tests/e2e/visual/snapshots.spec.ts-snapshots/invoices-list-visual-darwin.png new file mode 100644 index 0000000..ac447ba Binary files /dev/null and b/tests/e2e/visual/snapshots.spec.ts-snapshots/invoices-list-visual-darwin.png differ diff --git a/tests/e2e/visual/snapshots.spec.ts-snapshots/portal-login-visual-darwin.png b/tests/e2e/visual/snapshots.spec.ts-snapshots/portal-login-visual-darwin.png new file mode 100644 index 0000000..ae5ae72 Binary files /dev/null and b/tests/e2e/visual/snapshots.spec.ts-snapshots/portal-login-visual-darwin.png differ diff --git a/tests/e2e/visual/snapshots.spec.ts-snapshots/yachts-list-visual-darwin.png b/tests/e2e/visual/snapshots.spec.ts-snapshots/yachts-list-visual-darwin.png new file mode 100644 index 0000000..4f992eb Binary files /dev/null and b/tests/e2e/visual/snapshots.spec.ts-snapshots/yachts-list-visual-darwin.png differ