ScreenshotNeo

BlogHow-to

How to Run Chromatic Tests Only on Changed Storybook Stories

Enable Chromatic TurboSnap with `--only-changed` to test stories affected by your Git changes. Configure CI and monorepo paths, understand full retests, and troubleshoot missed changes.

By the ScreenshotNeo team4 October 20266 min read

Use Chromatic TurboSnap to run visual tests for stories affected by your changes. Enable it with --only-changed in the CLI or onlyChanged: true in the GitHub Action. TurboSnap compares Git changes with the bundler dependency graph; it captures affected stories and reuses baseline snapshots for stories judged unaffected.

1. Check the prerequisites

Before enabling TurboSnap, confirm your project meets Chromatic’s documented requirements. The current setup guide lists Chromatic CLI 10.0 or later, Storybook 6.5 or later (or Vitest 4+ for its Vitest setup), Git 2.28.0 or later, Webpack or Vite, configured stories, UI Tests enabled, and ten successful CI builds. Requirements can change, so check Chromatic’s TurboSnap setup guide for your project before adopting the configuration.

  1. Make sure Chromatic can build your Storybook and has established successful builds and baselines.
  2. Keep enough Git history in CI to identify the preceding Chromatic build and relevant ancestor.
  3. Check that the files in the Git diff correspond to files represented in the Storybook bundler graph.

2. Enable TurboSnap in the CLI

Add the flag to your existing Chromatic command. This is a runnable package script when Chromatic is installed in the project:

{
  "scripts": {
    "chromatic": "chromatic --only-changed"
  }
}

Then run it locally or in CI:

npm run chromatic -- --project-token=$CHROMATIC_PROJECT_TOKEN

Pass the project token through your CI secret store; do not commit a real token. You can also enable the setting in chromatic.config.json:

{
  "onlyChanged": true
}

3. Enable it in GitHub Actions

Set onlyChanged: true on the Chromatic action and store the token as a repository or organization secret:

name: Chromatic
on:
  push:
jobs:
  chromatic:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Run Chromatic
        uses: chromaui/action@latest
        with:
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
          onlyChanged: true

Chromatic’s setup guide specifically recommends running the workflow on push, rather than pull_request, because a pull-request workflow may use an ephemeral merge commit that is not yet in Git history. Retain enough history for ancestor detection; a shallow checkout can prevent reliable change analysis. Review the action’s current documentation when updating action versions or workflow triggers.

4. Understand what counts as changed

TurboSnap uses changes since the relevant ancestor build together with the Webpack or Vite dependency graph. If a component module is imported by a story, a change to that module can make the story eligible for capture. Unaffected stories can reuse their baseline snapshots.

The selection is at the story-file level: when one story in a .stories file is affected, Chromatic generally tests all stories in that file rather than isolating a single named story.

Changes that can trigger a broad or full retest

  • Global Storybook configuration: edits to files such as .storybook/main.js or .storybook/preview.js can affect the rendering environment for every story.
  • Shared imports: a decorator, global stylesheet, or broadly imported barrel/index file can make many stories depend on the changed file.
  • Package control files: a missing or out-of-sync lockfile can lead Chromatic to retest everything when dependency control files change.
  • Merge commits: Chromatic considers the union of changes since both ancestor builds. This conservative behavior avoids assuming changes from one side of a merge are irrelevant.

A full run after one of these changes is often expected: a global change can alter snapshots even when the individual story files did not change.

5. Configure TurboSnap in a monorepo

For reliable selection, paths in Git diffs must line up with the files represented in the Storybook build metadata. If the repository root, Storybook build, and Chromatic command use different directories, configure the Storybook base and config directories explicitly. For a Storybook in packages/webapp:

chromatic --only-changed \
  --storybook-base-dir packages/webapp \
  --storybook-config-dir packages/webapp/.storybook

