React Testing with Jest and React Testing Library Guide
react
testing
jest
react-testing-library
Installation
npm install --save-dev jest @testing-library/react @testing-library/jest-dom
Basic Test Structure
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
Commonly Used Queries
getByText
: Find an element by its text contentgetByRole
: Find an element by its ARIA rolegetByLabelText
: Find a form element by its labelgetByPlaceholderText
: Find an input by its placeholdergetByAltText
: Find an image by its alt textgetByTestId
: Find an element by itsdata-testid
attribute
Async Testing
test('loads items eventually', async () => {
render(<Page />);
// Wait for the items to be loaded
const items = await screen.findAllByRole('listitem');
expect(items).toHaveLength(3);
});
Simulating User Events
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
test('clicking button increments counter', () => {
render(<Counter />);
const button = screen.getByText('Increment');
fireEvent.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
// Using userEvent for more realistic user interactions
test('typing in a textbox', async () => {
render(<InputComponent />);
const input = screen.getByRole('textbox');
await userEvent.type(input, 'Hello, World!');
expect(input).toHaveValue('Hello, World!');
});
Mocking
// Mocking a module
jest.mock('./api', () => ({
fetchData: jest.fn(() => Promise.resolve({ data: 'mocked data' })),
}));
// Mocking a function
const mockFn = jest.fn();
mockFn.mockReturnValue(42);
// Asserting on mocks
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
Snapshot Testing
import renderer from 'react-test-renderer';
test('Component renders correctly', () => {
const tree = renderer.create(<MyComponent />).toJSON();
expect(tree).toMatchSnapshot();
});
Testing Hooks
import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';
test('should increment counter', () => {
const { result } = renderHook(() => useCounter());
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
Common Assertions
expect(element).toBeInTheDocument();
expect(element).toHaveTextContent('Expected text');
expect(element).toBeVisible();
expect(element).toBeDisabled();
expect(element).toHaveClass('example-class');
expect(element).toHaveAttribute('type', 'text');
Remember to always write tests that resemble how your software is used. Focus on testing behavior rather than implementation details.