What is the React Testing Library? - All you need to know

·7 min read

What is the React Testing Library? - All you need to know

If you are a React developer and still not using the React Testing Library, you ought to keep reading further. Sorry, we don’t make the rules! And also, why not! It’s simple, fun, and easiest to work with. Let’s get started already!

React Testing Library (RTL) is a collection of utilities that helps in testing React Components without relying on the details of their implementation. This method makes refactoring easy and encourages us to use best practices for accessibility.

 

Introduction

Testing is applicable for ensuring a reliable user experience without any errors in any functionality. In other words, testing an application makes sure that whatever functions and features that you have developed works as per your expected outcomes. Having maintainable tests makes your application robust and less error-prone.

React Testing Library is a lightweight solution used to avoid considering implementation details (how is a Component developed) and rather focus on testing the functionalities of React Components for their intended purpose. It is built on the DOM testing library. Application projects created with Create React App have the inbuilt support for React Testing Library. Otherwise, one can install it via npm as:

npm install --save-dev @testing-library/react

 

 

Types of Testing in React

  • Unit Testing: Testing a single component in a react application to check whether that component renders with the default props or not.
  • Integration Testing: This testing is based on checking the working of the family of components. For instance, if a child component updates its parent component’s context state.
  • End to End Testing: This testing combines both Unit and Integration tests into a big test. This type of test is run in a simulated browser. While running these tests, there is no guarantee of UI. For instance, this testing can be used to test authentication flow.

 

Clone the demo project from https://github.com/Ferin79/react-testing-library-article-demo

We will reference this simple react application for unit testing with React Testing Library in this article.

React testing demo project

React testing demo project

 

 

Why test with React Testing Library?

It is a simple and complete React DOM testing utility that encourages good testing practices. It provides light utility functions on the top of react-dom and react-dom/test-utils, in a way that encourages finer testing practices. React Testing Library is a tool in the Testing Frameworks category of a tech stack.

If you don’t want to use RTL, there are alternative libraries for testing like

  • Enzyme
  • Cypress
  • Jest
  • Cucumber
  • JUnit

 

Testing Header Component

In the react application that we have referenced, there is a Header component as shown below.

React header component

 This component can be tested individually by writing the following code.

 

/tests/components/Header.test.jsx

import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Header from "../../components/Header";

test("render title correctly", () => {
  render(<Header />);
  const titleElement = screen.getByText(/My Contacts/i);
  expect(titleElement).toBeInTheDocument();
});

In the above code, we are first rendering the Header component on the user screen, then we are storing the title of the element in the titleElement constant by getting the text on the screen. We can import the screen from the @testing-library/react. Lastly, we are expecting the titleElement to be present in the document. It is simply an assertion for testing. That is, if the text is not found in the document, then the test would fail otherwise it will pass successfully.

React Header Test

This is the output of the test done by the above code. The test has passed successfully because the expect method returns true for verifying that the text titleElement is on the screen.

 

Test Method: This method initiates the test in React and takes two arguments which are-

  • String: It is generally the title or unique identifier of a test. This title will be printed in the console before running the test.
  • Callback function: This is the method where the actual tests are written. After printing the string title in the console, this callback method is called.

 

Render Method: This method renders the React component into a container that is appended to document.body

 

Screen Object: The screen object is imported from ‘@testing-library/react’ which has all the query methods which you can use to select elements from DOM. Some of the queries are shown in the following table-

React Query table

This is the brief of single and multiple elements queries sourced from https://testing-library.com/docs/queries/about/#screen. You can use these queries with the screen object to retrieve the document element(s) for testing purposes. For instance, the getBy query can be used to retrieve a single node from the screen.

 

Expect method: This method is used to assert the selected elements. You can bind many assertion methods to expect method. We will discuss many assertion methods later on. 

In the above example, we have used the toBeInTheDocument assertion method exported by @testing-library/jest-dom with expect method which is used to inspect whether the selected element is present in DOM or not. This method returns a boolean, that is true or false, which assists tests to either pass or fail.

Now, let’s see the following code that fails the test.

import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Header from "../../components/Header";

test("Render Title Correctly", () => {
  render(<Header />);
  const titleElement = screen.getByText(/Ferin Patel/i);
  expect(titleElement).toBeInTheDocument();
});

The above code is the same code as the previous example that you have seen. The only difference here is in the getByText method that is trying to find Ferin Patel instead of My Contacts in the DOM.

Find text in DOM in React

This test failed because we are trying to find text ‘Ferin Patel’ which is not present in Header Component.

There’s an alternative method ‘It’ to the test method.

 

It method: The it method is an alternative method to the test method. Likely, it also expects two parameters string and the callback function while executing.

it("Render Title Correctly by it method", () => {
  render(<Header />);
  const titleElement = screen.getByText(/My Contacts/i);
  expect(titleElement).toBeInTheDocument();
});

React it method test

 

Describe method:  When there are a lot of tests in a single file, it becomes difficult to manage all tests. So for better management of the tests, we have the describe method. This method helps us to organize tests. It can also be referred to as Test Suite. For instance, let’s see the following code-

