Skip to content

Commit 318dd47

Browse files
committed
fix(@angular/build): adjust sourcemap sources when Vitest wrapper is bypassed
When code coverage is disabled, the Vitest builder bypasses the secondary import wrapper and serves the compiled output directly as the test file. This caused sourcemaps to be incorrect because the `sources` field in the map (relative to the build root) was being resolved relative to the test file's location. This commit adjusts the `sources` in the sourcemap to be relative to the test file's directory, ensuring correct source mapping in debuggers.
1 parent 09b791a commit 318dd47

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,11 @@ export async function createVitestConfigPlugin(
113113
delete config.plugins;
114114
}
115115

116-
// Add browser source map support
117-
if (browser || testConfig?.browser?.enabled) {
116+
// Add browser source map support if coverage is enabled
117+
if (
118+
(browser || testConfig?.browser?.enabled) &&
119+
(options.coverage.enabled || testConfig?.coverage?.enabled)
120+
) {
118121
projectPlugins.unshift(createSourcemapSupportPlugin());
119122
setupFiles.unshift('virtual:source-map-support');
120123
}
@@ -291,6 +294,17 @@ export function createVitestPlugins(pluginOptions: PluginOptions): VitestPlugins
291294
if (map) {
292295
if (!map.sources?.length && !map.sourcesContent?.length && !map.mappings) {
293296
map.sources = ['virtual:builder'];
297+
} else if (!vitestConfig.coverage.enabled && Array.isArray(map.sources)) {
298+
map.sources = (map.sources as string[]).map((source) => {
299+
if (source.startsWith('angular:')) {
300+
return source;
301+
}
302+
303+
// source is relative to the workspace root because the output file is at the root of the output.
304+
const absoluteSource = path.join(workspaceRoot, source);
305+
306+
return toPosixPath(path.relative(path.dirname(id), absoluteSource));
307+
});
294308
}
295309
}
296310

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import assert from 'node:assert/strict';
2+
import { applyVitestBuilder } from '../../utils/vitest';
3+
import { ng, noSilentNg } from '../../utils/process';
4+
import { writeFile } from '../../utils/fs';
5+
import { stripVTControlCharacters } from 'node:util';
6+
7+
export default async function (): Promise<void> {
8+
await applyVitestBuilder();
9+
await ng('generate', 'component', 'my-comp');
10+
11+
// Add a failing test to verify source map support
12+
await writeFile(
13+
'src/app/failing.spec.ts',
14+
`
15+
describe('Failing Test', () => {
16+
it('should fail', () => {
17+
expect(true).toBe(false);
18+
});
19+
});
20+
`,
21+
);
22+
23+
try {
24+
await noSilentNg('test', '--no-watch');
25+
throw new Error('Expected "ng test" to fail.');
26+
} catch (error: any) {
27+
const stdout = stripVTControlCharacters(error.stdout || error.message);
28+
// We expect the failure from failing.spec.ts
29+
assert.match(stdout, /1 failed/, 'Expected 1 test to fail.');
30+
// Check that the stack trace points to the correct file
31+
assert.match(
32+
stdout,
33+
/\bsrc[\/\\]app[\/\\]failing\.spec\.ts:4:\d+/,
34+
'Expected stack trace to point to the source file.',
35+
);
36+
}
37+
}

0 commit comments

Comments
 (0)