DEV Community

Cover image for Setup Jest and React Testing Library in a React project | a step-by-step guide
Ivad Yves HABIMANA
Ivad Yves HABIMANA

Posted on • Updated on

Setup Jest and React Testing Library in a React project | a step-by-step guide

Not long ago that I came across with the concept of testing specifically "writing tests". I used to test everything by opening browsers and doing everything manually but you can't know what can go wrong when you change something in your code, and usually it does.
The point is that real apps need testing to ensure that our features will not break unexpectedly, instead of testing the app yourself you write tests that you can run anytime to ensure that everything still works as expected.
In this tutorial I will walk you through the process of setting up Jest and React testing library (RTL) for testing React applications

Note: this is a third article in the series of setting up a React environment from scratch without create-react-app as Jest and React Testing Library are already included in CRA. in the first article, we created a brand new React project from scratch without using create-react-app, the second article we configured ESLint, Prettier and Husky and we will base on this progress to setup a Jest and RTL and write our first test.
You can find code from last article HERE

Prerequisites

  • I will assume that you have a react app running and everything we built from previous articles, you can also follow along if you need this article for other purposes but note that your code may look different than what I have but the idea should be the same.

  • VS code: I will be using Vs code as our code editor but feel free to use any of your preference

that's all you need let's get started

Why testing?
Tests can be boring to write and useless in some cases but I can't stress enough the importance of testing extensively your application. how you ensure that your app still works after adding new code? => you write tests, how do you spot bugs that you never though they existed? by writing test. it is recommended that you test everything you write to have confidence that your app is running as expected. Testing is very strictly enforced at many organizations and some use the Test-driven development where tests are written before you implement features

Jest
Jest is an open source test framework created by Facebook and is well integrated with React. it have many built-in like snapshot testing, function mocking, coverage collection and is usually easy to configure and use. In this configuration, we will be using Jest to run tests that we write and know which failed or passed and collect coverage (meaning tell us lines that are not covered/tested in our codebase). learn more about Jest here

React Testing Library
React testing library (RTL) is a lightweight testing Library that help us to test React by simulating how users will interact with our application. as mentioned Here the official React documentation recommends using RTL to encourage writing tests that use your components as the end users do. learn more about RTL here

in our example we will be using both Jest and RTL but note that any can be used on it's own or with other tools. for better testing we will be using React testing Library to find our components and manipulate them while Jest will determine passing and failing tests and testing coverage

This guide will be more of configuration so I won't cover much about writing tests. for more about details about testing React applications check this great article here

Enough with the talking. let's get this party started. Follow the following steps

1. Install React testing library dependencies

  • run the following command to install RTL dependencies (as dev dependencies)
npm install --save-dev @testing-library/react @testing-library/jest-dom
Enter fullscreen mode Exit fullscreen mode

if you prefer yarn

yarn add --dev @testing-library/react @testing-library/jest-dom
Enter fullscreen mode Exit fullscreen mode
  • @testing-library/react: the core dependency that install react testing library.
  • @testing-library/jest-dom: is a virtual DOM for jest allow us to use custom jest matchers to extend jest with react testing library. there matchers will make your tests more declarative, clear to read and to maintain. More on this later

2. Install Jest dependecies

  • run the following command to install jest dependencies (as a dev dependecies)
npm install --save-dev jest jest-environment-jsdom
Enter fullscreen mode Exit fullscreen mode

if you prefer yarn

yarn add --dev jest jest-environment-jsdom 
Enter fullscreen mode Exit fullscreen mode
  • jest: the core dependency required for Jest to work
  • jest-environment-jsdom: this will allow us to use jsdom and we will use it together with @testing-library/jest-dom that we installed earlier

3. Configure Jest
You can configure Jest by adding jest entry in the package.json or add a file named jest.config.js in the root folder. To keep package.json clean we will use jest.config.js

  • Create a file named jest.config.js in the root folder and add the following code configuration.
module.exports = {
    collectCoverage: true,
    collectCoverageFrom: ['src/**/*.{js,jsx}'],
    coverageDirectory: 'coverage',
    testEnvironment: 'jsdom',
}
Enter fullscreen mode Exit fullscreen mode

Understand this configuration

  • collectCoverage: enables collecting coverage
  • collectCoverageFrom specifies files to collect coverage from this will be from files files in all .js and jsx from src folder
  • coverageDirectory specifies folder jest will put coverage files
  • testEnvironment The test environment that will be used for testing note that we are setting it to jsdom and this will be coming from @testing-library/jest-dom and jest-environment-jsdom packages we installed earlier.

