React is a popular library for building user interfaces, and Jest is a widely used testing framework for JavaScript. In this article, we'll explore how to use Jest for snapshot testing in React, which is a technique for testing UI components by capturing their current state as a snapshot and comparing it against future changes.
What is snapshot testing?
Snapshot testing is a way of testing the UI components by taking a "snapshot" of their current state and comparing it against future changes. When you run a snapshot test, Jest will create a JSON file containing a representation of the component's current state. This file is called a snapshot.
When you run the test again, Jest compares the current state of the component to the snapshot to see if there are any differences. If there are differences, Jest will notify you and you can decide whether to update the snapshot or investigate the issue further.
Snapshot testing is useful for catching regressions in your UI components. It's especially valuable when you have a large number of components that are constantly changing, and you want to ensure that nothing is broken when you make changes.
Setting up Jest for snapshot testing
Before we can start snapshot testing, we need to set up Jest in our project. If you haven't already installed Jest, you can do so by running the following command:
npm install --save-dev jest
Once Jest is installed, you need to create a new file in your project called setupTests.js. This file is where you can configure Jest to work with React and other libraries you might be using in your project.
In setupTests.js, add the following code:
import '@testing-library/jest-dom';
import { configure } from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
configure({ adapter: new Adapter() });
This code imports the necessary libraries for working with Jest and configures it to work with React.
Next, you need to create a new folder in your project called __tests__. This folder is where you'll store your test files.
Writing a snapshot test
Let's create a simple React component and write a snapshot test for it. In this example, we'll create a functional component called Button that renders a button with some text.
import React from 'react';
function Button({ text }) {
return <button>{text}</button>;
}
export default Button;
To write a snapshot test for this component, create a new file in the __tests__ folder called Button.test.js. In this file, add the following code:
import React from 'react';
import renderer from 'react-test-renderer';
import Button from '../Button';
it('renders correctly', () => {
const tree = renderer.create(<Button text="Click me" />).toJSON();
expect(tree).toMatchSnapshot();
});
This code imports React and the react-test-renderer library, which allows us to render the component and capture a snapshot of its current state. It also imports the Button component we just created.
The it function is a Jest function that defines a single test case. In this test case, we create an instance of the Button component with the text prop set to "Click me". We then use the toJSON method to convert the component to a JSON representation, which we can compare against the snapshot.
The toMatchSnapshot matcher is a Jest matcher that compares the JSON representation of the component against the snapshot. If there are any differences, Jest will notify you and you can decide whether to update the snapshot or investigate the issue further.
Updating a snapshot
When you make changes to a component, you might need to update its snapshot to reflect the new state. To update a snapshot, simply run your test again with the --updateSnapshot flag, like this:
npm test -- --updateSnapshot
This command tells Jest to update any snapshots that have changed since the last test run.
It's important to note that updating a snapshot should be done with care. You should always review the changes before updating the snapshot to make sure they're intentional and expected.
Handling dynamic data
Sometimes your UI components will render dynamic data, like the current date or a randomly generated value. In these cases, snapshot testing can become more challenging, because the snapshot will be different every time the test runs.
To handle dynamic data, you can use Jest's snapshot serializers. A serializer is a function that converts a value into a string that can be compared against a snapshot.
For example, let's say we have a component that renders the current date:
import React from 'react';
function CurrentDate() {
const date = new Date();
return <div>{date.toString()}</div>;
}
export default CurrentDate;
If we write a snapshot test for this component, it will fail every time the test runs, because the date will be different each time.
To solve this problem, we can create a serializer that formats the date in a consistent way. Create a new file in your project called snapshotSerializers.js. In this file, add the following code:
module.exports = {
test(value) {
return value instanceof Date;
},
print(value) {
return value.toISOString();
},
};
This code exports a serializer that handles Date objects. The test function checks if the value is a Date, and the print function formats the date as an ISO string.
To use this serializer in our test, we need to update our Jest configuration in package.json. Add the following line to the jest section:
"snapshotSerializers": ["<rootDir>/snapshotSerializers.js"]
Now, when we run our snapshot test for CurrentDate, the serializer will be used to format the date in a consistent way, so the snapshot will be the same every time.
Conclusion
Snapshot testing is a powerful technique for testing React components, and Jest makes it easy to get started. By capturing a snapshot of your component's current state and comparing it against future changes, you can catch regressions and ensure that your UI components are working as expected.
In this article, we covered the basics of snapshot testing in React, including how to set up Jest, write a snapshot test, and handle dynamic data. With this knowledge, you should be well equipped to start testing your own React components with Jest.