Unit Tests in React

From Logic Wiki
Jump to: navigation, search


TDD in React

Installing Enzyme & Jest

npm i enzyme jest-cli@20.0.4 --save-dev

--save-dev only saves dependency in dev environment whereas --save saves dependency in production environment as well

to run tests

npm run tests

if it fails in the first time clear node_modules folder and run npm i then run the command above

npm i react-dom react-test-renderer --save-dev

We start with App.tests.js file

import React from 'react';
import { shallow } from 'enzyme';
import App from './App';

const app = shallow(<App />);

it('renders correctly', () => {
  expect(app).toMatchSnapshot();
});

Enzyme

Shallow wrapper api reference

https://github.com/airbnb/enzyme/blob/master/docs/api/shallow.md

Full Rendering API (mount(...))

https://github.com/airbnb/enzyme/blob/master/docs/api/mount.md

Jest

Expect

https://jestjs.io/docs/en/expect#tomatchsnapshotpropertymatchers-snapshotname

Globals

https://jestjs.io/docs/en/api

Fast Dive

toMatchSnapshot

it takes a snapshot on the first run and saves it. Later when we run unit tests it compares saved snapshot with current snapshot.

it('renders correctly', () => {
  expect(app).toMatchSnapshot();
});

toEqual

it('initializes the `state` with an empty list of gifts', ()=> {
   expect(app.state().gifts).toEqual([]);
 });

to pass this

constructor(){
   super();
   this.state = { gifts: [] };
 }

find & simulate

it('adds a new gift to `state` when clicking the `add gift` button', () => {
  app.find('.btn-add').simulate('click');

  expect(app.state().gifts).toEqual([{id: 1 }]);
});

to pass this

import { Button } from 'react-bootstrap';
...
addGift = () => {
  const { gifts } = this.state;
  const ids = this.state.gifts.map(gift => gift.id);
  const max_id = ids.length > 0 ? Math.max(...ids) : 0 ;
  gifts.push({ id: max_id + 1 });

  this.setState({ gifts });
}
...
<button className='btn-add' onClick={this.addGift}>Add Gift</Button>

children

expect(app.find('gift-list').children().length).toEqual(1);

Important: Enzyme Adapter

Please keep this in mind!

In order to use the most current version of React > 16, we now need to install "enzyme adapters" to provide full compatibility with React.

There's two options to take. The first is quicker, the second is recommended:

1. You can use the same versions for the node_modules libraries in the package.json files of the original repo:

Or you can:

2. Install the adapter for enzyme and react:

npm i enzyme-adapter-react-16 --save-dev  

Next, add a src/tempPolyfills.js file to create the global request animation frame function that React now depends on.

src/tempPolyfills.js should contain the following contents:

const requestAnimationFrame = global.requestAnimationFrame = callback => {
  setTimeout(callback, 0);
}
 
export default requestAnimationFrame;

Finally, add a src/setupTests.js file to configure the enzmye adapter for our tests. The disableLifecyleMethods portion is needed to allow us to modify props through different tests.

src/setupTests.js should contain the following contents:

import requestAnimationFrame from './tempPolyfills';
 
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
  
configure({ adapter: new Adapter(), disableLifecycleMethods: true });

Test Coverage

npm run test -- ---coverage

in package.json we can set up the coverage area

"jest":{
   collectCoverageFrom: [
     "src/**/*.js",
     "!src/index.js"
    ]
  }