Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -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".