|
| 1 | +--- |
| 2 | +applyTo: 'tests/playwright/**/*.spec.ts,tests/playwright/lib/visual.ts' |
| 3 | +description: 'Use when editing Playwright visual regression tests; enforce deterministic VRT setup, strict thresholds, and no sleep-based stabilization.' |
| 4 | +--- |
| 5 | + |
| 6 | +# VRT Stability Guardrails |
| 7 | + |
| 8 | +When changing Playwright visual regression tests, follow these standards. |
| 9 | + |
| 10 | +## Threshold policy |
| 11 | + |
| 12 | +- Default to `maxDiffPixelRatio: 0.1`. |
| 13 | +- Allow up to `0.15` only for clearly documented dynamic captures. |
| 14 | +- Do not introduce `maxDiffPixelRatio > 0.15`. |
| 15 | +- Keep `threshold: 0.2` and `scale: 'css'` in shared screenshot behavior. |
| 16 | + |
| 17 | +## Synchronization policy |
| 18 | + |
| 19 | +- Do not use `waitForTimeout(...)` for stabilization. |
| 20 | +- Use deterministic checks instead: |
| 21 | + - `await page.evaluateHandle(() => document.fonts.ready)` |
| 22 | + - `await page.waitForLoadState('networkidle')` |
| 23 | + - explicit assertions on target UI state (`toBeVisible`, `toHaveCSS`, `toHaveText`) |
| 24 | + - layout read/reflow (`await page.evaluate(() => document.body.offsetHeight)`) |
| 25 | + |
| 26 | +## Responsive screenshot policy |
| 27 | + |
| 28 | +- Always set viewport explicitly before responsive snapshots. |
| 29 | +- Wait for viewport convergence before capture: |
| 30 | + - `await page.waitForFunction((w) => document.body.clientWidth === w, width)` |
| 31 | + |
| 32 | +## Masking policy |
| 33 | + |
| 34 | +- Mask only truly dynamic elements (timers, live HR values, websocket-driven changing text). |
| 35 | +- Use shared mask helpers (`getDynamicContentMasks`, `getHrMasks`) to keep masks consistent. |
| 36 | +- Do not mask large stable layout containers. |
| 37 | + |
| 38 | +## Portal and locator policy |
| 39 | + |
| 40 | +- For menu/popover/modal locator screenshots, avoid full-page scroll side effects that can detach portals. |
| 41 | +- `skipA11y: true` is allowed for portal snapshots only when accompanied by a brief rationale comment. |
| 42 | + |
| 43 | +## Stateful suite policy |
| 44 | + |
| 45 | +- Use `resetServerState(request)` in `beforeEach` when server state can leak between tests. |
| 46 | +- Add deterministic teardown in `afterEach` for long-running state (for example `stopTimer(...)`). |
0 commit comments