7 things I learned adding Jest to my existing JavaScript boilerplate

Here are 7 things that I encountered when trying to add Facebook’s Jest to my existing React JS project.

This project was initially based on Corey House’s boilerplate – React Slingshot. There was nothing wrong with the test setup the boilerplate provided. I just wanted an excuse to try Jest.

1. Jest doesn’t play well with importing stylesheets

Here was the code I was using:

import React from 'react';
import '../styles/about-page.css';

const AboutPage = () => {
  return (

And the associated Jest output:

 FAIL  __tests__/components/AboutPage.react-test.js
  ● Test suite failed to run

    /home/chris/Development/react-registration-demo/src/styles/about-page.css:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){.alt-header {
                                                                                             ^
    SyntaxError: Unexpected token .
      
      at transformAndBuildScript (node_modules/jest-runtime/build/transform.js:284:10)
      at Object.<anonymous> (src/components/AboutPage.react.js:2:27)
      at Object.<anonymous> (__tests__/components/AboutPage.react-test.js:2:44)

To be fair, the output looks a bit nicer in the terminal.

Removing the stylesheet line:

import React from 'react';
// import '../styles/about-page.css';

const AboutPage = () => {
  return (

Now commented out, all passing:

 PASS  __tests__/components/AboutPage.react-test.js
  ✓ Can see header (10ms)

Snapshot Summary
 › 1 snapshot written in 1 test suite.

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 added, 1 total
Time:        1.077s
Ran all test suites.

2. Tests live in the __tests__ directory

The tutorial link doesn’t make it immediately obvious that the location and naming of your test files has an assumptive default config:

(/__tests__/.*|\\.(test|spec))\\.(js|jsx)$)

The boiler plate I am using has the test files in the same directory as the component itself. I followed the boiler plate pattern first, and it didn’t work.

I was confused why my tests wouldn’t run:

> jest

No tests found
  50 files checked.
  testPathDirs: /home/chris/Development/react-registration-demo - 50 matches
  testRegex: (/__tests__/.*|\.(test|spec))\.jsx?$ - 0 matches
  testPathIgnorePatterns: /node_modules/ - 50 matches

Tests need to go in a __tests__ directory, unless you are a regex ninja.

If you do want to overwrite it then you can update your package.json with extra config:

  "jest": {
    "testRegex": "your regex here dot star hash"
  }

I went with their defaults.

Now also note, you wouldn’t have this problem if you had read the landing page and the Docs link. I made the mistake of going direct to the Docs link via Google.

3. You may need to rename things

In React so far I have seen files named like either thing.jsx,  or thing.js. I’ve never seen anyone use thing.react.js.

However, the Jest docs use this convention.

So, having made two mistakes already, I made the switch myself.

Tangible benefit: None(?)

4. Jest ran existing tests just fine

This one threw me.

I had an existing file left over from my purge of the boilerplate demo site. I manually deleted the files as I worked my way through and replaced the boilerplate parts with my own.

One such file that was left was a utility class called mathHelper.spec.js 

Jest ran this just fine:

> jest

 PASS  __tests__/components/AboutPage.react-test.js
 PASS  src/utils/mathHelper.spec.js

Test Suites: 2 passed, 2 total
Tests:       13 passed, 13 total
Snapshots:   1 passed, 1 total
Time:        1.157s

5. Snapshot Testing is a really smart idea

You are kidding me.

Another concept to learn?

When will this learning ever end? Never. Get reading.

Actually though this is fairly simple to understand, and incredibly beneficial.

An example illustrates it best.

Let’s say I have a very basic component:

import React from 'react';

const AboutPage = () => {
  return (
    <div>
      <h2 className="alt-header">About</h2>
      <p>Who wouldn't want to know more?</p>
    </div>
  );
};

export default AboutPage;

And a really simple test:

import React from 'react';
import AboutPage from '../../src/components/AboutPage.react';
import renderer from 'react-test-renderer';

test('Can see header', () => {
  const component = renderer.create(
    <AboutPage />
  );
  let tree = component.toJSON();
  expect(tree).toMatchSnapshot();
});

The first time I run the tests with npm test then Jest will create a snapshot of how this page is expected to look:

exports[`test Can see header 1`] = `
<div>
  <h2
    className="alt-header">
    About
  </h2>
  <p>
    Who wouldn\'t want to know more?
  </p>
</div>
`;

And the test output:

> jest

 PASS  __tests__/components/AboutPage.react-test.js
  ✓ Can see header (9ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 passed, 1 total
Time:        0.827s, estimated 1s
Ran all test suites.

Then, should you make a change to your component in some way which causes the output to change:

import React from 'react';

const AboutPage = () => {
  return (
    <div>
      <h2 className="alt-header">About</h2>
      <p>Changed</p>
    </div>
  );
};

export default AboutPage;

Then re-run:

> jest

 FAIL  __tests__/components/AboutPage.react-test.js
  ● Can see header

    expect(value).toMatchSnapshot()
    
    Received value does not match stored snapshot 1.
    
    - Snapshot
    + Received
    
      <div>
        <h2
          className="alt-header">
          About
        </h2>
        <p>
    -     Who wouldn't want to know more?
    +     Changed
        </p>
      </div>
      
      at Object.<anonymous> (__tests__/components/AboutPage.react-test.js:10:16)
      at process._tickCallback (internal/process/next_tick.js:103:7)

  ✕ Can see header (11ms)

Snapshot Summary
 › 1 snapshot test failed in 1 test suite. Inspect your code changes or run with `npm test -- -u` to update them.

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   1 failed, 1 total
Time:        1.078s
Ran all test suites.
npm ERR! Test failed.  See above for more details.

Again, it looks nicer in the console.

6. You probably want an alias for updating snapshots

Here’s what I use, feel free to differ:

  "scripts": {
    "test": "jest",
    "testu": "npm run test -- -u",
  },

Every time you make a change to your component you likely need to re-update your snapshots. Having an alias is better than the alternative of typing out morse code.

7. There are concerns I only found out about after reading the Snapshot announcement blog post

Dropped in at the bottom of the blog post announcing Snapshot testing is some notes about forthcoming improvements.

This one caught my eye the most:

  • Mocking: The mocking system, especially around manual mocks, is not working well and is confusing. We hope to make it more strict and easier to understand.

Thankfully I did this migration on a new git branch 🙂

Published by

Code Review

CodeReviewVideos is a video training site helping software developers learn Symfony faster and easier.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.