Skip to content

Commit 39d230e

Browse files
clydindgp1130
authored andcommitted
fix(@angular/build): keep Vite server file watcher disabled in Vitest watch mode
In Vitest 5, the internal `vitest:config:append` plugin uses a post `configResolved` hook that resets `server.watch` to `{}` when watch mode is enabled (`server.watch ??= {}`), overriding the `server: { watch: null }` setting passed in `vitestServerConfig`. This caused Vite to start a duplicate Chokidar file watcher alongside the Angular CLI build watcher and trigger redundant, racing test reruns on file changes. Enforce `post` ordering on `angular:vitest-configuration` and reset `config.server.watch = null` in a post `configResolved` hook so Vite uses its no-op watcher.
1 parent 0306faf commit 39d230e

3 files changed

Lines changed: 43 additions & 5 deletions

File tree

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -398,11 +398,6 @@ export class VitestExecutor implements TestExecutor {
398398
const vitestServerConfig = {
399399
// Note `.vitest` is auto appended to the path.
400400
cacheDir: cacheOptions.path,
401-
server: {
402-
// Disable the actual file watcher. The boolean watch option above should still
403-
// be enabled as it controls other internal behavior related to rerunning tests.
404-
watch: null,
405-
},
406401
plugins: [
407402
await createVitestConfigPlugin({
408403
browser: browserOptions.browser,

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,16 @@ export async function createVitestConfigPlugin(
164164

165165
return {
166166
name: 'angular:vitest-configuration',
167+
enforce: 'post',
168+
configResolved: {
169+
order: 'post',
170+
handler(config: Vite.ResolvedConfig) {
171+
// Vitest's internal post-configResolved hook resets `server.watch` to `{}` when
172+
// `watch` is enabled (`server.watch ??= {}`). Force it back to `null` so Vite uses
173+
// a no-op watcher and relies solely on the Angular CLI build watcher.
174+
config.server.watch = null;
175+
},
176+
},
167177
async config(config: UserWorkspaceConfig & Vite.UserConfig) {
168178
const testConfig = config.test;
169179

‎packages/angular/build/src/builders/unit-test/tests/options/watch_spec.ts‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,38 @@ describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
5555
},
5656
]);
5757
});
58+
59+
it('should disable the Vite server file watcher when watch is true', async () => {
60+
harness.useTarget('test', {
61+
...BASE_OPTIONS,
62+
watch: true,
63+
runnerConfig: 'vitest.config.mts',
64+
});
65+
66+
await harness.writeFile(
67+
'vitest.config.mts',
68+
`
69+
import { defineConfig } from 'vitest/config';
70+
export default defineConfig({
71+
plugins: [
72+
{
73+
name: 'assert-watch-disabled',
74+
configureVitest({ vitest, project }) {
75+
if (vitest.vite.config.server.watch !== null || project.vite.config.server.watch !== null) {
76+
throw new Error('Expected Vite server.watch to be null');
77+
}
78+
},
79+
},
80+
],
81+
});
82+
`,
83+
);
84+
85+
await harness.executeWithCases([
86+
({ result }) => {
87+
expect(result?.success).toBeTrue();
88+
},
89+
]);
90+
});
5891
});
5992
});

0 commit comments

Comments
 (0)