From 7eb080362ffdb137c00cb0572f50a7664db807de Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 28 Aug 2018 22:50:25 +0200 Subject: [PATCH] fix(@angular-devkit/build-angular): only collect coverage from files under `sourceRoot` (#11974) In some cases when having libraries within the workspace this is causing a `Maximum call stack size exceeded`, Also for libraries coverage should be collected with the respective `ng test` Closes #11934 --- .../angular-cli-files/models/build-options.ts | 1 + .../models/webpack-configs/test.ts | 6 ++- .../build_angular/src/karma/index.ts | 6 ++- .../test/karma/code-coverage_spec_large.ts | 48 +++++++++++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/models/build-options.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/models/build-options.ts index a81e728e45de..4dac5449818a 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/models/build-options.ts +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/models/build-options.ts @@ -74,6 +74,7 @@ export interface WebpackTestOptions extends BuildOptions { export interface WebpackConfigOptions { root: string; projectRoot: string; + sourceRoot?: string; buildOptions: T; tsConfig: ts.ParsedCommandLine; tsConfigPath: string; diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/test.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/test.ts index 9a2c6bf10945..4c8b05aa6008 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/test.ts +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/test.ts @@ -23,7 +23,7 @@ import { WebpackConfigOptions, WebpackTestOptions } from '../build-options'; export function getTestConfig( wco: WebpackConfigOptions, ): webpack.Configuration { - const { root, buildOptions } = wco; + const { root, buildOptions, sourceRoot: include } = wco; const extraRules: webpack.Rule[] = []; const extraPlugins: webpack.Plugin[] = []; @@ -46,10 +46,12 @@ export function getTestConfig( } extraRules.push({ - test: /\.(js|ts)$/, loader: 'istanbul-instrumenter-loader', + test: /\.(js|ts)$/, + loader: 'istanbul-instrumenter-loader', options: { esModules: true }, enforce: 'post', exclude, + include, }); } diff --git a/packages/angular_devkit/build_angular/src/karma/index.ts b/packages/angular_devkit/build_angular/src/karma/index.ts index f12b29015c5a..df1138edc85a 100644 --- a/packages/angular_devkit/build_angular/src/karma/index.ts +++ b/packages/angular_devkit/build_angular/src/karma/index.ts @@ -71,11 +71,13 @@ export class KarmaBuilder implements Builder { karmaOptions.browsers = options.browsers.split(','); } + const sourceRoot = builderConfig.sourceRoot && resolve(root, builderConfig.sourceRoot); + karmaOptions.buildWebpack = { root: getSystemPath(root), projectRoot: getSystemPath(projectRoot), options: options as NormalizedKarmaBuilderSchema, - webpackConfig: this._buildWebpackConfig(root, projectRoot, host, + webpackConfig: this._buildWebpackConfig(root, projectRoot, sourceRoot, host, options as NormalizedKarmaBuilderSchema), // Pass onto Karma to emit BuildEvents. successCb: () => obs.next({ success: true }), @@ -108,6 +110,7 @@ export class KarmaBuilder implements Builder { private _buildWebpackConfig( root: Path, projectRoot: Path, + sourceRoot: Path | undefined, host: virtualFs.Host, options: NormalizedKarmaBuilderSchema, ) { @@ -130,6 +133,7 @@ export class KarmaBuilder implements Builder { wco = { root: getSystemPath(root), projectRoot: getSystemPath(projectRoot), + sourceRoot: sourceRoot && getSystemPath(sourceRoot), // TODO: use only this.options, it contains all flags and configs items already. buildOptions: compatOptions, tsConfig, diff --git a/packages/angular_devkit/build_angular/test/karma/code-coverage_spec_large.ts b/packages/angular_devkit/build_angular/test/karma/code-coverage_spec_large.ts index b67d3d41108e..8440e1143420 100644 --- a/packages/angular_devkit/build_angular/test/karma/code-coverage_spec_large.ts +++ b/packages/angular_devkit/build_angular/test/karma/code-coverage_spec_large.ts @@ -56,4 +56,52 @@ describe('Karma Builder code coverage', () => { }), ).toPromise().then(done, done.fail); }, 120000); + + it(`should collect coverage from paths in 'sourceRoot'`, (done) => { + const overrides: Partial = { codeCoverage: true }; + + const files: { [path: string]: string } = { + './dist/my-lib/index.d.ts': ` + export declare const title = 'app'; + `, + './dist/my-lib/index.js': ` + export const title = 'app'; + `, + './src/app/app.component.ts': ` + import { Component } from '@angular/core'; + import { title } from 'my-lib'; + + @Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] + }) + export class AppComponent { + title = title; + } + `, + }; + + host.writeMultipleFiles(files); + + host.replaceInFile('tsconfig.json', /"baseUrl": ".\/",/, ` + "baseUrl": "./", + "paths": { + "my-lib": [ + "./dist/my-lib" + ] + }, + `); + + runTargetSpec(host, karmaTargetSpec, overrides).pipe( + // It seems like the coverage files take a while being written to disk, so we wait 500ms here. + debounceTime(500), + tap(buildEvent => { + expect(buildEvent.success).toBe(true); + expect(host.scopedSync().exists(coverageFilePath)).toBe(true); + const content = virtualFs.fileBufferToString(host.scopedSync().read(coverageFilePath)); + expect(content).not.toContain('my-lib'); + }), + ).toPromise().then(done, done.fail); + }, 120000); });