Snapshot testing

Linked Projects:

Calreact
 
Lesson code - https://github.com/learnetto/calreact-frontend/tree/m10l3-snapshot-testing

In this lesson, we’ll look at snapshot testing. Snapshot testing is a way to testing the output of your code against a previously saved copy of the same output. It’s like taking a screenshot and comparing new screenshots to it, hence the name snapshot testing.

Instead of saving an image, snapshot testing with Jest works by storing a text representation of the UI.

We first need to install react-test-renderer for this to work.

So let’s run

npm install —save-dev react-test-renderer

and then import it in our Appointment test file, Appointment.test.js:

import React from 'react';
  import ReactDOM from 'react-dom';
  import Appointment from '../components/Appointment';
  import { BrowserRouter as Router } from 'react-router-dom';
  import { shallow, mount } from 'enzyme';
  import renderer from 'react-test-renderer';

Then, let’s write the test:

	expect(appointment.contains(appt_time)).toEqual(true);
  	})
test('renders appointment correctly', () =>{

Let’s copy the appointment from the appointment block:

describe('render', () => {
  	it('should display the appointment title', () => {
   const appointment = mount(<Router><Appointment appointment={{id:1, title: 'Team standup meeting', appt_time: new Date()}} /></Router>);
   const title = <h3>Team standup meeting</h3>;
  		expect(appointment.contains(title)).toEqual(true);
  	})

But actually, let’s move this test inside the describe('render') block:

describe('render', () => {
  	it('should display the appointment title', () => {
   const appointment = mount(<Router><Appointment appointment={{id:1, title: 'Team standup meeting', appt_time: new Date()}} /></Router>);
   const title = <h3>Team standup meeting</h3>;
  		expect(appointment.contains(title)).toEqual(true);
  	})

and change the test to it (compare with code above):

it('renders appointment correctly', () =>{
  	  const appointment = mount(<Router><Appointment appointment={{id:1, title: 'Team standup meeting', appt_time: new Date('04/11/2017, 12:00:00')}} /></Router>);	
  	})

Then, we’ll store the JSON representation of the appointment in a variable. 

To do that, in our it test, we will write: 

it('renders appointment correctly', () =>{
  	  const appointment = mount(<Router><Appointment appointment={{id:1, title: 'Team standup meeting', appt_time: new Date('04/11/2017, 12:00:00')}} /></Router>);
  		let tree = appointment.toJSON();
  	})

Actually, we need to use the renderer here, so let’s change mount to renderer.create:

const appointment = renderer.create(<Router>
 
Then we write the assertion:

it('renders appointment correctly', () =>{
    const appointment = renderer.create(<Router><Appointment appointment={{id:1, title: 'Team standup meeting', appt_time: new Date('04/11/2017, 12:00:00')}} /></Router>);
  let tree = appointment.toJSON();
  expect(tree).toMatchSnapshot();
  })
 });

When you run that test, you will see that it passes, too.

If we look in our directory, you’ll see that there is a new directory called __snapshots__. And inside the directory, we have a new file Appointment.test.js.snap which contains our new snapshot.

The snapshot has the name of our test and the markup for the Appointment component with the values we passed in.

exports[`render renders appointment correctly 1`] = `
  <div
    className="appointment">
    <a
      href="/appointments/1"
      onClick={[Function]}>
      <h3>
        Team standup meeting
      </h3>
    </a>
    <p>
      April 11 2017, 12:00:00 pm
    </p>
    <a
      href="/appointments/1/edit"
      onClick={[Function]}>
      Edit
    </a>
  </div>
  `;

This snapshot file is created the first time we run the test.

On subsequent tests, Jest will simply compare our output to the saved snapshot. If they don’t match, that means either we have a bug in our code or something has changed and the snapshot needs to be updated.

Note, in the appointment, we’re using the Date method: 

const appointment = mount(<Router><Appointment appointment={{id:1, title: 'Team standup meeting', appt_time: new Date()}} /></Router>);

This means that the next time we run this test, it won’t match the snapshot because the value of appt_time will be different.

Test it yourself by hitting save.

And the test fails and an error message appears which reads, Received value does not match stored snapshot 1.

To make the test work again, let’s use a fixed date and time value in newDate:

<Appointment appointment={{id:1, title: 'Team standup meeting', appt_time: new Date('04/11/2017, 12:00:00')}} /></Router>);

Then we can update the snapshot by pressing u.

The snapshot gets updated and our test passes.

That was an example of snapshot testing.

Liked this tutorial? Get more like this in your inbox