import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import Header from "../../components/Header";

describe("Example of 'test' method and 'it' method", () => {
  test("Render Title Correctly", () => {
	render(<Header />);
	const titleElement = screen.getByText(/My Contacts/i);
	expect(titleElement).toBeInTheDocument();
  });

  it("Render Title Correctly by it method", () => {
	render(<Header />);
	const titleElement = screen.getByText(/My Contacts/i);
	expect(titleElement).toBeInTheDocument();
  });
});

React it and test method for testing

 

More tests on Header

The following code shows the Header component in our referenced project.

/components/Header.jsx

import { Flex, Heading, Text } from "@chakra-ui/react";
import React from "react";

const Header = ({ total = 0 }) => {
  return (
	<Flex
  	w="100%"
  	h="10vh"
  	background="rgba(255,255,255,0.5)"
  	borderTopRadius="2xl"
  	px="6"
  	justify="center"
  	flexDirection="column"
	>
  	<Heading fontSize="2xl">My Contacts</Heading>
  	<Text color="green.500" fontWeight="semi-bold" data-testid="total-id">
    	{total} {total > 1 ? "Contacts" : "Contact"}
  	</Text>
	</Flex>
  );
};

export default Header;

 

/tests/components/Header.test.jsx

describe("Count Tests", () => {
  it("Check text is plural or not", () => {
	render(<Header total={256} />);
	const totalElement = screen.getByTestId("total-id");
	expect(totalElement.textContent).toBe("256 Contacts");
  });
  it("Check text is singular or not", () => {
	render(<Header total={1} />);
	const totalElement = screen.getByTestId("total-id");
	expect(totalElement.textContent).toBe("1 Contact");
  });
});

React check text is plural and singular tests

 

getByText method:  This method is used to retrieve elements from DOM with text. It throws an error if it doesn’t find any element or find more than 1 element.

 

getByTestId method:  This method is used to get elements by test ID provided to elements in a React application. You need to add ‘data-testid’ props in relevant React Components.

 

Fire Events

‘fireEvent', which can be imported from ‘@testing-library/react', helps to fire any kind of event from the test code. Click event, Scroll event, Change event, Drag/Drop event, Touch event, and so on. https://github.com/testing-library/dom-testing-library/blob/main/src/event-map.js has a list of all the supported events.

 

 

Testing Home Page component

Now, let’s test the Home Page component in the project by writing the following code in /tests/pages/Home.test.jsx

import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import Home from "../../pages/Home";

describe("Example of fire Events", () => {
  it("check if button is visible on screen", () => {
	render(<Home />);
	const buttonElement = screen.getByRole("button");
	expect(buttonElement).toBeVisible();
  });

  it("click on button", async () => {
	render(<Home />);
	const buttonElement = screen.getByRole("button");
	fireEvent.click(buttonElement);
	await waitFor(() => {
  	expect(buttonElement).not.toBeVisible();
	});
  });
});

 

getByRole Method: The getByRole method queries the DOM and looks for elements with roles. Roles are the valid HTML tags such as <button>, Headings like <h1>, <h2> ..., <h6>, Anchor link <a>, <input>, Paragraph <p> etc.

 

toBeVisible Assertion: This allows you to check if an element is currently visible to the user.

An element is visible to a user if all the following conditions are met:

  • it does not have its CSS property display set to none
  • it does not have its CSS property visibility set to either hidden or collapse
  • it does not have its CSS property opacity set to 0.

 

 

Assertion Methods

toBeInTheDocument():  This assertion method matches the expected element node in the DOM.

expect(element).toBeInTheDocument();

 

toBe():  This assertion method checks if the text content of the expected element is the string given in the toBe method (hello in this case).

expect(element.textContent).toBe('hello');

 

toHaveLength(): This matcher assertion verifies if the expected sequence (array) has the length specified in the toHaveLength method (that is 7 here).

expect(myArr).toHaveLength(7);

 

Other such methods are:

  • toBeDisabled()
  • toBeEnabled()
  • toBeEmpty()
  • toBeEmptyDOMElement()
  • toBeInvalid()
  • toBeRequired()
  • toBeValid()
  • toBeChecked()
  • toBePartiallyChecked()
  • toHaveAttribute()
  • toHaveClass()
  • toHaveFocus()
  • toHaveFormValues()
  • toHaveStyle()
  • toHaveTextContent()
  • toHaveValue()
  • toHaveDisplayValue()
  • toHaveDescription()
  • toContainElement()
  • toContainHTML()

 

 

Conclusion

So, from the recent learning about React Testing Library, it is pretty clear that React Testing Library is the relieving solution for all the tough procedures we had to go through when dealing with the component functionalities along with its implementation details. Moreover, by learning about the various methods, it seems that RTL is very simple and straightforward to use. So, with all these features and the utilities, who wouldn’t like to use the RTL! Lastly, there is a cheat sheet available for the same at https://testing-library.com/docs/react-testing-library/cheatsheet/. Enjoy coding and testing!