A complete exercise: installation to the first test
This exercise tests a synchronous React component in a simulated DOM. Use a Node version supported by your installed packages. Merge these settings into an existing Vitest configuration so project aliases and plugins remain available.
1. Install dependencies and configure the environment
npm install -D vitest jsdom @vitejs/plugin-react @testing-library/react @testing-library/dom @testing-library/jest-dom @testing-library/user-event
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: { environment: 'jsdom', setupFiles: ['./test/setup.ts'] },
});
// test/setup.ts
import '@testing-library/jest-dom/vitest';
import { afterEach } from 'vitest';
import { cleanup } from '@testing-library/react';
afterEach(cleanup);
2. Test the behavior users see
Save this example as Counter.test.tsx. Locate the button by its role and accessible name, await the interaction, and then inspect the output. This checks behavior without depending on internal variable names.
// Counter.test.tsx
import { useState } from 'react';
import { describe, expect, it } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
describe('Counter', () => {
it('updates the count after a click', async () => {
const user = userEvent.setup();
render(<Counter />);
await user.click(screen.getByRole('button', { name: 'Count: 0' }));
expect(screen.getByRole('button', { name: 'Count: 1' })).toBeInTheDocument();
});
});
npx vitest run
Expect one passing test. Remove the setCount call temporarily to verify the test fails when the button stops working, then restore the code.
3. Diagnose common failures
- document is not defined: check that the test uses jsdom rather than only the Node environment.
- toBeInTheDocument is unavailable: check the jest-dom/vitest import and setupFiles path.
- An element cannot be found: inspect its accessible name and await asynchronous work before asserting.
This test does not prove browser layout, database integration, or every application flow is correct. Add integration or browser tests for those behaviors. Coverage highlights unexecuted paths; it does not guarantee meaningful assertions.
To choose testable boundaries, continue with frontend architecture.
References: Vitest, React Testing Library, user-event.