Cypress Storybook Commands
This package registers a set of cypress commands that will allow you to test components in storybook visually and functionally.
Now for projects using cypress 10 and Storybook 6. (For storybook 5 projects use version 0.1.13)
Installation
Pre-requisites
You must include the cypress-image-snapshot
plugin in cypress/plugins/index.js
(create the folder and file if not there)
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin')
module.exports = (on, config) => {
addMatchImageSnapshotPlugin(on, config)
}
and ensure that your root cypress.config.js
is configured to load the plugins
const { defineConfig } = require('cypress');
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
return require('./cypress/plugins/index.js')(on, config);
},
},
});
Add the commands
In your cypress/support/commands.js
add the following:
import addStoryBookCommands from 'cypress-storybook-commands';
addStoryBookCommands({
platform: 'web',
viewportPresets: {
mobile: 'iphone-6',
tablet: 'ipad-2',
laptop: 'macbook-13',
desktop: [1920, 1080],
},
registerSnapshotCommands: true,
preSnapshotFunc: () => { console.log('code before snapshot: hide elements, etc' )},
postSnapshotFunc: () => { console.log('code after snapshot: reset elements, etc' )},
snapshotSelector: 'body'
})
Note: update platform accordingly for the type of storybook you are using, default is web
, the alternative is native
Add the run scripts
In your cypress/package.json
add a new script for storybook tests:
"scripts": {
...
"cy:storybook": "cypress open --e2e --config baseUrl=http://localhost:6006/,specPattern='cypress/storybook/*'",
"cy:storybook:headless": "cypress open --e2e --browser chrome --headless --config baseUrl=http://localhost:6006/,specPattern='cypress/storybook/*'"
}
Note we will put storybook tests in their own folder so they do not run with the rest of your e2e
tests, and we specify the baseUrl of where your storybook can be found.
Usage
Visual regression tests
In your test file e.g. cypress/storybook/visual-regression.cy.js
you can simply:
context('Storybook', () => {
it('render components as expected', () => {
cy.visit('http://localhost:6006/')
.runStorybookVisualRegression();
});
});
this will iterate over all the stories and capture visual snapshots.
Note: runStorybookVisualRegression
has optional settings storiesToSkip
and storyWaits
. You can use full story ids or story prefixes e.g. accordion--primary
or accordion--
cy.visit('http://localhost:6006/')
.runStorybookVisualRegression({
storiesToSkip: ['button-disabled'],
storyWaits: {'chart--': 1000}
});
Functional tests
In your test file e.g. cypress/storybook/accordion.cy.js
you can load the story to carry out functional testing as follows:
context('Storybook: Accordion', () => {
beforeEach(() => {
cy.visit('/')
.loadStory('Accordion.default')
});
it('toggles content as expected', () => {
cy.get('div[data-testid="tab"]').click()
... etc ...
});
});
Note: Accordion.default
is the testID set in the navigator for that story via the data-testid
attribute.
Running
Ensure storybook is available on a url (should match baseUrl in the above added scripts). Then run yarn run cy:storybook
or yarn run cy:storybook:headless
as preferred.
On CI if you build your storybook you can use npx serve
to serve the distribution files generated by storybook, alternatively just run the storybook app in the background. You will then want to use npx start-server-and-test
to wait for storybook to be ready before running the cypress headless command.
APPCMD="npx serve@13 --listen 6006 --single ./path/to/storybook/dist"
CYPRESSCMD="yarn cy:storybook:headless --env requireSnapshots=true"
npx start-server-and-test "$APPCMD" 6006 "$CYPRESSCMD"
Note the use of --env requireSnapshots=true
so that any missing snapshots in the branch cause a CI fail.
Minimising Cross OS visual differences
If you are running the snapshots locally on a different OS to what you run on CI, you can minimise visual differences with the following in cypress/plugins/index.js
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin')
module.exports = (on, config) => {
addMatchImageSnapshotPlugin(on, config);
on('before:browser:launch', (browser = {}, launchOptions) => {
const args = Array.isArray(launchOptions) ? launchOptions : launchOptions.args;
if (browser.name === 'chrome' || browser.name === 'chromium') {
args.push('--force-device-scale-factor=1');
args.push('--force-color-profile=srgb');
args.push('--font-render-hinting=none');
}
return launchOptions;
});
}