# 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.
