ADR-006: Vitest for Web App Testing
ADR-006: Vitest for Web App Testing
Status: Accepted Date: 2024-12-15 Deciders: Platform architect
Context
The Next.js 14 web application needed a test runner for unit tests, component tests, and integration tests. The application uses TypeScript, ES modules, and path aliases (@/ imports).
Requirements:
- Native TypeScript support without separate compilation step
- ES module support (the project uses
"type": "module"patterns) - Fast execution for developer feedback loop
- Compatible with
@testing-library/reactfor component tests - Compatible with path aliases (
@/→src/)
Decision
Use Vitest as the test runner with @vitest/coverage-v8 for coverage reporting. Vitest shares Vite's transform pipeline, providing native TypeScript and ESM support without additional configuration.
Configuration lives in apps/web/vitest.config.ts with tests in src/__tests__/.
Alternatives Considered
1. Jest
The established standard for React testing. However, Jest's ESM support requires experimental flags and additional configuration (--experimental-vm-modules). TypeScript support requires ts-jest or @swc/jest transformer. Path alias support requires moduleNameMapper configuration. The overall setup is significantly more complex for a modern ESM TypeScript project.
2. Node.js built-in test runner
Available since Node.js 20. Lightweight but lacks the ecosystem: no built-in coverage, no snapshot testing, no watch mode with HMR, no TypeScript support without a separate transform step. Too minimal for a production application.
3. Bun test runner
Fast and TypeScript-native. Rejected because the project uses Node.js (not Bun) as the runtime, and Bun's test runner has compatibility gaps with some @testing-library features.
Consequences
Positive:
- Zero-config TypeScript and ESM support — Vitest uses Vite's transform pipeline
- Path aliases work via the
resolve.aliasconfig (shared with Vite) - Fast watch mode with HMR-based re-runs
- API-compatible with Jest (
describe,it,expect) — low migration cost if switching later @vitest/coverage-v8provides V8-based coverage without additional setup- Globals mode (
globals: true) allows importing test functions implicitly
Negative:
- Smaller ecosystem than Jest — some Jest plugins may not have Vitest equivalents
- Vitest configuration is separate from Next.js configuration (not shared with the dev server)
- Component tests require explicit
environment: "jsdom"configuration (the default isnode)
Risks:
- Vitest major version updates may introduce breaking changes. Mitigated by pinning the version and updating intentionally.