/
🔥

React Testing Library Explain

https://www.robinwieruch.de/react-testing-library
ReactTesting
Table of contents
  • Confusions
  • Code Examples

React Testing Library (RTL) is alternative to Airbnb's Enzyme.

Confusions

JEST VS REACT TESTING LIBRARY

React beginners often confuse the tools for testing in React. React Testing Library is not an alternative to Jest, because they need each other and every one of them has a clear task.

Code Examples

Selecting Elements

jsx
import React from "react";
import { render, screen } from "@testing-library/react";
import App from "./App";
describe("App", () => {
test("renders App component", () => {
render(<App />);
// implicit assertion
// because getByText would throw error
// if element wouldn't be there
screen.getByText("Search:");
// explicit assertion
// recommended
expect(screen.getByText("Search:")).toBeInTheDocument();
});
});

Search Elements

jsx
// component
function getUser() {
return Promise.resolve({ id: "1", name: "Robin" });
}
function App() {
const [search, setSearch] = React.useState("");
const [user, setUser] = React.useState(null);
React.useEffect(() => {
const loadUser = async () => {
const user = await getUser();
setUser(user);
};
loadUser();
}, []);
function handleChange(event) {
setSearch(event.target.value);
}
return (
<div>
{user ? <p>Signed in as {user.name}</p> : null}
<Search value={search} onChange={handleChange}>
Search:
</Search>
<p>Searches for {search ? search : "..."}</p>
</div>
);
}
jsx
import React from "react";
import { render, screen } from "@testing-library/react";
import App from "./App";
describe("App", () => {
test("renders App component", async () => {
render(<App />);
expect(screen.queryByText(/Signed in as/)).toBeNull();
expect(await screen.findByText(/Signed in as/)).toBeInTheDocument();
});
});

Callback Handlers

jsx
describe("Search", () => {
test("calls the onChange callback handler", async () => {
const onChange = jest.fn();
render(
<Search value="" onChange={onChange}>
Search:
</Search>
);
await userEvent.type(screen.getByRole("textbox"), "JavaScript");
expect(onChange).toHaveBeenCalledTimes(10);
});
});

Async

jsx
import React from 'react';
import axios from 'axios';
import { render, screen, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import App from './App';
jest.mock('axios');
describe('App', () => {
test('fetches stories from an API and displays them', async () => {
const stories = [
{ objectID: '1', title: 'Hello' },
{ objectID: '2', title: 'React' },
];
const promise = Promise.resolve({ data: { hits: stories } });
axios.get.mockImplementationOnce(() => promise);
render(<App />);
await userEvent.click(screen.getByRole('button'));
await act(() => promise);
expect(screen.getAllByRole('listitem')).toHaveLength(2);
});
test('fetches stories from an API and fails', async () => {
...
});
});
Kelvin's Tech Notes