Β· react
Setting Up Vitest for React and Next.js Applications
Setting up Vitest for your Next.js application is quick and easy. Learn how to configure Vitest with React Testing Library for fast component tests without the overhead of browser-based testing.
Ever wanted to test your Next.js components without the hassle of spinning up a full browser? Vitest makes it super easy. In this tutorial, you'll learn how to set up Vitest with React Testing Library for lightning-fast component tests that are easy to maintain.
Contents
- Why Vitest?
- Install Dependencies
- Configure Vitest
- Setup Test Environment
- Write Your First Test
- Add NPM Scripts
Why Vitest?
Vitest is a modern test runner built on top of Vite. It offers blazing-fast test execution with hot module replacement and native ESM support. When combined with React Testing Library, you get lightweight component testing without spinning up real browsers. This is perfect for smoke tests that verify your components render correctly.
Install Dependencies
To get started with Vitest, install the following development dependencies:
npm install --save-dev vitest @vitejs/plugin-react happy-dom \
@testing-library/react @testing-library/jest-domPackage breakdown:
-
vitest: The test runner itself, built on Vite for maximum speed. It provides a Jest-compatible API but with better performance and developer experience.
-
@vitejs/plugin-react: This plugin enables JSX and TSX transformation in your test files. Without it, Vitest wouldn't know how to handle React components.
-
happy-dom: A lightweight DOM implementation that's faster than jsdom. It provides enough DOM functionality for component rendering tests without the overhead of a real browser.
-
@testing-library/react: Provides utilities for rendering React components and querying the DOM in tests. It encourages testing from the user's perspective rather than implementation details.
-
@testing-library/jest-dom: Adds custom matchers like
toBeInTheDocument()andtoHaveTextContent()that make your test assertions more readable.
Configure Vitest
Create a vitest.config.ts file in your project root:
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
test: {
environment: 'happy-dom',
globals: true,
setupFiles: ['./vitest.setup.ts'],
},
resolve: {
alias: {
'@': path.resolve(__dirname, './'),
},
},
});Understanding the configuration:
-
The
pluginsarray includes the React plugin, which tells Vitest how to transform JSX and TSX files. Without this, your component imports would fail. -
The
test.environmentsetting specifies which DOM implementation to use. We're using happy-dom because it's significantly faster than jsdom while providing all the DOM APIs we need for component testing. -
Setting
test.globalstotruemeans you don't need to importdescribe,it, andexpectin every test file. They're automatically available globally, just like in Jest. -
The
setupFilesoption points to a file that runs before each test suite. This is where we'll load our custom matchers. -
The
resolve.aliasconfiguration allows you to use path aliases in your tests. This matches your Next.js tsconfig path mappings, so you can import using@/componentsinstead of relative paths.
Setup Test Environment
Create a vitest.setup.ts file:
import '@testing-library/jest-dom/vitest';This import is powerful as it extends Vitest's expect function with DOM-specific matchers. Instead of writing awkward assertions like expect(element !== null).toBe(true), you can write expect(element).toBeInTheDocument(). These matchers make your tests more readable and maintainable.
Write Your First Test
Let's create a test file for a Next.js page component. A good approach is to keep your test files in a dedicated __tests__ folder located outside the pages directory. If your test files sit in the same directories as your pages, the production build may fail with a message saying it βfound a page without a React component as the default export.β
import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import Home from './index';
describe('Home Page', () => {
it('renders all category cards', () => {
render(<Home />);
expect(screen.getByText('My Homepage')).toBeInTheDocument();
});
});This test verifies basic rendering. We use render() from React Testing Library to mount the component in our happy-dom environment. Then we use screen.getByText() to query for specific text content. The toBeInTheDocument() matcher confirms that each element exists in the rendered output.
Notice we're testing from the user's perspective by looking for visible text rather than checking implementation details like state or props. This behavior-driven approach creates tests that remain valid even when you refactor your components.
Add NPM Scripts
Update your package.json to add test commands:
{
"scripts": {
"test": "vitest run",
"test:watch": "vitest"
}
}The test script runs all tests once and exits. This is perfect for CI/CD pipelines where you want tests to complete and report results. The test:watch script runs Vitest in watch mode. It monitors your files for changes and automatically reruns affected tests. This gives you instant feedback while developing and is ideal for test-driven development workflows.
