Storybook
Visual testing for Storybook
Covered in this doc
- Installing
@percy/storybook
- Using
@percy/storybook
- How to configure
@percy/storybook
- Upgrading from v3 of
@percy/storybook
These docs apply to version v4.0.0 or later. Previous versions of
@percy/storybook
are incompatible with what is described in this document. v3.x docs can be found here
Percy visual testing for Storybook.
Installation
$ npm install --save-dev @percy/cli @percy/storybook
Usage
Before running the following commands, make sure your project's PERCY_TOKEN
is properly configured.
# Unix
$ export PERCY_TOKEN="<your-project-token>"
# Windows
$ set PERCY_TOKEN="<your-project-token>"
# Powershell
$ $Env:PERCY_TOKEN="<your-project-token>"
With a static Storybook build:
$ percy storybook ./storybook-build
With a local or live Storybook URL:
$ percy storybook http://localhost:9009
$ percy storybook https://storybook.foobar.com
Automatically run start-storybook
:
$ percy storybook:start --port=9009 --static-dir=./public
CLI options:
Options:
-i, --include <pattern> Pattern matching story names to include in snapshots
-e, --exclude <pattern> Pattern matching story names to exclude from snapshots
--shard-count <number> Number of shards to split snapshots into
--shard-size <number> Size of each shard to split snapshots into
--shard-index <index> Index of the shard to take snapshots of
--partial Marks the build as a partial build
Percy options:
-c, --config <file> Config file path
-d, --dry-run Print snapshot names only
-h, --allowed-hostname <hostname> Allowed hostnames to capture in asset discovery
--disallowed-hostname <hostname> Disallowed hostnames to abort in asset discovery
-t, --network-idle-timeout <ms> Asset discovery network idle timeout
--disable-cache Disable asset discovery caches
--debug Debug asset discovery and do not upload snapshots
Global options:
-v, --verbose Log everything
-q, --quiet Log errors only
-s, --silent Log nothing
--help Display command help
Configuration
Storybook parameters are a set of static, named metadata about a story, used to control the behavior of Storybook features and addons. The percy
parameter can be provided to add per-snapshot configuration options to a story or set of stories.
// individual stories
MyStory.parameters = {
percy: { ... }
};
// global .storybook/preview.js
export const parameters = {
percy: { ... }
};
The following percy
Storybook parameters are accepted in addition to common per-snapshot options:
- skip - Boolean indicating whether or not to skip this story.
- name - Snapshot name. (default:
${story.kind}: ${story.name}
) - args - Story args to use when snapshotting.
- globals - Story globals to use when snapshotting.
- queryParams - Query parameters to use when snapshotting.
- waitForTimeout - Wait for a timeout before taking the snapshot.
- waitForSelector - Wait for a selector to exist before taking the snapshot.
- include - An array of regex patterns matching story names to only include for snapshotting.
- exclude - An array of regex patterns matching story names to always exclude from snapshotting.
- additionalSnapshots - An array of additional snapshots to take of this story.
- prefix - A prefix added to this additional snapshot's name.
- suffix - A suffix added to this additional snapshot's name.
- name - Snapshot name. Replaces the inherited name.
- args - Additional story args for this additional snapshot.
- globals - Additional story globals for this additional snapshot.
- queryParams - Additional query parameters for this additional snapshot.
- include - Only apply the additional snapshot to matching stories.
- exclude - Do not apply the additional snapshot to matching stories.
Example config
MyStory.parameters = {
percy: {
name: 'My snapshot',
additionalSnapshots: [
{ prefix: '[Dark mode] ', args: { colorScheme: 'dark' } },
{ suffix: ' with globals', globals: { textDirection: 'rtl' } },
{ name: 'Search snapshot', queryParams: { search: 'foobar' } }
]
}
};
With this example, 4 snapshots will be taken of this story with args, globals, and any other query params appended to the URL of each snapshot:
# --dry-run will log snapshots without creating a new build
# --verbose will show debug logs, including the snapshot url
$ percy storybook --dry-run --verbose ./example-storybook
# ...
[percy] Snapshot found: My snapshot
[percy] - url: [...]?id=component--my-story
[percy] Snapshot found: [Dark mode] My snapshot
[percy] - url: [...]?id=component--my-story&args=colorScheme:dark
[percy] Snapshot found: My snapshot with globals
[percy] - url: [...]?id=component--my-story&globals=textDirection:rtl
[percy] Snapshot found: Search snapshot
[percy] - url: [...]?id=component--my-story&search=foobar
Percy config file options
In addition to common Percy config file options, this SDK also adds the following Storybook specific options:
# .percy.yml
version: 2
storybook:
args: {}
globals: {}
queryParams: {}
waitForTimeout: 0
waitForSelector: ''
additionalSnapshots: []
include: []
exclude: []
See the configuration options above for details about each accepted config file option (note: the skip
and name
parameters are not accepted as Percy config file options).
Running in parallel
Storybook snapshots can be split into shards, so that they can be captured on multiple machines. The --shard-count
option will split all snapshots into a number of shards. The --shard-size
option is the inverse, splitting by number of snapshots. The --shard-index
option tells the SDK which shard to take snapshots of. For example, to split into three shards, each capturing one third of the snapshots, each of these commands would be run on a different machine in parallel:
$ percy storybook ./build-output --shard-count=3 --shard-index=0
$ percy storybook ./build-output --shard-count=3 --shard-index=1
$ percy storybook ./build-output --shard-count=3 --shard-index=2
That way your snapshots capture up to 3 times faster.
Parallel build support requires a
PERCY_PARALLEL_NONCE
environment variable, a unique ID for this parallel build. If your CI provider is supported by Percy, this variable will automatically be set for you. Percy uses this to group many builds into a single build (with matching nonce’s). It can only be used once.
Storybook interactions tests
Storybook support interactive tests using play function. Percy Supports it by default without any additional configuration.
[Optional] Percy by default doesn't wait for this play function to finish before taking the snapshot. In this case, The waitForSelector
config can be used for Percy SDK to wait for that selector to appear. This selector can be added just before the play function completes, let's check with a help of an example.
// ...
Primary.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
const button = await canvas.getByText('Check Button');
userEvent.click(button);
// Add an identifier post interactions is complete
button.classList.add('percy-selector-placeholder');
}
// ...
Primary.parameters = {
percy: {
waitForSelector: '.percy-selector-placeholder'
},
}
Upgrading
Prior versions of the Storybook SDK were drastically different than the current version. The command, it's arguments, and how the SDK works internally have changed completely. Using the old command with new versions will now result in an error message. The new command is now integrated into @percy/cli
as a plugin.
To use new versions of this SDK, you will have to also install the CLI with the SDK:
$ npm install --save-dev @percy/cli @percy/storybook
Since both the command and arguments have changed, you'll need to replace your existing usage with the new usage described above. For some projects, this may require setting additional configuration options. See the list of breaking changes below for details.
Breaking changes
Most importantly, the command itself has changed and all previous arguments are no longer accepted.
-
The
percy-storybook
command has been replaced with apercy
CLI subcommand,percy storybook
. -
The previous
--build_dir
flag is now a command argument and there is no default build directory. If you relied on the default, it must now be explicitly provided.# before $ percy-storybook # after $ percy storybook ./storybook-static # before $ percy-storybook --build_dir ./build # after $ percy storybook ./build
-
The
--widths
flag is no longer accepted. Widths can be set using the respectivewidths
Percy config filesnapshot
option orpercy
Storybook parameter. -
The
--minimum_height
flag is no longer accepted and therefore no longer defaults to 800px. The default minimum height shared by all SDKs is 1024px. The minimum height can be set using the respectivemin-height
Percy config filesnapshot
option orpercy
Storybook parameter. -
The
--debug
flag is now--verbose
, inherited from the CLI. -
The
--output_format
flag is no longer accepted and has no alternative. If you relied on this flag, please open an issue. -
The
--rtl
and--rtl_regex
flags are no longer accepted. The--rtl
flag duplicated stories and set thedirection=rtl
query parameter for the duplicate's URL. The--rtl_regex
flag was used to determine when to create this RTL duplicate story.Click here to see how to replicate the old behaviour with new configuration options
// .storybook/preview.js export const parameters = { percy: { // tell percy to take an additional RTL snapshot for matching stories additionalSnapshots: [{ suffix: ' [RTL]', queryParams: { direction: 'rtl' }, include: ['^FormElement: .*'] }] } };
Performance
The old SDK did not take DOM snapshots or perform asset discovery, as all other modern Percy SDKs do. This sometimes resulted in flakey snapshots or snapshots with missing assets. However, DOM snapshots and asset discovery add an overhead cost of performance. Where the old SDK was very quick to simply upload the local build directory, the new SDK can be a little slower while it is capturing the real DOM and relevant assets of each story.
Unexpected diffs
Because the old SDK did not take DOM snapshots, JavaScript had to be enabled in our rendering environment for Storybook to properly load. This is in contrast to all of our other SDKs, where JavaScript is disabled by default to prevent flakey diffs caused by animations or other JavaScript running on the page. With the new SDK and real DOM snapshots, JS is disabled by default. If you upgrade and experience diffs due to the lack of JavaScript, it can be re-enabled using the matching Percy config file or per-snapshot option, enableJavaScript
.
Updated about 1 month ago