Skip to content

Commit ba3d363

Browse files
committed
React Native Storybook Commands
0 parents  commit ba3d363

File tree

9 files changed

+659
-0
lines changed

9 files changed

+659
-0
lines changed

.editorconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# This file allows IDEs to automatically adjust spacing
2+
# In order to take advantage of this file, please use an .editorconfig plugin for your IDE
3+
# editorconfig.org
4+
5+
[*]
6+
charset = utf-8
7+
end_of_line = lf
8+
indent_size = 2
9+
indent_style = space
10+
insert_final_newline = true
11+
trim_trailing_whitespace = true
12+
13+
[*.md]
14+
trim_trailing_whitespace = false
15+
16+
[Makefile*]
17+
indent_size = 4
18+
indent_style = tab

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Cypress Storybook Commands
2+
3+
This package registers a set of cypress commands that will allow you to test components in storybook visually and functionally.
4+
5+
## Usage
6+
7+
In your `cypress/support/commands.js` add the following:
8+
9+
```
10+
import addStoryBookCommands from 'cypress-storybook-commands';
11+
12+
addStoryBookCommands({
13+
platform: 'web', // set to native if using storybook-native
14+
viewportPresets: { // see https://docs.cypress.io/api/commands/viewport.html#Arguments
15+
mobile: 'iphone-6',
16+
tablet: 'ipad-2',
17+
laptop: 'macbook-15',
18+
desktop: [1920, 1080]
19+
},
20+
registerSnapshotCommands: true // set to false if you already include cypress-image-snapshot/command in your setup
21+
})
22+
23+
```
24+
25+
Note: update platform accordingly for the type of storybook you are using, default is web.
26+
27+
### Visual regression tests
28+
29+
In your test file e.g. `cypress/tests/components/visual-regression.js` you can simply:
30+
31+
```
32+
context('Components', () => {
33+
it('render components as expected', () => {
34+
cy.visit('/')
35+
.runStorybookVisualRegression();
36+
});
37+
});
38+
```
39+
40+
### Functional tests
41+
42+
In your test file e.g. `cypress/tests/components/accordion.js` you can load the story to carry out functional testing as follows:
43+
44+
```
45+
context('Components: Accordion', () => {
46+
beforeEach(() => {
47+
cy.visit('/')
48+
.loadStory('Accordion.default')
49+
});
50+
51+
it('toggles content as expected', () => {
52+
cy.get('div[data-testid="tab"]').click()
53+
... etc ...
54+
});
55+
});
56+
```
57+
58+
Note: `Accordion.default` is the testID set in the navigator for that story via the `data-testid` attribute.

package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "cypress-storybook-commands",
3+
"version": "0.1.2",
4+
"description": "Commands to help navigate storybook in Cypress for functional and visual component level testing",
5+
"main": "src/index.js",
6+
"author": "Daniel Antelo",
7+
"peerDependencies": {
8+
"cypress": "^3.0.0",
9+
"cypress-image-snapshot": "^3.1.1"
10+
}
11+
}

src/index.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const addStoryBookWebCommands = require('./storybook');
2+
const addStoryBookNativeCommands = require('./storybook-native');
3+
const addVisualSnapshotCommands = require('./visual');
4+
5+
module.exports = function addStoryBookCommands({
6+
platform = 'web',
7+
viewportPresets,
8+
registerSnapshotCommands = true
9+
}) {
10+
addVisualSnapshotCommands({ viewportPresets, registerSnapshotCommands });
11+
12+
switch (platform) {
13+
case 'web':
14+
addStoryBookWebCommands();
15+
break;
16+
case 'native':
17+
addStoryBookNativeCommands();
18+
break;
19+
}
20+
};

src/storybook-native.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module.exports = function addStoryBookNativeCommands() {
2+
Cypress.Commands.add('openStorybookNavigator', () => {
3+
return cy.get('.css-text-901oao').contains('NAVIGATOR').click();
4+
});
5+
6+
Cypress.Commands.add('openStorybookPreview', () => {
7+
return cy.get('.css-text-901oao').contains('PREVIEW').click();
8+
});
9+
10+
Cypress.Commands.add('getStories', () => {
11+
return cy.get('[data-testid="Storybook.ListView"] [data-testid]');
12+
});
13+
14+
Cypress.Commands.add('loadStory', (story) => {
15+
return cy
16+
.openStorybookNavigator()
17+
.get(story)
18+
.scrollIntoView()
19+
.click()
20+
.openStorybookPreview()
21+
.wait(100) // wait for animation to finish;
22+
});
23+
24+
Cypress.Commands.add('runStorybookVisualRegression', () => {
25+
return cy
26+
.openStorybookNavigator()
27+
.getStories()
28+
.each((story) => {
29+
cy
30+
.loadStory(story)
31+
.matchesBaselineScreenshot(story.attr('data-testid'));
32+
});
33+
});
34+
}

src/storybook.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module.exports = function addStoryBookWebCommands() {
2+
Cypress.Commands.add('getStories', () => {
3+
4+
});
5+
6+
Cypress.Commands.add('loadStory', (story) => {
7+
8+
});
9+
10+
Cypress.Commands.add('runStorybookVisualRegression', () => {
11+
return cy
12+
.getStories()
13+
.each((story) => {
14+
cy
15+
.loadStory(story)
16+
.matchesBaselineScreenshot(story.attr('data-testid'));
17+
});
18+
});
19+
}

src/visual.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const defaultViewportPresets = {
2+
mobile: 'iphone-6',
3+
tablet: 'ipad-2',
4+
desktop: 'macbook-15'
5+
};
6+
7+
module.exports = function addVisualSnapshotCommands({ viewportPresets = defaultViewportPresets, registerSnapshotCommands }) {
8+
if (registerSnapshotCommands) {
9+
const addMatchImageSnapshotCommand = require('cypress-image-snapshot/command').addMatchImageSnapshotCommand;
10+
registerSnapshotCommands && addMatchImageSnapshotCommand({
11+
failureThreshold: 0.03,
12+
failureThresholdType: 'percent',
13+
customDiffConfig: { threshold: 0.1 },
14+
customDiffDir: 'cypress/__visual_diff_errors__'
15+
});
16+
};
17+
18+
Cypress.Commands.add('matchesBaselineScreenshot', (name, { selector = 'body' } = {}) => {
19+
Object.keys(viewportPresets).forEach((current) => {
20+
const viewport = viewportPresets[current];
21+
cy.viewport(...(Array.isArray(viewport) ? viewport : [viewport]))
22+
.wait(250) // avoid capturing resize flickers
23+
.get(selector)
24+
.then(() => {
25+
cy.matchImageSnapshot(`${name}-${current}`);
26+
});
27+
});
28+
});
29+
};

0 commit comments

Comments
 (0)