Introduction to the React Testing Library
React Testing Library is an amazing yet simple testing library from Kent Dodds. It works alongside the testing library Jest to provide React specific testing for snapshots, verifying DOM attributes or content, triggering click (or other) events, etc... you would use it in place of Enzyme, which although very useful, can tend to be quite a bit more complicated given that it has 3 different ways to render/mount your React components.
In this article we'll be covering the basics of React Testing Library, starting with the bare minimum and working our way up through the examples found in the docs.
The code for this article can be found on GitHub at https://github.com/leighhalliday/learning-react-testing-library
Snapshots
Snapshot tests allow you to take a snapshot (hence the name) of the HTML produced from your React component. By having this, you'll be made aware when you change your component in some way that does not produce the same output as you previously expected. If the output does differ, you can then make a decision to update the snapshot, or to fix your code so that no difference is found.
The component we'll be taking a snapshot of takes in a text
prop, and puts it into a header and h1 tag.
import React from "react";export default function Header({ text }) {return (<header><h1>{text}</h1></header>);}
After importing the necessary packages, we can write a test which calls the render
function provided by React Testing Library, which returns an object that we can extract asFragment
from. Using this we can use the built-in functionality from Jest to perform a snapshot test.
import React from "react";import { render, cleanup } from "react-testing-library";import Header from "./Header";afterEach(cleanup);it("renders", () => {const { asFragment } = render(<Header text="Hello!" />);expect(asFragment()).toMatchSnapshot();});
DOM selectors and expectations
If you would like to isolate specific DOM elements to test their content or properties they might have, this is when we'll want to use one of the provided getter/selector functions provided by RTL. In this example we'll look at getByTestId
and getByText
. For this test let's modify our component slightly, adding a data
attribute and a class which we'll be testing for.
export default function Header({ text }) {return (<header><h1 data-testid="h1tag" className="fancy-h1">{text}</h1></header>);}
For our test, let's ensure the h1
tag contains a specific class and has the text content we are expecting. For that we'll add a package called jest-dom that will add on some expectations to Jest. Make sure to add the additional import to your test file (as shown below).
import React from "react";import { render, cleanup } from "react-testing-library";import "jest-dom/extend-expect";import Header from "./Header";afterEach(cleanup);it("inserts text in h1", () => {const { getByTestId, getByText } = render(<Header text="Hello!" />);expect(getByTestId("h1tag")).toHaveTextContent("Hello!");expect(getByText("Hello!")).toHaveClass("fancy-h1");});
This time we used the 2 getter functions to find our DOM element, and then used toHaveTextContent
and toHaveClass
to ensure our DOM element matches our expectations.
Next steps
Now that we have the basics of React Testing Library covered, it's time to move on to firing events to see how to trigger and test click events.