Snapshot Tests in React Using Jest
Writing tests might not have been the most enjoyable thing for you in the past but I for sure hope that after reading this article, you'll be able to increase the test coverage.
Today, I am going to talk about snapshot tests using Jest. They're easy to write, they're fast, and most importantly, you'll for sure know if something is not right if you use them correctly. These snapshots will warn you for every change you make that affects the rendering: whether you're doing something simple, or more advanced rendering that includes conditions or looping.
Configure Jest
First, you need to set up Jest in the project. For that, install a few packages:
npm install --save-dev jest babel-jest babel-core regenerator-runtime babel-preset-es2015 babel-preset-react
You don't need to install regenerator-runtime if you use npm 3 or 4 or Yarn.
You'll have to add .babelrc
file in project root next:
{
"presets": ["env", "es2015", "react"]
}
Also, you need to install react-test-renderer package. This package is used to render React components to pure JavaScript objects.
npm i react-test-renderer --save
If you need some specific configuration for your tests, you can configure Jest using package.json file.
You're now ready to write your first snapshot test!
Writing snapshot tests
When writing snapshot tests using Jest, you should basically just follow the next template:
import renderer from 'react-test-renderer';
import Component from '../Component.react';
it('renders correctly', () => {
const tree = renderer.create(
<Component
prop={propValue}
/>
).toJSON();
expect(tree).toMatchSnapshot();
});
You use react-test-renderer
to create a component with desired props, transform it to JSON and then check if it matches a snapshot. Easy, right?
Here's a more concrete example — let's say you have a dummy component called Input
, for which you want to write a snapshot test:
function Input({ id, placeholder, label, onChange, value }) {
return (
<div>
<label htmlFor={id} >
{ label }
</label>
<input
id={id}
placeholder={placeholder}
onChange={onChange}
value={value}
/>
</div>
)
}
For the Input component, it can look something like this:
import renderer from 'react-test-renderer';
import Input from '../Input.react';
it('renders correctly', () => {
const tree = renderer.create(
<Input
id={'id'}
label={'label'}
placeholder={'Placeholder'}
onChange={() => {}}
value={''}
/>
).toJSON();
expect(tree).toMatchSnapshot();
});
Running tests
To run the test, you just need to type jest
command in terminal. Output snapshot file will be created, and when running the test next time, Jest will compare that output snapshot file to your updated component.
If you make some changes to a component that affects its rendering, (for example, adding a new item to the list to be mapped), the test will fail because the new object will be different from previous one. If changes were intended, you can update snapshot using the command jest --updateSnapshot
.
Keep in mind that all of these output snapshot files should be committed alongside the modules they are covering and their tests, as they are part of the test.
Of course, while your snapshot tests cover things like if conditional rendering is working properly, they don't test whether clicking on that link will properly redirect to another page. You will still need to write tests that check if the functionality works as expected, but those I'll be covering in some future article.
Thank you for taking the time to read this article! I hope you find it helpful.
This article was originally pubslihed on Kolosek Blog.
I’ve done lots of testing with React, using Jest and Enzyme. But now I built a React Native app and its the second part I had trouble with: testing for functionality like touches. The problem is that with react-native-test-utils I couldn’t get at any of my component’s sub-components to simulate a press. In other words, query(‘ComponentName’) was useless. I tried reading the snapshots to see if I could find some way of identifying components but I could find only components with generic names like ‘Text’. Hope you’ll write that next article soon, although I’m not sure it will apply to React Native.
I just found this: https://medium.com/react-native-training/learning-to-test-react-native-with-jest-part-1-f782c4e30101
I didn’t know that Enzyme is compatible with React Native.