4.3 KiB
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
postVisithook 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-motionis'reduce'AND fonts are loaded AND viewport is1280×720
Scenario: Color scheme honoured
- WHEN a story declares
parameters.colorScheme === 'dark' - THEN
pinStoryEnvironment(page)callspage.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-snapshotsis NOT set - THEN the run throws
StorybookVisualErrorwithcode === 'TESTING_DOM.STORYBOOK_VISUAL.BASELINE_MISSING'
Scenario: Variant pixel diff exceeded
- WHEN a variant comparison exceeds the configured
maxDiffPixelRatio - THEN the run throws
StorybookVisualErrorwithcode === 'TESTING_DOM.STORYBOOK_VISUAL.PIXEL_DIFF_EXCEEDED'whosecontextcontains{ 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 TestingDomErroris true ANDerr.codematches 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-domruns - THEN statements, branches, functions, and lines coverage all equal 100%