Advanced React Development

Master advanced React patterns, state management, performance optimization, and testing.

advanced Frontend Frameworks 8 hours

Chapter 7: React Testing Library

Chapter 7 of 15

Chapter 7: React Testing Library

7.1 Component Testing

React Testing Library focuses on testing components from the user's perspective, not implementation details.

import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

test('increments counter on button click', () => {
    render(<Counter />);
    
    const button = screen.getByRole('button', { name: /increment/i });
    const count = screen.getByText(/count:/i);
    
    expect(count).toHaveTextContent('Count: 0');
    
    fireEvent.click(button);
    
    expect(count).toHaveTextContent('Count: 1');
});

7.2 Query Methods

// getBy - throws if not found (use for required elements)
screen.getByRole('button');
screen.getByText('Submit');
screen.getByLabelText('Email');

// queryBy - returns null if not found (use for optional elements)
screen.queryByText('Error message');

// findBy - returns promise (use for async elements)
await screen.findByText('Data loaded');

// getAllBy - returns array (use for multiple elements)
screen.getAllByRole('listitem');

7.3 Testing User Interactions

import { render, screen, fireEvent, waitFor } from '@testing-library/react';

test('handles form submission', async () => {
    const handleSubmit = jest.fn();
    render(<Form onSubmit={handleSubmit} />);
    
    const emailInput = screen.getByLabelText('Email');
    const submitButton = screen.getByRole('button', { name: /submit/i });
    
    fireEvent.change(emailInput, { target: { value: 'test@example.com' } });
    fireEvent.click(submitButton);
    
    await waitFor(() => {
        expect(handleSubmit).toHaveBeenCalledWith({
            email: 'test@example.com'
        });
    });
});

7.4 Testing Async Operations

import { render, screen, waitFor } from '@testing-library/react';
import { rest } from 'msw';
import { setupServer } from 'msw/node';

const server = setupServer(
    rest.get('/api/user', (req, res, ctx) => {
        return res(ctx.json({ name: 'John' }));
    })
);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

test('loads and displays user data', async () => {
    render(<UserProfile userId="1" />);
    
    expect(screen.getByText('Loading...')).toBeInTheDocument();
    
    await waitFor(() => {
        expect(screen.getByText('John')).toBeInTheDocument();
    });
});