As if we don't have enough new tech in our stack at this point, I'm going to use Jest - Facebook's JavaScript test framework - as our test tool in this project.

I've deliberately chosen Jest as our stack is already heavily Facebook-friendly, and it makes the most sense (to me, at least) to use the tools that FB use, as they deal with React at scales vastly larger than I ever will. And if it works for them...

Honestly though, if you have any experience at all with JavaScript testing (especially Jasmine / Mocha), the syntax for Jest should feel extremely familiar. And if you've never done testing before, hopefully you will see that not only is it easy to get started, it also makes writing code that works first time a lot more commonplace.

Adding Jest to our project is easy enough:

yarn add -D jest

And then we need to update the test script inside package.json to use Jest rather than anything else you might already have configured:

// /package.json

  "scripts": {
    "test": "jest"
  },

And with that, you should be good to run yarn test to trigger a test suite run.

Once that works, it's nice to add two more things in here.

The first is to have a test watcher, so if you change any files, the tests will automatically re-run:

// /package.json

  "scripts": {
    "test": "jest",
    "test:watch": "npm run test -- --watch"
  },

Then instead of running yarn test, you need to run yarn test:watch.

And also, I like to have some coverage information output:

// /package.json

  "scripts": {
    "test": "jest --coverage",
    "test:watch": "npm run test -- --watch"
  },

I follow the convention of putting all my tests in /__tests__, and have a directory structure under the __tests__ directory that mirrors my src dir.

That is to say, if I have a src/reducers/requestReducer.js file, then I would have a __tests__/reducers/requestReducer.react-test.js file to match it. I use the *.react-test.js suffix to distinguish between the real and test files, to avoid any accidents during import.

With that we are good to start writing some tests.

Basic Reducer Tests

The video covers this in further depth, so I'm going to do the "code speaks a thousand words" approach here, and simply show you the final test file as of at the end of this video.

// /__tests__/reducers/requestReducer.react-test.js

import request from '../../src/reducers/requestReducer';
import {SENDING_REQUEST} from '../../src/constants/actionTypes';

describe('Request Reducer', () => {

  it('has a default state', () => {
    expect(request(undefined, { type: 'unexpected'})).toEqual({
      sendingRequest: false
    });
  });

  it('can handle SENDING_REQUEST', () => {
    expect(request(undefined, {
      type: SENDING_REQUEST,
      payload: {
        sendingRequest: true
      }
    })).toEqual({
      sendingRequest: true
    });
  });

});

The key thing to take away here is that we are only really interested in what a test file looks like at this point. The actual tests themselves are about to change as we re-implement the requestReducer to handle our array of named requests, as per the previous video.

I'll finish up with my favourite saying:

If you don't have time for tests, you must have plenty of time for problems

:)

Gotchas

Specifically to this boilerplate, I've noticed a bug when trying to run the Jest filter facility in conjunction with the automated tests run by npm start -s. The filter input tends to glitch out. My solution to this is to simply run a seperate console tab with yarn test:watch running completely separate to the server.

I also wrote a blog post on adding Jest to this boilerplate which you may find interesting if you continue with Jest.


Code For This Course

Get the code for this course.

Code For This Episode

Get the code for this episode.

Share This Episode

If you have found this video helpful, please consider sharing. I really appreciate it.


Episodes in this series

# Title Duration
1 App Walkthrough - User Experience 03:15
2 App Walkthrough - Developer Experience 07:41
3 Development Environment Setup 06:34
4 Login - Part 1 09:15
5 Login - Part 2 07:55
6 Login - Part 3 12:37
7 Login - Part 4 10:22
8 Login - Part 5 08:00
9 Saving Redux State to Local Storage 08:50
10 Logout 10:57
11 Adding an Auth-aware NavBar 14:43
12 Cleanup, Linting, and Login Form Styling 09:58
13 Showing Spinning Icons, Because Why Not? 08:11
14 More Robust Request Tracking 09:07
15 Getting Started Testing With Jest 06:43
16 Testing Request Reducer - Part 1 11:35
17 Testing Request Reducer - Part 2 05:25
18 Testing AuthSaga - Happy Path 09:19
19 Testing AuthSaga - Unhappy Paths 04:38
21 Testing JavaScript's Fetch with Jest - Happy Path 05:15
21 Testing JavaScript's Fetch with Jest - Unhappy Paths 04:35
22 Getting Started with Jest Mocks 08:52
23 Using Webpack Environment Variables in Jest Tests 09:37
24 User Profile Page - Part 1 07:31
25 User Profile Page - Part 2 10:25
26 User Profile Page - Part 3 07:23
27 Change Password - Part 1 10:01
28 Change Password - Part 2 07:59
29 Change Password - Part 3 - Displaying Errors 06:28
30 Change Password - Part 4 - Converting Errors From Symfony to Redux Form 05:39
31 Change Password - Part 5 - Adding More Tests 05:06
32 Change Password - Part 6 - Avoid Blocking, and Wrap Up 06:23
33 Registration - Part 1 08:50