Skip to content

Commit edeb41c

Browse files
committed
fix(@angular/build): ensure tests run when compilation error is resolved
This commit fixes an issue in the Vitest unit test runner where tests would sometimes fail to re-run after a compilation error was resolved in watch mode. The issue occurred because the incremental build result's `added` files were not being included in the list of modified files passed to the test runner. When a file had a compilation error, it might be treated as "added" in the subsequent successful build, and previously it was ignored. A new regression test has been added to `packages/angular/build/src/builders/unit-test/tests/behavior/watch_rebuild_spec.ts` to verify that tests are correctly re-run when a compilation error is fixed, even if a test failure is introduced simultaneously.
1 parent 5119d75 commit edeb41c

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export class VitestExecutor implements TestExecutor {
9090
if (buildResult.kind === ResultKind.Incremental) {
9191
// To rerun tests, Vitest needs the original test file paths, not the output paths.
9292
const modifiedSourceFiles = new Set<string>();
93-
for (const modifiedFile of buildResult.modified) {
93+
for (const modifiedFile of [...buildResult.modified, ...buildResult.added]) {
9494
// The `modified` files in the build result are the output paths.
9595
// We need to find the original source file path to pass to Vitest.
9696
const source = this.entryPointToTestFile.get(modifiedFile);
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import { execute } from '../../index';
10+
import {
11+
BASE_OPTIONS,
12+
describeBuilder,
13+
UNIT_TEST_BUILDER_INFO,
14+
setupApplicationTarget,
15+
} from '../setup';
16+
17+
describeBuilder(execute, UNIT_TEST_BUILDER_INFO, (harness) => {
18+
describe('Watch Mode Behavior', () => {
19+
beforeEach(async () => {
20+
setupApplicationTarget(harness);
21+
});
22+
23+
it('should run tests when a compilation error is fixed and a test failure is introduced simultaneously', async () => {
24+
harness.useTarget('test', {
25+
...BASE_OPTIONS,
26+
watch: true,
27+
});
28+
29+
await harness.executeWithCases([
30+
// 1. Initial success
31+
({ result }) => {
32+
expect(result?.success).toBeTrue();
33+
34+
// 2. Introduce compilation error
35+
harness.writeFiles({
36+
'src/app/app.component.spec.ts': `
37+
import { describe, expect, test } from 'vitest'
38+
describe('AppComponent', () => {
39+
test('should create the app', () => {
40+
expect(true).toBe(true); // Syntax error incoming
41+
const x: string = 1; // Type error
42+
});
43+
});`,
44+
});
45+
},
46+
// 3. Expect compilation error
47+
({ result }) => {
48+
expect(result?.success).toBeFalse();
49+
50+
// 4. Fix compilation error BUT introduce test failure
51+
harness.writeFiles({
52+
'src/app/app.component.spec.ts': `
53+
import { describe, expect, test } from 'vitest'
54+
describe('AppComponent', () => {
55+
test('should create the app', () => {
56+
expect(true).toBe(false); // Logic failure
57+
});
58+
});`,
59+
});
60+
},
61+
// 5. Expect test failure (NOT success, which would happen if the test was skipped)
62+
({ result }) => {
63+
expect(result?.success).toBeFalse();
64+
},
65+
]);
66+
});
67+
});
68+
});

0 commit comments

Comments
 (0)