Back to articles

moving from mocha and chai to Jest

I already had unit tests against govuk-elements-nunjucks.

They were using mocha (test runner) chai (assertion) and cheerio to query the HTML.

One of the gaps in doing it this way is that it doesn’t guard against new markup being added.

Snapshots in jest

A lot like visual regression (which compares screenshots) snapshots lets you compare rendered markup against a baseline.

These are outputted as exports attached to the text name, with the rendered markup.

These could also be exported with jest-html so they can be explored.

To make a snapshot we just need to add one line of code to a test.


// code to match snapshot where output is rendered HTML
expect(output).toMatchSnapshot();

Snapshots are saved in a single file, and each one is exported so you can use them in other places.


// example baseline
exports[`gov-error-summary should render h1, p and correct links when data is supplied 1`] = 
`<div class="error-summary" role="group" aria-labelledby="error-summary-heading" tabindex="-1">
  <h1 class="heading-medium error-summary-heading" id="error-summary-heading">Error Heading</h1>
  <p>Details of error</p>
  <ul class="error-summary-list">
    <li>
      <a href="#link-1-form">This is an error 1</a>
    </li>
    <li>
      <a href="#link-2-form">This is an error 2</a>
    </li>
  </ul>
</div>`;

I like this approach to snapshots. It took few seconds to wire into existing tests. These could be shared against different implementations of templates.

Switch from mocha/chai

The switch required a couple of updates, there is a slight difference between Jest assertions and chai ones, but this was a find and replace job.


// chai example
expect(inputs).to.be.length(2);
expect(inputs.get(0).attribs.id).to.equal(`input-${name}-one`);

// jest example
expect(inputs).toHaveLength(2);
expect(inputs).toBe(`input-${name}-one`);


The only thing that was different was the contains, first you had to define a straingContaining var to check against.


// chai examples
expect(firstLabel.text()).to.contain('One');

// jest examples
const oneCheck = expect.stringContaining('One')
expect(firstLabel.text()).toEqual(oneCheck);


This is something that can be improved in my current tests as a couple of times I am using toBe(undefined) instead of toBeUndefined().

There is also a tool to help you migrate to Jest from other test frameworks.