Playwright Testing
chongdashu/vibejam-starter-pack
Plan, implement, and debug frontend tests: unit/integration/E2E/visual/a11y.
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.
$ npx skills add sanity-io/sanity --skill sanity-visual-regression -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install sanity-io/sanity sanity-visual-regression --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/sanity-visual-regression .claude/skills/sanity-visual-regression && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "sanity-visual-regression" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/sanity-visual-regression into .claude/skills/sanity-visual-regression/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sanity-visual-regression", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/sanity-io/sanity/tree/main/.agents/skills/sanity-visual-regressionType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add sanity-io/sanity --skill sanity-visual-regression -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install sanity-io/sanity sanity-visual-regression --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/sanity-visual-regression .agents/skills/sanity-visual-regression && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "sanity-visual-regression" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/sanity-visual-regression into .agents/skills/sanity-visual-regression/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sanity-visual-regression", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add sanity-io/sanity --skill sanity-visual-regression -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install sanity-io/sanity sanity-visual-regression --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/sanity-visual-regression .cursor/skills/sanity-visual-regression && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "sanity-visual-regression" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/sanity-visual-regression into .cursor/skills/sanity-visual-regression/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sanity-visual-regression", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/sanity-io/sanity.git --path .agents/skills/sanity-visual-regression--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add sanity-io/sanity --skill sanity-visual-regression -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install sanity-io/sanity sanity-visual-regression --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/sanity-visual-regression .gemini/skills/sanity-visual-regression && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "sanity-visual-regression" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/sanity-visual-regression into .gemini/skills/sanity-visual-regression/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sanity-visual-regression", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install sanity-io/sanity sanity-visual-regressionInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add sanity-io/sanity --skill sanity-visual-regression -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/sanity-visual-regression .github/skills/sanity-visual-regression && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "sanity-visual-regression" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/sanity-visual-regression into .github/skills/sanity-visual-regression/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sanity-visual-regression", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add sanity-io/sanity --skill sanity-visual-regression -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install sanity-io/sanity sanity-visual-regression --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/sanity-visual-regression .opencode/skills/sanity-visual-regression && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "sanity-visual-regression" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/sanity-visual-regression into .opencode/skills/sanity-visual-regression/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sanity-visual-regression", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
sanity-visual-regressionAdd, review, and maintain Chromatic visual regression coverage in the Sanity monorepo via dev/storybook stories, the vitest browser-mode suite, and Playwright e2e snapshots.
Sanity Visual Regression is an agent skill from sanity-io/sanity, published by the product's own GitHub organization. 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.
Its SKILL.md is about 3.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `REFERENCE.md`).
It sits in Testing & QA, covering Visual regression testing, Unit testing and End-to-end testing. It works with Playwright, Vitest and Storybook. The repository describes itself as: Sanity Studio – Rapidly configure content workspaces powered by structured content. The licence is MIT.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit efa15fb. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pnpmFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
chromatic.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Sanity Visual Regression loads about 3.4k tokens when it runs. Until then it costs about 104 tokens; SKILL.md has 1,525 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from sanity-io/sanity at commit efa15fb, republished under its MIT licence (© sanity-io). 1,525 words, ~3,355 tokens.
.claude/skills/sanity-visual-regression/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.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 studio" | CHROMATIC_PROJECT_TOKEN_STORYBOOK | Active |
| Vitest browser tests (in place) | "sanity studio vitest" | CHROMATIC_PROJECT_TOKEN_VITEST | Active |
Playwright e2e takeSnapshot() | "sanity studio playwright" | 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.
The two chromatic.yml sources only run on a pull request that carries the trigger:chromatic
label — a PR without it shows both jobs as skipped and produces no Chromatic build to review. The
label persists, so every later push re-runs them until it is removed. Pushes to main always run,
which is what keeps the baselines current. The Playwright source rides along with the e2e suite in
e2e.yml and is not gated by the label.
Each source owns a disjoint set of states. Decide by how the state is reached, and never move a state between sources:
| The state is… | It belongs in |
|---|---|
Reachable from props/fixtures alone, or one play interaction (open a menu, hover a tooltip) | A *.stories.tsx in the owning package (dev/storybook snapshots it) |
| Reached by driving the UI: typing, drag, clipboard, focus tracking, viewport changes, server commands | A *.browser.test.tsx — its end state is the snapshot; takeSnapshot() for mid-test states (see below) |
| Full-studio chrome against a real deployment and dataset | A Playwright spec using e2e/studio-visual-test.ts ("sanity studio playwright" project), read-only states only |
Consequences:
*.browser.test.tsx is the snapshot source for everything it renders — the Vitest plugin
archives every test's end state with no test code changes. Browser tests keep their harness
component inline (function FooHarness() in the test file) and never get a Storybook story on
top. Do not re-export a browser test as a story, and do not port a browser test into a story
with an elaborate play function.*Story.tsx file is a Storybook harness imported by a *.stories.tsx. Stories cover the
states no browser test renders.e2e/. Do not put specs, @chromatic-com/playwright, or e2e fixtures under
dev/storybook, and do not turn an e2e spec into a story (or the reverse) to get a snapshot.
dev/storybook's playwright dependency is only the browser runner for @storybook/addon-vitest.Chromatic / … job that uploads one source's output to another source's project;
Chromatic requires one project per integration type.Before writing anything, run pnpm visual-coverage <path> --prs and follow
sanity-visual-coverage. It reports whether a story already
renders the component or an open PR is about to, so you only add what is missing.
*.stories.tsx file to the owning package's src tree, usually in the same
__tests__ directory as the component or harness. Storybook discovers story files in workspace
package src trees — do not add CSF under dev/storybook/stories/. Two patterns:TestWrapper (+ TestForm for form inputs) from
packages/sanity/test/browser — the same wrapper the browser tests use — see
Dialog.stories.tsx
and
EditorChrome.stories.tsx.
New coverage can use a colocated *Story.tsx when the grid needs TestWrapper inside the
harness — see
ConfirmPopover.stories.tsx.
Do not extract a browser test's inline harness into a *Story.tsx to reuse it from a
story: that state is snapshotted by the Vitest integration, and the story would be a
duplicate snapshot of the same pixels. If the test's harness lacks a state you need, add it
to the test, or build a separate story-only harness.play
function using storybook/test (userEvent + waitFor/expect(...).toBeVisible(), querying
within(document.body) for portaled content). Chromatic and addon-vitest both run play
before capturing, so the snapshot shows the open overlay — see
Tooltip.stories.tsx
and
MenuGroup.stories.tsx
(the latter also documents an animation pitfall with nested popovers). Statically controllable
overlays (e.g. Popover's open prop) don't need play.pnpm dev:storybook (port 6006), then pnpm --filter sanity-storybook test
(every story runs as a vitest browser-mode test via @storybook/addon-vitest).Chromatic / Storybook visual tests check 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.
The Storybook is a living document of how reusable components look and behave, and every story
in it is meant to be read: authored variant grids, component states and migration sentinels,
each with a concise JSDoc description of what it shows and why. Do not use story tags to hide
stories from the sidebar (!dev) or docs (!autodocs). That convention existed only for the
stories that re-exported vitest browser tests, and those are gone — browser tests are snapshotted
in place by the Vitest project. If a state is not worth a person looking at, it does not belong
in Storybook; drive it in a browser test instead (see "Which source owns a state").
A story that should be browsable but never snapshotted sets
parameters: {chromatic: {disableSnapshot: true}}.
parameters.chromatic per 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).Chromatic for Vitest Browser Mode
is generally available (@chromatic-com/vitest 1.x) and the "sanity studio vitest" project is
live: the Chromatic / Vitest browser visual tests job re-runs the suite on chromium with
CHROMATIC=1 on every PR and pushes the archives. Every *.browser.test.tsx is in the visual
suite without any code in the test, and the MyComponent.browser.test.tsx +
MyComponentStory.tsx + MyComponent.stories.tsx triple that existed only to snapshot a browser
test is gone (see "Which source owns a state").
describe chain / it title / Snapshot #n under the test file's path.configure({disableAutoSnapshot: true}) from @chromatic-com/vitest. The
scope follows where it is called: at the top level of a test file it applies to every test in
the file; inside a describe() to that suite and its nested suites; inside a test() to that
test only. Use it for tests whose end state is not worth a snapshot (pure interaction checks,
cleanup-only states) — the snapshot budget is per test case.await takeSnapshot('state name') inside a test(), for states
the test moves through but does not end on (a menu open before the click that closes it, a
drag mid-way). Always await it; the plugin fails the test on un-awaited calls. Docs:
targeted snapshots.:hover /
:focus / :active at capture and re-applies them, so the real pointer position and React
hover/focus state are part of the snapshot. End interactive tests with
settleChromaticEndState() (packages/sanity/test/browser/testHelpers.ts: parks the pointer,
asserts a hover-free tree and no open tooltip, waits for toolbar/popover geometry) and assert
the exact state you want captured (toBeEnabled(), data-focused="true", a visible menu)
right before the test ends or before takeSnapshot(). Never fix a flaky snapshot with global
CSS from the test setup (zeroed transitions, hidden carets, forced opacity). Reduced motion is a
capture-time setting only: Chromatic renders the uploaded archive with
prefersReducedMotion: 'reduce' and pauseAnimationAtEnd (vitest.browser.config.mts), which
the @sanity/ui v5 stylesheet (ui5/styles.css) honors. The browser the tests run in — local
runs, the functional browser-tests.yml shards and the capture run alike — has no
reduced-motion emulation, so transitions run at full length there; wait for the settled state
instead of assuming the media query shortened it.vitest.browser.config.mts on every run, so
both @chromatic-com/vitest helpers (configure, takeSnapshot) work in plain
pnpm --filter sanity test:browser runs and in the functional browser-tests.yml shards; those
two are no-ops on firefox and webkit. settleChromaticEndState() is not part of the plugin and
is not a no-op anywhere: it parks the pointer and runs its stability waits on every browser, so
a test's end state is asserted in the functional shards too — do not skip it on firefox or
webkit. Only CHROMATIC=1 turns on capturing (automatic snapshots, TurboSnap stats, reporter
output, Chromatic telemetry); a normal run writes nothing except the archive of an explicit
takeSnapshot() call, into the gitignored .vitest/chromatic.See REFERENCE.md for local capture runs, TurboSnap, sharding and cost controls.
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.
REFERENCE.md: architecture and rationale, local Chromatic runs, CLI flags,
snapshot cost management, Vercel deployment (studio-storybook.sanity.dev), troubleshooting.
© sanity-io, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in .agents/skills/sanity-visual-regression of sanity-io/sanity.
Open the folder on GitHubat commit efa15fb
Sanity Visual Regression next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Sanity Visual Regression this skillsanity-io/sanity | 6.4k | — | ~3.4k | Automated safety check: Pass | MIT | |
| Playwright Testingchongdashu/vibejam-starter-pack | 149 | — | ~2.2k | Automated safety check: Pass | None | |
| Web Testing with Playwright and Vitestwithkynam/vibecode-pro-max-kit | 1.1k | — | ~892 | Automated safety check: Pass | Apache-2.0 | |
| Test CommanderEliasOulkadi/shokunin | 114 | — | ~3k | Automated safety check: Notes | MIT | |
| Control UI E2Eopenclaw/openclaw | 392k | — | ~2.9k | Automated safety check: Pass | MIT | |
| Ckeditor5 TestingTriliumNext/Trilium | 38k | — | ~3.3k | Automated safety check: Pass | AGPL-3.0 |
chongdashu/vibejam-starter-pack
Plan, implement, and debug frontend tests: unit/integration/E2E/visual/a11y.
withkynam/vibecode-pro-max-kit
Covers web testing from unit to E2E, load, visual, accessibility and security checks, with Playwright, Vitest and k6 guides plus a Playwright setup script.
EliasOulkadi/shokunin
Generate unit, integration, E2E, and visual regression tests following the Testing Trophy methodology (80% integration).
openclaw/openclaw
A skill your agent uses when designing, testing, fixing, or extending the OpenClaw Control UI GUI, including UI stress-test galleries with feedback inputs, Vitest + Playwright end-to-end checks…
TriliumNext/Trilium
Testing CKEditor 5 plugins in the Trilium monorepo. An agent skill from TriliumNext/Trilium.
igrlk/storybook-addon-test-codegen
Check the visual impact of an edit mid-task with uiverify check — render just the components you're touching on the UI Verify fleet and diff them against the real CI baseline, without opening a PR…
sanity-io/sanity
Automates browser interactions for web testing, form filling, screenshots, and data extraction.
sanity-io/sanity
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities.
sanity-io/sanity
React and Next.js performance optimization guidelines from Vercel Engineering.
sanity-io/sanity
Add existing screenshots or screen recordings to a GitHub pull request as a before/after or preview block.
sanity-io/sanity
React DevTools CLI for AI agents. An agent skill from sanity-io/sanity.
sanity-io/sanity
Test-driven development with red-green-refactor loop. An agent skill from sanity-io/sanity.
Works with
Categories
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. Sanity Visual Regression is an agent skill from sanity-io/sanity, published by the product's own GitHub organization. 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.
Sanity Visual Regression fits situations like: adding visual test coverage; writing stories; reviewing Chromatic diffs; working on the styled-components to vanilla-extract.
Run `npx skills add sanity-io/sanity --skill sanity-visual-regression -a claude-code`. Or copy the skill folder (.agents/skills/sanity-visual-regression in sanity-io/sanity) into .claude/skills/sanity-visual-regression in your project. Claude Code loads it when a task matches its description.
Run `npx skills add sanity-io/sanity --skill sanity-visual-regression -a codex`. Or copy the skill folder (.agents/skills/sanity-visual-regression in sanity-io/sanity) into .agents/skills/sanity-visual-regression in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add sanity-io/sanity --skill sanity-visual-regression -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/sanity-visual-regression, .gemini/skills/sanity-visual-regression, .github/skills/sanity-visual-regression and .opencode/skills/sanity-visual-regression in your project.
Going by SKILL.md and its folder, Sanity Visual Regression needs the command-line tools its instructions call (pnpm).
SKILL.md names 1 domain. As links in the text: chromatic.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Sanity Visual Regression is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.4k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Sanity Visual Regression: Playwright Testing (chongdashu/vibejam-starter-pack, 149 stars), Web Testing with Playwright and Vitest (withkynam/vibecode-pro-max-kit, 1.1k stars), Test Commander (EliasOulkadi/shokunin, 114 stars) and Control UI E2E (openclaw/openclaw, 392k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
sanity-io (a GitHub organization, an official publisher) maintains it in sanity-io/sanity, which has 6,352 GitHub stars. The repository holds 34 skills in this directory. The repository was last updated on October 9, 2026.
Source: sanity-io/sanity on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.