Unit Testing of React Component using Jest and Enzyme…

Hi Guys ,in this article we will discuss about how to test our React Components using Jest and Enzyme.We will divide our discussion in some points:

  1. What are Jest and Enzyme ?
  2. How to Setup those in our Vs code ?
  3. How to write and run Test cases and Check the code coverage ?
  4. Demo of Unit Testing
  5. Conclusion .
  6. What are Jest and Enzyme ?

Jest is an open-source testing framework created by Facebook. Jest offers the best integration with React JS including a command line tool for test execution.Whereas Enzyme is also an open-source testing framework which is maintained by Airbnb. It is easier to assert, manipulate, and traverse React components in Enzyme.

2. How to Setup those in our Vs code ?

To add unit test cases in our component , we have to install few npm packages namely enzyme ,enzyme-adapter-react-16 and enzyme-to-json. To install those packages we have to run the below command in our terminal:

npm i enzyme enzyme-adapter-react-16 enzyme-to-json

Once we install those npm packages, we will modify some scripts in our package.json file:

“test”: “react-scripts test — env=jsdom — watchAll=false — coverage -u”,

“test-coverage”: “react-scripts test — env=jsdom — coverage -u”

We can actually configure jest by writing some additional scripts in package.json:

package.json
package.json

We can also ignore some files for getting included in test coverage by adding those file’s path in collectCoverageFrom array like this in package.json :

“jest”: {

“collectCoverageFrom”: [

“src/**/*.js”,

“!<rootDir>/node_modules/”,

“!<rootDir>/src/index.js”,

“!<rootDir>/src/registerServiceWorker.js”,

]

}

Now we also need to configure adapter in our code base which will actually allow enzyme to run test cases in our application,we will create enzyme.js file for the configuration:

enzyme.js

In enzyme.js we are configuring our jest configuration,by importing Adapter from ‘enzyme-adapter-react-16’. Now we are ready to add unit test cases in our application.

3. How to write and run Test cases and Check the code coverage ?

There are some basic rules to add test files in our application, There are 3 ways to name our test files , our test file should have name ending with .test.js or .spec.js or those file should be kept in a folder named__tests__.We will discuss how to write test file while we will be going through the demo part. For now to run a test file we run the command react-scripts test ,for getting overall coverage of our code base we run react-scripts test — coverage.In this demo we are actually doing snapshot testing , while we run our test file for first time , a snapshot folder automatically gets created in our code base which contains snapshot files of all our components. After that Each time when we run the test scripts it will actually match our component with that snapshot file. After we do some DOM changes in our component after running test cases, it may throw error , because the current dom created will not actually match with the snapshot file.So for that reason we add -u in our test script , so that our old snapshot gets updated with the current DOM structure of our component automatically. Now after running the test script we will see a coverage folder will be created in our code base, we will open that folder → open Icov-report →index.html, in the browser something like this will apply:

All folder Coverage Report

Here we can actually check what is the code coverage of our application,These color changes according to the coverage , below 50 % is red, above 50% below 80% is yellow and above 80% is green. If we iterate into the folder it will contain coverage percentage for each file , so how you can check which lines to the code is not covered in each file? If we open a component we may see no color marked lines in the file , which means we are good with that file, but if we saw pink or yellow marked lines in the file this actually we have to add more test cases in the file. Red color actually indicates those lines which are not even touched or tested by the test cases we have written, This actually happen when we do not send certain required value to the props of our test component while running the test cases. Another is yellow these are the branch code which are not required value for the DOM to render but still needs to be tested .If we actually want to increase our code coverage we should always target to remove the red marked lines first.

4. Demo of Unit Testing