Chromatic documents path resolution rules for its options; consult the TurboSnap config paths guide before adapting this example to a nested package. The npx @chromatic-com/turbosnap-helper utility can report base/config paths and optionally update configuration.

Prebuilt Storybook

If you build Storybook before running Chromatic, configure the build directory and generate the stats JSON as described in the setup documentation. TurboSnap needs the build metadata to trace imports. If a changed file is not represented in the bundler dependency graph, configure --externals for files whose changes should trigger a full retest.

6. Choose automatic filtering or manual story selection

Approach How stories are selected Coverage consideration
onlyChanged / --only-changed Automatically from Git history and dependency tracing Chromatic determines which stories may be affected and reuses unaffected baselines
onlyStoryFiles or onlyStoryNames You explicitly include files or stories Omitted stories are not automatically checked for dependency impact

Chromatic documents onlyChanged as incompatible with the manual filters onlyStoryFiles and onlyStoryNames. Use a manual filter only when you intend to test a fixed subset and accept that it does not infer the effect of changes on omitted stories. See the configuration reference.

7. Troubleshoot missing or unexpectedly broad test runs

Symptom Likely cause What to check or change
Every story is tested A global Storybook config/import changed, a shared file reaches most stories, or package control files are out of sync Inspect the changed files and dependency graph. Confirm the lockfile matches the package manager state; a full run may be correct for a global change.
No story files detected from changes Git paths and Storybook metadata paths do not align, or the changed file is not included in the build graph Run with --debug, inspect base/config paths, and use --externals for relevant files that cannot be traced.
Changes from a pull request are not considered correctly The workflow uses an ephemeral merge commit unavailable in Git history Follow Chromatic’s setup guidance to run on push and ensure sufficient Git history is checked out.
One story change runs several stories Multiple stories share one .stories file or changed dependency This is expected at file granularity; split unrelated stories into separate files if that better reflects your test boundaries.
A dependency change causes a full run Package files or lockfile changes can affect rendering dependencies beyond the directly changed component Verify the lockfile is current and treat broad dependency changes as potentially affecting the whole Storybook.
Stories are missed after adding --untraced The matching dependency path was excluded from tracing Remove or narrow the exclusion. Chromatic notes this reduces reliability; if used, consider disabling TurboSnap on the main branch so a full run still catches changes.

For further diagnostics, use Chromatic’s TurboSnap troubleshooting guide and best practices.

8. Snapshot billing, runtime, and reliability

TurboSnap reduces captured work by reusing snapshots, but it does not guarantee a fixed runtime reduction: build time, test setup, changed dependency fan-out, and global changes still matter. Its selection also depends on Git history, ancestor builds, and accurate dependency tracing, so preserve those inputs and review broad exclusions carefully.

Chromatic’s published TurboSnap billing units are: a captured snapshot is 1 billed snapshot, a copied snapshot is 0.2, and a bypassed snapshot is 0. Chromatic’s documentation illustrates this with 10 captured and 40 copied stories in a 50-story Storybook, totaling 18 billed snapshots. These are billing units, not a guarantee of a specific bill or time saving; actual totals depend on captured, copied, and bypassed snapshots. Review Chromatic’s TurboSnap introduction and your current plan terms for billing details.

9. FAQ

Does TurboSnap test only the exact story I edited?

No. It traces affected story files. If one story in a file changes or is affected, other stories in that file may be included as well.

Can I combine onlyChanged with onlyStoryNames?

No. Chromatic documents automatic change detection and manual story filters as incompatible configuration choices.

TurboSnap considers changes since both ancestor builds for a merge, so it conservatively includes the union of potentially relevant changes.

Or skip the browser setup

Chromatic is for visual testing of Storybook stories. If your task is to capture a website page as an image or PDF, ScreenshotNeo provides a screenshot API and MCP server; it does not replace Chromatic’s story regression workflow. Its API can capture pages with one request, without installing or maintaining a browser in your project.

cURL:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before capture. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

Sign up free for 1,000 screenshots a month, no card required.