Skip to content

Commit 8d8ba4f

Browse files
committed
fix(@angular/build): allow overriding Vitest coverage reportsDirectory option
The Vitest `reportsDirectory` coverage option can now be customized via a `runnerConfig` configuration file.
1 parent 63c3e3f commit 8d8ba4f

File tree

2 files changed

+70
-12
lines changed

2 files changed

+70
-12
lines changed

packages/angular/build/src/builders/unit-test/runners/vitest/plugins.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,11 @@ export async function createVitestConfigPlugin(
154154

155155
return {
156156
test: {
157-
coverage: await generateCoverageOption(options.coverage, projectName),
157+
coverage: await generateCoverageOption(
158+
options.coverage,
159+
testConfig?.coverage,
160+
projectName,
161+
),
158162
// eslint-disable-next-line @typescript-eslint/no-explicit-any
159163
...(reporters ? ({ reporters } as any) : {}),
160164
projects: [projectConfig],
@@ -303,40 +307,44 @@ export function createVitestPlugins(pluginOptions: PluginOptions): VitestPlugins
303307
}
304308

305309
async function generateCoverageOption(
306-
coverage: NormalizedUnitTestBuilderOptions['coverage'],
310+
optionsCoverage: NormalizedUnitTestBuilderOptions['coverage'],
311+
configCoverage: VitestCoverageOption | undefined,
307312
projectName: string,
308313
): Promise<VitestCoverageOption> {
309314
let defaultExcludes: string[] = [];
310-
if (coverage.exclude) {
315+
if (optionsCoverage.exclude) {
311316
try {
312317
const vitestConfig = await import('vitest/config');
313318
defaultExcludes = vitestConfig.coverageConfigDefaults.exclude;
314319
} catch {}
315320
}
316321

317322
return {
318-
enabled: coverage.enabled,
319323
excludeAfterRemap: true,
324+
reportsDirectory:
325+
configCoverage?.reportsDirectory ?? toPosixPath(path.join('coverage', projectName)),
326+
...(optionsCoverage.enabled !== undefined ? { enabled: optionsCoverage.enabled } : {}),
320327
// Vitest performs a pre-check and a post-check for sourcemaps.
321328
// The pre-check uses the bundled files, so specific bundled entry points and chunks need to be included.
322329
// The post-check uses the original source files, so the user's include is used.
323-
...(coverage.include ? { include: ['spec-*.js', 'chunk-*.js', ...coverage.include] } : {}),
324-
reportsDirectory: toPosixPath(path.join('coverage', projectName)),
325-
thresholds: coverage.thresholds,
326-
watermarks: coverage.watermarks,
330+
...(optionsCoverage.include
331+
? { include: ['spec-*.js', 'chunk-*.js', ...optionsCoverage.include] }
332+
: {}),
333+
thresholds: optionsCoverage.thresholds,
334+
watermarks: optionsCoverage.watermarks,
327335
// Special handling for `exclude`/`reporters` due to an undefined value causing upstream failures
328-
...(coverage.exclude
336+
...(optionsCoverage.exclude
329337
? {
330338
exclude: [
331339
// Augment the default exclude https://vitest.dev/config/#coverage-exclude
332340
// with the user defined exclusions
333-
...coverage.exclude,
341+
...optionsCoverage.exclude,
334342
...defaultExcludes,
335343
],
336344
}
337345
: {}),
338-
...(coverage.reporters
339-
? ({ reporter: coverage.reporters } satisfies VitestCoverageOption)
346+
...(optionsCoverage.reporters
347+
? ({ reporter: optionsCoverage.reporters } satisfies VitestCoverageOption)
340348
: {}),
341349
};
342350
}

packages/angular/build/src/builders/unit-test/tests/behavior/runner-config-vitest_spec.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,56 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
4242
harness.expectFile('vitest-results.xml').toExist();
4343
});
4444

45+
it('should use custom reportsDirectory defined in runnerConfig file', async () => {
46+
harness.useTarget('test', {
47+
...BASE_OPTIONS,
48+
runnerConfig: 'vitest.config.ts',
49+
coverage: true,
50+
});
51+
52+
harness.writeFile(
53+
'vitest.config.ts',
54+
`
55+
import { defineConfig } from 'vitest/config';
56+
export default defineConfig({
57+
test: {
58+
coverage: {
59+
reportsDirectory: './custom-coverage-reports',
60+
},
61+
},
62+
});
63+
`,
64+
);
65+
66+
const { result } = await harness.executeOnce();
67+
expect(result?.success).toBeTrue();
68+
harness.expectFile('custom-coverage-reports/coverage-final.json').toExist();
69+
});
70+
71+
it('should use default reportsDirectory when not defined in runnerConfig file', async () => {
72+
harness.useTarget('test', {
73+
...BASE_OPTIONS,
74+
coverage: true,
75+
runnerConfig: 'vitest.config.ts',
76+
});
77+
78+
harness.writeFile(
79+
'vitest.config.ts',
80+
`
81+
import { defineConfig } from 'vitest/config';
82+
export default defineConfig({
83+
test: {
84+
coverage: {},
85+
},
86+
});
87+
`,
88+
);
89+
90+
const { result } = await harness.executeOnce();
91+
expect(result?.success).toBeTrue();
92+
harness.expectFile('coverage/test/coverage-final.json').toExist();
93+
});
94+
4595
it('should exclude test files based on runnerConfig file', async () => {
4696
harness.useTarget('test', {
4797
...BASE_OPTIONS,

0 commit comments

Comments
 (0)