From 8c8377fee4999266f4e58bf3c3091100d4393df7 Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Tue, 8 Feb 2022 11:35:19 +0100 Subject: [PATCH] fix(@angular-devkit/build-angular): block Karma from starting until build is complete This change is inspired by https://github.com/karma-runner/karma-chrome-launcher/issues/154#issuecomment-986661937 which blocks Karma from launching the browsers until the compilation is complete. This is needed especially for large applications when using code-coverage where otherwise the users would have to fine-tune several Karma timeouts such as `captureTimeout` for various environments. Closes #22495 (cherry picked from commit 7ce50002a20373d494f08bfb36e7773b39263dba) --- .../src/webpack/plugins/karma/karma.ts | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/webpack/plugins/karma/karma.ts b/packages/angular_devkit/build_angular/src/webpack/plugins/karma/karma.ts index 892d61e30802..8feb3c4415ec 100644 --- a/packages/angular_devkit/build_angular/src/webpack/plugins/karma/karma.ts +++ b/packages/angular_devkit/build_angular/src/webpack/plugins/karma/karma.ts @@ -169,6 +169,12 @@ const init: any = (config: any, emitter: any) => { compiler.hooks.watchRun.tapAsync('karma', (_: any, callback: () => void) => handler(callback)); compiler.hooks.run.tapAsync('karma', (_: any, callback: () => void) => handler(callback)); + webpackMiddleware = webpackDevMiddleware(compiler, webpackMiddlewareConfig); + emitter.on('exit', (done: any) => { + webpackMiddleware.close(); + done(); + }); + function unblock() { isBlocked = false; blocked.forEach((cb) => cb()); @@ -176,22 +182,29 @@ const init: any = (config: any, emitter: any) => { } let lastCompilationHash: string | undefined; - compiler.hooks.done.tap('karma', (stats) => { - if (stats.hasErrors()) { - lastCompilationHash = undefined; - } else if (stats.hash != lastCompilationHash) { - // Refresh karma only when there are no webpack errors, and if the compilation changed. - lastCompilationHash = stats.hash; - emitter.refreshFiles(); - } - unblock(); - }); + let isFirstRun = true; + + return new Promise((resolve) => { + compiler.hooks.done.tap('karma', (stats) => { + if (isFirstRun) { + // This is needed to block Karma from launching browsers before Webpack writes the assets in memory. + // See the below: + // https://github.com/karma-runner/karma-chrome-launcher/issues/154#issuecomment-986661937 + // https://github.com/angular/angular-cli/issues/22495 + isFirstRun = false; + resolve(); + } - webpackMiddleware = webpackDevMiddleware(compiler, webpackMiddlewareConfig); + if (stats.hasErrors()) { + lastCompilationHash = undefined; + } else if (stats.hash != lastCompilationHash) { + // Refresh karma only when there are no webpack errors, and if the compilation changed. + lastCompilationHash = stats.hash; + emitter.refreshFiles(); + } - emitter.on('exit', (done: any) => { - webpackMiddleware.close(); - done(); + unblock(); + }); }); };