Simple and complete React DOM testing utilities that encourage good testing practices.
@testing-library/react is a lightweight testing utility that helps you test React components by interacting with actual DOM nodes rather than component internals. With over 28 million weekly downloads, it has become the de facto standard for React testing, replacing approaches that test implementation details like component state or props. The library builds on top of react-dom and react-dom/test-utils, providing a clean API for querying elements and simulating user interactions.
The core philosophy is simple: your tests should resemble how users interact with your application. Instead of accessing component state or calling methods directly, you query elements by their accessible labels, roles, or visible text—exactly as a user or screen reader would. This approach creates tests that are resilient to refactoring; you can change how a component works internally without breaking tests, as long as the user experience remains the same.
The library emphasizes accessibility by default. Queries like getByRole and getByLabelText encourage you to build components that work with assistive technologies. If you can't query an element using accessible selectors, it's often a signal that your component needs accessibility improvements. This makes testing a forcing function for better UX.
Developers use @testing-library/react for unit tests of individual components, integration tests of component trees, and end-to-end workflows within the React layer. It pairs naturally with Jest for assertions and mocking, but works with any test runner. The library supports both hooks and class components, handles async operations elegantly, and requires minimal configuration to get started.
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LoginForm } from './LoginForm';
test('shows error message when login fails', async () => {
const user = userEvent.setup();
const mockLogin = jest.fn().mockRejectedValue(
new Error('Invalid credentials')
);
render(<LoginForm onLogin={mockLogin} />);
const emailInput = screen.getByLabelText(/email/i);
const passwordInput = screen.getByLabelText(/password/i);
const submitButton = screen.getByRole('button', { name: /sign in/i });
await user.type(emailInput, 'user@example.com');
await user.type(passwordInput, 'wrongpassword');
await user.click(submitButton);
expect(submitButton).toBeDisabled();
await waitFor(() => {
expect(screen.getByRole('alert')).toHaveTextContent(/invalid credentials/i);
});
expect(mockLogin).toHaveBeenCalledWith({
email: 'user@example.com',
password: 'wrongpassword'
});
expect(submitButton).toBeEnabled();
});Form validation workflows: Test that form fields show error messages when users enter invalid data, that submit buttons become disabled appropriately, and that successful submissions trigger the correct behavior. Query inputs by their labels, fill them with userEvent, and assert on visible feedback messages.
Conditional rendering based on data loading: Verify that loading spinners appear while data fetches, that error states display when requests fail, and that content renders correctly when data arrives. Use findBy queries and waitFor to handle async state changes without arbitrary timeouts.
User authentication flows: Test login forms, protected routes that redirect unauthenticated users, and UI changes based on auth state. Render components wrapped in your auth context provider and simulate the full user journey from logged-out to logged-in states.
Accessible component libraries: Validate that custom dropdowns, modals, and interactive widgets work with keyboard navigation and screen readers. Use getByRole with specific ARIA attributes to ensure components meet accessibility standards while testing their functionality.
Shopping cart and checkout processes: Test adding items to a cart, updating quantities, removing items, and proceeding through multi-step checkout flows. Verify that cart totals calculate correctly, that out-of-stock items show appropriate warnings, and that the entire workflow maintains state properly across renders.
npm install @testing-library/reactpnpm add @testing-library/reactbun add @testing-library/react