import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ testDir: './tests/e2e', fullyParallel: true, retries: process.env.CI ? 1 : 0, reporter: [['list']], use: { baseURL: 'http://localhost:5173', trace: 'on-first-retry', // The app turns off antd's transitions under this preference. Animated // popups never settle long enough for Playwright's stability check when // the machine is loaded, which showed up as clicks timing out on a button // that was plainly visible and enabled. reducedMotion: 'reduce' }, // Playwright's default is 5s, and nothing overrode it. That is generous on an // idle laptop and tight on this runner: a full CI pass takes around 21.5 // minutes on a single machine that also builds, migrates and runs three other // suites, and the #239 failure reported exactly `Timeout: 5000ms`. // // Costs nothing on a green run. This bounds how long a *failing* assertion // waits before giving up, not how long a passing one takes — a locator that // resolves in 200ms still resolves in 200ms. expect: { timeout: 10000 }, webServer: { command: 'npm run dev', url: 'http://localhost:5173', // Forwarded so the dev server instruments its modules when the run is a // coverage run. Without this the tests still pass and every page reports no // coverage at all, which publishes a 0% that reads as "the tests stopped // covering things" rather than "collection was never switched on". env: { COVERAGE: process.env.COVERAGE ?? '' }, // Reusing a server that was started without COVERAGE would silently collect // nothing, so a coverage run always starts its own. reuseExistingServer: !process.env.CI && process.env.COVERAGE !== 'true', timeout: 30000 }, projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }] });