I have actually taken one of my previous articles (https://medium.com/@yudhajitadhikary/how-to-print-reactive-form-data-with-custom-styling-using-react-to-print-and-redux) code base for implementing unit testing on that application .So let’s start testing :

Folder Structure

So our code base is having both stateful and stateless component so that we can cover all type of scenarios which we face while we are writing test cases.We will also write test cases for redux like for reducer, actions etc.We will also write test cases for React Hooks and React LifeCycle methods.First we will add for Component.js:

Component.js
Component.js
Component.js
Component.js
Component.js
Component.js
Component.js
Component.js

This is actually the same code base we used in my previous article.I have added some lifecycle methods , document.getelementById and functions to increase the complexity to the file.Now let’s see the test case file:

Component.test.js

In Component.test.js we are importing mount from enzyme.js, importing Component from Component.js ,Since Component.js is a connected component, connected with Redux MapStatetoProps and mapDispatchToProps ,we are also import those separately for testing.Since our component is wrapped with Provider having store , we are importing Provider and store.Now we write all our test cases inside it ,first parameter is the description of our test , and then we write the function of our test cases.We actually can perform snapshot testing in two ways by using shallow or mount.

wrapper = mount(<Provider store={store}><Component/></Provider>, { attachTo: document.body });

In our case we are using mount, So we are mounting our component by wrapping it with Provider and attach document.body with it.We add document.body with it because we have used document.getelementById in our component.If we don’t add it , it will throw error while running test cases.

expect(shallowToJson(wrapper)).toMatchSnapshot();

Here we are actually matching our component with the snapshot created after running test cases for first time.

Now if we run the test we will see that our test coverage file will show red lines in handleClick() ,childrenClick(),content in ReactToPrint ,onSubmit on Formik,mapStateToProps and mapDispatchToProps.

wrapper.find(‘#testOnClick’).simulate(‘click’)

Since handleClick is directly called in the DOM we are adding an id of testOnClick to that div and using .find method to find that div and triggered click function.

shallowToJson(wrapper).children[0].children[0].node.instance.childrenClick()

So what happen if we pass a function inside a child function , there are ways like we can add the function as the instance to the component and trigger it .But I personal do this in a bit different ways so that wherever it’s going wrong we can Identify that , for that reason we use shallowToJson. shallowToJson actually allow us the see our component in a json format .For getting more clarity you can console.log(wrapper)and start comparing the result with the Dom structure of our component.So we are iterating through the result and finally triggered the function childrenClick(),same goes for content( ) in ReactToPrint and onSubmit() in Formik. So why we use this approach it’s like the alternative once something .find or .instance does not work for child component at that time we can use these as an alternative way and it will also work if it is implemented properly.

wrapper.setProps({})

For testing the ComponentDidUpdate() we used setProps function.

it(“should map state to props”, () => {

const initialState = {

email: ‘’,

password:’’,

address:’’,

pincode:’’,

phoneno:’’

};

expect(mapStateToProps(initialState).email).toEqual(‘’);

});

So to test mapStateToProps we are actually testing whether the values from the store is actually getting updated here.

it(“should call mapDispatchToProps”, () => {

const dispatch = jest.fn();

mapDispatchToProps(dispatch).submitAction();

});

To tests mapDispatchToProps we are triggering the action from component, and check whether it’s triggering correctly or not.

Similarly for Component1 ,Component2 and ComponentPrint we are adding unit test cases:

Component1.js
Component1.test.js
Component2.js
Component2.test.js
ComponentPrint.test.js

Now let’s see the test cases for reducers:

reducer.test.js
reducer.test.js

So in reducer we are checking whether initial state of the Reducer is same as it’s expected.After that we are checking whether the reducer is updating data accordingly when action is dispatching with type:’SUBMIT’ and payload:{email: ‘yudhajitadhikary@gmail.com’,

password:’1234',

address:’Kolkata’,

pincode:’700137',

phoneno:’9903547318'

}.

Now let’s see the test cases for actions:

action.test.js

In actions.test.js we are importing submitAction from ‘./actions’,also imported SUBMIT from ‘./actionTypes.js’. Here we are checking whether the submitAction in actions.js is dispatching with expected payload value.

Now let’s see the App.js test file:

App.test.js

Now let’s see the index.js test file:

index.test.js

So we covered all the file in our code base, let’s see the overall coverage now, To see overall code coverage run the below command in terminal of vs code:

npm run test-coverage

All files Coverage
src/Component Coverage
src/Print Coverage
src Coverage

So we can see all the files are having 100% percentage coverage.

5. Conclusion:

So we covered most of the scenarios which we face while we are doing unit test case, but There are still many scenario which comes in more complex applications.So I am leaving some links down below which I find helpful :

  1. https://enzymejs.github.io/enzyme/
  2. https://blog.carbonfive.com/shallow-testing-hooks-with-enzyme/
  3. https://medium.com/@netxm/test-async-redux-actions-jest
  4. https://jsramblings.com/3-ways-to-test-mapstatetoprops-and-mapdispatchtoprops

Leaving my GitHub repo as the reference of this tutorial:

HAPPY CODING….:)

--

--

--

Web developer by profession,Photographer,Blog Writer,Singer,Pianist,Seeker of Solution

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Animation using Framer-motion in React….

state and props in React

//platform.twitter.com/widgets.js from Twitter https://twitter.com/livrpoollocks

JavaScript’s Rest vs. Spread Operator: What’s the Difference?

Add limit to the Api search

Use NUXT with PNPM

Announcing Ditsmod 2.0 beta (with RealWorld example)

Immutable data structures in games

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Yudhajit Adhikary

Yudhajit Adhikary

Web developer by profession,Photographer,Blog Writer,Singer,Pianist,Seeker of Solution

More from Medium

Optimization Techniques in React Apps

Awesome Ways To Style Your ReactJS App

Puzzle Image in React

How to Use Typescript with React