Testing UI with Testing Library
Test user-facing behavior — queries by role and label, async utilities, and what not to assert.
intermediate1 min read
- testing
- react
- a11y
The guiding principle from Testing Library: test software the way users use it. Prefer roles, labels, and text over CSS selectors and internal state.
Query priority
getByRole— buttons, links, headings, dialogsgetByLabelText/getByPlaceholderText— form fieldsgetByText— non-interactive contentgetByTestId— last resort
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LoginForm } from './LoginForm';
test('submits email and password', async () => {
const user = userEvent.setup();
const onSubmit = vi.fn();
render(<LoginForm onSubmit={onSubmit} />);
await user.type(screen.getByLabelText(/email/i), 'a@b.com');
await user.type(screen.getByLabelText(/password/i), 'secret');
await user.click(screen.getByRole('button', { name: /sign in/i }));
expect(onSubmit).toHaveBeenCalledWith({
email: 'a@b.com',
password: 'secret',
});
});
If getByRole cannot find a control, your UI may have an accessibility bug, not just a test problem.
Async
expect(await screen.findByRole('alert')).toHaveTextContent(/saved/i);
Use findBy* for content that appears after fetch. Prefer waitFor sparingly when asserting non-element conditions.
What not to do
- Snapshot entire pages as the only test
- Assert on class names that are design-system internals
- Test implementation details (
useStatevalues) - Mock so much that the test only verifies the mock
Coverage of failure paths
Good suites include empty, loading, error, and unauthorized states — the same states your design system should define.
Related guides
- Visual Regression TestingVisual Regression Testing explained for frontend engineers — mental model, examples, common mistakes, and interview tips.
- Accessibility Testing in CIAccessibility Testing in CI explained for frontend engineers — mental model, examples, common mistakes, and interview tips.
- Snapshot Testing When UsefulSnapshot Testing When Useful explained for frontend engineers — mental model, examples, common mistakes, and interview tips.
- Test IDs as Last ResortTest IDs as Last Resort explained for frontend engineers — mental model, examples, common mistakes, and interview tips.
- Flaky Tests Common CausesFlaky Tests Common Causes explained for frontend engineers — mental model, examples, common mistakes, and interview tips.