Learn the concept
React Testing Library
React Testing Library tests components from the user's perspective. Use render() to mount components, query methods (getByRole, getByText, etc.) to find elements, fireEvent or userEvent for interactions, and waitFor for async updates.
Philosophy:
Query Methods:
getBy*: Throws if not found (sync)queryBy*: Returns null if not foundfindBy*: Returns Promise (async)Query Priority:
getByRole: Accessibility rolesgetByLabelText: Form elementsgetByPlaceholderTextgetByText: Non-form elementsgetByTestId: Last resortUser Events:
userEvent: More realistic than fireEvent// Counter.jsx
function Counter({ initialCount = 0 }) {
const [count, setCount] = useState(initialCount);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
<button onClick={() => setCount(c => c - 1)}>Decrement</button>
</div>
);
}
// Counter.test.jsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Counter from './Counter';
describe('Counter', () => {
test('renders initial count', () => {
render(<Counter initialCount={5} />);
expect(screen.getByText('Count: 5')).toBeInTheDocument();
});
test('increments count when button clicked', async () => {
const user = userEvent.setup();
render(<Counter />);
await user.click(screen.getByRole('button', { name: /increment/i }));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
test('decrements count when button clicked', async () => {
const user = userEvent.setup();
render(<Counter initialCount={5} />);
await user.click(screen.getByRole('button', { name: /decrement/i }));
expect(screen.getByText('Count: 4')).toBeInTheDocument();
});
});Using RTL to simulate user typing (`userEvent.type`), clicking buttons (`userEvent.click`), and asserting on displayed error messages (`getByRole('alert')`) or successful submission feedback, ensuring the form behaves correctly from a user's perspective.
Employing `getByRole` and other semantic queries to locate elements, which naturally encourages writing tests that align with accessibility best practices, ensuring components are usable for all users.
Using RTL's `findBy*` queries or `waitFor` utility to handle asynchronous updates, asserting that loading indicators appear and disappear correctly, and that data is rendered once available.
Build a React counter component with increment/decrement buttons and a display. Write tests using RTL to ensure the count updates correctly on button clicks and displays the initial value.
Develop a simple login form with email and password fields. Use RTL to simulate user input, trigger validation, and assert on error messages and successful form submission.
Stripe uses React for many of its user-facing dashboards and integration elements. React Testing Library is a primary tool for ensuring the robustness and user-centric behavior of these UI components, verifying interactions and accessibility.
For their enterprise-grade applications like Jira and Confluence, Atlassian leverages React Testing Library to write reliable and maintainable tests for their extensive suite of React components, focusing on how users interact with their complex UIs.