import { defineConfig, devices } from '@playwright/test'; /** * Visual-regression suite for theme work. * * Deliberately separate from `playwright.config.ts`. That suite drives real * cross-app workflows and therefore needs the API, a database and migrations; * this one only needs to know what the theme renders. Loading the same * dependencies here would make a screenshot diff fail for reasons that have * nothing to do with the theme — a migration, a seeded row, an expired token. * * So: static routes only, `vite preview` over an already-built bundle, no * backend. Run `vite build` for both apps first. */ const PORTAL_PORT = Number(process.env.VISUAL_PORTAL_PORT ?? 4312); const BACKOFFICE_PORT = Number(process.env.VISUAL_BACKOFFICE_PORT ?? 4313); export const VISUAL = { portalUrl: `http://localhost:${PORTAL_PORT}`, backofficeUrl: `http://localhost:${BACKOFFICE_PORT}`, }; export default defineConfig({ testDir: './visual', workers: 1, fullyParallel: false, forbidOnly: !!process.env.CI, // A visual diff that passes on a retry is a flake, and a flake here would // mask exactly the regressions this suite exists to catch. retries: 0, timeout: 60_000, expect: { // Anti-aliasing differs slightly between runs; a handful of pixels is not // a regression. Anything the theme actually changed is far larger. toHaveScreenshot: { maxDiffPixelRatio: 0.01, animations: 'disabled' }, }, reporter: [['list'], ['html', { outputFolder: '../../dist/visual-report', open: 'never' }]], use: { trace: 'retain-on-failure', actionTimeout: 15_000, }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }], webServer: [ { name: 'portal', command: `npx vite preview --config apps/portal/vite.config.mts --port ${PORTAL_PORT} --strictPort`, cwd: '../..', url: VISUAL.portalUrl, reuseExistingServer: !process.env.CI, timeout: 120_000, }, { name: 'backoffice', command: `npx vite preview --config apps/backoffice/vite.config.mts --port ${BACKOFFICE_PORT} --strictPort`, cwd: '../..', url: VISUAL.backofficeUrl, reuseExistingServer: !process.env.CI, timeout: 120_000, }, ], });