Migrate all automated tests in this repository from Jest to latest Vitest with no feature regressions, stable CI reports, and same or better local developer experience
- Monorepo with three active workspaces:
client,server,nestjs - Jest is used in all three workspaces through local scripts and dedicated config files
- Current usage footprint is large (
421Jest-related references in source and test files, across97files) - Current CI uploads
jest-junit-*.xmlartifacts and relies on per-workspacetest:ci - Root ESLint setup loads
eslint-plugin-jesttest recommendations
- Use phased migration with strict checkpoints
- Keep repository green after each phase
- Prefer adapter-compatible migration first (test runtime switch), then API cleanup
- Migrate workspace by workspace, not all at once
- Keep rollback path simple by limiting each pull request scope
- Create tracking issue and checklist for all steps in this document
- Freeze non-critical test refactors during migration window
- Define acceptance criteria
- all current test scripts have Vitest equivalents
- CI test jobs pass in all workspaces
- XML reports still published and consumed by report workflow
- no Jest runtime package remains in active dependencies
- Define branch strategy
- one umbrella branch for the migration
- optional child branches by workspace if team parallelizes
- Define rollback strategy
- each phase merged only after green CI
- keep isolated commits for dependency changes, config changes, and test API updates
- Build complete inventory of Jest touchpoints
- dependency graph (
jest,ts-jest,@types/jest,jest-environment-jsdom,jest-junit,jest-mock-axios) - config files (
client/jest.config.mjs,server/jest.config.mjs,nestjs/jest.config.mjs,nestjs/test/jest-e2e.json) - scripts in
package.jsonfiles - ESLint test plugin configuration
- CI workflow references to Jest output names
- dependency graph (
- Build test API usage inventory
- global APIs (
jest.fn,jest.spyOn,jest.mock, fake timers, reset helpers) - type usages (
jest.Mock,jest.mocked) - setup files and global matchers
- global APIs (
- Build workspace-specific complexity score
client: Next.js + jsdom + module mocks +jest-mock-axiosserver: Node + TypeScript transform + legacy backendnestjs: Node + Nest testing utilities + e2e config
- Lock expected command matrix for final validation
- root:
npm run lint,npm run test,npm run compile,npm run format - plus workspace-level targeted test runs during migration
- root:
- Choose Vitest version and lockfile policy
- Decide transform strategy for TypeScript in each workspace
- native Vitest + Vite transform where possible
- avoid keeping Jest-specific transform chain
- Decide coverage provider and reporter format parity
- Decide XML reporter replacement strategy for
jest-junit- select Vitest-compatible junit reporter
- preserve artifact naming or update workflows accordingly
- Decide lint strategy
- replace
eslint-plugin-jestwith Vitest-aware ruleset, or mixed mode during transition
- replace
- Decide test file naming policy
- keep current
.test/.specnames for minimal churn
- keep current
- Decide future approach for Nest e2e tests
- keep in Vitest as integration tests
- or keep separate runner temporarily with clear deprecation date
- Update root dependencies
- add Vitest core and shared helpers
- remove root Jest packages when no longer needed
- Add shared base Vitest config pattern
- either reusable root config module or per-workspace local configs extending shared defaults
- Update root lint config for test files
- switch from Jest plugin defaults to Vitest-aware defaults
- Update root scripts only if needed for monorepo ergonomics
- keep
turbo run testbehavior unchanged for contributors
- keep
- Regenerate lockfile and confirm deterministic install
- Replace Jest config with Vitest config compatible with Next.js client tests
- Recreate jsdom environment setup and test globals
- Migrate
setupJestfile naming and imports to Vitest-compatible setup - Replace Jest scripts in
client/package.jsontest,test:ci,test:watch,coverage
- Replace or adapt
jest-mock-axiosusage- evaluate native module mocking and spies first
- if replacement package is needed, add it explicitly
- Update test files in batches
- convert
jest.*runtime calls tovi.* - convert typed mocks from Jest types to Vitest types
- fix hoisting-sensitive mocks (
jest.mockpatterns)
- convert
- Run client tests repeatedly until green
- Ensure junit XML output generated for CI artifact upload
- Replace
server/jest.config.mjswith Vitest config for Node environment - Replace Jest scripts in
server/package.json - Convert server test runtime APIs from
jest.*tovi.* - Validate module resolution parity (
moduleDirectories, aliases, TS paths) - Validate timers and mocks behavior in legacy service tests
- Run server test suite and coverage commands
- Ensure CI XML report is emitted at expected path
- Replace
nestjs/jest.config.mjswith Vitest config - Replace
nestjs/test/jest-e2e.jsonstrategy- either merge into Vitest project config
- or split unit/integration projects in a single Vitest config
- Replace Jest scripts in
nestjs/package.json - Convert Nest unit tests from
jest.*tovi.* - Validate compatibility with Nest testing module patterns
- Rework debug script strategy (
test:debug) for Vitest runtime - Migrate e2e command to Vitest-equivalent workflow
- Ensure junit XML report is emitted at expected path
- Update
.github/workflows/pull_request.yml- keep per-workspace test jobs
- update artifact paths and names if reporter file names changed
- Update
.github/workflows/test_report.yml- replace any Jest-specific reporter assumptions
- ensure parsed reports still annotate PRs
- Update deploy workflow test command assumptions where relevant
- Validate that all workflows still run under current Node version policy
- Remove Jest-only types from tsconfig include/types if present
- Ensure Vitest globals typing configured per workspace or explicit imports used
- Remove obsolete Jest dependencies and config files
- Remove stale test setup filenames referencing Jest
- Remove dead helper code or mocks created only for Jest behavior
- Full local validation
npm run lintnpm run testnpm run compilenpm run format
- Spot-check changed tests for deterministic behavior
- fake timers
- async expectations
- module mocks
- Run CI on migration branch and verify all jobs green
- Compare test duration before/after and capture regression notes
- Compare coverage before/after and capture gaps
- Update contributor docs
- root
README.mdtesting section if needed CONTRIBUTING.mdtest commands and local workflow- workspace READMEs if they mention Jest
- root
- Add migration notes
- known incompatibilities
- new mocking patterns
- timer usage guidance
- Create follow-up backlog for non-blocking improvements
- optimize slow tests
- improve test isolation
- enforce new lint rules for Vitest patterns
- Work in small PRs with one phase or one workspace per PR
- Keep PRs reviewable (target under ~400 changed lines unless mechanical rename)
- Do not mix runtime migration with unrelated refactors
- After each PR, run full required checks and attach outputs
- If migration blocks on one workspace, ship completed workspace migrations first behind stable CI
- PR 1: root dependencies, lint plugin transition, shared Vitest base
- PR 2: client migration
- PR 3: server migration
- PR 4: nestjs migration including e2e strategy
- PR 5: CI/reporting cleanup and docs
- PR 6: final Jest removal and dead-code cleanup
- No active workspace uses Jest runtime commands
- No active workspace depends on Jest-only packages
- All local required commands pass at root
- CI test and reporting workflows pass with Vitest outputs
- Documentation reflects Vitest-based workflow
- Mock hoisting differences break tests
- mitigate with batch conversion and per-file verification
- Timer behavior differences create flaky tests
- mitigate by standardizing fake timer lifecycle in setup/teardown
- Next.js client transform differences cause import failures
- mitigate by validating module transform and alias mapping early in client phase
- Nest e2e behavior differs from Jest config assumptions
- mitigate by isolating e2e migration and validating with dedicated command before merge
- CI report parser mismatch after reporter switch
- mitigate by updating report workflow and testing artifact parsing in draft PR
- Hidden Jest references survive in tooling
- mitigate with final repository-wide scan for
jesttokens and config filenames
- mitigate with final repository-wide scan for
- Root dependencies switched to Vitest stack
- ESLint test rules updated for Vitest
- Client tests green on Vitest
- Server tests green on Vitest
- NestJS tests green on Vitest
- NestJS e2e path migrated or formally isolated with deadline
- CI test jobs green
- CI test reports parsed and published
- Jest configs removed
- Jest packages removed from lockfile and package manifests
- Root validation commands pass
- Documentation updated