React · Lesson 12 of 15
Testing Components
Test behaviour with Vitest and Testing Library, not implementation details.
- Intermediate
- 17 min read
- 3 objectives
Before this lessonLesson 11: Suspense and Error Boundaries
What you will learn
- Render and query the DOM
- Fire user events
- Mock a fetch
Your Progress
0 of 15 lessons 0%
- Lessons0 / 15
- Completed0
- Est. time left~ 4 hours
Create a free account to keep your progress on every device.
Test what the user sees and does, not the internals of a hook. Vitest (or Jest) runs the tests; Testing Library renders components into a fake DOM and queries them the way a person would.
Setup
npm install -D vitest jsdom @testing-library/react @testing-library/user-event @testing-library/jest-dom// vitest.config.js
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
test: { environment: "jsdom", setupFiles: "./src/setupTests.js" },
});// src/setupTests.js
import "@testing-library/jest-dom/vitest";Render, query, click
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 />);
await user.click(screen.getByRole("button", { name: /add/i }));
expect(screen.getByText("1")).toBeInTheDocument();
});Prefer getByRole, getByLabelText and getByText over getByTestId. If a test cannot find a button by its name, neither can a screen reader.
Mocking the network
test("shows users", async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: async () => [{ id: 1, name: "Ada" }],
});
render(<Users />);
expect(await screen.findByText("Ada")).toBeInTheDocument();
});