Set Up React Testing Library with Vitest
Configure React Testing Library with Vite and Vitest for fast component testing covering installation and test setup.
Objective
Configure a React project with Vitest and React Testing Library, write a component test that verifies rendering and interaction, and run it successfully with coverage reporting.
Environment
- Node.js 20+ with pnpm (or npm)
- Existing Vite + React project
- Terminal with shell access (bash/zsh/PowerShell)
Steps
1. Install testing dependencies
Add vitest, @testing-library/react, @testing-library/jest-dom, @testing-library/user-event, and jsdom as dev dependencies
Expected state: package.json includes vitest ^2.x, @testing-library/react ^16.x, @testing-library/jest-dom ^6.x in devDependencies
2. Configure Vitest
Add a test section to vite.config.ts (or create vitest.config.ts) with the React plugin and jsdom environment
Expected state: vite.config.ts has a test block: { environment: 'jsdom', globals: true, setupFiles: './src/test/setup.ts' }
3. Create test setup file
Create src/test/setup.ts to import '@testing-library/jest-dom/vitest' for extended matchers like toBeInTheDocument()
Expected state: src/test/setup.ts exists with the jest-dom import
4. Write your first component test
Create a test file that imports a simple React component, renders it, and asserts it appears in the document
Expected state: File src/components/__tests__/Counter.test.tsx exists and passes when vitest runs
5. Run tests
Execute vitest in run mode, then with --coverage
Expected state: Test output shows 1 passed, 1 total. Coverage report shows component coverage above 80%.
Decision points
Do you use TypeScript?
- Yes
- No
Yes — add @vitest/coverage-v8 and configure 'types: ["vitest/globals"]' in tsconfig.json
Do you need component snapshot testing?
- Yes, add @snaplet/snapshot or vitest snapshot
- No
No for new projects — prefer user-observable assertions over snapshots for maintainability.
Expected outcome
A working Vitest + RTL setup where `pnpm test` runs component tests and they pass correctly.
Verification
Run `pnpm test` in your project root. Expected: PASS with 1+ test case and coverage report.
Cleanup
Remove any test scaffold files you don't need. The configuration is additive and can remain.
Workflow Overview
You will set up React Testing Library (RTL) with Vitest in a Vite-based React project. The process takes about 20 minutes and requires only npm/pnpm commands and a few config file edits.
Step 1: Install Dependencies
pnpm add -D vitest @testing-library/react @testing-library/jest-dom \
@testing-library/user-event jsdom @vitest/coverage-v8
Verify in package.json that all packages appear in devDependencies.
Step 2: Configure Vitest
Update vite.config.ts:
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './src/test/setup.ts',
css: true,
},
});
Step 3: Create Setup File
Create src/test/setup.ts:
import '@testing-library/jest-dom/vitest';
This gives you matchers like toBeInTheDocument(), toHaveTextContent(), toBeEnabled().
Step 4: Write Your First Test
Create src/components/Counter.tsx:
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>;
}
Test it in src/components/__tests__/Counter.test.tsx:
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Counter } from '../Counter';
test('increments on click', async () => {
const user = userEvent.setup();
render(<Counter />);
const button = screen.getByRole('button');
expect(button).toHaveTextContent('Count: 0');
await user.click(button);
expect(button).toHaveTextContent('Count: 1');
});
Step 5: Run and Verify
pnpm test --run
# or with coverage:
pnpm test -- --coverage
Expected output:
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 15:42:01
Duration 1.23s
Troubleshooting
| Cause | Fix |
|---|---|
"document is not defined" |
Add environment: 'jsdom' to test config |
Cannot find module '@testing-library/react' |
Re-run pnpm install and check devDependencies |
toHaveTextContent is not a function |
Add setupFiles and confirm @testing-library/jest-dom/vitest import |
describe is not defined |
Set globals: true or import from vitest |