Initial Commit
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
## Architecture
|
||||
|
||||
Two cooperating helpers share one threshold, one viewport, and one font/animation discipline so the e2e and Storybook baselines stay comparable.
|
||||
|
||||
### Adapter choice
|
||||
|
||||
- **e2e path:** Playwright's built-in `expect(page).toHaveScreenshot()` — already in the dependency closure, supports per-OS baselines natively, threshold semantics (`maxDiffPixelRatio`, `maxDiffPixels`) are well documented. No `pixelmatch` direct dep needed.
|
||||
- **Storybook path:** `@storybook/test-runner` is the canonical Storybook→Playwright bridge. It exposes `preVisit` / `postVisit` hooks where we capture screenshots using the same Playwright `Page` instance, so the comparator and threshold match the e2e path bit-for-bit.
|
||||
|
||||
A pure-Node `pixelmatch` helper was rejected: it would fork the comparator, drift in floating-point handling between OSes, and double the surface to maintain.
|
||||
|
||||
### Default thresholds
|
||||
|
||||
- `maxDiffPixelRatio: 0.005` (0.5%). Tighter ratios (e.g. 0.001) produce noise from sub-pixel font rendering on different GPU drivers.
|
||||
- `animations: 'disabled'`, `caret: 'hide'`, `scale: 'css'`.
|
||||
- Viewport: 1280×720 default. Stories pin to the same default unless the story sets an explicit `parameters.viewport`.
|
||||
- `prefers-reduced-motion: reduce` forced via `page.emulateMedia`.
|
||||
|
||||
### OS matrix
|
||||
|
||||
Baselines are stored per platform: `__snapshots__/<linux|darwin|win32>/...`. CI MUST run at least the platforms it intends to gate on. A platform with no baseline directory MUST skip the comparison (no implicit pass) and emit a warning.
|
||||
|
||||
### Baseline-update workflow
|
||||
|
||||
1. Developer runs `bunx turbo test --filter=<pkg> -- --update-snapshots` locally.
|
||||
2. Diff is committed in a **separate, review-tagged commit** prefixed `chore(visual): refresh baselines — <reason>`. Squashing into feature commits is forbidden.
|
||||
3. PR reviewer compares before/after PNGs in the diff view; CI re-runs the comparator on the new baselines to catch accidental cross-platform drift.
|
||||
|
||||
### Determinism levers
|
||||
|
||||
- Fonts: `await document.fonts.ready` after `networkidle`. Web fonts that load lazily are the #1 source of flake.
|
||||
- Color scheme: stories with `parameters.colorScheme === 'dark'` toggle via `page.emulateMedia({ colorScheme: 'dark' })` before capture.
|
||||
- Time: any time-display surfaces under test must already accept an injected `Clock` per `openspec/project.md`; visual specs SHALL pass a `FakeClock` set to a fixed instant.
|
||||
|
||||
### Error model
|
||||
|
||||
`VisualRegressionError extends TestingE2eError` for the e2e path, `StorybookVisualError extends TestingDomError` for the Storybook path. Each carries `{ code, cause?, context: { baselinePath, actualPath, diffPath, pixelRatio } }`.
|
||||
|
||||
### Cross-links
|
||||
|
||||
- Release-readiness gate: `../enterprise-testbed-verification/proposal.md`.
|
||||
- Audit driver: `/mnt/s/web/genesis/docs/superpowers/specs/2026-04-25-test-suite-audit.md` §2 row 2.
|
||||
- Project rules: `/mnt/s/web/genesis/CLAUDE.md` "Web App & Page Verification".
|
||||
Reference in New Issue
Block a user