Setting Up Vitest & Cypress in a React + Vite Project
Modern front-end development requires fast feedback for developers and reliable end-to-end testing for production confidence. That's why pairing Vitest (for lightning-fast unit and component testing) with Cypress (for real browser end-to-end testing) is a killer combo.
In this guide, we'll set up both in a React + Vite + TypeScript project.
๐ 1. Create a React + Vite Project
If you don't already have a project:
pnpm create vite@latest my-app --template react-ts
cd my-app
pnpm install
Pro Tip
Using pnpm for faster installs and better disk space management!
๐จ 2. Install & Configure Tailwind (Optional but Recommended)
If you want a clean UI quickly:
pnpm add -D tailwindcss postcss autoprefixer
pnpm exec tailwindcss init -p
Configure Tailwind
In tailwind.config.js:
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: { extend: {} },
plugins: [],
};
In src/index.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
โก 3. Set Up Vitest for Unit & Component Testing
Why Vitest?
Vitest is blazing fast because it reuses Vite's config and runs tests in parallel with smart caching.
Install Vitest & Testing Library:
pnpm add -D vitest @testing-library/react @testing-library/jest-dom jsdom
Update Vite Config
Update vite.config.ts:
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",
},
});
Setup Test Environment
Create src/test/setup.ts:
import "@testing-library/jest-dom";
Add a Sample Test
Create src/App.test.tsx:
import { render, screen } from "@testing-library/react";
import App from "./App";
test("renders app component", () => {
render(<App />);
expect(screen.getByText(/vite/i)).toBeInTheDocument();
});
Run Tests
pnpm exec vitest
Expected Output: You should see your tests running in watch mode with instant feedback on file changes.
๐ 4. Set Up Cypress for E2E Testing
Why Cypress?
Cypress runs tests in a real browser, giving you confidence that your app works exactly as users experience it.
Install Cypress:
pnpm add -D cypress
Run the installer (downloads the Electron binary):
pnpm exec cypress install
Configure Cypress
Add cypress.config.ts:
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
baseUrl: "http://localhost:5173",
supportFile: "src/test/cypress/support/e2e.ts",
specPattern: "src/test/cypress/e2e/**/*.cy.{js,ts,jsx,tsx}",
},
});
Create Folder Structure
src/test/cypress/
โโโ e2e/
โ โโโ home.cy.ts
โโโ support/
โโโ e2e.ts
โโโ commands.ts
Add E2E Test
src/test/cypress/e2e/home.cy.ts:
describe("Home Page", () => {
it("loads successfully", () => {
cy.visit("/");
cy.contains("Vite").should("exist");
});
});
Run Cypress
GUI Mode (recommended for development):
pnpm exec cypress open
Headless Mode (for CI):
pnpm exec cypress run
๐ 5. Scripts for Convenience
Add these to your package.json:
{
"scripts": {
"test:unit": "vitest",
"test:unit:watch": "vitest --watch",
"test:e2e": "cypress run",
"test:e2e:gui": "cypress open"
}
}
๐งช Testing Workflow
1
Run
pnpm test:unit:watch
while developing
2
Use
pnpm test:e2e:gui
to debug E2E tests
3
Run
pnpm test:e2e
before deployment
๐ 6. Where to Go Next?
๐ก Mock APIs
Set up MSW (Mock Service Worker) for reliable API testing in Vitest
๐ Auth Testing
Protect routes and test authentication flows with Cypress
๐ CI/CD Integration
Set up GitHub Actions to run both test suites on every PR
>๐ญ Final Thoughts
Makes unit/component tests blazing fast and DX-friendly.
Runs your app in a real browser, testing actual user flows.
They cover your testing pyramid: Unit โ Integration โ E2E.
Ship features confidently: test small pieces with Vitest and verify full flows with Cypress.
View GitHub Repository โ