| name | testing-react-testing-lib |
| description | Apply when testing React components: rendering, user interactions, and accessibility-focused testing. |
When to Use
Apply when testing React components: rendering, user interactions, and accessibility-focused testing.
Patterns
Pattern 1: Basic Render and Query
import { render, screen } from '@testing-library/react';
test('renders greeting', () => {
render(<Greeting name="World" />);
expect(screen.getByRole('heading')).toHaveTextContent('Hello, World');
expect(screen.getByText(/hello/i)).toBeInTheDocument();
});
Pattern 2: Query Priority
screen.getByRole('button', { name: /submit/i });
screen.getByRole('heading', { level: 1 });
screen.getByLabelText(/email/i);
screen.getByPlaceholderText('Enter email');
screen.getByText(/welcome/i);
screen.getByTestId('custom-element');
Pattern 3: User Interactions
import userEvent from '@testing-library/user-event';
test('submits form', async () => {
const user = userEvent.setup();
const onSubmit = jest.fn();
render(<LoginForm onSubmit={onSubmit} />);
await user.type(screen.getByLabelText(/email/i), 'test@example.com');
await user.type(screen.getByLabelText(/password/i), 'secret123');
await user.click(screen.getByRole('button', { name: /sign in/i }));
expect(onSubmit).toHaveBeenCalledWith({
email: 'test@example.com',
password: 'secret123',
});
});
Pattern 4: Async Waiting
import { waitFor, waitForElementToBeRemoved } from '@testing-library/react';
test('loads data', async () => {
render(<UserList />);
await waitForElementToBeRemoved(() => screen.queryByText(/loading/i));
expect(await screen.findByText('John Doe')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByRole('list').children).toHaveLength(3);
});
});
Pattern 5: Testing with Context/Providers
function renderWithProviders(ui: React.ReactElement) {
return render(
<QueryClientProvider client={new QueryClient()}>
<ThemeProvider>
{ui}
</ThemeProvider>
</QueryClientProvider>
);
}
test('themed component', () => {
renderWithProviders(<ThemedButton />);
expect(screen.getByRole('button')).toHaveClass('dark-theme');
});
Pattern 6: Query Variants
screen.getByRole('button');
expect(screen.queryByRole('button')).toBeNull();
await screen.findByText(/loaded/i);
Anti-Patterns
- Testing implementation - Test what user sees/does
- Using container.querySelector - Use accessible queries
- Not awaiting user events - userEvent is async
- getBy for absence checks - Use queryBy
Verification Checklist