Test your React components using Jest and react-testing-library to ensure their functionality and performance. In this blog post, we will walk you through the process of creating and running tests for your React components.

Getting Started

To start testing your React components, it is recommended to use snapshot testing. This technique allows you to test components in isolation, similar to unit testing for classes. If you have already created a React app using create-react-app, you will have Jest installed, which is the testing package we will be using.

Snapshot Testing

Let’s begin with a simple test. You can use CodeSandbox to try this out. Start by creating a React sandbox and add an App.js component in a components folder. Also, create an App.test.js file.

Here is the code for the App.js component:

import React from 'react';

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

Now, let’s create our first test in the App.test.js file:

test('First test', () => {
  expect(true).toBeTruthy();
});

When CodeSandbox detects test files, it will automatically run them for you. You can click the “Tests” button in the bottom of the view to see the test results.

A test file can contain multiple tests. This allows you to test different functionality of your components. Let’s move on to testing a more useful React component.

Testing a Counter App

In order to test a React component, we need a more functional application. Let’s consider the counter app we built previously. If you haven’t built it yet, you can go back and follow the instructions in the tutorial. For easier reference, let’s quickly go through the code again.

The counter app consists of two components: App and Button. Create the App.js file with the following code:

import React, { useState } from 'react';
import Button from './Button';

const App = () => {
  const [count, setCount] = useState(0);

  const incrementCount = increment => {
    setCount(count + increment);
  };

  return (
    <div>
      <Button increment={1} onClickFunction={incrementCount} />
      <Button increment={10} onClickFunction={incrementCount} />
      <Button increment={100} onClickFunction={incrementCount} />
      <Button increment={1000} onClickFunction={incrementCount} />
      <span>{count}</span>
    </div>
  );
};

export default App;

Next, create the Button.js file with the following code:

import React from 'react';

const Button = ({ increment, onClickFunction }) => {
  const handleClick = () => {
    onClickFunction(increment);
  };

  return <button onClick={handleClick}>+{increment}</button>;
};

export default Button;

Now, let’s test the Button component using react-testing-library.

Testing the Button Component

Start by importing the necessary functions from react-testing-library. This will allow us to render JSX and emit events on components. Create a Button.test.js file and import the required dependencies:

import React from 'react';
import { render, fireEvent } from 'react-testing-library';
import Button from './Button';

Since buttons in our app are used to accept click events and call a function passed through the onClickFunction prop, we need to create a count variable and a function that increments it:

let count;

const incrementCount = increment => {
  count += increment;
};

Next, let’s move on to the actual tests. Initialize count to 0 and render a +1 Button component, passing 1 to the increment prop and our incrementCount function to the onClickFunction prop. Then, get the content of the first child of the component and check if it outputs +1. Finally, simulate a click event on the button and check if the count increases by 1:

test('+1 Button works', () => {
  count = 0;
  const { container } = render(
    <Button increment={1} onClickFunction={incrementCount} />
  );
  const button = container.firstChild;
  expect(button.textContent).toBe('+1');
  expect(count).toBe(0);
  fireEvent.click(button);
  expect(count).toBe(1);
});

Similarly, we can test a +100 button. This time, we will check if the output is +100 and if the button click increments the count by 100:

test('+100 Button works', () => {
  count = 0;
  const { container } = render(
    <Button increment={100} onClickFunction={incrementCount} />
  );
  const button = container.firstChild;
  expect(button.textContent).toBe('+100');
  expect(count).toBe(0);
  fireEvent.click(button);
  expect(count).toBe(100);
});

Now, let’s move on to testing the App component.

Testing the App Component

The App component displays four buttons and the result on the page. We can inspect each button and see if the result increases when we click them. We will also check if clicking multiple times increases the result accordingly.

import React from 'react';
import { render, fireEvent } from 'react-testing-library';
import App from './App';

test('App works', () => {
  const { container } = render(<App />);
  console.log(container);
  const buttons = container.querySelectorAll('button');

  expect(buttons[0].textContent).toBe('+1');
  expect(buttons[1].textContent).toBe('+10');
  expect(buttons[2].textContent).toBe('+100');
  expect(buttons[3].textContent).toBe('+1000');

  const result = container.querySelector('span');
  expect(result.textContent).toBe('0');

  fireEvent.click(buttons[0]);
  expect(result.textContent).toBe('1');
  fireEvent.click(buttons[1]);
  expect(result.textContent).toBe('11');
  fireEvent.click(buttons[2]);
  expect(result.textContent).toBe('111');
  fireEvent.click(buttons[3]);
  expect(result.textContent).toBe('1111');
  fireEvent.click(buttons[2]);
  expect(result.textContent).toBe('1211');
  fireEvent.click(buttons[1]);
  expect(result.textContent).toBe('1221');
  fireEvent.click(buttons[0]);
  expect(result.textContent).toBe('1222');
});

You can see the code working in this CodeSandbox.

Great job! You have now learned how to test your React components using Jest and react-testing-library. Remember to always test your components thoroughly to ensure their functionality and integrity.

Tags: testing, react components, Jest, snapshot testing, unit testing