Skip to content

Commit f7145f0

Browse files
committed
feat: support DOM snapshot testing
1 parent 7277f47 commit f7145f0

File tree

9 files changed

+442
-6
lines changed

9 files changed

+442
-6
lines changed

.storybook/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const stories = [
1111
directory: '../stories/molecules',
1212
},
1313
// general glob
14-
'../stories/pages/**/*.stories.*',
14+
'../stories/pages/**/*.stories.@(js|jsx|ts|tsx)',
1515
];
1616

1717
if (process.env.STRESS_TEST) {

.storybook/test-runner.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,19 @@ const config: TestRunnerConfig = {
99
expect.extend({ toMatchImageSnapshot });
1010
},
1111
async postRender(page, context) {
12+
// Visual snapshot tests
1213
const image = await page.screenshot({ fullPage: true });
1314
expect(image).toMatchImageSnapshot({
1415
customSnapshotsDir,
1516
customSnapshotIdentifier: context.id,
1617
failureThreshold: 0.03,
1718
failureThresholdType: 'percent',
1819
});
20+
21+
const elementHandler = await page.$('#root');
22+
const innerHTML = await elementHandler.innerHTML();
23+
// HTML snapshot tests
24+
expect(innerHTML).toMatchSnapshot();
1925
},
2026
};
2127

