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".
|
||||
@@ -0,0 +1,51 @@
|
||||
## Why
|
||||
|
||||
The 2026-04-25 test-suite audit (`/mnt/s/web/genesis/docs/superpowers/specs/2026-04-25-test-suite-audit.md` §2 row 2) flagged "no visual regression" as a critical gap. Stories existing in Storybook is not visual coverage — pixel drift between commits goes unnoticed until a user reports it. CLAUDE.md's "Web App & Page Verification" section requires verifying the rendered DOM contains expected content; visual regression is the strongest automated form of that check.
|
||||
|
||||
This change introduces baseline-screenshot coverage on two surfaces:
|
||||
|
||||
1. **Playwright e2e** — `expect(page).toHaveScreenshot()` baselines for every page in `apps/<app>/e2e/`.
|
||||
2. **Storybook** — every `*.stories.tsx` story produces a screenshot baseline per variant via `@storybook/test-runner`.
|
||||
|
||||
Both paths share the same threshold, viewport pinning, and animation-disabling discipline so a single `--update-snapshots` workflow covers them.
|
||||
|
||||
## What Changes
|
||||
|
||||
### New surface in `@suaveplan/testing-e2e`
|
||||
|
||||
- `configureVisualRegression(config?)` — emits a `PlaywrightTestConfig` fragment with `expect.toHaveScreenshot.maxDiffPixelRatio: 0.005`, `expect.toHaveScreenshot.animations: 'disabled'`, viewport pinned to 1280×720, `prefers-reduced-motion: reduce` forced.
|
||||
- `prepareForVisual(page)` — disables animations, waits for `networkidle` + `document.fonts.ready`, sets `prefers-reduced-motion`. Called inside e2e specs before `toHaveScreenshot`.
|
||||
- Baselines stored under `apps/<app>/e2e/__snapshots__/<platform>/<spec>/<test>.png`.
|
||||
- Structured error codes under `TESTING_E2E.VISUAL.*` (`PIXEL_DIFF_EXCEEDED`, `BASELINE_MISSING`, `FONTS_NOT_READY`, `VIEWPORT_MISMATCH`).
|
||||
|
||||
### New surface in `@suaveplan/testing-dom`
|
||||
|
||||
- `createStorybookTestRunnerConfig(opts)` — returns the `@storybook/test-runner` config with the visual hooks pre-wired (`postVisit` snapshot capture, threshold matching the e2e path).
|
||||
- `pinStoryEnvironment(page)` — locks viewport, font loading, and reduced-motion for stories.
|
||||
- Structured error codes under `TESTING_DOM.STORYBOOK_VISUAL.*` (`PIXEL_DIFF_EXCEEDED`, `BASELINE_MISSING`, `RUNNER_LOAD_FAILED`).
|
||||
|
||||
### Modified surface
|
||||
|
||||
- Storybook stories MUST register through the test-runner config so every variant produces a baseline.
|
||||
- Theme/locale decorators MUST honour the `pinStoryEnvironment` contract (deterministic theme + locale per story file).
|
||||
- `--update-snapshots` runs MUST land in a separate review-tagged commit per genesis policy.
|
||||
- Cross-link to the `enterprise-testbed-verification` change: visual diffs feed the release-readiness gate.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
(none — extensions to existing `testing-e2e` and `testing-dom` capabilities)
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `testing-e2e`: adds `configureVisualRegression`, `prepareForVisual`, `TESTING_E2E.VISUAL.*` error codes, baseline-storage layout requirement, per-OS matrix requirement.
|
||||
- `testing-dom`: adds Storybook test-runner config factory, `pinStoryEnvironment`, `TESTING_DOM.STORYBOOK_VISUAL.*` error codes, per-story baseline requirement.
|
||||
|
||||
## Impact
|
||||
|
||||
- **Affected code:** `/mnt/s/web/genesis/packages/testing/testing-e2e/src/visual/**`, `/mnt/s/web/genesis/packages/testing/testing-dom/src/storybook-visual/**`, every consumer with stories or e2e specs.
|
||||
- **Catalog adds:** `@storybook/test-runner` to `catalogs.testing` in root `package.json`. (Pixel diffing reuses Playwright's built-in `pixelmatch`-equivalent — no extra catalog dep.)
|
||||
- **Coverage:** 100% Istanbul on every helper module per project rule.
|
||||
- **Baselines:** committed to repo under `__snapshots__/`. Per-OS subdirectory matches CI matrix (linux / darwin / win32). CI updated to run the full matrix or skip the platform check explicitly.
|
||||
- **No version bump:** both packages stay at `0.1.0`.
|
||||
@@ -0,0 +1,70 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Storybook test-runner config factory
|
||||
|
||||
The `@suaveplan/testing-dom` package SHALL export `createStorybookTestRunnerConfig(opts?)` returning a `@storybook/test-runner` config object that wires a `postVisit` hook capturing a screenshot for every story variant. The threshold (`maxDiffPixelRatio: 0.005`), animation policy (`animations: 'disabled'`), and viewport (`1280×720`) MUST match the e2e visual path defined in `testing-e2e/spec.md`.
|
||||
|
||||
#### Scenario: Threshold matches e2e path
|
||||
|
||||
- **WHEN** `createStorybookTestRunnerConfig()` is invoked with no overrides
|
||||
- **THEN** the resulting config's screenshot threshold equals the value emitted by `configureVisualRegression()` in `@suaveplan/testing-e2e`
|
||||
|
||||
#### Scenario: postVisit hook installed
|
||||
|
||||
- **WHEN** the test-runner executes a story
|
||||
- **THEN** the `postVisit` hook captures a screenshot named after the story id
|
||||
|
||||
### Requirement: `pinStoryEnvironment` determinism harness
|
||||
|
||||
The package SHALL export `pinStoryEnvironment(page)` which locks viewport to `1280×720`, awaits `document.fonts.ready`, sets `prefers-reduced-motion: reduce`, and applies the story's declared `colorScheme` (`light` or `dark`) via `page.emulateMedia`. Failure to reach font readiness within `timeoutMs` MUST throw `StorybookVisualError` with `code === 'TESTING_DOM.STORYBOOK_VISUAL.RUNNER_LOAD_FAILED'`.
|
||||
|
||||
#### Scenario: Determinism levers applied
|
||||
|
||||
- **WHEN** `pinStoryEnvironment(page)` resolves
|
||||
- **THEN** `prefers-reduced-motion` is `'reduce'` AND fonts are loaded AND viewport is `1280×720`
|
||||
|
||||
#### Scenario: Color scheme honoured
|
||||
|
||||
- **WHEN** a story declares `parameters.colorScheme === 'dark'`
|
||||
- **THEN** `pinStoryEnvironment(page)` calls `page.emulateMedia({ colorScheme: 'dark' })` before capture
|
||||
|
||||
### Requirement: Theme and locale decorator pinning
|
||||
|
||||
`ThemeDecorator` and `LocaleDecorator` consumed by `*.stories.tsx` files SHALL apply a deterministic theme and locale per story file (no per-render randomness, no `Date.now()`-derived choices). Stories that need to vary theme or locale MUST do so via explicit `parameters` rather than runtime state.
|
||||
|
||||
#### Scenario: Decorator output stable
|
||||
|
||||
- **WHEN** the same story is rendered twice with identical `parameters`
|
||||
- **THEN** the resulting DOM and visual screenshot are bit-identical
|
||||
|
||||
### Requirement: Per-variant baseline coverage
|
||||
|
||||
Every `*.stories.tsx` file registered with the Storybook test-runner SHALL produce a baseline screenshot per declared variant (named export). Stories with no baseline on the active platform MUST throw `StorybookVisualError` with `code === 'TESTING_DOM.STORYBOOK_VISUAL.BASELINE_MISSING'` unless `--update-snapshots` is in effect.
|
||||
|
||||
#### Scenario: Variant baseline missing
|
||||
|
||||
- **WHEN** a story variant has no baseline on the active platform AND `--update-snapshots` is NOT set
|
||||
- **THEN** the run throws `StorybookVisualError` with `code === 'TESTING_DOM.STORYBOOK_VISUAL.BASELINE_MISSING'`
|
||||
|
||||
#### Scenario: Variant pixel diff exceeded
|
||||
|
||||
- **WHEN** a variant comparison exceeds the configured `maxDiffPixelRatio`
|
||||
- **THEN** the run throws `StorybookVisualError` with `code === 'TESTING_DOM.STORYBOOK_VISUAL.PIXEL_DIFF_EXCEEDED'` whose `context` contains `{ storyId, baselinePath, actualPath, diffPath, pixelRatio }`
|
||||
|
||||
### Requirement: Structured error codes
|
||||
|
||||
All errors thrown from the Storybook visual helpers SHALL be subclasses of `TestingDomError` carrying `{ code, cause?, context? }` and SHALL match the regex `^TESTING_DOM\.STORYBOOK_VISUAL\.[A-Z_]+$`. Defined codes are `TESTING_DOM.STORYBOOK_VISUAL.PIXEL_DIFF_EXCEEDED`, `TESTING_DOM.STORYBOOK_VISUAL.BASELINE_MISSING`, `TESTING_DOM.STORYBOOK_VISUAL.RUNNER_LOAD_FAILED`.
|
||||
|
||||
#### Scenario: Coded error
|
||||
|
||||
- **WHEN** any Storybook visual helper throws
|
||||
- **THEN** the thrown value `instanceof TestingDomError` is true AND `err.code` matches the regex
|
||||
|
||||
### Requirement: Coverage gate at 100%
|
||||
|
||||
Istanbul statement, branch, function, and line coverage across `packages/testing/testing-dom/src/storybook-visual/` (excluding `*.bench.ts`, `*.schemas.ts`, barrel `index.ts`) MUST be 100% on every dimension. The pre-publish gate (`bunx turbo test:coverage --filter=@suaveplan/testing-dom`) hard-fails below 100%.
|
||||
|
||||
#### Scenario: Coverage gate enforces 100%
|
||||
|
||||
- **WHEN** `bunx turbo test:coverage --filter=@suaveplan/testing-dom` runs
|
||||
- **THEN** statements, branches, functions, and lines coverage all equal 100%
|
||||
@@ -0,0 +1,84 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: `configureVisualRegression` factory
|
||||
|
||||
The `@suaveplan/testing-e2e` package SHALL export `configureVisualRegression(config?)` returning a `PlaywrightTestConfig` fragment with `expect.toHaveScreenshot.maxDiffPixelRatio` defaulted to `0.005`, `expect.toHaveScreenshot.animations` defaulted to `'disabled'`, `expect.toHaveScreenshot.caret` defaulted to `'hide'`, and `use.viewport` defaulted to `{ width: 1280, height: 720 }`. Caller-supplied values MUST take precedence over defaults.
|
||||
|
||||
#### Scenario: Defaults emitted
|
||||
|
||||
- **WHEN** `configureVisualRegression()` is called with no arguments
|
||||
- **THEN** the returned fragment contains `expect.toHaveScreenshot.maxDiffPixelRatio === 0.005` AND `expect.toHaveScreenshot.animations === 'disabled'` AND `use.viewport.width === 1280`
|
||||
|
||||
#### Scenario: Caller override wins
|
||||
|
||||
- **WHEN** `configureVisualRegression({ expect: { toHaveScreenshot: { maxDiffPixelRatio: 0.001 } } })` is called
|
||||
- **THEN** the returned fragment has `expect.toHaveScreenshot.maxDiffPixelRatio === 0.001`
|
||||
|
||||
### Requirement: `prepareForVisual` determinism harness
|
||||
|
||||
The package SHALL export `prepareForVisual(page)` which MUST: disable animations via `page.emulateMedia({ reducedMotion: 'reduce' })`, wait for `page.waitForLoadState('networkidle')`, await `document.fonts.ready` inside the page context, and assert the active viewport matches the configured visual viewport. Failure to reach font readiness within `timeoutMs` MUST throw `VisualRegressionError` with `code === 'TESTING_E2E.VISUAL.FONTS_NOT_READY'`.
|
||||
|
||||
#### Scenario: Determinism levers applied
|
||||
|
||||
- **WHEN** `prepareForVisual(page)` resolves successfully
|
||||
- **THEN** `prefers-reduced-motion` is `'reduce'` AND `document.fonts.status === 'loaded'` AND the page has reached `networkidle`
|
||||
|
||||
#### Scenario: Font timeout
|
||||
|
||||
- **WHEN** `document.fonts.ready` does not resolve within `timeoutMs`
|
||||
- **THEN** the call throws `VisualRegressionError` with `code === 'TESTING_E2E.VISUAL.FONTS_NOT_READY'`
|
||||
|
||||
#### Scenario: Viewport mismatch
|
||||
|
||||
- **WHEN** the page viewport differs from the configured visual viewport at capture time
|
||||
- **THEN** the call throws `VisualRegressionError` with `code === 'TESTING_E2E.VISUAL.VIEWPORT_MISMATCH'`
|
||||
|
||||
### Requirement: Per-OS baseline storage
|
||||
|
||||
Visual baselines SHALL be stored under `apps/<app>/e2e/__snapshots__/<platform>/<spec>/<test>.png` where `<platform>` is one of `linux`, `darwin`, `win32`. A run on a platform with no baseline directory MUST NOT pass implicitly — it MUST throw `VisualRegressionError` with `code === 'TESTING_E2E.VISUAL.BASELINE_MISSING'` unless `--update-snapshots` is in effect.
|
||||
|
||||
#### Scenario: Missing baseline fails
|
||||
|
||||
- **WHEN** an e2e spec calls `expect(page).toHaveScreenshot()` on a platform with no baseline directory and `--update-snapshots` is NOT set
|
||||
- **THEN** the call throws `VisualRegressionError` with `code === 'TESTING_E2E.VISUAL.BASELINE_MISSING'`
|
||||
|
||||
#### Scenario: Pixel diff exceeded
|
||||
|
||||
- **WHEN** a comparison exceeds the configured `maxDiffPixelRatio`
|
||||
- **THEN** the call throws `VisualRegressionError` with `code === 'TESTING_E2E.VISUAL.PIXEL_DIFF_EXCEEDED'` whose `context` contains `{ baselinePath, actualPath, diffPath, pixelRatio }`
|
||||
|
||||
### Requirement: Baseline-update workflow discipline
|
||||
|
||||
Updates to committed baselines SHALL only occur via runs invoked with `--update-snapshots` AND MUST land in a dedicated commit prefixed `chore(visual): refresh baselines` separate from any feature or fix commit.
|
||||
|
||||
#### Scenario: Baseline refresh commit isolated
|
||||
|
||||
- **WHEN** baselines are updated
|
||||
- **THEN** the resulting commit contains only `__snapshots__/` changes AND its message starts with `chore(visual): refresh baselines`
|
||||
|
||||
### Requirement: Per-spec visual invariant
|
||||
|
||||
Every page-level Playwright spec under `apps/<app>/e2e/` that asserts rendered DOM SHALL also call `expect(page).toHaveScreenshot()` after `prepareForVisual(page)` resolves. Specs that exclusively test API endpoints (no DOM render) are exempt.
|
||||
|
||||
#### Scenario: Page-level spec includes screenshot
|
||||
|
||||
- **WHEN** a spec navigates to a route, runs `prepareForVisual(page)`, and asserts rendered DOM
|
||||
- **THEN** the spec also calls `expect(page).toHaveScreenshot()` before completing
|
||||
|
||||
### Requirement: Structured error codes
|
||||
|
||||
All errors thrown from the visual helpers SHALL be subclasses of `TestingE2eError` carrying `{ code, cause?, context? }` and SHALL match the regex `^TESTING_E2E\.VISUAL\.[A-Z_]+$`. Defined codes are `TESTING_E2E.VISUAL.PIXEL_DIFF_EXCEEDED`, `TESTING_E2E.VISUAL.BASELINE_MISSING`, `TESTING_E2E.VISUAL.FONTS_NOT_READY`, `TESTING_E2E.VISUAL.VIEWPORT_MISMATCH`.
|
||||
|
||||
#### Scenario: Coded error
|
||||
|
||||
- **WHEN** any visual helper throws
|
||||
- **THEN** the thrown value `instanceof TestingE2eError` is true AND `err.code` matches the regex
|
||||
|
||||
### Requirement: Coverage gate at 100%
|
||||
|
||||
Istanbul statement, branch, function, and line coverage across `packages/testing/testing-e2e/src/visual/` (excluding `*.bench.ts`, `*.schemas.ts`, barrel `index.ts`) MUST be 100% on every dimension. The pre-publish gate hard-fails below 100%.
|
||||
|
||||
#### Scenario: Coverage gate enforces 100%
|
||||
|
||||
- **WHEN** `bunx turbo test:coverage --filter=@suaveplan/testing-e2e` runs
|
||||
- **THEN** statements, branches, functions, and lines coverage all equal 100%
|
||||
@@ -0,0 +1,80 @@
|
||||
# Tasks
|
||||
|
||||
## 0. Pre-flight (non-negotiable)
|
||||
|
||||
- [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each)
|
||||
- [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
|
||||
- [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest.
|
||||
|
||||
## 1. Catalog and dependency wiring
|
||||
|
||||
- [ ] 1.1 Add `@storybook/test-runner` to `catalogs.testing` in root `/mnt/s/web/genesis/package.json` (exact version, no bare strings).
|
||||
- [ ] 1.2 Add the catalog ref to `packages/testing/testing-dom/package.json` `dependencies`.
|
||||
- [ ] 1.3 Confirm Playwright already provides the e2e screenshot comparator — no extra dep for `testing-e2e`.
|
||||
- [ ] 1.4 Run the nuclear clean install per `openspec/AGENTS.md` §1.
|
||||
|
||||
## 2. e2e visual helpers (`@suaveplan/testing-e2e`)
|
||||
|
||||
- [ ] 2.1 Create `packages/testing/testing-e2e/src/visual/configure-visual-regression.ts` exporting `configureVisualRegression(config?)`.
|
||||
- [ ] 2.2 Create `src/visual/prepare-for-visual.ts` exporting `prepareForVisual(page)` — disables animations, waits `networkidle`, awaits `document.fonts.ready`, sets `prefers-reduced-motion: reduce`.
|
||||
- [ ] 2.3 Add `VisualRegressionError` subclass with codes `TESTING_E2E.VISUAL.PIXEL_DIFF_EXCEEDED`, `BASELINE_MISSING`, `FONTS_NOT_READY`, `VIEWPORT_MISMATCH`.
|
||||
- [ ] 2.4 Add Zod schemas in sibling `*.schemas.ts`.
|
||||
- [ ] 2.5 Add types in sibling `*.types.ts`.
|
||||
|
||||
## 3. Storybook visual helpers (`@suaveplan/testing-dom`)
|
||||
|
||||
- [ ] 3.1 Create `packages/testing/testing-dom/src/storybook-visual/create-storybook-test-runner-config.ts`.
|
||||
- [ ] 3.2 Create `src/storybook-visual/pin-story-environment.ts`.
|
||||
- [ ] 3.3 Add `StorybookVisualError` subclass with codes `TESTING_DOM.STORYBOOK_VISUAL.PIXEL_DIFF_EXCEEDED`, `BASELINE_MISSING`, `RUNNER_LOAD_FAILED`.
|
||||
- [ ] 3.4 Add Zod schemas + types siblings.
|
||||
|
||||
## 4. Tests
|
||||
|
||||
- [ ] 4.1 Unit tests for `configureVisualRegression` — defaults, overrides, viewport pinning.
|
||||
- [ ] 4.2 Unit tests for `prepareForVisual` — fonts.ready awaited, motion forced, network idle observed.
|
||||
- [ ] 4.3 Integration test capturing a known-stable fixture page and comparing to a committed baseline.
|
||||
- [ ] 4.4 Storybook unit tests for `createStorybookTestRunnerConfig` and `pinStoryEnvironment`.
|
||||
- [ ] 4.5 Cross-cutting test: baselines stored under `__snapshots__/<platform>/`.
|
||||
- [ ] 4.6 Property test over the threshold predicate using `fast-check`.
|
||||
|
||||
## 5. Docs
|
||||
|
||||
- [ ] 5.1 Sibling `.md` for each implementation file (≥200 words, basic + advanced examples, full API reference, implementation notes).
|
||||
- [ ] 5.2 Update `packages/testing/testing-e2e/README.md` and `packages/testing/testing-dom/README.md` Modules sections.
|
||||
- [ ] 5.3 Add a baseline-update workflow section to each README (separate review-tagged commits, never squashed into feature commits).
|
||||
|
||||
## 6. Subpath exports
|
||||
|
||||
- [ ] 6.1 Add `"./visual/configure-visual-regression"` and `"./visual/prepare-for-visual"` to `testing-e2e/package.json` `exports`.
|
||||
- [ ] 6.2 Add `"./storybook-visual/create-storybook-test-runner-config"` and `"./storybook-visual/pin-story-environment"` to `testing-dom/package.json` `exports`.
|
||||
- [ ] 6.3 Verify subpath count matches feature module count for both packages.
|
||||
|
||||
## 7. Adoption
|
||||
|
||||
- [ ] 7.1 Wire `configureVisualRegression()` into `apps/testbed/playwright.config.ts`.
|
||||
- [ ] 7.2 Add `expect(page).toHaveScreenshot()` calls to every page-level spec in `apps/testbed/e2e/`.
|
||||
- [ ] 7.3 Wire `createStorybookTestRunnerConfig()` into the Storybook test-runner script.
|
||||
- [ ] 7.4 Update the existing `ThemeDecorator` and `LocaleDecorator` to honour `pinStoryEnvironment`.
|
||||
- [ ] 7.5 Generate initial baselines on linux; commit under `__snapshots__/linux/`.
|
||||
- [ ] 7.6 Cross-link the release-readiness gate in `../enterprise-testbed-verification` so visual diffs fail the gate.
|
||||
|
||||
## 8. CI matrix
|
||||
|
||||
- [ ] 8.1 Add `ubuntu-latest` (linux) baseline lane.
|
||||
- [ ] 8.2 Add `macos-14` (darwin) lane — generate and commit darwin baselines on first run.
|
||||
- [ ] 8.3 Document the windows-latest decision (gate or skip-with-warning) in `apps/testbed/README.md`.
|
||||
|
||||
## 9. Pre-publish gate
|
||||
|
||||
- [ ] 9.1 `bunx turbo lint typecheck test --filter=@suaveplan/testing-e2e` green.
|
||||
- [ ] 9.2 `bunx turbo lint typecheck test --filter=@suaveplan/testing-dom` green.
|
||||
- [ ] 9.3 `bunx turbo test:coverage --filter=@suaveplan/testing-e2e` at 100%.
|
||||
- [ ] 9.4 `bunx turbo test:coverage --filter=@suaveplan/testing-dom` at 100%.
|
||||
- [ ] 9.5 Banned-pattern scan clean.
|
||||
- [ ] 9.6 Missing-`.md` scan clean.
|
||||
|
||||
## 10. Spec archive
|
||||
|
||||
- [ ] 10.1 Fold `specs/testing-e2e/spec.md` deltas into `openspec/specs/testing-e2e/spec.md`.
|
||||
- [ ] 10.2 Fold `specs/testing-dom/spec.md` deltas into `openspec/specs/testing-dom/spec.md`.
|
||||
- [ ] 10.3 Move this folder to `openspec/archive/<yyyy-mm-dd>-enterprise-testing-visual-regression/`.
|
||||
Reference in New Issue
Block a user