Testing React Components with React Testing Library
Learn how to test React components focusing on user behavior
Component Example
1// Component to test2import React, { useState } from 'react';34const Counter = ({ initialValue = 0 }) => {5 const [count, setCount] = useState(initialValue);67 return (8 <div>9 <h1>Counter</h1>10 <p data-testid="count-value">Count: {count}</p>11 <button onClick={() => setCount(count + 1)}>12 Increment13 </button>14 <button onClick={() => setCount(count - 1)}>15 Decrement16 </button>17 <button onClick={() => setCount(0)}>18 Reset19 </button>20 </div>21 );22};2324export default Counter;
Test Implementation
1// Counter.test.js2import React from 'react';3import { render, screen, fireEvent } from '@testing-library/react';4import userEvent from '@testing-library/user-event';5import Counter from './Counter';67describe('Counter Component', () => {8 test('renders counter with initial value', () => {9 render(<Counter initialValue={5} />);1011 expect(screen.getByText('Counter')).toBeInTheDocument();12 expect(screen.getByTestId('count-value')).toHaveTextContent('Count: 5');13 });1415 test('increments count when increment button is clicked', async () => {16 const user = userEvent.setup();17 render(<Counter />);1819 const incrementButton = screen.getByText('Increment');20 await user.click(incrementButton);2122 expect(screen.getByTestId('count-value')).toHaveTextContent('Count: 1');23 });2425 test('decrements count when decrement button is clicked', async () => {26 const user = userEvent.setup();27 render(<Counter initialValue={5} />);2829 const decrementButton = screen.getByText('Decrement');30 await user.click(decrementButton);3132 expect(screen.getByTestId('count-value')).toHaveTextContent('Count: 4');33 });3435 test('resets count to 0 when reset button is clicked', async () => {36 const user = userEvent.setup();37 render(<Counter initialValue={10} />);3839 const resetButton = screen.getByText('Reset');40 await user.click(resetButton);4142 expect(screen.getByTestId('count-value')).toHaveTextContent('Count: 0');43 });4445 test('handles multiple interactions correctly', async () => {46 const user = userEvent.setup();47 render(<Counter />);4849 const incrementButton = screen.getByText('Increment');50 const decrementButton = screen.getByText('Decrement');5152 // Click increment 3 times53 await user.click(incrementButton);54 await user.click(incrementButton);55 await user.click(incrementButton);5657 expect(screen.getByTestId('count-value')).toHaveTextContent('Count: 3');5859 // Click decrement once60 await user.click(decrementButton);6162 expect(screen.getByTestId('count-value')).toHaveTextContent('Count: 2');63 });64});
Key Concepts
- ✓Use data-testid for reliable element selection
- ✓Test user interactions, not implementation details
- ✓Use userEvent for realistic user interactions
- ✓Test component behavior, not internal state