Add unit testing support to a React project using Vite and Typescript
If you want to test your components in a React + Vite project, the best way is using React Testing Library. This allows you to render your component with different props, interact with it and do assertions on the final output.
To get it set up, you first need to install vitest
- this will run the actual tests:
npm install -D vitest
Next, you'll need to install React Testing Library. Since the components will be rendered in a Node context, you need to install jsdom
, which emulates the browser DOM for test purposes:
npm install -D @testing-library/react @testing-library/jest-dom jsdom
Next, we need to configure how we want vitest
to run our tests. We can do that in the vite.config.ts
file:
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// [https://vitejs.dev/config/](https://vitejs.dev/config/)
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./src/setupTests.ts'],
},
});
globals: true
allows us to use describe
, test
and it
statements in our code without having to first import them - great to keep the code concise!
We also linked to a test config file - we need this to configure React Testing Library custom assertions, like expect(...).toBeInTheDocument()
. Let's create the file:
// src/setupTests.ts
import * as matchers from '@testing-library/jest-dom/matchers';
import { expect } from 'vitest';
expect.extend(matchers);
All right, now we're almost ready to run our first test - let's add the test
script to package.json
:
// package.json
{
...
"scripts": {
...
"test": "vitest"
},
...
}
When creating tests in React, it's common to place them under a __tests__
folder, in the same location as the component we are testing.
Let's create a test for the App
component that the Vite boilerplate comes with:
// src/__tests/App.test.tsx
import { render, screen } from "@testing-library/react";
import App from "../App";
describe("App", () => {
it("renders the demo Vite text", () => {
render(<App />);
expect(screen.getByText("Vite + React")).toBeInTheDocument();
});
});
If we now run npm run test
in the console, we'll see our test passes:

But our entire test file is red! Why is that?
Even if we configured globals:true
in the Vite config file, Typescript still does not know of that. We need to update the tsconfig.app.json
file to also recognise these globals:
{
"compilerOptions": {
...
"types": ["vitest/globals", "@testing-library/jest-dom"]
},
...
}
With this change in place, the red lines are gone and we can write unit tests in our app 💪
Member discussion