Loading...
Loading...
Loading...
Jest and Vitest for unit and component tests. Learn setup, mocking, and best practices for frontend testing.
Both support React Testing Library and a similar API. Vitest is faster and ESM-first; Jest is the industry standard with more docs and examples.
Use describe/it (or test) and expect. For React, pair with React Testing Library and user-event for realistic interactions.
// sum.test.ts
import { sum } from './sum';
describe('sum', () => {
it('adds two numbers', () => {
expect(sum(1, 2)).toBe(3);
});
it('handles negatives', () => {
expect(sum(-1, 1)).toBe(0);
});
});
// Component test with React Testing Library
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Button } from './Button';
test('button calls onClick when clicked', async () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click me</Button>);
await userEvent.click(screen.getByRole('button', { name: /click me/i }));
expect(handleClick).toHaveBeenCalledTimes(1);
});Vitest reuses your Vite config. Enable globals for describe/it/expect, set environment to jsdom for DOM tests, and optionally add coverage.
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts'],
include: ['src/**/*.{test,spec}.{ts,tsx}'],
coverage: {
provider: 'v8',
reporter: ['text', 'html'],
exclude: ['node_modules/', '**/*.d.ts'],
},
},
resolve: {
alias: { '@': path.resolve(__dirname, './src') },
},
});Mock modules with vi.mock() and control return values with vi.fn().mockResolvedValue(). Same pattern works in both Jest and Vitest.
// Mocking a fetch module
import { vi } from 'vitest';
vi.mock('@/lib/api', () => ({
fetchUser: vi.fn().mockResolvedValue({
id: '1',
name: 'Jane Doe',
email: '[email protected]',
}),
}));
// In your test
import { fetchUser } from '@/lib/api';
import { render, screen } from '@testing-library/react';
import { UserProfile } from './UserProfile';
test('displays user name', async () => {
render(<UserProfile userId="1" />);
expect(await screen.findByText('Jane Doe')).toBeInTheDocument();
expect(fetchUser).toHaveBeenCalledWith('1');
});