Most of jest configurations are well configured by default so we don't need to edit much in this file, but you can customize everything however you want. Learn more about all configurations and their values HERE

4.Integrate Jest with React testing Library

  • in the root folder create a file named jest.setup.jsenter the following line of code
import '@testing-library/jest-dom'
Enter fullscreen mode Exit fullscreen mode

this means that we are importing everything from @testing-library/jest-dom package

  • in the jest.config.js file we created earlier add another field of setupFilesAfterEnv and set it's value to be ['<rootDir>/jest.setup.js'] this will tell jest for every test we write it will load configuration from jest.setup.js i.e. use React testing libraly your jest.config.js should look like this
module.exports = {
  collectCoverage: true,
  collectCoverageFrom: ['src/**/*.{js,jsx}'],
  coverageDirectory: 'coverage',
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
};

Enter fullscreen mode Exit fullscreen mode

5.Integrate Jest with ESLint
In the second article we setup ESLint to help us clean code. By default if you use Jest with Eslint installed Eslint will give errors because with Jest tests we use some functions directly without importing them, and ESLint doesn't accept that, therefore we need to integrate Eslint with Jest

follow the following steps, if you don't have Eslint in your project you can skip this section

  • Run the following command to install eslint-plugin-jest which will make Eslint recognise Jest code
npm install --save-dev eslint-plugin-jest
Enter fullscreen mode Exit fullscreen mode
yarn add --dev eslint-plugin-jest
Enter fullscreen mode Exit fullscreen mode
  • in the eslintrc.json add "jest" in the plugins array
  • in the eslintrc.json add "plugin:jest/recommended", in the extends to use recommended jest syntax
  • in the eslintrc.json in the env entry add "jest/globals": true to enable jest in our eslint environment

Your eslintrc.json should end up looking like this

{
    "env": {
        "browser": true,
        "es2021": true,
        "jest/globals": true
    },
    "extends": [
        "plugin:react/recommended",
        "plugin:jest/recommended",
        "airbnb",
        "prettier"
    ],
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": "latest",
        "sourceType": "module"
    },
    "plugins": ["react", "jest"],
    "rules": {
        "no-underscore-dangle": 0,
        "import/extensions": [
            "error",
            "ignorePackages",
            {
                "js": "always",
                "jsx": "always"
            }
        ]
    }
}
Enter fullscreen mode Exit fullscreen mode

6. Adding testing scripts
in the package.json in the script object add the following scripts

scripts:{
... //scripts you already have
test: "jest",
coverage: "jest --coverage"
}
Enter fullscreen mode Exit fullscreen mode

test: "jest": will find all our test to which whicha passing and failing
coverage: "jest --coverage": will run our tests too and also collect our coverage

That's all the configuration now you can write some tests

Writing tests
By convection we create a folder called test or __test__ in the folder you have files you want to test and tests will have name foo.test.js or bar.test.js

  • in the src folder create a test folder and add App.test.jsx to test App.jsx and the following code
import { render, screen } from '@testing-library/react';
import React from 'react';
import App from '../App.jsx';

describe('App tests', () => {
    it('should contains the heading 1', () => {
    render(<App />);
        const heading = screen.getByText(/Hello world! I am using React/i);
        expect(heading).toBeInTheDocument()
    });
});
Enter fullscreen mode Exit fullscreen mode
  • run test by running npm run test and it should pass

in this test we are testing that we have text Hello world! I am using React in our page, and this should pass as that's the text we used in article 1

There you have it that's how we setup Jest and React Testing Library to test React applications

For reference of code mentioned in this article check this GitHub repository

Top comments (17)

Collapse
 
sysionbit profile image
Sysion-bit • Edited

Everything looks very simple and clear, thanks for the guide. I just recently started diving into the world of programming by picking up math from textbooks with plainmath.net/textbooks/math/calculus just for myself. So now I'm collecting different guides to better understand how it all works and where to start. I'm interested in learning React now and I'm thinking of taking some more courses to get practical skills and a certificate to work with.

Collapse
 
malikidrees profile image
Malik-Idrees

The series is going great :)

Collapse
 
adeodatus profile image
Adeodatus Abdul

Wow.. It work. thank you

