sanity-visual-regression
GitHub用于在 Sanity monorepo 中通过 Storybook、Vitest 和 Playwright 添加、审查和维护 Chromatic 视觉回归测试覆盖。
Trigger Scenarios
Install
npx skills add sanity-io/sanity --skill sanity-visual-regression -g -y
SKILL.md
Frontmatter
{
"name": "sanity-visual-regression",
"description": "Add, review, and maintain Chromatic visual regression coverage in the Sanity monorepo via dev\/storybook stories, the vitest browser-mode suite, and Playwright e2e snapshots. Use when adding visual test coverage, writing stories, reviewing Chromatic diffs, working on the styled-components to vanilla-extract or @sanity\/ui to ui5 migrations, or when a PR needs visual regression protection."
}
Sanity Visual Regression Testing
Visual regression runs on Chromatic, wired via .github/workflows/chromatic.yml. Three snapshot sources, one Chromatic project each:
| Source | Chromatic project | Repo secret | Status |
|---|---|---|---|
dev/storybook stories |
sanity |
CHROMATIC_PROJECT_TOKEN_STORYBOOK |
Active |
| Vitest browser tests (in place) | vitest project | CHROMATIC_PROJECT_TOKEN_VITEST |
Dormant (early access) — see activation below |
Playwright e2e takeSnapshot() |
sanity_e2e |
CHROMATIC_PROJECT_TOKEN_E2E |
Active, curated opt-in |
All checks are non-gating during burn-in (exitZeroOnChanges); merges to main auto-accept
baselines. Review diffs on the Chromatic build linked from the PR check.
Quick start: add visual coverage for a component
- Add a co-located
*.stories.tsxfile to the owning package'ssrctree, usually in the same__tests__directory as the component or harness. Storybook discovers story files in workspace packagesrctrees. Two patterns:- Plain component states (ui-components wrappers, tone/card sentinels): render variants directly — see Button.stories.tsx. Put many variants in one story (a grid) to keep snapshot count low.
- Studio-context states (form inputs, anything needing workspace/i18n/layers): wrap in the
browser-test harness
TestWrapper(+TestFormfor form inputs) — see Dialog.stories.tsx and the Portable Text stories. If a vitest browser test already has a*Story.tsxharness, put the story beside it and reuse it (never fork it): the harness stays shared between the test and the story.
- Verify locally:
pnpm dev:storybook(port 6006), thenpnpm --filter sanity-storybook test(every story runs as a vitest browser-mode test via@storybook/addon-vitest). - Push — the
Chromatic / Storybook visual testscheck snapshots only affected stories (TurboSnap) and links the build for review.
Migration priority: card and tone-related components first (tones cascade through everything),
box primitives later. Snapshot the wrapper components in packages/sanity/src/ui-components
and vanilla-extract-migrated components (change indicators, DocumentLayout) as sentinels.
Determinism rules for stories
- Harness stories are deterministic by construction (mock client/workspace, no network).
- Never render live timestamps, random ids, or unfinished loading states. Chromatic pauses CSS animations automatically.
- Knobs via
parameters.chromaticper story/meta:delay(ms before capture — Portable Text stories use 300 for editor boot),diffThreshold,disableSnapshot: true(story stays in Storybook + addon-vitest but is never snapshotted),modes(viewport/theme matrix — the global 1280×900 desktop mode in preview.tsx matches the vitest browser viewport).
Vitest integration activation runbook (when early access lands)
@chromatic-com/vitest is pre-wired but dormant. To activate:
- Create the Vitest-type Chromatic project (requires Chromatic early access enablement).
- Add its token as the
CHROMATIC_PROJECT_TOKEN_VITESTrepo secret. - Done — the
Chromatic / Vitest browser visual testsjob self-activates on the next run. No code changes. Every browser test's end state becomes a snapshot; the first build is the full baseline.
Afterwards, consider slimming co-located harness-reuse stories that overlap with end-of-test
snapshots (keep them if the browsable workbench view is worth the snapshot spend). See
REFERENCE.md for local capture runs, takeSnapshot()/configure() usage inside
tests (only valid once the plugin is active — takeSnapshot() THROWS in normal runs, so never
commit calls to it while the integration is dormant), and cost controls.
Playwright e2e snapshots
e2e/studio-test.ts wraps @chromatic-com/playwright with auto-snapshots disabled globally —
the suite runs against per-PR staging datasets (live timestamps, presence, parallel mutations),
so blanket end-of-test snapshots would be pure diff noise. Opt in per spec with takeSnapshot()
at deterministic moments only. See REFERENCE.md before
adding e2e snapshots.
More
REFERENCE.md: architecture and rationale, local Chromatic runs, CLI flags,
snapshot cost management, Vercel deployment (studio-storybook.sanity.dev), troubleshooting.
Version History
- 3235fb3 Current 2026-08-20 10:56


