Component Tests with React Testing Library

Testing a Client Component

React Testing Library renders a component in jsdom and lets you interact with it the way a user does (find by role/text, click, type).

// components/QuantityPicker.test.tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, expect, it, vi } from 'vitest';
import QuantityPicker from './QuantityPicker';

describe('QuantityPicker', () => {
  it('increments and does not go above stock', async () => {
    const onChange = vi.fn();
    render(<QuantityPicker stock={2} onChange={onChange} />);

    const plus = screen.getByRole('button', { name: 'Increase quantity' });
    await userEvent.click(plus);
    await userEvent.click(plus);
    await userEvent.click(plus);

    expect(screen.getByText('2')).toBeInTheDocument();
    expect(plus).toBeDisabled();
    expect(onChange).toHaveBeenLastCalledWith(2);
  });
});

Mocking next/navigation

import { vi } from 'vitest';

const push = vi.fn();
vi.mock('next/navigation', () => ({
  useRouter: () => ({ push, replace: vi.fn(), refresh: vi.fn() }),
  usePathname: () => '/products',
  useSearchParams: () => new URLSearchParams('sort=price_asc'),
}));

// later: expect(push).toHaveBeenCalledWith('/search?q=redmi');