React Testing Helper
A comprehensive skill for writing effective React component tests.
When to Use
- Writing unit tests for React components
- Debugging failing component tests
- Setting up React Testing Library
- Testing user interactions and async behavior
Quick Reference
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
// Basic render
render(<MyComponent prop="value" />);
// Query elements
screen.getByRole('button', { name: /submit/i });
screen.getByText(/welcome/i);
screen.getByTestId('my-element');
// User interactions
await userEvent.click(button);
await userEvent.type(input, 'hello');
// Async assertions
await waitFor(() => {
expect(screen.getByText('loaded')).toBeInTheDocument();
});
Best Practices
- Query by accessibility: Prefer
getByRole,getByLabelTextovergetByTestId - Test behavior, not implementation: Focus on what users see and do
- Use userEvent over fireEvent: More realistic user interactions
- Avoid testing implementation details: Don't test state or internal methods
Common Patterns
Testing Forms
test('submits form with user data', async () => {
const
render(<LoginForm />);
await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com');
await userEvent.type(screen.getByLabelText(/password/i), 'password123');
await userEvent.click(screen.getByRole('button', { name: /submit/i }));
expect(onSubmit).toHaveBeenCalledWith({
email: 'test@example.com',
password: 'password123'
});
});
Testing Async Components
test('loads and displays data', async () => {
render(<DataLoader />);
expect(screen.getByText(/loading/i)).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText(/data loaded/i)).toBeInTheDocument();
});
});
Troubleshooting
- Element not found: Use
screen.debug()to see current DOM - Act warnings: Wrap state updates in
act()or usewaitFor - Stale queries: Re-query elements after state changes