Let's go through the process of setting up JEST with our React application, writing our first test and mocking an api call.

Setup

First we'll need to install dependencies via yarn

yarn add enzyme
yarn add enzyme-adapter-react-16
yarn add jest
yarn add jest-enzyme
yarn add nock

And add jest to our package.json to fire up JEST

"scripts": {
  "start": "webpack-dev-server --mode development --open --hot --progress",
  "build": "webpack --mode production",
  "test": "jest"
},

We'll also need a JEST setup file to load the enzyme adapter for React

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });

File Layout

__mockData__/[mock json files]
__mocks__/[test files]
jest.setup.js
package.json

Mock Data

Rather than interact with live data we need to mock any data we give our tests so we have a staple ground with which to interact with our application.

We'll do this quite simply by storing our mock data in JSON files and pulling it in much like how our api would send it.

// __mockData__/videos.json
[
  {
    "id": "01"
    "title": "Avengers Infinity War"
  },
  {
    "id": "02"
    "title": "Avengers Endgame"
  }
]

Now lets move to writing our first test. For this example we're going to use a simple Async request and then use Nock to intercept the GET request and give it the data from our videos.json file.

First our sample API call

//../src/videoRequest.js
import request from 'superagent';

async function listVideos(category) {
  return await request
    .get(`/v1/videos/category/${category}`)
    .set('accept', 'json')
    .then(function(response) {
      return response.body
  });
}
export {
  listVideos
}

And now our Test

// __tests__/testAPI.js
import React, { component } from 'react';
import { mount, shallow } from 'enzyme';
import toJSON from 'enzyme-to-json';
import nock from 'nock';

// load helper get method for video categories
import listVideos from './../src/videoRequest';

// load mock data
let mockVideos = require('./../__mockData__/videos.json');

// setup get intercepts,
// specifying the API path and data to return.
nock('http://localhost')
  .get('/v1/videos/')
  .reply(200, { mockVideos });

nock('http://localhost')
  .get('/v1/videos/category/all')
  .reply(200, { mockVideos });

// describe tests
describe('videoRequest Component', () => {
  describe('when helpers fired', () => {
    // define test, applying async similar to the live version
    it('return videos in category all', async () => {
      // fire get request
      const results = await listVideos('all')
      // define expected returned data
      expect(results.mockVideos[0].title).toEqual("Avengers Infinity War")
    })
  })
});

Notice at the start we load the mock data into memory.

let mockVideos = require('./../__mockData__/videos.json');

Then knoking the API route the request will use we tell nock to intercept that very path and method returning it that very same data.

nock('http://localhost')
  .get('/v1/videos/category/all')
  .reply(200, { mockVideos });

That way when we test the data give we can have predictable results.

expect(results.mockVideos[0].title).toEqual("Avengers Infinity War")

We can use this same method to mock other GET requests, POST requests, error handling for front-end so we're able to test out our components without them touching live data.