We're actively integrating community feedback to improve the tooling and documentation for snapshot testing with Storybook. If you're interested in participating in this process and helping us improve it. Please fill out this form to share your feedback.
This guide will teach you how to migrate your snapshot tests from the Storyshots addon to Storybook's test-runner or portable stories. Also, you will be able to understand the differences between them and set up, configure, and run snapshot tests using the available tooling provided by Storybook.
Storybook test-runner turns all of your stories into executable tests. Powered by Jest and Playwright. It's a standalone, framework-agnostic utility that runs parallel to your Storybook. It enables you to run multiple testing patterns in a multi-browser environment, including interaction testing with the play function, DOM snapshot, and accessibility testing.
To get started with the migration process from the Storyshots addon to the test-runner, we recommend that you remove the Storyshots addon and similar packages (i.e., storybook/addon-storyshots-puppeteer ) from your project, including any related configuration files. Then, follow the test-runner's setup instructions to install, configure and run it.
The Storyshots addon offered a highly customizable testing solution, allowing users to extend testing coverage in various ways. However, the test-runner provides a similar experience but with a different API. Below, you will find additional examples of using the test-runner to achieve results similar to those you achieved with Storyshots.
To enable DOM snapshot testing with the test-runner, you can extend the test-runner's configuration file and use the available hooks and combine them with Playwright's built-in APIs to generate DOM snapshots for each story in your project. For example:
.storybook/test-runner.ts
💡
If you've set up DOM snapshot tests in your project with the test-runner and enabled the index.json mode via CLI flag, tests are generated in a temporary folder outside your project, and snapshots get stored alongside them. You'll need to extend the test-runner's configuration and provide a custom snapshot resolver to allow a different location for the snapshots. See the Troubleshooting section for more information.
By default, the test-runner provides you with the option to run multiple testing patterns (e.g., DOM snapshot testing, accessibility) with minimal configuration. However, if you want, you can extend it to run visual regression testing alongside your other tests. For example:
Storybook provides a composeStories utility that helps convert stories from a story file into renderable elements that can be reused in your Node tests with JSDOM. It also allows you to apply other Storybook features that you have enabled in your project (e.g., decorators, args), which allows your component to render correctly. This is what is known as portable stories.
We recommend you turn off your current storyshots tests to start the migration process. To do this, rename the configuration file (i.e., storybook.test.ts|js or similar) to storybook.test.ts|js.old. This will prevent the tests from being detected, as you'll create a new testing configuration file with the same name. By doing this, you'll be able to preserve your existing tests while transitioning to portable stories before removing the Storyshots addon from your project.
If you need project-level annotations (e.g., decorators, args, styles) enabled in your ./storybook/preview.js|ts included in your tests, adjust your test set up file to import the annotations as follows:
setupFile.js|ts
ℹ️
If you're using Vue3, you must install the @storybook/testing-vue3 package to use the setProjectAnnotations API in your setup file and the composeStories API in your existing tests.
To help you migrate from Storyshots addon to Storybook's portable stories with the composeStories helper API, we've prepared examples to help you get started. Listed below are examples of two of the most popular testing frameworks: Jest and Vitest. We recommend placing the code in a newly created storybook.test.ts|js file and adjusting the code accordingly, depending on your testing framework. Both examples below will:
Import all story files based on a glob pattern
Iterate over these files and use composeStories on each of their modules, resulting in a list of renderable components from each story
Cycle through the stories, render them, and snapshot them
If you're using Vitest as your testing framework, you can begin migrating your snapshot tests to Storybook's portable stories with the composeStories helper API by referring to the following example. You will need to modify the code in your storybook.test.ts|js file as follows:
storybook.test.ts
When your test is executed with Vitest, it will generate a single snapshot file (i.e., storybook.test.ts|js.snap) with all the stories in your project. However, if you want to generate individual snapshot files, you can use Vitest's toMatchFileSnapshot API. For example:
If you're using Jest as your testing framework, you can begin migrating your snapshot tests to Storybook's portable stories with the composeStories helper API by referring to the following example. You will need to modify the code in your storybook.test.ts|js file as follows:
storybook.test.ts
When your test is executed with Jest, it will generate a single snapshot file (i.e., __snapshots__/storybook.test.ts|js.snap) with all the stories in your project. However, if you want to generate individual snapshot files, you can use the jest-specific-snapshot package. For example:
If you opt to use portable stories in your tests, you'll have a single test file that can run in a JSDOM environment, rendering and snapshotting all your stories. However, as your project grows, you may run into the limitations you had with Storyshots previously:
You are not testing against a real browser.
You must mock many browser utilities (e.g., canvas, window APIs, etc).
Your debugging experience will not be as good, given you can't access the browser as part of your tests.
Alternatively, you may want to consider migrating to the other available option for snapshot testing with Storybook: the test-runner for a more robust solution that runs tests against a real browser environment with Playwright.
As running snapshot tests with Storybook and the test-runner can lead to some technical limitations that may prevent you from setting up or running your tests successfully, we've prepared a set of instructions to help you troubleshoot any issues you may encounter.
If you're experiencing intermittent test failures with the test-runner, uncaught errors may occur when your tests run in the browser. These errors might not have been caught if you were using the Storyshots addons previously. The test-runner will, by default, consider these uncaught errors as failed tests. However, if these errors are expected, you can ignore them by enabling custom story tags in your stories and test-runner configuration files. For more information, please refer to the test-runner documentation.
If you've configured the test-runner to run snapshot tests, you may notice that the paths and names of the snapshot files differ from those previously generated by the Storyshots addon. This is because the test-runner uses a different naming convention for snapshot files. Using a custom snapshot resolver, you can configure the test-runner to use the same naming convention you used previously.
Run the following command to generate a custom configuration file for the test-runner that you can use to configure Jest:
Update the file and enable the snapshotResolver option to use a custom snapshot resolver:
./test-runner-jest.config.js
Finally, create a snapshot-resolver.js file to implement a custom snapshot resolver:
By default, the test-runner uses jest-serializer-html to serialize HTML snapshots. This may cause differences in formatting compared to your existing snapshots, even if you're using specific CSS-in-JS libraries like Emotion, Angular's ng attributes, or other similar libraries that generate hash-based identifiers for CSS classes. However, you can configure the test-runner to use a custom snapshot serializer to solve this issue by overriding the random class names with a static one that will be the same for each test run.
Run the following command to generate a custom configuration file for the test-runner that you can use to provide additional configuration options.
Update the file and enable the snapshotSerializers option to use a custom snapshot resolver. For example:
./test-runner-jest.config.js
Finally, create a snapshot-serializer.js file to implement a custom snapshot serializer:
./snapshot-serializer.js
When the test-runner executes your tests, it will introspect the resulting HTML and replace any dynamically generated attributes with the static ones provided by the regex expression before snapshotting the component.