2

I'm trying to test a React app with Rails backend. I'm trying to write tests in jest.

I'm using jest-fetch-mock node module to mock API calls. For some reason, it doesn't work properly.

This works, but fails in tests

//PhoneCodeList.jsx
class PhoneCodeList extends React.Component {
  async componentDidMount() {
    try {
      const response = await fetch(`/api/v1/phone-codes`);
      const response_json = await response.json()
      // do stuff
      console.log(response_json)
    }
    catch(e) {
      console.log(e)
    }
  }
}
// PhoneCodeList.test.js

import React from 'react'
import {mount, shallow, render, configure} from 'enzyme'
import PhoneCodeList from 'components/PhoneCodeList.js'
import Adapter from 'enzyme-adapter-react-16';
global.fetch = require('jest-fetch-mock')

configure({ adapter: new Adapter() })
const wrapper = mount(<PhoneCodeList />);

describe('Phone list', function() {
  test('Lists at least one phone code from database', async () => {
    fetch.mockResponse(JSON.stringify({ data: [{id: 1, attributes: { prefix: 'foo'}},
                                               {id: 2, attributes: { prefix: 'bar'}}]}))
    var resp = render(<PhoneCodeList />);
    expect(resp.find('.phone-code-row').length).toBeGreaterThan(0);
  })
})

Response:

Response {
      size: 0,
      timeout: 0,
      [Symbol(Body internals)]: { body: '', disturbed: false, error: null },
      [Symbol(Response internals)]:
       { url: undefined,
         status: 200,
         statusText: 'OK',
         headers: Headers { [Symbol(map)]: [Object: null prototype] {} } } }

But mock suddenly starts working if I place it in react file

//PhoneCodeList.jsx
class PhoneCodeList extends React.Component {
  async componentDidMount() {
    try {
      fetch.mockResponse(JSON.stringify({ data: [{id: 1, attributes: { prefix: 'foo'}},
                                                 {id: 2, attributes: { prefix: 'bar'}}]}))
      const response = await fetch(`/api/v1/phone-codes`);
      const response_json = await response.json()
      // do stuff
      console.log(response_json)
    }
    catch(e) {
      console.log(e)
    }
  }
}

Obviously, I don't want to leave mocks in my actual React files. What causes them to fail and how to prevent it?

update 01

Config files:

// setupJest.js

global.fetch = require('jest-fetch-mock')
// package.json

{
  "name": "germany_phone_codes",
  "private": true,
  "dependencies": {
    "@babel/preset-react": "^7.6.3",
    "@rails/webpacker": "^4.0.7",
    "@reach/router": "^1.2.1",
    "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
    "enzyme": "^3.10.0",
    "enzyme-adapter-react-16": "^1.15.1",
    "jest-enzyme": "^7.1.2",
    "prop-types": "^15.7.2",
    "react": "^16.11.0",
    "react-dom": "^16.11.0",
    "react_ujs": "^2.6.0",
    "yarn": "^1.19.1"
  },
  "devDependencies": {
    "babel-jest": "^24.9.0",
    "jest": "^24.9.0",
    "jest-fetch-mock": "^2.1.2",
    "react-test-renderer": "^16.12.0",
    "regenerator-runtime": "^0.13.3",
    "webpack-dev-server": "^3.9.0"
  },
  "scripts": {
    "test": "jest",
    "test-watch": "jest --watch"
  },
  "jest": {
    "roots": [
      "test/javascript"
    ],
    "moduleDirectories": [
      "node_modules",
      "app/javascript"
    ],
    "automock": false,
    "setupFiles": [
      "./setupJest.js"
    ]
  }
}
Steve Redka
  • 108
  • 1
  • 10

0 Answers0