# 0003 — Vitest in libs and overlay, Jest in API - **Status:** Accepted - **Date:** 2026-05-06 ## Context and problem statement The Nx workspace contains an Angular frontend, a NestJS backend, and three TypeScript libraries. Each subsystem has different test runner support in current Nx generators. Should the workspace standardise on a single runner, accept mixed runners, or prioritise tooling alignment over uniformity? ## Decision drivers - **Generator support.** Forcing a non-default runner means working against the grain of the Nx generator and maintaining custom configuration. - **Speed.** Vitest is meaningfully faster than Jest for monorepo work. - **Ecosystem fit.** Angular 21 made Vitest the official default. NestJS examples and community resources still assume Jest. - **Test isolation.** API tests and frontend tests rarely run in the same breath; the cost of a mixed setup is mostly cognitive, not operational. - **Future migration cost.** If we standardise wrong now, the cost of switching later is non-trivial — Jest and Vitest mock semantics differ subtly. ## Considered options 1. **Jest everywhere.** Use the API's default and force Jest into the libs and overlay. 2. **Vitest everywhere.** Force Vitest into the API by manually configuring it after the Nx Nest generator runs. 3. **Mixed: Vitest in libs and overlay, Jest in API.** Use each subsystem's native default. 4. **Vitest in shared libs, Jest in both apps.** Compromise position. ## Decision outcome **Chosen: Mixed — Vitest in libs and overlay, Jest in API.** The Nx Nest generator (`@nx/nest:application`) only supports `jest` and `none` for its `unitTestRunner` option in the version we're using. The Angular generator (`@nx/angular:application`) supports `vitest-angular` (the official Angular Vitest integration) and uses it as the default. The plain JS library generator (`@nx/js:library`) supports both; we chose Vitest there for consistency with the overlay. Working with the generator defaults avoids fighting the tooling. The cost — two test runners in one workspace — is small in practice because: - Nx's `run-many --target=test` runs both transparently. - Property-based tests (`fast-check`) work identically in both. - Mock semantics differ slightly, but the differences only matter at the test author level, and shared libs use one runner consistently. ## Consequences ### Positive - Each generator runs cleanly with default flags — minimal custom configuration. - Vitest gives us fast feedback on the overlay and shared libs (the parts most under iteration). - Jest gives us battle-tested Nest testing utilities (`Test.createTestingModule`, `getRepositoryToken`, etc.) without translation. - When `@nx/nest` adds first-class Vitest support (likely a future Nx version), migration is contained to one project. ### Negative - Two sets of test config files (`jest.config.cts` for API, `vitest.config.mts` for libs and overlay). - Onboarding requires explaining the split. - A test utility that targets one runner can't be trivially shared to projects using the other. ### Neutral - This decision should be revisited when `@nx/nest` ships native Vitest support, or when the Nest community shifts decisively to Vitest. Track in `PROJECT_CONTEXT.md` "Open decisions" section.