Photo by Lautaro Andreani on Unsplash
Testing React Apps Built with Vite: Setting up Jest and React Testing Library
Introduction to Testing React Applications with Jest and React Testing Library
Testing our React applications is essential for ensuring its functionality and reliability. With numerous modern testing frameworks available for React applications, selecting the right one depends on our preferences and project requirements. In this tutorial, we will utilize Jest and React Testing Library.
Jest is a JavaScript testing framework with a focus on simplicity. It seamlessly integrates with React applications and offers features such as snapshot testing, mocking, and coverage reports.
React Testing Library is a lightweight testing library for React applications that promotes writing tests closely resembling user interactions with our application.
Please note that this article does not extensively cover writing tests for React applications. Instead, it focuses on installing all required dependencies and showcasing a very simple test case. The build tool I am using for my React projects is Vite.
Installing All Necessary Dependencies
To set up Jest with React Testing Library in our Vite project, we need to install the necessary dependencies:
npm install --save-dev @testing-library/react @testing-library/jest-dom jest
Next, we have to update our
package.json
file to include a test script that runs Jest. The modifiedscripts
section:"scripts": { ..., "test": "jest" },
Since Jest doesn't understand JSX out of the box, it needs to be transformed into standard JavaScript. To achieve that, we need to install the following dependency:
npm install --save-dev @babel/preset-react
Next, we're going to install
@babel/preset-env
to transpile ES6 modules to CommonJS:npm install --save-dev @babel/preset-env
Create Babel config file named either
.babelrc
, orbabel.config.json
and add the followingpresets
:{ "presets": ["@babel/preset-env", "@babel/preset-react"] }
Additionally, specify the test environment by installing
jest-environment-jsdom
:npm install --save-dev jest-environment-jsdom
Update your Jest configuration, either in
jest.config.js
orpackage.json
. The example below is in apackage.json
file:"jest": { "testEnvironment": "jest-environment-jsdom", }
With this configuration, Jest will use
jest-environment-jsdom
as the test environment, providing a DOM implementation for running your tests.Configure Jest to use Babel for transforming files:
npm install --save-dev babel-jest
and update your Jest configuration injest.config.js
orpackage.json
"jest": { "transform": { "^.+\\\\.[jt]sx?$": "babel-jest", } }
We also need to instruct Jest to ignore CSS files during testing, as they are not JavaScript files and should not be parsed as such. We can achieve this by specifying a custom transformation for CSS files. Install jest-transform-stub
transformer: npm install --save-dev jest-transform-stub
Then, update your jest
configuration to use jest-transform-stub
for CSS files:
//package.json
"jest": {
"transform": {
"^.+\\\\.jsx?$": "babel-jest",
"\\\\.(css|scss)$": "jest-transform-stub"
}
}
package.json
Overview
After installing all the required dependencies, our package.json
should now be extended with the following dependencies and Jest setup. Please note that the exact versions might vary depending on when you're reading this article.
{
...
"scripts": {
...
"test": "jest"
},
"dependencies": {
...
},
"devDependencies": {
"@babel/preset-env": "^7.24.0",
"@babel/preset-react": "^7.23.3",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
"babel-jest": "^29.7.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-transform-stub": "^2.0.0",
},
"jest": {
"testEnvironment": "jsdom",
"transform": {
"^.+\\\\.[jt]sx?$": "babel-jest",
"\\\\.(css|scss)$": "jest-transform-stub"
}
}
}
Folder Structure
To start adding test files into our project, we first need to create a folder called __tests__
in the root directory. While this is my preferred folder structure, yours may differ based on personal preference. Here's an example of what the folder structure could look like:
├── src
│ ├── components
│ │ └── Button.jsx
│ ├── App.jsx
│ └── main.jsx
├── __tests__
│ ├── components
│ └── Button.test.js
├── babel.config.json
├── package.json
└── ...
In this structure:
The
src
directory contains our application source code.Within
src
, we have acomponents
directory housing our React components.The
Button.jsx
file represents an example component.The
__tests__
directory, created in the root directory, is dedicated to storing our test files.Inside
__tests__
, we create acomponents
directory to mirror the structure of thesrc
directory.Within
__tests__/components
, we create test files following a naming convention:<ComponentName>.test.js
, such asButton.test.js
, which is a test file specifically for theButton.jsx
component.
Creating Our First Test File
After creating our test file, we need to make sure React
is imported into both the component we're testing and the test file itself. Without this import, JSX syntax won't be recognized, leading to the React is not defined
error.
Let's consider an example component called Button.jsx
:
import React from 'react';
import './Button.css';
const Button = (props) => {
return (
<button className="btn" type="button" onClick={props.generateMemeImg}>
{props.text}
</button>
);
};
export default Button;
Additionally, we need to add import '@testing-library/jest-dom';
to the Button.test.js
file.
Here's an example test for Button.jsx
. This verifies that the button renders correctly and that the generateMemeImg
function is called when the button is clicked:
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import Button from '../src/components/Button'; //Adjust the path based on your folder structure
import '@testing-library/jest-dom';
test('renders button with correct text', () => {
//Define a mock function for generateMemeImg
const mockGenerateMemeImg = jest.fn();
//Render the Button component with the mock function passed as props
const { getByText } = render(
<Button text="Generate Meme" generateMemeImg={mockGenerateMemeImg} />
);
//Get the button element by its text content
const buttonElement = getByText('Generate Meme');
//Assert that the button is rendered
expect(buttonElement).toBeInTheDocument();
//Simulate a click event on the button
fireEvent.click(buttonElement);
// Assert that the mock function was called once
expect(mockGenerateMemeImg).toHaveBeenCalledTimes(1);
});
Conclusion
This tutorial focused on utilizing Jest and React Testing Library, two modern testing frameworks, to streamline the testing process. By following the installation guide and organizing test files effectively, we can create robust test suites to validate the behavior of their React components. Emphasizing simplicity and clarity, this tutorial aimed to equip developers with the necessary tools and knowledge to incorporate effective testing practices into their React projects.