Skip to content

Commit a05248e

Browse files
alexkrolickKent C. Dodds
authored and
Kent C. Dodds
committed
docs: add global setup, custom render docs (#166)
1 parent 056b1e5 commit a05248e

File tree

1 file changed

+140
-57
lines changed

1 file changed

+140
-57
lines changed

README.md

Lines changed: 140 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,56 @@ facilitate testing implementation details). Read more about this in
7373
> [`dom-testing-library`](https://github.com/kentcdodds/dom-testing-library)
7474
> which is where most of the logic behind the queries is.
7575
76+
## Example
77+
78+
```javascript
79+
// __tests__/fetch.js
80+
import React from 'react'
81+
import {render, fireEvent, cleanup, waitForElement} from 'react-testing-library'
82+
// this adds custom jest matchers from jest-dom
83+
import 'jest-dom/extend-expect'
84+
import axiosMock from 'axios' // the mock lives in a __mocks__ directory
85+
import Fetch from '../fetch' // see the tests for a full implementation
86+
87+
// automatically unmount and cleanup DOM after the test is finished.
88+
afterEach(cleanup)
89+
90+
test('Fetch makes an API call and displays the greeting when load-greeting is clicked', async () => {
91+
// Arrange
92+
axiosMock.get.mockResolvedValueOnce({data: {greeting: 'hello there'}})
93+
const url = '/greeting'
94+
const {getByText, getByTestId, container} = render(<Fetch url={url} />)
95+
96+
// Act
97+
fireEvent.click(getByText('Load Greeting'))
98+
99+
// Let's wait until our mocked `get` request promise resolves and
100+
// the component calls setState and re-renders.
101+
// getByTestId throws an error if it cannot find an element with the given ID
102+
// and waitForElement will wait until the callback doesn't throw an error
103+
const greetingTextNode = await waitForElement(() =>
104+
getByTestId('greeting-text'),
105+
)
106+
107+
// Assert
108+
expect(axiosMock.get).toHaveBeenCalledTimes(1)
109+
expect(axiosMock.get).toHaveBeenCalledWith(url)
110+
expect(getByTestId('greeting-text')).toHaveTextContent('hello there')
111+
expect(getByTestId('ok-button')).toHaveAttribute('disabled')
112+
// snapshots work great with regular DOM nodes!
113+
expect(container.firstChild).toMatchSnapshot()
114+
})
115+
```
116+
76117
## Table of Contents
77118

78119
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
79120
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
80121

81122
- [Installation](#installation)
123+
- [Setup](#setup)
124+
- [Global Config](#global-config)
125+
- [Custom Render](#custom-render)
82126
- [Usage](#usage)
83127
- [`render`](#render)
84128
- [`cleanup`](#cleanup)
@@ -118,45 +162,106 @@ This library has a `peerDependencies` listing for `react-dom`.
118162
You may also be interested in installing `jest-dom` so you can use
119163
[the custom jest matchers](https://github.com/gnapse/jest-dom#readme)
120164

121-
## Usage
165+
## Setup
166+
167+
`react-testing-library` does not require any configuration to be used (as demonstrated in the example above). However, there are some things you can do to when configuring your testing framework to reduce some boilerplate. In these docs we'll demonstrate configuring Jest, but you should be able to do similar things with any testing framework (react-testing-library does not require that you use Jest).
168+
169+
170+
### Global Config
171+
172+
There are several options you can add to your global test config that simplify
173+
the setup and teardown of tests in individual files. For example, you can ensure
174+
[`cleanup`](#cleanup) is called after each test and import additional
175+
assertions.
176+
177+
To do this with Jest, you can add the
178+
[`setupTestFrameworkScriptFile`](https://facebook.github.io/jest/docs/en/configuration.html#setuptestframeworkscriptfile-string)
179+
option to your Jest config. The setup file can be anywhere, for example `jest.setup.js` or `./utils/setupTests.js`.
180+
181+
If you are using the default setup from create-react-app, this option is set to `src/setupTests.js`. You should create this file if it doesn't exist and put the setup code there.
122182

123183
```javascript
124-
// __tests__/fetch.js
125-
import React from 'react'
126-
import {render, fireEvent, cleanup, waitForElement} from 'react-testing-library'
127-
// this adds custom jest matchers from jest-dom
184+
// jest.config.js
185+
module.exports = {
186+
setupTestFrameworkScriptFile: require.resolve('./jest.setup.js'),
187+
// ... other options ...
188+
}
189+
```
190+
191+
```javascript
192+
// jest.setup.js
193+
194+
// add some helpful assertions
128195
import 'jest-dom/extend-expect'
129-
import axiosMock from 'axios' // the mock lives in a __mocks__ directory
130-
import Fetch from '../fetch' // see the tests for a full implementation
131196

132-
// automatically unmount and cleanup DOM after the test is finished.
133-
afterEach(cleanup)
197+
// this is basically: afterEach(cleanup)
198+
import 'react-testing-library/cleanup-after-each'
199+
```
134200

135-
test('Fetch makes an API call and displays the greeting when load-greeting is clicked', async () => {
136-
// Arrange
137-
axiosMock.get.mockResolvedValueOnce({data: {greeting: 'hello there'}})
138-
const url = '/greeting'
139-
const {getByText, getByTestId, container} = render(<Fetch url={url} />)
201+
### Custom Render
140202

141-
// Act
142-
fireEvent.click(getByText('Load Greeting'))
203+
It's often useful to define a custom render method that includes things like
204+
global context providers, data stores, etc. To make this available globally, one
205+
approach is to define a utility file that re-exports everything from
206+
`react-testing-library`. You can replace react-testing-library with this file in
207+
all your imports.
143208

144-
// let's wait for our mocked `get` request promise to resolve
145-
// wait will wait until the callback doesn't throw an error
146-
const greetingTextNode = await waitForElement(() =>
147-
getByTestId('greeting-text'),
209+
```diff
210+
// my-component.test.js
211+
- import { render, fireEvent } from 'react-testing-library';
212+
+ import { render, fireEvent } from '../test-utils';
213+
```
214+
215+
```js
216+
// test-utils.js
217+
import {render} from 'react-testing-library'
218+
import {ThemeProvider} from 'my-ui-lib'
219+
import {TranslationProvider} from 'my-i18n-lib'
220+
import defaultStrings from 'i18n/en-x-default'
221+
222+
const customRender = (node, ...options) => {
223+
return render(
224+
<ThemeProvider theme="light">
225+
<TranslationProvider messages={defaultStrings}>
226+
{node}
227+
</TranslationProvider>
228+
</ThemeProvider>,
229+
...options,
148230
)
231+
}
149232

150-
// Assert
151-
expect(axiosMock.get).toHaveBeenCalledTimes(1)
152-
expect(axiosMock.get).toHaveBeenCalledWith(url)
153-
expect(getByTestId('greeting-text')).toHaveTextContent('hello there')
154-
expect(getByTestId('ok-button')).toHaveAttribute('disabled')
155-
// snapshots work great with regular DOM nodes!
156-
expect(container.firstChild).toMatchSnapshot()
157-
})
233+
// re-export everything
234+
export * from 'react-testing-library'
235+
236+
// override render method
237+
export {customRender as render}
158238
```
159239

240+
To make this file accessible without using relative imports, add the folder
241+
containing the file to the Jest `moduleDirectories` option. Note: this will
242+
make _all_ the .js files in that directory importable without `../`.
243+
244+
```diff
245+
// my-component.test.js
246+
- import { render, fireEvent } from '../test-utils';
247+
+ import { render, fireEvent } from 'test-utils';
248+
```
249+
250+
```diff
251+
// jest.config.js
252+
module.exports = {
253+
moduleDirectories: [
254+
'node_modules',
255+
+ // add the directory with the test-utils.js file, for example:
256+
+ 'utils', // a utility folder
257+
+ __dirname, // the root directory
258+
],
259+
// ... other options ...
260+
}
261+
```
262+
263+
## Usage
264+
160265
### `render`
161266

162267
Defined as:
@@ -174,9 +279,7 @@ Render into a container which is appended to `document.body`. It should be used
174279
with [cleanup](#cleanup):
175280

176281
```javascript
177-
import {render, cleanup} from 'react-testing-library'
178-
179-
afterEach(cleanup)
282+
import {render} from 'react-testing-library'
180283
181284
render(<div />)
182285
```
@@ -408,12 +511,14 @@ Unmounts React trees that were mounted with [render](#render).
408511
```javascript
409512
import {cleanup, render} from 'react-testing-library'
410513

411-
afterEach(cleanup)
514+
afterEach(cleanup) // <-- add this
412515

413516
test('renders into document', () => {
414517
render(<div />)
415518
// ...
416519
})
520+
521+
// ... more tests ...
417522
```
418523
419524
Failing to call `cleanup` when you've called `render` could result in a memory
@@ -422,31 +527,8 @@ errors in your tests).
422527
423528
**If you don't want to add this to _every single test file_** then we recommend
424529
that you configure your test framework to run a file before your tests which
425-
does this automatically.
426-
427-
For example, to do this with jest, you can use
428-
[`setupTestFrameworkScriptFile`](https://facebook.github.io/jest/docs/en/configuration.html#setuptestframeworkscriptfile-string):
429-
430-
```javascript
431-
// jest.config.js
432-
module.exports = {
433-
setupTestFrameworkScriptFile: require.resolve('./test/setup-test-env.js'),
434-
}
435-
```
436-
437-
Then:
438-
439-
```javascript
440-
// test/setup-test-env.js
441-
442-
// add some helpful assertions
443-
import 'jest-dom/extend-expect'
444-
// this is basically: afterEach(cleanup)
445-
import 'react-testing-library/cleanup-after-each'
446-
```
447-
448-
Or if you're using react-scripts (create-react-app), it has a default value
449-
that's set to `src/setupTests.js` so put the code above in that file.
530+
does this automatically. See the [setup](#setup) section for guidance on how to
531+
set up your framework.
450532
451533
## `dom-testing-library` APIs
452534
@@ -1033,6 +1115,7 @@ light-weight, simple, and understandable.
10331115
Thanks goes to these people ([emoji key][emojis]):
10341116
10351117
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
1118+
10361119
<!-- prettier-ignore -->
10371120
| [<img src="https://avatars.githubusercontent.com/u/1500684?v=3" width="100px;"/><br /><sub><b>Kent C. Dodds</b></sub>](https://kentcdodds.com)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Code") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Documentation") [🚇](#infra-kentcdodds "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Tests") | [<img src="https://avatars1.githubusercontent.com/u/2430381?v=4" width="100px;"/><br /><sub><b>Ryan Castner</b></sub>](http://audiolion.github.io)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=audiolion "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/8008023?v=4" width="100px;"/><br /><sub><b>Daniel Sandiego</b></sub>](https://www.dnlsandiego.com)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=dnlsandiego "Code") | [<img src="https://avatars2.githubusercontent.com/u/12592677?v=4" width="100px;"/><br /><sub><b>Paweł Mikołajczyk</b></sub>](https://github.com/Miklet)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=Miklet "Code") | [<img src="https://avatars3.githubusercontent.com/u/464978?v=4" width="100px;"/><br /><sub><b>Alejandro Ñáñez Ortiz</b></sub>](http://co.linkedin.com/in/alejandronanez/)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=alejandronanez "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/1402095?v=4" width="100px;"/><br /><sub><b>Matt Parrish</b></sub>](https://github.com/pbomb)<br />[🐛](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Apbomb "Bug reports") [💻](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Code") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Documentation") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Tests") | [<img src="https://avatars1.githubusercontent.com/u/1288694?v=4" width="100px;"/><br /><sub><b>Justin Hall</b></sub>](https://github.com/wKovacs64)<br />[📦](#platform-wKovacs64 "Packaging/porting to new platform") |
10381121
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |

0 commit comments

Comments
 (0)