Setup Jest and React Testing Library in a React project | a step-by-step guide
Tags: react, testing, beginners, javascript
Published: 2022-05-17 00:22:19

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](https://github.com/Yvad60/blog-code-references/tree/setup-eslint-prettier-and-husky)

**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](https://jestjs.io/)

**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](https://reactjs.org/docs/test-utils.html) 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](https://testing-library.com/docs/react-testing-library/intro/)

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](https://www.freecodecamp.org/news/8-simple-steps-to-start-testing-react-apps-using-react-testing-library-and-jest/)

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
```
if you prefer yarn 
```
yarn add --dev @testing-library/react @testing-library/jest-dom
```
- `@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
```
if you prefer yarn 
```
yarn add --dev jest jest-environment-jsdom 
``` 
- `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.

```js
module.exports = {
	collectCoverage: true,
	collectCoverageFrom: ['src/**/*.{js,jsx}'],
	coverageDirectory: 'coverage',
	testEnvironment: 'jsdom',
}
``` 

**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](https://jestjs.io/docs/configuration#coveragedirectory-string)

**4.Integrate Jest with React testing Library**
- in the root folder create a file named `jest.setup.js`enter the following line of code
```js
import '@testing-library/jest-dom'
```
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

```js
module.exports = {
  collectCoverage: true,
  collectCoverageFrom: ['src/**/*.{js,jsx}'],
  coverageDirectory: 'coverage',
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
};

```
**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
```
```
yarn add --dev eslint-plugin-jest
```

- 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 
```js
{
	"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"
			}
		]
	}
}
```

**6. Adding testing scripts**
in the `package.json` in the script object add the following scripts
```js
scripts:{
... //scripts you already have
test: "jest",
coverage: "jest --coverage"
}
```
`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

```js
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()
	});
});
```
- 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](https://github.com/Yvad60/blog-code-references/tree/setup-jest-and-react-testing-library)