Skip to content
This repository was archived by the owner on Mar 5, 2022. It is now read-only.

Commit be8f669

Browse files
authored
Add snapshot example (#261)
1 parent 7613e48 commit be8f669

File tree

18 files changed

+255
-19
lines changed

18 files changed

+255
-19
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ Folder Name | Description
169169
[react-scripts-folder](examples/react-scripts-folder) | A project using `react-scripts` with component tests in `cypress/component`
170170
[tailwind](examples/tailwind) | Testing styles built using [Tailwind CSS](https://tailwindcss.com/)
171171
[sass-and-ts](examples/sass-and-ts) | Example with Webpack, Sass and TypeScript
172+
[snapshots](examples/snapshots) | Component HTML and JSON snapshots using [cypress-plugin-snapshots](https://github.com/meinaart/cypress-plugin-snapshots)
172173
[visual-sudoku](examples/visual-sudoku) | [Visual testing](#visual-testing) for components using open source plugin [cypress-image-snapshot](https://github.com/palmerhq/cypress-image-snapshot). For larger example with an hour long list of explanation videos, see [bahmutov/sudoku](https://github.com/bahmutov/sudoku).
173174
[visual-testing-with-percy](examples/visual-testing-with-percy) | [Visual testing](#visual-testing) for components using 3rd party service [Percy.io](https://percy.io/)
174175
[visual-testing-with-happo](examples/visual-testing-with-happo) | [Visual testing](#visual-testing) for components using 3rd party service [Happo](https://happo.io/)

circle.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,19 @@ workflows:
159159
npm run only-covered
160160
working_directory: examples/sass-and-ts
161161

162+
- cypress/run:
163+
name: Example Snapshots
164+
requires:
165+
- Install
166+
executor: cypress/base-12
167+
# each example installs "cypress-react-unit-test" as a local dependency (symlink)
168+
install-command: npm install
169+
verify-command: echo 'Already verified'
170+
no-workspace: true
171+
working_directory: examples/snapshots
172+
command: npm test
173+
store_artifacts: true
174+
162175
- cypress/run:
163176
name: Visual Sudoku
164177
executor: cypress/base-12
@@ -256,6 +269,7 @@ workflows:
256269
- Example Component Folder
257270
- Example React Scripts
258271
- Example Sass
272+
- Example Snapshots
259273
- Example Tailwind
260274
- Example Webpack options
261275
- Visual Sudoku

cypress/component/basic/react-tutorial/pretty-snapshots-spec.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,4 @@ it('says hello world', () => {
1111
.invoke('html')
1212
.then(pretty)
1313
.should('equal', '<h1>Hello, world!</h1>')
14-
15-
// too bad - cypress-plugin-snapshots throws
16-
// ReferenceError: regeneratorRuntime is not defined
17-
// .toMatchSnapshot()
1814
})

cypress/plugins/index.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
const path = require('path')
22
const webpackPreprocessor = require('@cypress/webpack-preprocessor')
33
const babelConfig = require('../../babel.config.js')
4-
// const { initPlugin } = require('cypress-plugin-snapshots/plugin')
54

65
// should we just reuse root webpack config?
76
const webpackOptions = {
@@ -42,7 +41,5 @@ const options = {
4241

4342
module.exports = (on, config) => {
4443
on('file:preprocessor', webpackPreprocessor(options))
45-
46-
// initPlugin(on, config)
4744
return config
4845
}

cypress/support/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,3 @@
1616
// custom commands provided by this package, built from TypeScript code in "lib"
1717
// using "npm run transpile"
1818
import 'cypress-react-unit-test/hooks'
19-
// import '@percy/cypress'
20-
// import 'cypress-plugin-snapshots/commands'

examples/snapshots/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

examples/snapshots/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# example: react-snapshots
2+
3+
> Component testing with snapshots using [cypress-plugin-snapshots](https://github.com/meinaart/cypress-plugin-snapshots)
4+
5+
Note: run `npm install` in this folder to symlink `cypress-react-unit-test` dependency.
6+
7+
```shell
8+
npm install
9+
npm run cy:open
10+
# or just run headless tests
11+
npm test
12+
```
13+
14+
Example component taken from [Snapshot Testing React Components with Jest](https://semaphoreci.com/community/tutorials/snapshot-testing-react-components-with-jest)
15+
16+
![Snapshot test](images/snapshot-test.png)
17+
18+
See [cypress/component/PositiveCounter-spec.js](cypress/component/PositiveCounter-spec.js) and saved snapshots in [cypress/component/**snapshots**/](cypress/component/__snapshots__/PositiveCounter-spec.js.snap).
19+
20+
## Failing test
21+
22+
If the snapshot contents does not match the saved snapshot file, the test fails. You can click on the snapshot command, review the difference, and if the difference is expected, update the snapshot from the Test Runner's GUI.
23+
24+
![Update snapshot](images/update-snapshot.gif)

examples/snapshots/cypress.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"fixturesFolder": false,
3+
"testFiles": "**/*-spec.js",
4+
"viewportWidth": 500,
5+
"viewportHeight": 500,
6+
"experimentalComponentTesting": true,
7+
"ignoreTestFiles": [
8+
"**/__snapshots__/*",
9+
"**/__image_snapshots__/*"
10+
],
11+
"env": {
12+
"cypress-plugin-snapshots": {
13+
"prettier": true
14+
}
15+
}
16+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/// <reference types="cypress" />
2+
import React from 'react'
3+
import { mount } from 'cypress-react-unit-test'
4+
import PositiveCounter from './PositiveCounter'
5+
6+
// current version 1.4.3 of cypress-plugin-snapshots only works with
7+
// objects and images.
8+
// https://github.com/meinaart/cypress-plugin-snapshots/issues/122
9+
it.skip('sanity check: string snapshots work', () => {
10+
cy.wrap('hello, world').toMatchSnapshot()
11+
})
12+
13+
// utility child command that grabs element's HTML and snapshots its as an object
14+
Cypress.Commands.add('toMatchHTML', { prevSubject: 'element' }, $el => {
15+
return cy
16+
.wrap({
17+
html: $el[0].outerHTML,
18+
})
19+
.toMatchSnapshot()
20+
})
21+
22+
describe('PositiveCounter', () => {
23+
it('starts with zero', () => {
24+
mount(<PositiveCounter />)
25+
cy.contains('Value: 0')
26+
// previous command yields jQuery element
27+
// I would like to get its outer HTML which
28+
// we can do via $el[0].outerHTML shorthand
29+
.its('0.outerHTML')
30+
// convert text to JSON object for the snapshot plugin to work
31+
// https://github.com/meinaart/cypress-plugin-snapshots/issues/122
32+
.then(html => ({
33+
html,
34+
}))
35+
.toMatchSnapshot()
36+
37+
// in other tests we will use utility child command .toMatchHTML()
38+
})
39+
40+
it('should render counts', () => {
41+
mount(<PositiveCounter />)
42+
cy.get('.increment')
43+
.click()
44+
.click()
45+
.click()
46+
// make sure the component updates
47+
cy.contains('Value: 3').toMatchHTML()
48+
49+
cy.get('.increment')
50+
.click()
51+
.click()
52+
.click()
53+
54+
cy.contains('Value: 6').toMatchHTML()
55+
})
56+
57+
it('should not go negative', () => {
58+
mount(<PositiveCounter />)
59+
cy.get('.increment').click()
60+
cy.get('.decrement')
61+
.click()
62+
.click()
63+
cy.contains('Value: 0').toMatchHTML()
64+
})
65+
66+
it('snapshots the component state', () => {
67+
mount(<PositiveCounter />)
68+
cy.get('.increment')
69+
.click()
70+
.click()
71+
.click()
72+
.click()
73+
// The component's code set its reference
74+
// as a property on the "window" object
75+
// when running inside Cypress. This allows
76+
// the test to access it.
77+
cy.window()
78+
.its('PositiveCounter.state')
79+
.toMatchSnapshot()
80+
})
81+
})
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React, { Component } from 'react'
2+
3+
export default class PositiveCounter extends Component {
4+
constructor(props) {
5+
super(props)
6+
this.state = {
7+
count: 0,
8+
}
9+
// if we are running inside Cypress, expose the state
10+
if (window.Cypress) {
11+
window.PositiveCounter = this
12+
}
13+
}
14+
15+
increment = () => {
16+
this.setState({
17+
count: this.state.count + 1,
18+
})
19+
}
20+
21+
decrement = () => {
22+
this.setState({
23+
count: Math.max(0, this.state.count - 1),
24+
})
25+
}
26+
27+
render() {
28+
return (
29+
<span>
30+
Value: {this.state.count}
31+
<button className="decrement" onClick={this.decrement}>
32+
&minus;
33+
</button>
34+
<button className="increment" onClick={this.increment}>
35+
+
36+
</button>
37+
</span>
38+
)
39+
}
40+
}

0 commit comments

Comments
 (0)