Skip to content

Commit e3c84b5

Browse files
authored
chore: update React examples to match with the new React guidelines (#12217)
1 parent bc0a91a commit e3c84b5

20 files changed

+97
-88
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
- `[*]` [**BREAKING**] Drop support for Node v10 and v15 and target first LTS `16.13.0` ([#12220](https://github.com/facebook/jest/pull/12220))
2323
- `[*]` [**BREAKING**] Drop support for `[email protected]`, minimum version is now `4.2` ([#11142](https://github.com/facebook/jest/pull/11142))
2424
- `[*]` Bundle all `.d.ts` files into a single `index.d.ts` per module ([#12345](https://github.com/facebook/jest/pull/12345))
25+
- `[docs, examples]` Update React examples to match with the new React guidelines for code examples ([#12217](https://github.com/facebook/jest/pull/12217))
2526
- `[expect]` [**BREAKING**] Remove support for importing `build/utils` ([#12323](https://github.com/facebook/jest/pull/12323))
2627
- `[expect]` [**BREAKING**] Migrate to ESM ([#12344](https://github.com/facebook/jest/pull/12344))
2728
- `[jest-cli]` Update `yargs` to v17 ([#12357](https://github.com/facebook/jest/pull/12357))

docs/SnapshotTesting.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ A typical snapshot test case renders a UI component, takes a snapshot, then comp
1212
A similar approach can be taken when it comes to testing your React components. Instead of rendering the graphical UI, which would require building the entire app, you can use a test renderer to quickly generate a serializable value for your React tree. Consider this [example test](https://github.com/facebook/jest/blob/main/examples/snapshot/__tests__/link.test.js) for a [Link component](https://github.com/facebook/jest/blob/main/examples/snapshot/Link.js):
1313

1414
```tsx
15-
import React from 'react';
1615
import renderer from 'react-test-renderer';
1716
import Link from '../Link';
1817

docs/TutorialReact.md

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ Your `package.json` should look something like this (where `<current-version>` i
4848

4949
```js title="babel.config.js"
5050
module.exports = {
51-
presets: ['@babel/preset-env', '@babel/preset-react'],
51+
presets: [
52+
'@babel/preset-env',
53+
['@babel/preset-react', {runtime: 'automatic'}],
54+
],
5255
};
5356
```
5457

@@ -59,14 +62,14 @@ module.exports = {
5962
Let's create a [snapshot test](SnapshotTesting.md) for a Link component that renders hyperlinks:
6063

6164
```tsx title="Link.js"
62-
import React, {useState} from 'react';
65+
import {useState} from 'react';
6366

6467
const STATUS = {
6568
HOVERED: 'hovered',
6669
NORMAL: 'normal',
6770
};
6871

69-
const Link = ({page, children}) => {
72+
export default function Link({page, children}) {
7073
const [status, setStatus] = useState(STATUS.NORMAL);
7174

7275
const onMouseEnter = () => {
@@ -87,35 +90,36 @@ const Link = ({page, children}) => {
8790
{children}
8891
</a>
8992
);
90-
};
91-
92-
export default Link;
93+
}
9394
```
9495

9596
> Note: Examples are using Function components, but Class components can be tested in the same way. See [React: Function and Class Components](https://reactjs.org/docs/components-and-props.html#function-and-class-components). **Reminders** that with Class components, we expect Jest to be used to test props and not methods directly.
9697
9798
Now let's use React's test renderer and Jest's snapshot feature to interact with the component and capture the rendered output and create a snapshot file:
9899

99100
```tsx title="Link.react.test.js"
100-
import React from 'react';
101-
import renderer from 'react-test-renderer';
102101
import Link from '../Link.react';
102+
import renderer from 'react-test-renderer';
103103

104-
test('Link changes the class when hovered', () => {
104+
it('changes the class when hovered', () => {
105105
const component = renderer.create(
106106
<Link page="http://www.facebook.com">Facebook</Link>,
107107
);
108108
let tree = component.toJSON();
109109
expect(tree).toMatchSnapshot();
110110

111111
// manually trigger the callback
112-
tree.props.onMouseEnter();
112+
renderer.act(() => {
113+
tree.props.onMouseEnter();
114+
});
113115
// re-rendering
114116
tree = component.toJSON();
115117
expect(tree).toMatchSnapshot();
116118

117119
// manually trigger the callback
118-
tree.props.onMouseLeave();
120+
renderer.act(() => {
121+
tree.props.onMouseLeave();
122+
});
119123
// re-rendering
120124
tree = component.toJSON();
121125
expect(tree).toMatchSnapshot();
@@ -125,32 +129,35 @@ test('Link changes the class when hovered', () => {
125129
When you run `yarn test` or `jest`, this will produce an output file like this:
126130

127131
```javascript title="__tests__/__snapshots__/Link.react.test.js.snap"
128-
exports[`Link changes the class when hovered 1`] = `
132+
exports[`changes the class when hovered 1`] = `
129133
<a
130134
className="normal"
131135
href="http://www.facebook.com"
132136
onMouseEnter={[Function]}
133-
onMouseLeave={[Function]}>
137+
onMouseLeave={[Function]}
138+
>
134139
Facebook
135140
</a>
136141
`;
137142

138-
exports[`Link changes the class when hovered 2`] = `
143+
exports[`changes the class when hovered 2`] = `
139144
<a
140145
className="hovered"
141146
href="http://www.facebook.com"
142147
onMouseEnter={[Function]}
143-
onMouseLeave={[Function]}>
148+
onMouseLeave={[Function]}
149+
>
144150
Facebook
145151
</a>
146152
`;
147153

148-
exports[`Link changes the class when hovered 3`] = `
154+
exports[`changes the class when hovered 3`] = `
149155
<a
150156
className="normal"
151157
href="http://www.facebook.com"
152158
onMouseEnter={[Function]}
153-
onMouseLeave={[Function]}>
159+
onMouseLeave={[Function]}
160+
>
154161
Facebook
155162
</a>
156163
`;
@@ -160,7 +167,7 @@ The next time you run the tests, the rendered output will be compared to the pre
160167

161168
The code for this example is available at [examples/snapshot](https://github.com/facebook/jest/tree/main/examples/snapshot).
162169

163-
#### Snapshot Testing with Mocks, Enzyme and React 16
170+
#### Snapshot Testing with Mocks, Enzyme and React 16+
164171

165172
There's a caveat around snapshot testing when using Enzyme and React 16+. If you mock out a module using the following style:
166173

@@ -205,9 +212,9 @@ You have to run `yarn add --dev @testing-library/react` to use react-testing-lib
205212
Let's implement a checkbox which swaps between two labels:
206213
207214
```tsx title="CheckboxWithLabel.js"
208-
import React, {useState} from 'react';
215+
import {useState} from 'react';
209216
210-
const CheckboxWithLabel = ({labelOn, labelOff}) => {
217+
export default function CheckboxWithLabel({labelOn, labelOff}) {
211218
const [isChecked, setIsChecked] = useState(false);
212219
213220
const onChange = () => {
@@ -220,13 +227,10 @@ const CheckboxWithLabel = ({labelOn, labelOff}) => {
220227
{isChecked ? labelOn : labelOff}
221228
</label>
222229
);
223-
};
224-
225-
export default CheckboxWithLabel;
230+
}
226231
```
227232
228233
```tsx title="__tests__/CheckboxWithLabel-test.js"
229-
import React from 'react';
230234
import {cleanup, fireEvent, render} from '@testing-library/react';
231235
import CheckboxWithLabel from '../CheckboxWithLabel';
232236
@@ -256,11 +260,14 @@ You have to run `yarn add --dev enzyme` to use Enzyme. If you are using a React
256260
Let's rewrite the test from above using Enzyme instead of react-testing-library. We use Enzyme's [shallow renderer](http://airbnb.io/enzyme/docs/api/shallow.html) in this example.
257261
258262
```tsx title="__tests__/CheckboxWithLabel-test.js"
259-
import React from 'react';
260-
import {shallow} from 'enzyme';
263+
import Enzyme, {shallow} from 'enzyme';
264+
import Adapter from 'enzyme-adapter-react-16';
265+
266+
Enzyme.configure({adapter: new Adapter()});
267+
261268
import CheckboxWithLabel from '../CheckboxWithLabel';
262269
263-
test('CheckboxWithLabel changes the text after click', () => {
270+
it('CheckboxWithLabel changes the text after click', () => {
264271
// Render a checkbox with label in the document
265272
const checkbox = shallow(<CheckboxWithLabel labelOn="On" labelOff="Off" />);
266273

examples/enzyme/.babelrc.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
22

33
module.exports = {
4-
presets: ['@babel/preset-env', '@babel/preset-react'],
5-
plugins: ['@babel/plugin-proposal-class-properties']
4+
presets: [
5+
'@babel/preset-env',
6+
['@babel/preset-react', {runtime: 'automatic'}],
7+
],
68
};
Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
// Copyright 2004-present Facebook. All Rights Reserved.
22

3-
import React from 'react';
3+
import {useState} from 'react';
44

5-
export default class CheckboxWithLabel extends React.Component {
6-
state = {
7-
isChecked: false,
8-
};
5+
export default function CheckboxWithLabel({
6+
labelRef,
7+
inputRef,
8+
labelOn,
9+
labelOff,
10+
}) {
11+
const [isChecked, setIsChecked] = useState(false);
912

10-
onChange = () => {
11-
this.setState({isChecked: !this.state.isChecked});
13+
const onChange = () => {
14+
setIsChecked(!isChecked);
1215
};
1316

14-
render() {
15-
return (
16-
<label>
17-
<input
18-
type="checkbox"
19-
checked={this.state.isChecked}
20-
onChange={this.onChange}
21-
/>
22-
{this.state.isChecked ? this.props.labelOn : this.props.labelOff}
23-
</label>
24-
);
25-
}
17+
return (
18+
<label ref={labelRef}>
19+
<input
20+
ref={inputRef}
21+
type="checkbox"
22+
checked={isChecked}
23+
onChange={onChange}
24+
/>
25+
{isChecked ? labelOn : labelOff}
26+
</label>
27+
);
2628
}

examples/enzyme/__tests__/CheckboxWithLabel-test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Copyright 2004-present Facebook. All Rights Reserved.
22

3-
import React from 'react';
43
import Enzyme, {shallow} from 'enzyme';
54
import Adapter from 'enzyme-adapter-react-16';
65

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
22

33
module.exports = {
4-
presets: ['@babel/preset-env', '@babel/preset-react'],
5-
plugins: ['@babel/plugin-proposal-class-properties'],
4+
presets: [
5+
'@babel/preset-env',
6+
['@babel/preset-react', {runtime: 'automatic'}],
7+
],
68
};
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Copyright 2004-present Facebook. All Rights Reserved.
22

3-
import React, {useState} from 'react';
3+
import {useState} from 'react';
44

5-
const CheckboxWithLabel = ({labelOn, labelOff}) => {
5+
export default function CheckboxWithLabel({labelOn, labelOff}) {
66
const [isChecked, setIsChecked] = useState(false);
77

88
const onChange = () => {
@@ -15,6 +15,4 @@ const CheckboxWithLabel = ({labelOn, labelOff}) => {
1515
{isChecked ? labelOn : labelOff}
1616
</label>
1717
);
18-
};
19-
20-
export default CheckboxWithLabel;
18+
}

examples/react-testing-library/__tests__/CheckboxWithLabel-test.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Copyright 2004-present Facebook. All Rights Reserved.
22

3-
import React from 'react';
43
import {cleanup, fireEvent, render} from '@testing-library/react';
54
import CheckboxWithLabel from '../CheckboxWithLabel';
65

examples/react/.babelrc.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
22

33
module.exports = {
4-
presets: ['@babel/preset-env', '@babel/preset-react'],
4+
presets: [
5+
'@babel/preset-env',
6+
['@babel/preset-react', {runtime: 'automatic'}],
7+
],
58
};

0 commit comments

Comments
 (0)