Snapshot Tests in React Using Jest

Writing tests might not have been the most enjoyable thing for you in the past but we for sure hope that after reading this article, you'll be able to increase the test coverage.

Today we're talking about snapshot tests using Jest. They're easy to write, they're fast, and most importantly, we'll for sure know if something is not right if we use them correctly. These snapshots will warn us for every change we make that affects the rendering: whether we'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 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 isused 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 we have a dummy component called Input, for which we 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 our 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 the terminal. Output snapshot file will be created, and when running the test next time, jest will compare that output snapshot file to our updated component.

If you make some changes to a component that affects it's rendering, ( for example add 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 the 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 our 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 we'll be covering in some future article.

Thank you for your time reading!

Did you enjoy this article? We're regularly publishing new React content, so make sure to subscribe so you don't miss anything out!