Collapse
 
sarahfarjallah profile image
sarahFarjallah • Edited

I did exactly what you did but I'm getting Syntax Error can't use import outside of module.

This is my package.json

{
"engines": {
"node": "14.20.0",
"npm": "6.x.x"
},
"name": "ui-v2",
"version": "0.1.0",
"private": true,
"dependencies": {
"@amcharts/amcharts3-react": "^3.1.1",
"@amcharts/amcharts4": "^4.10.35",
"@emotion/react": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@material-ui/core": "^4.12.4",
"@mui/icons-material": "^5.11.16",
"@mui/material": "^5.13.0",
"@reduxjs/toolkit": "^1.9.5",
"file-saver": "^2.0.5",
"firebase": "^9.9.0",
"inflected": "^2.1.0",
"javascript-color-gradient": "^2.4.4",
"jquery": "^3.7.0",
"jqueryui": "^1.11.1",
"moment": "^2.29.4",
"plotly.js": "^2.23.0",
"rc-slider": "^9.7.5",
"react": "^17.0.2",
"react-cookies": "^0.1.1",
"react-dom": "^16.14.0",
"react-dropdown-tree-select": "^2.8.0",
"react-grid-layout": "^1.3.4",
"react-helmet": "^6.1.0",
"react-https-redirect": "^1.1.0",
"react-phone-input-2": "^2.15.1",
"react-plotly.js": "^2.6.0",
"react-popup": "^0.10.0",
"react-redux": "^8.0.5",
"react-router-dom": "^5.3.4",
"react-scripts": "^5.0.1",
"react-select": "^4.3.1",
"react-table": "6.9.0",
"react-trello": "^2.2.11",
"redux": "^4.2.0",
"shortid": "^2.2.16",
"tabulator-tables": "~4.9.3",
"uikit": "~3.11.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "jest",
"coverage": "jest --coverage",
"eject": "react-scripts eject"
},
"client": {
"machine_name": "pi",
"categoryToolkit": true,
"isAdmin": true,
"version": "2.87.0.17"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"@babel/plugin-transform-private-property-in-object": "^7.21.11",
"@redux-devtools/core": "^3.13.1",
"@svgr/webpack": "^6.2.1",
"@testing-library/jest-dom": "^6.1.5",
"@testing-library/react": "^14.1.2",
"eslint-plugin-jest": "^27.6.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"resolve-url-loader": "^5.0.0",
"webpack-dev-server": "~4.10.0"
},
"overrides": {
"@svgr/webpack": "$@svgr/webpack",
"resolve-url-loader": "$resolve-url-loader",
"webpack-dev-server": "$webpack-dev-server"
}
}

my jest.config and jest.setup are exactly the same
What am i missing here?

Collapse
 
ivadyhabimana profile image
Ivad Yves HABIMANA

@sarahfarjallah Try also adding "type": "module" in your package.json

Collapse
 
sarahfarjallah profile image
sarahFarjallah

Sadly it didn't work

Collapse
 
digitalrisedorset profile image
Herve Tribouilloy • Edited

My project is a typescript one, so I changed the config you suggest to the below and it works pretty well. Practical read, great help, thanks
module.exports = {
collectCoverage: true,
collectCoverageFrom: ['src/**/*.{ts,tsx}'],
coverageDirectory: 'coverage',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.js']
}

Collapse
 
shubham12346 profile image
Shubham Agrahari

It works thanks , This article is really helpful , but one question in my project there is file setupTests.js in which import '@testing-library/jest-dom' is done and works but doing a separte file jest.setup.js does 'nt work

Collapse
 
jboiero profile image
jboiero

I have a problem in my project. Previously, enzyme and jest were used for testing. But when we updating the react version, enzyme became deprecated. So it was decided to start using Jest with React testing library.
I did all the installation´s steps that is detailed in this post, but when running jest I get the error TypeError: Cannot destructure property 'config' of 'cacheKeyOptions' as it is undefined. Could someone help me to solve it?

Collapse
 
andrewbaisden profile image
Andrew Baisden

Nice easy to follow guide.

Collapse
 
paolobiavati profile image
Paolo Biavati

It is depressing to read create a .js (JAVASCRIPT FILE) file and write import "@testing-library/jest-dom" (TYPESCRIPT SYNTAX)

Collapse
 
heero7 profile image
Kevin Mudiandambo

Thank you again!!