Skip to content

fix(frontend): guarantee JIT compiler in vitest runs to stop PlatformLocation flake#636

Merged
philmerrell merged 1 commit into
developfrom
fix/vitest-jit-compiler-flake
Jul 11, 2026
Merged

fix(frontend): guarantee JIT compiler in vitest runs to stop PlatformLocation flake#636
philmerrell merged 1 commit into
developfrom
fix/vitest-jit-compiler-flake

Conversation

@philmerrell

Copy link
Copy Markdown
Contributor

Problem

On a clean checkout, npm test in frontend/ai.client can fail in src/app/app.spec.ts with:

The injectable 'PlatformLocation' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available

raised from import('./app')@angular/router@angular/common _platform_location-chunk. Both tests in the file fail (module-level import failure). The failure is flaky and environment/timing dependent.

Root cause

  • @angular/build:unit-test builds specs with externalPackages: true, so @angular/* packages are never bundled/linked — vitest loads the raw npm fesm2022 files at runtime (_platform_location-chunk.mjs is a file shipped inside @angular/common 21.2).
  • Those shipped chunks contain partial declarations (ɵɵngDeclareInjectable/ɵɵngDeclareFactory) that compile eagerly at module evaluation via getCompilerFacade — they require @angular/compiler the moment the module is evaluated, not at first injection.
  • The compiler was only present incidentally: the builder's init-testbed setup imports @angular/core/testing, which transitively evaluates @angular/compiler. Nothing guarantees that ordering. app.spec.ts is uniquely exposed because it has no static Angular imports — when the evaluation order breaks, the whole file dies at import time.

Upstream reports of the same failure mode: angular/angular-cli#31993, angular/angular-cli#32095; the upstream remedy (angular/angular-cli#32304) is the same one applied here — guarantee the compiler is loaded.

Fix

  • src/test-setup.tsimport '@angular/compiler';, wired via the test target's setupFiles in angular.json, so the JIT fallback is an explicit invariant in every vitest worker instead of an accident of import order.
  • tsconfig.spec.json — includes the setup file in the spec TS program (the builder hard-errors otherwise).
  • src/test-setup.spec.ts — guard spec mirroring app.spec.ts's shape (no static Angular imports): asserts the compiler facade is registered and that an unlinked partial-declared injectable actually JIT-compiles. If the setup file is ever removed, this fails deterministically instead of the suite failing flakily.
  • shared-view.page.spec.ts — separate flake caught while soak-testing (1-in-9 full-suite runs): the file's first test pays the one-time dynamic page-chunk import and exceeded vitest's 5s default under parallel load (5011ms observed). Bumped that single test to 15s.

Verification

  • 5 consecutive full ng test runs green (126 files / 1449 tests) on the pinned dependency tree (npm ci), including cold-cache runs (.angular/cache + node_modules/.vite removed).
  • Confirmed setup-test-setup.js appears as a build entry point and runs before specs.
  • Failure mode reproduced directly during diagnosis: a probe spec declaring an unlinked partial injectable fails/passes exactly according to compiler availability.

🤖 Generated with Claude Code

…Location flake

The unit-test builder keeps Angular packages external, so vitest evaluates
raw fesm2022 chunks whose partial declarations (ɵɵngDeclareInjectable/
ɵɵngDeclareFactory) compile eagerly and require @angular/compiler. Its
presence was incidental — loaded transitively via @angular/core/testing in
the builder's init-testbed setup — so specs with no static Angular imports
(app.spec.ts dynamic-imports './app') could evaluate an unlinked
@angular/common chunk first and fail with "The injectable
'PlatformLocation' needs to be compiled using the JIT compiler, but
'@angular/compiler' is not available" (angular/angular-cli#31993).

- add src/test-setup.ts importing @angular/compiler, wired via the test
  target's setupFiles and included in tsconfig.spec.json
- add src/test-setup.spec.ts guarding the invariant deterministically
- bump the first shared-view.page spec to 15s: it pays the one-time
  dynamic page-chunk import, which can exceed 5s under full-suite load

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@philmerrell philmerrell merged commit 389e0dd into develop Jul 11, 2026
4 checks passed
@philmerrell philmerrell deleted the fix/vitest-jit-compiler-flake branch July 11, 2026 22:00
@philmerrell philmerrell mentioned this pull request Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant