Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): improve sourcemap fidelity during…
Browse files Browse the repository at this point in the history
… code-coverage

We now pass the input sourcemap to istanbul babel plugin, since this is used directly by the instrumenter https://github.com/istanbuljs/babel-plugin-istanbul/blob/d58c92a7de5e8ac84c598e02325b05f5b9800107/src/index.js#L126-L129 and is needed to remapped instrumented code back to the original source.

Previously, the lack of this caused incorrect reports of uncovered and coverage code and also incorrectly mappings in the HTML report.

Closes #22118

(cherry picked from commit 5990ed9)
  • Loading branch information
alan-agius4 authored and clydin committed Nov 9, 2021
1 parent ff4538e commit ef8815d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
Expand Up @@ -49,6 +49,7 @@ export interface ApplicationPresetOptions {
forceAsyncTransformation?: boolean;
instrumentCode?: {
includedBasePath: string;
inputSourceMap: unknown;
};
optimize?: {
looseEnums: boolean;
Expand Down Expand Up @@ -249,7 +250,10 @@ export default function (api: unknown, options: ApplicationPresetOptions) {
if (options.instrumentCode) {
plugins.push([
require('babel-plugin-istanbul').default,
{ inputSourceMap: false, cwd: options.instrumentCode.includedBasePath },
{
inputSourceMap: options.instrumentCode.inputSourceMap ?? false,
cwd: options.instrumentCode.includedBasePath,
},
]);
}

Expand Down
Expand Up @@ -73,7 +73,7 @@ export default custom<ApplicationPresetOptions>(() => {
});

return {
async customOptions(options, { source }) {
async customOptions(options, { source, map }) {
const { i18n, scriptTarget, aot, optimize, instrumentCode, ...rawOptions } =
options as AngularBabelLoaderOptions;

Expand Down Expand Up @@ -176,6 +176,7 @@ export default custom<ApplicationPresetOptions>(() => {
// `babel-plugin-istanbul` has it's own includes but we do the below so that we avoid running the the loader.
customOptions.instrumentCode = {
includedBasePath: instrumentCode.includedBasePath,
inputSourceMap: map,
};

shouldProcess = true;
Expand Down
Expand Up @@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import { tags } from '@angular-devkit/core';
import { last, tap } from 'rxjs/operators';
import { promisify } from 'util';
import { execute } from '../../index';
Expand Down Expand Up @@ -85,5 +86,36 @@ describeBuilder(execute, KARMA_BUILDER_INFO, (harness) => {
)
.toPromise();
});

it('should remapped instrumented code back to the original source', async () => {
await harness.modifyFile('src/app/app.component.ts', (content) => {
return content.replace(
`title = 'app'`,
tags.stripIndents`
title = 'app';
async foo() {
return 'foo';
}
`,
);
});

harness.useTarget('test', {
...BASE_OPTIONS,
codeCoverage: true,
});

const { result } = await harness.executeOnce();
expect(result?.success).toBeTrue();

await setTimeoutPromise(1000);

harness
.expectFile('coverage/app.component.ts.html')
.content.toContain(
'<span class="fstat-no" title="function not covered" >async </span>foo()',
);
});
});
});

0 comments on commit ef8815d

Please sign in to comment.