From c8126dc978d54f68d26edac1c404456c1d6d745e Mon Sep 17 00:00:00 2001 From: Keen Yee Liau Date: Tue, 8 Dec 2020 14:03:11 -0800 Subject: [PATCH] fix(@angular-devkit/build-angular): identify plugin provided as string Karma plugins could be provided either a string or object, but our detection logic for code coverage plugin only covers the string case. Fix #19571 --- .../src/karma/code-coverage_spec.ts | 15 ++++++++++++++ .../src/webpack/plugins/karma.ts | 20 +++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/karma/code-coverage_spec.ts b/packages/angular_devkit/build_angular/src/karma/code-coverage_spec.ts index ab92ac8fd261..381d8c5b2f94 100644 --- a/packages/angular_devkit/build_angular/src/karma/code-coverage_spec.ts +++ b/packages/angular_devkit/build_angular/src/karma/code-coverage_spec.ts @@ -169,4 +169,19 @@ describe('Karma Builder code coverage', () => { await run.stop(); }, 120000); + + it('is able to process coverage plugin provided as string', async () => { + host.replaceInFile('karma.conf.js', /plugins: \[.+?\]/s, `plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('@angular-devkit/build-angular/plugins/karma'), + 'karma-coverage', // instead of require('karma-coverage') + ]`); + const run = await architect.scheduleTarget(karmaTargetSpec, { codeCoverage: true }); + + const {success} = await run.result; + expect(success).toBe(true); + await run.stop(); + }, 120000); }); diff --git a/packages/angular_devkit/build_angular/src/webpack/plugins/karma.ts b/packages/angular_devkit/build_angular/src/webpack/plugins/karma.ts index 898d1363d512..c0e2c22907a4 100644 --- a/packages/angular_devkit/build_angular/src/webpack/plugins/karma.ts +++ b/packages/angular_devkit/build_angular/src/webpack/plugins/karma.ts @@ -93,8 +93,8 @@ const init: any = (config: any, emitter: any, customFileHandlers: any) => { config.plugins = config.plugins || []; config.reporters = config.reporters || []; const {plugins, reporters} = config; - const hasCoveragePlugin = plugins.some((p: {}) => 'reporter:coverage' in p); - const hasIstanbulPlugin = plugins.some((p: {}) => 'reporter:coverage-istanbul' in p); + const hasCoveragePlugin = plugins.some(isPlugin('karma-coverage', 'reporter:coverage')); + const hasIstanbulPlugin = plugins.some(isPlugin('karma-coverage-istanbul-reporter', 'reporter:coverage-istanbul')); const hasCoverageReporter = reporters.includes('coverage'); const hasIstanbulReporter = reporters.includes('coverage-istanbul'); if (hasCoveragePlugin && !hasCoverageReporter) { @@ -334,6 +334,22 @@ function fallbackMiddleware() { }; } +/** + * Returns a function that returns true if the plugin identifier matches the + * `moduleId` or `pluginName`. A plugin identifier can be either a string or + * an object according to https://karma-runner.github.io/5.2/config/plugins.html + * @param moduleId name of the node module (e.g. karma-coverage) + * @param pluginName name of the karma plugin (e.g. reporter:coverage) + */ +function isPlugin(moduleId: string, pluginName: string) { + return (plugin: string|{}): boolean => { + if (typeof plugin === 'string') { + return plugin === moduleId; + } + return pluginName in plugin; + } +} + module.exports = { 'framework:@angular-devkit/build-angular': ['factory', init], 'reporter:@angular-devkit/build-angular--sourcemap-reporter': ['type', sourceMapReporter],