Skip to content

Commit d90da47

Browse files
committed
fix(@angular/build): preserve custom config options in runnerConfig for vitest
Ensure optional Vitest configuration keys (such as `outputFile`, `cache`, and `testNamePattern`) are only defined on the inline options passed to `startVitest` if they are not `undefined`. This prevents Vitest's config merging from overriding user-defined custom configuration values in the runner configuration file with `undefined`.
1 parent a2346bf commit d90da47

2 files changed

Lines changed: 60 additions & 3 deletions

File tree

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,10 @@ export class VitestExecutor implements TestExecutor {
354354
config: externalConfigPath,
355355
root: workspaceRoot,
356356
project,
357-
outputFile,
358-
cache: cacheOptions.enabled ? undefined : (false as const),
359-
testNamePattern: this.options.filter,
360357
watch,
358+
...(outputFile !== undefined ? { outputFile } : {}),
359+
...(cacheOptions.enabled ? {} : { cache: false as const }),
360+
...(this.options.filter !== undefined ? { testNamePattern: this.options.filter } : {}),
361361
...(typeof ui === 'boolean' ? { ui } : {}),
362362
...debugOptions,
363363
};

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

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

45+
it('should use custom reporters and outputFile defined as an object in runnerConfig file', async () => {
46+
harness.useTarget('test', {
47+
...BASE_OPTIONS,
48+
runnerConfig: 'vitest.config.ts',
49+
});
50+
51+
harness.writeFile(
52+
'vitest.config.ts',
53+
`
54+
import { defineConfig } from 'vitest/config';
55+
export default defineConfig({
56+
test: {
57+
reporters: ['junit'],
58+
outputFile: {
59+
junit: './vitest-results-outputfile.xml',
60+
},
61+
},
62+
});
63+
`,
64+
);
65+
66+
const { result } = await harness.executeOnce();
67+
expect(result?.success).toBeTrue();
68+
harness.expectFile('vitest-results-outputfile.xml').toExist();
69+
});
70+
71+
it('should preserve custom coverage options (e.g. clean: false) from runnerConfig file', async () => {
72+
harness.useTarget('test', {
73+
...BASE_OPTIONS,
74+
runnerConfig: 'vitest.config.ts',
75+
coverage: true,
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+
clean: false,
86+
},
87+
},
88+
});
89+
`,
90+
);
91+
92+
// Create a placeholder file in the coverage directory before running the test
93+
harness.writeFile('coverage/test/placeholder-file.txt', 'do-not-delete');
94+
95+
const { result } = await harness.executeOnce();
96+
expect(result?.success).toBeTrue();
97+
// The builder outputs to coverage/test by default.
98+
// If clean: false is preserved, the placeholder-file.txt should still exist.
99+
harness.expectFile('coverage/test/placeholder-file.txt').toExist();
100+
});
101+
45102
it('should override reporters defined in runnerConfig file when CLI option is present', async () => {
46103
harness.useTarget('test', {
47104
...BASE_OPTIONS,

0 commit comments

Comments
 (0)