Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing Overview: update JS example to use React Testing Library #34423

Merged
merged 10 commits into from
Sep 1, 2021
39 changes: 23 additions & 16 deletions docs/contributors/code/testing-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ When writing tests consider the following:

## JavaScript Testing

Tests for JavaScript use [Jest](https://jestjs.io/) as the test runner and its API for [globals](https://jestjs.io/docs/en/api.html) (`describe`, `test`, `beforeEach` and so on) [assertions](https://jestjs.io/docs/en/expect.html), [mocks](https://jestjs.io/docs/en/mock-functions.html), [spies](https://jestjs.io/docs/en/jest-object.html#jestspyonobject-methodname) and [mock functions](https://jestjs.io/docs/en/mock-function-api.html). If needed, you can also use [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) for React component testing.
Tests for JavaScript use [**Jest**](https://jestjs.io/) as the test runner and its API for [globals](https://jestjs.io/docs/en/api.html) (`describe`, `test`, `beforeEach` and so on) [assertions](https://jestjs.io/docs/en/expect.html), [mocks](https://jestjs.io/docs/en/mock-functions.html), [spies](https://jestjs.io/docs/en/jest-object.html#jestspyonobject-methodname) and [mock functions](https://jestjs.io/docs/en/mock-function-api.html). Tests for React components should use [**React Testing Library**](https://testing-library.com/docs/react-testing-library/intro).
ciampo marked this conversation as resolved.
Show resolved Hide resolved

It should be noted that in the past, React components were unit tested with [Enzyme](https://github.com/airbnb/enzyme). However, for new tests, it is preferred to use React Testing Library (RTL) and over time old tests should be refactored to use RTL too (typically when working on code that touches an old test).
_It should be noted that in the past, React components were unit tested with [Enzyme](https://github.com/airbnb/enzyme). However, React Testing Library (RTL) should be used for new tests, and over time old tests should be refactored to use RTL too (typically when working on code that touches an old test)._
ciampo marked this conversation as resolved.
Show resolved Hide resolved

Assuming you've followed the [instructions](/docs/contributors/code/getting-started-with-code-contribution.md) to install Node and project dependencies, tests can be run from the command-line with NPM:

Expand Down Expand Up @@ -274,23 +274,24 @@ You should never create or modify a snapshot directly, they are generated and up
Snapshot are mostly targeted at component testing. They make us conscious of changes to a component's structure which makes them _ideal_ for refactoring. If a snapshot is kept up to date over the course of a series of commits, the snapshot diffs record the evolution of a component's structure. Pretty cool 😎

```js
ciampo marked this conversation as resolved.
Show resolved Hide resolved
import { shallow } from 'enzyme';
import { render } from '@testing-library/react';
import SolarSystem from 'solar-system';
import { Mars } from 'planets';

describe( 'SolarSystem', () => {
test( 'should render', () => {
const wrapper = shallow( <SolarSystem /> );
const { container } = render( <SolarSystem /> );

expect( wrapper ).toMatchSnapshot();
expect( container.firstChild ).toMatchSnapshot();
} );

test( 'should contain mars if planets is true', () => {
const wrapper = shallow( <SolarSystem planets /> );
const { container, getByText } = render( <SolarSystem planets /> );
ciampo marked this conversation as resolved.
Show resolved Hide resolved

expect( wrapper ).toMatchSnapshot();
expect( wrapper.find( Mars ) ).toHaveLength( 1 );
expect( container.firstChild ).toMatchSnapshot();
expect( getByText( /mars/i ) ).toBeInTheDocument();
} );


} );
gziolo marked this conversation as resolved.
Show resolved Hide resolved
```

Expand Down Expand Up @@ -334,21 +335,27 @@ Snapshots themselves don't express anything about what we expect. Snapshots are

```js
ciampo marked this conversation as resolved.
Show resolved Hide resolved
test( 'should contain mars if planets is true', () => {
const wrapper = shallow( <SolarSystem planets /> );
const { container, getByText } = render( <SolarSystem planets /> );

// Snapshot will catch unintended changes
expect( wrapper ).toMatchSnapshot();
expect( container.firstChild ).toMatchSnapshot();

// This is what we actually expect to find in our test
expect( wrapper.find( Mars ) ).toHaveLength( 1 );
expect( getByText( /mars/i ) ).toBeInTheDocument();
} );
```

[`shallow`](http://airbnb.io/enzyme/docs/api/shallow.html) rendering is your friend:

> Shallow rendering is useful to constrain yourself to testing a component as a unit, and to ensure that your tests aren't indirectly asserting on behavior of child components.
Another good technique is to use the `toMatchDiffSnapshot` function (provided by the [`snapshot-diff` package](https://github.com/jest-community/snapshot-diff)), which allows to snapshot only the difference between two different states of the DOM. This approach is useful to test the effects of a prop change on the resulting DOM while generating a much smaller snapshot, live in this example:
gziolo marked this conversation as resolved.
Show resolved Hide resolved

It's tempting to snapshot deep renders, but that makes for huge snapshots. Additionally, deep renders no longer test a single component, but an entire tree. With `shallow`, we snapshot just the components that are directly rendered by the component we want to test.
```js
test( 'should render a darker background when isShady is true', () => {
ciampo marked this conversation as resolved.
Show resolved Hide resolved
const { container } = render( <CardBody>Body</CardBody> );
const { container: containerShady } = render(
<CardBody isShady>Body</CardBody>
);
expect( container ).toMatchDiffSnapshot( containerShady );
} );
```

#### Troubleshooting

Expand Down