Description
When using `@angular/build:unit-test` executor with vitest v8 coverage provider, code coverage always reports 0% for application source files. Library packages imported via `node_modules` (external packages) correctly show coverage.
Root Cause
PR #31615 fixed this issue for `@angular-devkit/build-angular` by patching `BaseCoverageProvider.prototype.isIncluded` to handle in-memory virtual files generated by the esbuild build process. However, this fix was never applied to the `@angular/build` package, which has its own separate unit-test builder implementation.
The `@angular/build:unit-test` executor bundles test files and their dependencies via esbuild into `chunk-.js` / `spec-.js` virtual files. The v8 coverage provider's `isIncluded()` method checks for physical file existence (`existsSync`), which fails for these in-memory files, causing them to be excluded from coverage analysis.
Key findings from debugging:
- Source maps are correct - esbuild generates source maps with proper `sources` paths pointing to original `.ts` files
- Source map remapping works - when chunks pass `isIncluded`, the `coverageMap` correctly contains 484 files (417 after filtering virtual-only entries)
- `isIncluded` is the bottleneck - without the patch, virtual chunk files are silently excluded
Reproduction
```bash
Using @angular/build:unit-test with vitest runner
ng test --coverage
Result: All files | 0 | 0 | 0 | 0
```
Environment:
- `@angular/build`: 21.1.5 (also confirmed on 21.2.x)
- `vitest`: 4.x
- `@vitest/coverage-v8`: 4.x
Expected Behavior
The same `isIncluded` patch from PR #31615 should be applied to `@angular/build`'s unit-test builder.
Workaround
Manually patching `node_modules/@angular/build/src/builders/unit-test/runners/vitest/executor.js` to override `BaseCoverageProvider.prototype.isIncluded` to always include virtual/in-memory build result files.
Result after patch: `All files | 35.63 | 33.59 | 22.81 | 35.54`
Related Issues
Description
When using `@angular/build:unit-test` executor with vitest v8 coverage provider, code coverage always reports 0% for application source files. Library packages imported via `node_modules` (external packages) correctly show coverage.
Root Cause
PR #31615 fixed this issue for `@angular-devkit/build-angular` by patching `BaseCoverageProvider.prototype.isIncluded` to handle in-memory virtual files generated by the esbuild build process. However, this fix was never applied to the `@angular/build` package, which has its own separate unit-test builder implementation.
The `@angular/build:unit-test` executor bundles test files and their dependencies via esbuild into `chunk-.js` / `spec-.js` virtual files. The v8 coverage provider's `isIncluded()` method checks for physical file existence (`existsSync`), which fails for these in-memory files, causing them to be excluded from coverage analysis.
Key findings from debugging:
Reproduction
```bash
Using @angular/build:unit-test with vitest runner
ng test --coverage
Result: All files | 0 | 0 | 0 | 0
```
Environment:
Expected Behavior
The same `isIncluded` patch from PR #31615 should be applied to `@angular/build`'s unit-test builder.
Workaround
Manually patching `node_modules/@angular/build/src/builders/unit-test/runners/vitest/executor.js` to override `BaseCoverageProvider.prototype.isIncluded` to always include virtual/in-memory build result files.
Result after patch: `All files | 35.63 | 33.59 | 22.81 | 35.54`
Related Issues