More Related Content Similar to Crushing React bugs with Jest and Enzyme (20) More from All Things Open (20) Crushing React bugs with Jest and Enzyme2. This talk is for those...
Build React Components
New or interested in getting started with unit
testing
2
9. What is Jest
JavaScript Testing Framework
Open source created by Facebook
Assert, snapshots, code coverage
reports...
6 . 4
10. What is Enzyme?
JavaScript Testing Utility
Open source created by AirBnB
Easily manipulate, traverse
Can be used in conjunction with Jest
6 . 5
11. Setup
// https://github.com/FormidableLabs/enzyme-matchers/tree/mast
yarn add jest-environment-enzyme jest-enzyme enzyme-adapter-re
1
2
3
4
///setupTest.js5
import Enzyme from 'enzyme';6
import Adapter from 'enzyme-adapter-react-16';7
Enzyme.configure({ adapter: new Adapter() });8
9
10
// Another option, make Enzyme functions available globally wi11
// global.React = React;12
// global.shallow = shallow;13
// global.render = render;14
// global.mount = mount;15
16
17
// Can add configuration in package.json or a jest.config.js f18
// package.json19
{20
6 . 6
12. Setup
// https://github.com/FormidableLabs/enzyme-matchers/tree/mast
yarn add jest-environment-enzyme jest-enzyme enzyme-adapter-re
1
2
3
4
///setupTest.js5
import Enzyme from 'enzyme';6
import Adapter from 'enzyme-adapter-react-16';7
Enzyme.configure({ adapter: new Adapter() });8
9
10
// Another option, make Enzyme functions available globally wi11
// global.React = React;12
// global.shallow = shallow;13
// global.render = render;14
// global.mount = mount;15
16
17
// Can add configuration in package.json or a jest.config.js f18
// package.json19
{20
///setupTest.js
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
// https://github.com/FormidableLabs/enzyme-matchers/tree/mast1
yarn add jest-environment-enzyme jest-enzyme enzyme-adapter-re2
3
4
5
6
7
8
9
10
// Another option, make Enzyme functions available globally wi11
// global.React = React;12
// global.shallow = shallow;13
// global.render = render;14
// global.mount = mount;15
16
17
// Can add configuration in package.json or a jest.config.js f18
// package.json19
{20
6 . 6
13. Setup
// https://github.com/FormidableLabs/enzyme-matchers/tree/mast
yarn add jest-environment-enzyme jest-enzyme enzyme-adapter-re
1
2
3
4
///setupTest.js5
import Enzyme from 'enzyme';6
import Adapter from 'enzyme-adapter-react-16';7
Enzyme.configure({ adapter: new Adapter() });8
9
10
// Another option, make Enzyme functions available globally wi11
// global.React = React;12
// global.shallow = shallow;13
// global.render = render;14
// global.mount = mount;15
16
17
// Can add configuration in package.json or a jest.config.js f18
// package.json19
{20
///setupTest.js
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
// https://github.com/FormidableLabs/enzyme-matchers/tree/mast1
yarn add jest-environment-enzyme jest-enzyme enzyme-adapter-re2
3
4
5
6
7
8
9
10
// Another option, make Enzyme functions available globally wi11
// global.React = React;12
// global.shallow = shallow;13
// global.render = render;14
// global.mount = mount;15
16
17
// Can add configuration in package.json or a jest.config.js f18
// package.json19
{20
// Can add configuration in package.json or a jest.config.js f
// package.json
{
"jest": {
"collectCoverage": true,
"coverageDirectory": "coverage",
"collectCoverageFrom": [
"src/components/**/*.{js,jsx,ts,tsx}"
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
],
// global.shallow = shallow;13
// global.render = render;14
// global.mount = mount;15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
"coverageReporters": [30
"text"31
],32
"coverageThreshold": {33
"global": {34
6 . 6
14. Setup
// https://github.com/FormidableLabs/enzyme-matchers/tree/mast
yarn add jest-environment-enzyme jest-enzyme enzyme-adapter-re
1
2
3
4
///setupTest.js5
import Enzyme from 'enzyme';6
import Adapter from 'enzyme-adapter-react-16';7
Enzyme.configure({ adapter: new Adapter() });8
9
10
// Another option, make Enzyme functions available globally wi11
// global.React = React;12
// global.shallow = shallow;13
// global.render = render;14
// global.mount = mount;15
16
17
// Can add configuration in package.json or a jest.config.js f18
// package.json19
{20
///setupTest.js
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
// https://github.com/FormidableLabs/enzyme-matchers/tree/mast1
yarn add jest-environment-enzyme jest-enzyme enzyme-adapter-re2
3
4
5
6
7
8
9
10
// Another option, make Enzyme functions available globally wi11
// global.React = React;12
// global.shallow = shallow;13
// global.render = render;14
// global.mount = mount;15
16
17
// Can add configuration in package.json or a jest.config.js f18
// package.json19
{20
// Can add configuration in package.json or a jest.config.js f
// package.json
{
// https://github.com/FormidableLabs/enzyme-matchers/tree/mast1
yarn add jest-environment-enzyme jest-enzyme enzyme-adapter-re2
3
4
///setupTest.js5
import Enzyme from 'enzyme';6
import Adapter from 'enzyme-adapter-react-16';7
Enzyme.configure({ adapter: new Adapter() });8
9
10
// Another option, make Enzyme functions available globally wi11
// global.React = React;12
// global.shallow = shallow;13
// global.render = render;14
// global.mount = mount;15
16
17
18
19
20
// https://github.com/FormidableLabs/enzyme-matchers/tree/mast
yarn add jest-environment-enzyme jest-enzyme enzyme-adapter-re
///setupTest.js
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
// Another option, make Enzyme functions available globally wi
// global.React = React;
// global.shallow = shallow;
// global.render = render;
// global.mount = mount;
// Can add configuration in package.json or a jest.config.js f
// package.json
{
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
6 . 6
15. //ATOForm.js
import { Form, TextInput } from 'carbon-component
import React from 'react';
const ATOForm = () => {
return (
<Form className="someForm">
<h4 className="title">Our Test Subjec
<div style={{ marginBottom: '2rem' }}
<TextInput
id="test2"
invalidText="Invalid error me
labelText="First input field"
l h ld "Pl h ld t t
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ATOForm.js
6 . 7
16. //ATOForm.js
import { Form, TextInput } from 'carbon-components-react';
import React from 'react';
const ATOForm = () => {
return (
<Form className="someForm">
<h4 className="title">Our Test Subject</h4>
<div style={{ marginBottom: '2rem' }}>
<TextInput
id="test2"
invalidText="Invalid error message."
labelText="First input field"
placeholder="Placeholder text"
/>
</div>
</Form>
)
}
export default ATOForm;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
6 . 8
17. //ATOForm.test.js
import React from 'react';
import { shallow } from 'enzyme';
import ATOForm from './ATOForm';
1
2
3
4
5
describe( '<ATOForm /> rendering', () => {6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
6 . 9
18. //ATOForm.test.js
import React from 'react';
import { shallow } from 'enzyme';
import ATOForm from './ATOForm';
1
2
3
4
5
describe( '<ATOForm /> rendering', () => {6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
describe( '<ATOForm /> rendering', () => {
} );
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
import ATOForm from './ATOForm';4
5
6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
19
6 . 9
19. //ATOForm.test.js
import React from 'react';
import { shallow } from 'enzyme';
import ATOForm from './ATOForm';
1
2
3
4
5
describe( '<ATOForm /> rendering', () => {6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
describe( '<ATOForm /> rendering', () => {
} );
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
import ATOForm from './ATOForm';4
5
6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
19
it( 'should render 1 form ', () => {
expect( wrapper ).toMatchSnapshot();
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
import ATOForm from './ATOForm';4
5
describe( '<ATOForm /> rendering', () => {6
7
8
const wrapper = shallow( <ATOForm /> );9
10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
6 . 9
20. //ATOForm.test.js
import React from 'react';
import { shallow } from 'enzyme';
import ATOForm from './ATOForm';
1
2
3
4
5
describe( '<ATOForm /> rendering', () => {6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
describe( '<ATOForm /> rendering', () => {
} );
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
import ATOForm from './ATOForm';4
5
6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
19
it( 'should render 1 form ', () => {
expect( wrapper ).toMatchSnapshot();
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
import ATOForm from './ATOForm';4
5
describe( '<ATOForm /> rendering', () => {6
7
8
const wrapper = shallow( <ATOForm /> );9
10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
import ATOForm from './ATOForm';
const wrapper = shallow( <ATOForm /> );
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
4
5
describe( '<ATOForm /> rendering', () => {6
7
it( 'should render 1 form ', () => {8
9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
6 . 9
21. //ATOForm.test.js
import React from 'react';
import { shallow } from 'enzyme';
import ATOForm from './ATOForm';
1
2
3
4
5
describe( '<ATOForm /> rendering', () => {6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
describe( '<ATOForm /> rendering', () => {
} );
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
import ATOForm from './ATOForm';4
5
6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
19
it( 'should render 1 form ', () => {
expect( wrapper ).toMatchSnapshot();
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
import ATOForm from './ATOForm';4
5
describe( '<ATOForm /> rendering', () => {6
7
8
const wrapper = shallow( <ATOForm /> );9
10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
import ATOForm from './ATOForm';
const wrapper = shallow( <ATOForm /> );
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
4
5
describe( '<ATOForm /> rendering', () => {6
7
it( 'should render 1 form ', () => {8
9
expect( wrapper ).toMatchSnapshot();10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
expect( wrapper ).toMatchSnapshot();
//ATOForm.test.js1
import React from 'react';2
import { shallow } from 'enzyme';3
import ATOForm from './ATOForm';4
5
describe( '<ATOForm /> rendering', () => {6
7
it( 'should render 1 form ', () => {8
const wrapper = shallow( <ATOForm /> );9
10
} );11
12
it( 'should render a title ', () => {13
const wrapper = shallow( <ATOForm /> );14
console.log(wrapper.debug());15
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr16
} );17
18
} );19
6 . 9
22. //ATOForm.test.js
import React from 'react';
import { shallow } from 'enzyme';
import ATOForm from './ATOForm';
describe( '<ATOForm /> rendering', () => {
it( 'should render 1 form ', () => {
const wrapper = shallow( <ATOForm /> );
expect( wrapper ).toMatchSnapshot();
} );
it( 'should render a title ', () => {
const wrapper = shallow( <ATOForm /> );
console.log(wrapper.debug());
expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe(tr
} );
} );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// yarn test --watch
PASS src/components/ATOForm/ATOForm.test.js
<ATOForm /> rendering
✓ should render 1 form (7ms)
✓ should render a title (3ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 1 passed, 1 total
Time: 4.306s
Ran all test suites related to changed files.
1
2
3
4
5
6
7
8
9
10
11
6 . 10
23. Snapshot Testing
//ATOForm.js
import { Form, TextInput } from 'carbon-components-react';
import React from 'react';
const ATOForm = () => {
return (
<Form className="someForm">
<h4 className="title">Our Test Subject</h4>
<div style={{ marginBottom: '2rem' }}>
<TextInput
id="test2"
invalidText="Invalid error message."
labelText="First input field"
placeholder="Placeholder text"
/>
</div>
</Form>
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// __snapshots__/ATOForm.test.js.snap
exports[`<ATOForm /> rendering should render 1 form 1`] = `
<Form
className="someForm"
>
<h4
className="title"
>
Our Test Subject
</h4>
<div
style={
Object {
"marginBottom": "2rem",
}
}
>
<ForwardRef(TextInput)
disabled={false}
helperText=""
id="test2"
inline={false}
invalid={false}
invalidText="Invalid error message."
labelText="First input field"
light={false}
onChange={[Function]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 6 . 11
24. Snapshot Testing
//ATOForm.js
import { Form, TextInput } from 'carbon-components-react';
import React from 'react';
const ATOForm = () => {
return (
<Form className="someForm">
<h4 className="title">Our Test Subject</h4>
<div style={{ marginBottom: '2rem' }}>
<TextInput
id="test2"
invalidText="Invalid error message."
labelText="First input field"
placeholder="Placeholder text"
/>
</div>
</Form>
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// __snapshots__/ATOForm.test.js.snap
exports[`<ATOForm /> rendering should render 1 form 1`] = `
<Form
className="someForm"
>
<h4
className="title"
>
Our Test Subject
</h4>
<div
style={
Object {
"marginBottom": "2rem",
}
}
>
<ForwardRef(TextInput)
disabled={false}
helperText=""
id="test2"
inline={false}
invalid={false}
invalidText="Invalid error message."
labelText="First input field"
light={false}
onChange={[Function]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// __snapshots__/ATOForm.test.js.snap
exports[`<ATOForm /> rendering should render 1 form 1`] = `
<Form
className="someForm"
>
<h4
className="title"
>
Our Test Subject
</h4>
<div
style={
Object {
"marginBottom": "2rem",
}
}
>
<ForwardRef(TextInput)
disabled={false}
helperText=""
id="test2"
inline={false}
invalid={false}
invalidText="Invalid error message."
labelText="First input field"
light={false}
onChange={[Function]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 6 . 11
25. Snapshot Testing
// __snapshots__/ATOForm.test.js.snap1
2
exports[`<ATOForm /> rendering should render3
<Form4
className="someForm"5
>6
<h47
className="title"8
>9
Our Test Subject10
</h4>11
<div12
style={13
Object {14
"marginBottom": "2rem",15
}16
}17
>18
<ForwardRef(TextInput)19
disabled={false}20
helperText=""21
id="test2"22
inline={false}23
invalid={false}24
invalidText="Invalid error message."25
labelText="First input field"26
light={false}27
onChange={[Function]}28
<h4 className="title">Our Subject</h4>
//ATOForm.js1
import { Form, TextInput } from 'carbon-components-react';2
import React from 'react';3
4
const ATOForm = () => {5
return (6
<Form className="someForm">7
8
<div style={{ marginBottom: '2rem' }}>9
<TextInput10
id="test2"11
invalidText="Invalid error message."12
labelText="First input field"13
placeholder="Placeholder text"14
/>15
</div>16
</Form>17
18
)19
6 . 12
26. Snapshot Testing
// __snapshots__/ATOForm.test.js.snap1
2
exports[`<ATOForm /> rendering should render3
<Form4
className="someForm"5
>6
<h47
className="title"8
>9
Our Test Subject10
</h4>11
<div12
style={13
Object {14
"marginBottom": "2rem",15
}16
}17
>18
<ForwardRef(TextInput)19
disabled={false}20
helperText=""21
id="test2"22
inline={false}23
invalid={false}24
invalidText="Invalid error message."25
labelText="First input field"26
light={false}27
onChange={[Function]}28
Our Test Subject
// __snapshots__/ATOForm.test.js.snap1
2
exports[`<ATOForm /> rendering should render3
<Form4
className="someForm"5
>6
<h47
className="title"8
>9
10
</h4>11
<div12
style={13
Object {14
"marginBottom": "2rem",15
}16
}17
>18
<ForwardRef(TextInput)19
disabled={false}20
helperText=""21
id="test2"22
inline={false}23
invalid={false}24
invalidText="Invalid error message."25
labelText="First input field"26
light={false}27
onChange={[Function]}28
<h4 className="title">Our Subject</h4>
//ATOForm.js1
import { Form, TextInput } from 'carbon-components-react';2
import React from 'react';3
4
const ATOForm = () => {5
return (6
<Form className="someForm">7
8
<div style={{ marginBottom: '2rem' }}>9
<TextInput10
id="test2"11
invalidText="Invalid error message."12
labelText="First input field"13
placeholder="Placeholder text"14
/>15
</div>16
</Form>17
18
)19
6 . 12
27. Snapshot Testing
Our Test Subject
// __snapshots__/ATOForm.test.js.snap1
2
exports[`<ATOForm /> rendering should render3
<Form4
className="someForm"5
>6
<h47
className="title"8
>9
10
</h4>11
<div12
style={13
Object {14
"marginBottom": "2rem",15
}16
}17
>18
<ForwardRef(TextInput)19
disabled={false}20
helperText=""21
id="test2"22
inline={false}23
invalid={false}24
invalidText="Invalid error message."25
labelText="First input field"26
light={false}27
onChange={[Function]}28
<h4 className="title">Our Subject</h4>
//ATOForm.js1
import { Form, TextInput } from 'carbon-components-react';2
import React from 'react';3
4
const ATOForm = () => {5
return (6
<Form className="someForm">7
8
<div style={{ marginBottom: '2rem' }}>9
<TextInput10
id="test2"11
invalidText="Invalid error message."12
labelText="First input field"13
placeholder="Placeholder text"14
/>15
</div>16
</Form>17
18
)19
6 . 13
28. Snapshot Testing
Our Test Subject
// __snapshots__/ATOForm.test.js.snap1
2
exports[`<ATOForm /> rendering should render3
<Form4
className="someForm"5
>6
<h47
className="title"8
>9
10
</h4>11
<div12
style={13
Object {14
"marginBottom": "2rem",15
}16
}17
>18
<ForwardRef(TextInput)19
disabled={false}20
helperText=""21
id="test2"22
inline={false}23
invalid={false}24
invalidText="Invalid error message."25
labelText="First input field"26
light={false}27
onChange={[Function]}28
// __snapshots__/ATOForm.test.js.snap
exports[`<ATOForm /> rendering should render
<Form
className="someForm"
>
<h4
className="title"
>
Our Test Subject
</h4>
<div
style={
Object {
"marginBottom": "2rem",
}
}
>
<ForwardRef(TextInput)
disabled={false}
helperText=""
id="test2"
inline={false}
invalid={false}
invalidText="Invalid error message."
labelText="First input field"
light={false}
onChange={[Function]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<h4 className="title">Our Subject</h4>
//ATOForm.js1
import { Form, TextInput } from 'carbon-components-react';2
import React from 'react';3
4
const ATOForm = () => {5
return (6
<Form className="someForm">7
8
<div style={{ marginBottom: '2rem' }}>9
<TextInput10
id="test2"11
invalidText="Invalid error message."12
labelText="First input field"13
placeholder="Placeholder text"14
/>15
</div>16
</Form>17
18
)19
6 . 13
29. Snapshot Testing Fail
Our Test Subject
// __snapshots__/ATOForm.test.js.snap1
2
exports[`<ATOForm /> rendering should render3
<Form4
className="someForm"5
>6
<h47
className="title"8
>9
10
</h4>11
<div12
style={13
Object {14
"marginBottom": "2rem",15
}16
}17
>18
<ForwardRef(TextInput)19
disabled={false}20
helperText=""21
id="test2"22
inline={false}23
invalid={false}24
invalidText="Invalid error message."25
labelText="First input field"26
light={false}27
onChange={[Function]}28
<h4 className="title">Our Subject</h4>
//ATOForm.js1
import { Form, TextInput } from 'carbon-components-react';2
import React from 'react';3
4
const ATOForm = () => {5
return (6
<Form className="someForm">7
8
<div style={{ marginBottom: '2rem' }}>9
<TextInput10
id="test2"11
invalidText="Invalid error message."12
labelText="First input field"13
placeholder="Placeholder text"14
/>15
</div>16
</Form>17
18
)19
FAIL src/components/ATOForm/ATOForm.test.js
<ATOForm /> rendering
✓ should render 1 form (5ms)
✕ should render a title (5ms)
● <ATOForm /> rendering › should render a title
expect(received).toBe(expected) // Object.is equality
Expected: true
Received: false
19 | it( 'should render a title ', () => {
20 | const wrapper = shallow( <ATOForm /> );
> 21 | expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe
| ^
22 | } );
23 | } );
at Object.<anonymous> (src/components/ATOForm/ATOForm.test.js:21:73)
› 1 snapshot updated.
Snapshot Summary
› 1 snapshot updated from 1 test suite.
Test Suites: 1 failed, 1 total
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 6 . 14
30. Snapshot Testing Fail
Our Test Subject
// __snapshots__/ATOForm.test.js.snap1
2
exports[`<ATOForm /> rendering should render3
<Form4
className="someForm"5
>6
<h47
className="title"8
>9
10
</h4>11
<div12
style={13
Object {14
"marginBottom": "2rem",15
}16
}17
>18
<ForwardRef(TextInput)19
disabled={false}20
helperText=""21
id="test2"22
inline={false}23
invalid={false}24
invalidText="Invalid error message."25
labelText="First input field"26
light={false}27
onChange={[Function]}28
// __snapshots__/ATOForm.test.js.snap
exports[`<ATOForm /> rendering should render
<Form
className="someForm"
>
<h4
className="title"
>
Our Test Subject
</h4>
<div
style={
Object {
"marginBottom": "2rem",
}
}
>
<ForwardRef(TextInput)
disabled={false}
helperText=""
id="test2"
inline={false}
invalid={false}
invalidText="Invalid error message."
labelText="First input field"
light={false}
onChange={[Function]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<h4 className="title">Our Subject</h4>
//ATOForm.js1
import { Form, TextInput } from 'carbon-components-react';2
import React from 'react';3
4
const ATOForm = () => {5
return (6
<Form className="someForm">7
8
<div style={{ marginBottom: '2rem' }}>9
<TextInput10
id="test2"11
invalidText="Invalid error message."12
labelText="First input field"13
placeholder="Placeholder text"14
/>15
</div>16
</Form>17
18
)19
FAIL src/components/ATOForm/ATOForm.test.js
<ATOForm /> rendering
✓ should render 1 form (5ms)
✕ should render a title (5ms)
● <ATOForm /> rendering › should render a title
expect(received).toBe(expected) // Object.is equality
Expected: true
Received: false
19 | it( 'should render a title ', () => {
20 | const wrapper = shallow( <ATOForm /> );
> 21 | expect( wrapper.find( '.title' ).contains('Our Test Subject') ).toBe
| ^
22 | } );
23 | } );
at Object.<anonymous> (src/components/ATOForm/ATOForm.test.js:21:73)
› 1 snapshot updated.
Snapshot Summary
› 1 snapshot updated from 1 test suite.
Test Suites: 1 failed, 1 total
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 6 . 14
31. Coverage reports
PASS src/components/Launch/Launch.test.js
PASS src/components/ATOForm/ATOForm.test.js
------------|----------|----------|----------|----------
File | % Stmts | % Branch | % Funcs | % Lines
------------|----------|----------|----------|----------
All files | 100 | 0 | 100 | 100
ATOForm.js | 100 | 0 | 100 | 100
------------|----------|----------|----------|----------
Test Suites: 2 passed, 2 total
Tests: 4 passed, 4 total
S h t 2 d 2 t t l
1
2
3
4
5
6
7
8
9
10
11
12
6 . 15
33. Lauch.js1
2
describe( '<Launch /> interactions', () => {3
4
//Simulate DOM events or a click on the button5
it( 'should open Launch Modal when clicked', () => {6
const wrapper = mount( <Launch /> );7
const button = wrapper.find('button');8
button.at(0).simulate('click');9
10
//After inspecting the code, I can see this is toggled to visible one clicked11
const modalDiv = wrapper.find('div#input-modal');12
expect(modalDiv.hasClass('is-visible')).toBe(true);13
} )14
} );15
6 . 17
34. Lauch.js1
2
describe( '<Launch /> interactions', () => {3
4
//Simulate DOM events or a click on the button5
it( 'should open Launch Modal when clicked', () => {6
const wrapper = mount( <Launch /> );7
const button = wrapper.find('button');8
button.at(0).simulate('click');9
10
//After inspecting the code, I can see this is toggled to visible one clicked11
const modalDiv = wrapper.find('div#input-modal');12
expect(modalDiv.hasClass('is-visible')).toBe(true);13
} )14
} );15
describe( '<Launch /> interactions', () => {
} )
Lauch.js1
2
3
4
//Simulate DOM events or a click on the button5
it( 'should open Launch Modal when clicked', () => {6
const wrapper = mount( <Launch /> );7
const button = wrapper.find('button');8
button.at(0).simulate('click');9
10
//After inspecting the code, I can see this is toggled to visible one clicked11
const modalDiv = wrapper.find('div#input-modal');12
expect(modalDiv.hasClass('is-visible')).toBe(true);13
14
} );15
6 . 17
35. Lauch.js1
2
describe( '<Launch /> interactions', () => {3
4
//Simulate DOM events or a click on the button5
it( 'should open Launch Modal when clicked', () => {6
const wrapper = mount( <Launch /> );7
const button = wrapper.find('button');8
button.at(0).simulate('click');9
10
//After inspecting the code, I can see this is toggled to visible one clicked11
const modalDiv = wrapper.find('div#input-modal');12
expect(modalDiv.hasClass('is-visible')).toBe(true);13
} )14
} );15
describe( '<Launch /> interactions', () => {
} )
Lauch.js1
2
3
4
//Simulate DOM events or a click on the button5
it( 'should open Launch Modal when clicked', () => {6
const wrapper = mount( <Launch /> );7
const button = wrapper.find('button');8
button.at(0).simulate('click');9
10
//After inspecting the code, I can see this is toggled to visible one clicked11
const modalDiv = wrapper.find('div#input-modal');12
expect(modalDiv.hasClass('is-visible')).toBe(true);13
14
} );15
it( 'should open Launch Modal when clicked', () => {
const wrapper = mount( <Launch /> );
const button = wrapper.find('button');
button.at(0).simulate('click');
} )
Lauch.js1
2
describe( '<Launch /> interactions', () => {3
4
//Simulate DOM events or a click on the button5
6
7
8
9
10
//After inspecting the code, I can see this is toggled to visible one clicked11
const modalDiv = wrapper.find('div#input-modal');12
expect(modalDiv.hasClass('is-visible')).toBe(true);13
14
} );15
6 . 17
36. Lauch.js1
2
describe( '<Launch /> interactions', () => {3
4
//Simulate DOM events or a click on the button5
it( 'should open Launch Modal when clicked', () => {6
const wrapper = mount( <Launch /> );7
const button = wrapper.find('button');8
button.at(0).simulate('click');9
10
//After inspecting the code, I can see this is toggled to visible one clicked11
const modalDiv = wrapper.find('div#input-modal');12
expect(modalDiv.hasClass('is-visible')).toBe(true);13
} )14
} );15
describe( '<Launch /> interactions', () => {
} )
Lauch.js1
2
3
4
//Simulate DOM events or a click on the button5
it( 'should open Launch Modal when clicked', () => {6
const wrapper = mount( <Launch /> );7
const button = wrapper.find('button');8
button.at(0).simulate('click');9
10
//After inspecting the code, I can see this is toggled to visible one clicked11
const modalDiv = wrapper.find('div#input-modal');12
expect(modalDiv.hasClass('is-visible')).toBe(true);13
14
} );15
it( 'should open Launch Modal when clicked', () => {
const wrapper = mount( <Launch /> );
const button = wrapper.find('button');
button.at(0).simulate('click');
} )
Lauch.js1
2
describe( '<Launch /> interactions', () => {3
4
//Simulate DOM events or a click on the button5
6
7
8
9
10
//After inspecting the code, I can see this is toggled to visible one clicked11
const modalDiv = wrapper.find('div#input-modal');12
expect(modalDiv.hasClass('is-visible')).toBe(true);13
14
} );15
it( 'should open Launch Modal when clicked', () => {
const wrapper = mount( <Launch /> );
const button = wrapper.find('button');
button.at(0).simulate('click');
//After inspecting the code, I can see this is toggled to visible one clicked
const modalDiv = wrapper.find('div#input-modal');
expect(modalDiv.hasClass('is-visible')).toBe(true);
Lauch.js1
2
describe( '<Launch /> interactions', () => {3
4
//Simulate DOM events or a click on the button5
6
7
8
9
10
11
12
13
} )14
} );15
6 . 17
38. “
Keep your code organized
with 'describe' and 'it' blocks.
--
Sometimes testing can take just as long as
writing the component, if not longer.
--
Don't be afraid to refactor your
code to make the test work.
--
Writing tests will help you to gain a broad
understanding of your codebase. Also help you
to become a better programmer.
“
6 . 19
39. Thank you for joining
Crushing React Bugs with Jest and Enyme
@jannaeesick
References:
, , ,
,
,
,
Jest Enzyme Carbon Design System How to read Test
Coverage report generated using Jest. React function
components with Hooks Testing with Jest and Enzyme in
React — Part 3 (Best Practices when testing with Jest and
Enzyme) Red Hat Marketplace
link to this code6 . 20