Thursday, 1 June, 2017 UTC


Summary

Snapshot testing is particularly useful in testing React components. Let’s see how it’s done.
react-test-renderer
You need to render your React components before you serialize them. Be sure to install react-test-renderer so you can do so.
yarn add --dev react-test-renderer
Creating a Snapshot for a Component
Let’s say you have a component that pages a person when you click a button
// Pager.js import React from 'react'; export default function Pager({ name }) { const onClickCallback = () => alert(`Paging ${name}!`); return ( <div> <h1>{name}</h1> <button onClick={onClickCallback}>Page</button> </div> ); } 
Your test should look something like
// Pager.test.js import React from 'react'; import renderer from 'react-test-renderer'; import Pager from './Pager'; it('looks okay.', () => { const name = 'John'; // Render the component with the props. const tree = renderer.create(<Pager name={name}/>) // Convert it to JSON. .toJSON(); // And compare it to the snapshot. expect(tree).toMatchSnapshot(); }); 
The snapshot goes to the __snapshots__ folder and all subsequent test runs will compare to that. From there you can edit Pager as you please; so long as the same props give the same result, the snapshot will match. But that’s also a problem.
Snapshots Are Not a Magic Bullet
It’s important to note that, while objects are serializable, functions (and therefore callbacks) are not. If you open up Pager.test.js.snap, you’ll see that onClickCallback is being represented as [Function].
// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`properly writes name. 1`] = ` <div> <h1> John </h1>  <button onClick={[Function]} > Page </button> </div> `; 
If Pager is rewritten so that onClickCallback does something else, the snapshot will still pass.
export default function Pager({ name }) { // Not what you want it to do, but it will still pass. const onClickCallback = () => alert(`Paging {name}!`); return ( <div> <h1>{name}</h1> <button onClick={onClickCallback}>Page</button> </div> ); }