From 5469999bd98183c744473c4a9d4f005212bd9153 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Fri, 23 Jan 2026 21:09:26 -0500 Subject: [PATCH] refactor(@angular/build): avoid secondary import wrapper in Vitest unless coverage is enabled This commit optimizes the Vitest test runner by removing the secondary import wrapper for test entry points when code coverage is not enabled. The wrapper is only necessary to support coverage exclusion of the test files themselves. By capturing the resolved Vitest configuration within the `configureVitest` hook, the plugin can now determine if coverage is enabled and conditionally apply the wrapper. This simplifies the module graph for standard test runs. --- .../unit-test/runners/vitest/plugins.ts | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts index 4bd6666250e7..710d28c8103d 100644 --- a/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts +++ b/packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts @@ -14,6 +14,7 @@ import path from 'node:path'; import type { BrowserConfigOptions, InlineConfig, + ResolvedConfig, UserWorkspaceConfig, VitestPlugin, } from 'vitest/node'; @@ -185,11 +186,15 @@ async function loadResultFile(file: ResultFile): Promise { export function createVitestPlugins(pluginOptions: PluginOptions): VitestPlugins { const { workspaceRoot, buildResultFiles, testFileToEntryPoint } = pluginOptions; const isWindows = platform() === 'win32'; + let vitestConfig: ResolvedConfig; return [ { name: 'angular:test-in-memory-provider', enforce: 'pre', + configureVitest(context) { + vitestConfig = context.vitest.config; + }, resolveId: (id, importer) => { // Fast path for test entry points. if (testFileToEntryPoint.has(id)) { @@ -248,7 +253,7 @@ export function createVitestPlugins(pluginOptions: PluginOptions): VitestPlugins // If the module cannot be resolved from the build artifacts, let other plugins handle it. return undefined; }, - load: async (id) => { + async load(id) { assert(buildResultFiles.size > 0, 'buildResult must be available for in-memory loading.'); // Attempt to load as a source test file. @@ -257,11 +262,14 @@ export function createVitestPlugins(pluginOptions: PluginOptions): VitestPlugins if (entryPoint) { outputPath = entryPoint + '.js'; - // To support coverage exclusion of the actual test file, the virtual - // test entry point only references the built and bundled intermediate file. - return { - code: `import "./${outputPath}";`, - }; + if (vitestConfig.coverage.enabled) { + // To support coverage exclusion of the actual test file, the virtual + // test entry point only references the built and bundled intermediate file. + // If vitest supported an "excludeOnlyAfterRemap" option, this could be removed completely. + return { + code: `import "./${outputPath}";`, + }; + } } else { // Attempt to load as a built artifact. const relativePath = path.relative(workspaceRoot, id);