README.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ Read the announcement: [Interaction Testing with Storybook](https://storybook.js
1919
- [Image snapshot recipe](#image-snapshot-recipe)
2020
- [Render lifecycle](#render-lifecycle)
2121
- [Troubleshooting](#troubleshooting)
22-
- [The test runner seems flaky and keeps timing out](#the-test-runner-seems-flaky-and-keeps-timing-out)
23-
- [Adding the test runner to other CI environments](#adding-the-test-runner-to-other-ci-environments)
22+
- [The test runner seems flaky and keeps timing out](#the-test-runner-seems-flaky-and-keeps-timing-out)
23+
- [Adding the test runner to other CI environments](#adding-the-test-runner-to-other-ci-environments)
2424
- [Future work](#future-work)
2525

2626
## Features
@@ -170,7 +170,7 @@ module.exports = {
170170
};
171171
```
172172

173-
Once you have a valid `stories.json` file, your Storybook will be compatible with the "stories.json mode".
173+
Once you have a valid `stories.json` file, your Storybook will be compatible with the "stories.json mode".
174174

175175
By default, the test runner will detect whether your Storybook URL is local or remote, and if it is remote, it will run in "stories.json mode" automatically. To disable it, you can pass the `--no-stories-json` flag:
176176

@@ -265,9 +265,25 @@ All three functions can be set up in the configuration file `.storybook/test-run
265265

266266
> **NOTE:** These test hooks are experimental and may be subject to breaking changes. We encourage you to test as much as possible within the story's play function.
267267

268+
### DOM snapshot recipe
269+
270+
The `postRender` function provides a [Playwright page](https://playwright.dev/docs/api/class-page) instance, of which you can use for DOM snapshot testing:
271+
272+
```js
273+
// .storybook/test-runner.js
274+
module.exports = {
275+
async postRender(page, context) {
276+
// the #root element wraps the story
277+
const elementHandler = await page.$('#root');
278+
const innerHTML = await elementHandler.innerHTML();
279+
expect(innerHTML).toMatchSnapshot();
280+
},
281+
};
282+
```
283+
268284
### Image snapshot recipe
269285

270-
Consider, for example, the following recipe to take image snapshots:
286+
Here's a slightly different recipe for image snapshot testing:
271287

272288
```js
273289
// .storybook/test-runner.js

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
"global": "^4.4.0",
103103
"is-localhost-ip": "^1.4.0",
104104
"jest-playwright-preset": "^1.7.0",
105+
"jest-serializer-html": "^7.1.0",
105106
"jest-watch-typeahead": "^1.0.0",
106107
"node-fetch": "^2",
107108
"playwright": "^1.14.0",

src/config/jest-playwright.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const getJestConfig = () => {
1414
globalTeardown: '@storybook/test-runner/playwright/global-teardown.js',
1515
testEnvironment: '@storybook/test-runner/playwright/custom-environment.js',
1616
setupFilesAfterEnv: ['@storybook/test-runner/playwright/jest-setup.js'],
17+
snapshotSerializers: ['jest-serializer-html'],
1718
testEnvironmentOptions: {
1819
'jest-playwright': {
1920
browsers: TEST_BROWSERS.split(',')
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Atoms/Button Demo play-test 2`] = `
4+
<button type="button">
5+
Click
6+
</button>
7+
`;
8+
9+
exports[`Atoms/Button FindBy play-test 2`] = `
10+
<button type="button">
11+
Loaded!
12+
</button>
13+
`;
14+
15+
exports[`Atoms/Button Primary smoke-test 2`] = `
16+
<button type="button"
17+
class="storybook-button storybook-button--medium storybook-button--primary"
18+
>
19+
Button
20+
</button>
21+
`;
22+
23+
exports[`Atoms/Button WaitFor play-test 2`] = `
24+
<button type="button">
25+
Click
26+
</button>
27+
`;
28+
29+
exports[`Atoms/Button WaitForElementToBeRemoved play-test 2`] = `
30+
<button type="button">
31+
Loaded!
32+
</button>
33+
`;
34+
35+
exports[`Atoms/Button WithLoaders play-test 2`] = `
36+
<button type="button">
37+
Todo: delectus aut autem
38+
</button>
39+
`;
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Molecules/Header LoggedIn smoke-test 2`] = `
4+
<header>
5+
<div class="wrapper">
6+
<div>
7+
<svg width="32"
8+
height="32"
9+
viewbox="0 0 32 32"
10+
xmlns="http://www.w3.org/2000/svg"
11+
>
12+
<g fill="none"
13+
fill-rule="evenodd"
14+
>
15+
<path d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
16+
fill="#FFF"
17+
>
18+
</path>
19+
<path d="M5.3 10.6l10.4 6v11.1l-10.4-6v-11zm11.4-6.2l9.7 5.5-9.7 5.6V4.4z"
20+
fill="#555AB9"
21+
>
22+
</path>
23+
<path d="M27.2 10.6v11.2l-10.5 6V16.5l10.5-6zM15.7 4.4v11L6 10l9.7-5.5z"
24+
fill="#91BAF8"
25+
>
26+
</path>
27+
</g>
28+
</svg>
29+
<h1>
30+
Acme
31+
</h1>
32+
</div>
33+
<div>
34+
<button type="button"
35+
class="storybook-button storybook-button--small storybook-button--secondary"
36+
>
37+
Log out
38+
</button>
39+
</div>
40+
</div>
41+
</header>
42+
`;
43+
44+
exports[`Molecules/Header LoggedOut smoke-test 2`] = `
45+
<header>
46+
<div class="wrapper">
47+
<div>
48+
<svg width="32"
49+
height="32"
50+
viewbox="0 0 32 32"
51+
xmlns="http://www.w3.org/2000/svg"
52+
>
53+
<g fill="none"
54+
fill-rule="evenodd"
55+
>
56+
<path d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
57+
fill="#FFF"
58+
>
59+
</path>
60+
<path d="M5.3 10.6l10.4 6v11.1l-10.4-6v-11zm11.4-6.2l9.7 5.5-9.7 5.6V4.4z"
61+
fill="#555AB9"
62+
>
63+
</path>
64+
<path d="M27.2 10.6v11.2l-10.5 6V16.5l10.5-6zM15.7 4.4v11L6 10l9.7-5.5z"
65+
fill="#91BAF8"
66+
>
67+
</path>
68+
</g>
69+
</svg>
70+
<h1>
71+
Acme
72+
</h1>
73+
</div>
74+
<div>
75+
<button type="button"
76+
class="storybook-button storybook-button--small storybook-button--secondary"
77+
>
78+
Log in
79+
</button>
80+
<button type="button"
81+
class="storybook-button storybook-button--small storybook-button--primary"
82+
>
83+
Sign up
84+
</button>
85+
</div>
86+
</div>
87+
</header>
88+
`;

0 commit comments

Comments
 (0)