Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit abf0032

Browse files
committed
fix(@angular/build): correct Vitest builder watch mode execution
The experimental Vitest-based unit test builder did not always correctly re-run tests in watch mode. This commit refactors the Vitest executor to provide more accurate watch mode behavior by: - Disabling Vitest's internal file watcher (`watch: null`) to make the Angular builder's watcher the single source of truth. - Triggering a test run via `vitest.rerunTestSpecifications()` within the `execute` method after each incremental build is complete.
1 parent 557f7c2 commit abf0032

File tree

1 file changed

+39
-5
lines changed
  • packages/angular/build/src/builders/unit-test/runners/vitest

1 file changed

+39
-5
lines changed

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

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import type { InlineConfig, Vitest } from 'vitest/node';
1515
import { assertIsError } from '../../../../utils/error';
1616
import { loadEsmModule } from '../../../../utils/load-esm';
1717
import { toPosixPath } from '../../../../utils/path';
18-
import type{FullResult, IncrementalResult } from '../../../application/results';
18+
import {typeFullResult, typeIncrementalResult,ResultKind } from '../../../application/results';
1919
import { writeTestFiles } from '../../../karma/application_builder';
2020
import { NormalizedUnitTestBuilderOptions } from '../../options';
2121
import type { TestExecutor } from '../api';
@@ -40,20 +40,49 @@ export class VitestExecutor implements TestExecutor {
4040
await writeTestFiles(buildResult.files, this.outputPath);
4141

4242
this.latestBuildResult = buildResult;
43+
44+
// Initialize Vitest if not already present.
4345
this.vitest ??= await this.initializeVitest();
46+
const vitest = this.vitest;
47+
48+
let testResults;
49+
if (buildResult.kind === ResultKind.Incremental) {
50+
const addedFiles = buildResult.added.map((file) => path.join(this.outputPath, file));
51+
const modifiedFiles = buildResult.modified.map((file) => path.join(this.outputPath, file));
52+
53+
if (addedFiles.length === 0 && modifiedFiles.length === 0) {
54+
yield { success: true };
55+
56+
return;
57+
}
58+
59+
// If new files are added, use `start` to trigger test discovery.
60+
// Also pass modified files to `start` to ensure they are re-run.
61+
if (addedFiles.length > 0) {
62+
await vitest.start([...addedFiles, ...modifiedFiles]);
63+
} else {
64+
// For modified files only, use the more efficient `rerunTestSpecifications`
65+
const specsToRerun = modifiedFiles.flatMap((file) => vitest.getModuleSpecifications(file));
66+
67+
if (specsToRerun.length > 0) {
68+
modifiedFiles.forEach((file) => vitest.invalidateFile(file));
69+
testResults = await vitest.rerunTestSpecifications(specsToRerun);
70+
}
71+
}
72+
}
4473

4574
// Check if all the tests pass to calculate the result
46-
const testModules = this.vitest.state.getTestModules();
75+
const testModules = testResults?.testModules;
4776

48-
yield { success: testModules.every((testModule) => testModule.ok()) };
77+
yield { success: testModules?.every((testModule) => testModule.ok())??true };
4978
}
5079

5180
async [Symbol.asyncDispose](): Promise<void> {
5281
await this.vitest?.close();
5382
}
5483

5584
private async initializeVitest(): Promise<Vitest> {
56-
const { codeCoverage, reporters, watch,workspaceRoot, setupFiles, browsers, debug } =
85+
const { codeCoverage, reporters, workspaceRoot, setupFiles, browsers, debug, watch } =
5786
this.options;
5887
const { outputPath, projectName, latestBuildResult } = this;
5988

@@ -101,7 +130,7 @@ export class VitestExecutor implements TestExecutor {
101130

102131
return startVitest(
103132
'test',
104-
undefined/* cliFilters */,
133+
undefined,
105134
{
106135
// Disable configuration file resolution/loading
107136
config: false,
@@ -115,6 +144,11 @@ export class VitestExecutor implements TestExecutor {
115144
...debugOptions,
116145
},
117146
{
147+
server: {
148+
// Disable the actual file watcher. The boolean watch option above should still
149+
// be enabled as it controls other internal behavior related to rerunning tests.
150+
watch: null,
151+
},
118152
plugins: [
119153
{
120154
name: 'angular:project-init',

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /