@@ -13,23 +13,13 @@ import * as glob from 'glob';
13
13
import * as webpack from 'webpack' ;
14
14
const webpackDevMiddleware = require ( 'webpack-dev-middleware' ) ;
15
15
16
- import { KarmaWebpackFailureCb } from './karma-webpack-failure-cb' ;
17
16
import { statsErrorsToString } from '../../utils/stats' ;
18
- import { getWebpackStatsConfig } from '../../configs/stats' ;
19
17
import { createConsoleLogger } from '@angular-devkit/core/node' ;
20
18
import { logging } from '@angular-devkit/core' ;
21
19
import { WebpackTestOptions } from '../../../utils/build-options' ;
22
20
import { normalizeSourceMaps } from '../../../utils/index' ;
23
21
24
- /**
25
- * Enumerate needed (but not require/imported) dependencies from this file
26
- * to let the dependency validator know they are used.
27
- *
28
- * require('source-map-support')
29
- * require('karma-source-map-support')
30
- */
31
-
32
- const KARMA_APPLICATION_PATH = '_karma_webpack_' ;
22
+ const KARMA_APPLICATION_PATH = '_karma_webpack_' ;
33
23
34
24
35
25
let blocked : any [ ] = [ ] ;
@@ -64,7 +54,7 @@ function addKarmaFiles(files: any[], newFiles: any[], prepend = false) {
64
54
const init : any = ( config : any , emitter : any ) => {
65
55
if ( ! config . buildWebpack ) {
66
56
throw new Error ( `The '@angular-devkit/build-angular/plugins/karma' karma plugin is meant to` +
67
- ` be used from within Angular CLI and will not work correctly outside of it.`
57
+ ` be used from within Angular CLI and will not work correctly outside of it.`
68
58
)
69
59
}
70
60
const options = config . buildWebpack . options as WebpackTestOptions ;
@@ -94,7 +84,7 @@ const init: any = (config: any, emitter: any) => {
94
84
if ( options . codeCoverage ) {
95
85
config . plugins = config . plugins || [ ] ;
96
86
config . reporters = config . reporters || [ ] ;
97
- const { plugins, reporters} = config ;
87
+ const { plugins, reporters } = config ;
98
88
const hasCoveragePlugin = plugins . some ( isPlugin ( 'karma-coverage' , 'reporter:coverage' ) ) ;
99
89
const hasIstanbulPlugin = plugins . some ( isPlugin ( 'karma-coverage-istanbul-reporter' , 'reporter:coverage-istanbul' ) ) ;
100
90
const hasCoverageReporter = reporters . includes ( 'coverage' ) ;
@@ -110,8 +100,8 @@ const init: any = (config: any, emitter: any) => {
110
100
111
101
if ( hasIstanbulPlugin ) {
112
102
logger . warn ( `'karma-coverage-istanbul-reporter' usage has been deprecated since version 11.\n` +
113
- `Please install 'karma-coverage' and update 'karma.conf.js.' ` +
114
- 'For more info, see https://github.com/karma-runner/karma-coverage/blob/master/README.md' ) ;
103
+ `Please install 'karma-coverage' and update 'karma.conf.js.' ` +
104
+ 'For more info, see https://github.com/karma-runner/karma-coverage/blob/master/README.md' ) ;
115
105
}
116
106
}
117
107
@@ -123,21 +113,9 @@ const init: any = (config: any, emitter: any) => {
123
113
publicPath : `/${ KARMA_APPLICATION_PATH } /` ,
124
114
} ;
125
115
126
- const compilationErrorCb = ( error : string | undefined , errors : string [ ] ) => {
127
- // Notify potential listeners of the compile error
128
- emitter . emit ( 'compile_error' , errors ) ;
129
-
130
- // Finish Karma run early in case of compilation error.
131
- emitter . emit ( 'run_complete' , [ ] , { exitCode : 1 } ) ;
132
-
133
- // Unblock any karma requests (potentially started using `karma run`)
134
- unblock ( ) ;
135
- }
136
- webpackConfig . plugins . push ( new KarmaWebpackFailureCb ( compilationErrorCb ) ) ;
137
-
138
116
// Use existing config if any.
139
- config . webpack = Object . assign ( webpackConfig , config . webpack ) ;
140
- config . webpackMiddleware = Object . assign ( webpackMiddlewareConfig , config . webpackMiddleware ) ;
117
+ config . webpack = { ... webpackConfig , ... config . webpack } ;
118
+ config . webpackMiddleware = { ... webpackMiddlewareConfig , ... config . webpackMiddleware }
141
119
142
120
// Our custom context and debug files list the webpack bundles directly instead of using
143
121
// the karma files array.
@@ -151,7 +129,11 @@ const init: any = (config: any, emitter: any) => {
151
129
config . middleware . push ( '@angular-devkit/build-angular--fallback' ) ;
152
130
153
131
// The webpack tier owns the watch behavior so we want to force it in the config.
154
- webpackConfig . watch = ! config . singleRun ;
132
+ // When not in watch mode, webpack-dev-middleware will call `compiler.watch` anyway.
133
+ // https://github.com/webpack/webpack-dev-middleware/blob/698c9ae5e9bb9a013985add6189ff21c1a1ec185/src/index.js#L65
134
+ // https://github.com/webpack/webpack/blob/cde1b73e12eb8a77eb9ba42e7920c9ec5d29c2c9/lib/Compiler.js#L379-L388
135
+ webpackConfig . watch = true ;
136
+
155
137
if ( config . singleRun ) {
156
138
// There's no option to turn off file watching in webpack-dev-server, but
157
139
// we can override the file watcher instead.
@@ -167,46 +149,54 @@ const init: any = (config: any, emitter: any) => {
167
149
webpackConfig . output . path = `/${ KARMA_APPLICATION_PATH } /` ;
168
150
webpackConfig . output . publicPath = `/${ KARMA_APPLICATION_PATH } /` ;
169
151
170
- let compiler ;
171
- try {
172
- compiler = webpack ( webpackConfig ) ;
173
- } catch ( e ) {
174
- logger . error ( e . stack || e )
175
- if ( e . details ) {
176
- logger . error ( e . details )
152
+ const compiler = webpack ( webpackConfig , ( error , stats ) => {
153
+ if ( error ) {
154
+ throw error ;
177
155
}
178
- throw e ;
179
- }
180
156
181
- function handler ( callback ?: ( ) => void ) {
182
- isBlocked = true ;
157
+ if ( stats ?. hasErrors ( ) ) {
158
+ // Only generate needed JSON stats and when needed.
159
+ const statsJson = stats ?. toJson ( {
160
+ all : false ,
161
+ children : true ,
162
+ errors : true ,
163
+ warnings : true ,
164
+ } ) ;
183
165
184
- if ( typeof callback === 'function' ) {
185
- callback ( ) ;
166
+ logger . error ( statsErrorsToString ( statsJson , { colors : true } ) ) ;
167
+
168
+ // Notify potential listeners of the compile error.
169
+ emitter . emit ( 'compile_error' , {
170
+ errors : statsJson . errors ?. map ( e => e . message ) ,
171
+ } ) ;
172
+
173
+ // Finish Karma run early in case of compilation error.
174
+ emitter . emit ( 'run_complete' , [ ] , { exitCode : 1 } ) ;
175
+
176
+ // Emit a failure build event if there are compilation errors.
177
+ failureCb ( ) ;
186
178
}
179
+ } ) ;
180
+
181
+ function handler ( callback ?: ( ) => void ) : void {
182
+ isBlocked = true ;
183
+ callback ?.( ) ;
187
184
}
188
185
189
186
compiler . hooks . invalid . tap ( 'karma' , ( ) => handler ( ) ) ;
190
-
191
187
compiler . hooks . watchRun . tapAsync ( 'karma' , ( _ : any , callback : ( ) => void ) => handler ( callback ) ) ;
192
-
193
188
compiler . hooks . run . tapAsync ( 'karma' , ( _ : any , callback : ( ) => void ) => handler ( callback ) ) ;
194
189
195
- function unblock ( ) {
190
+ function unblock ( ) {
196
191
isBlocked = false ;
197
192
blocked . forEach ( ( cb ) => cb ( ) ) ;
198
193
blocked = [ ] ;
199
194
}
200
195
201
196
let lastCompilationHash : string | undefined ;
202
- const statsConfig = getWebpackStatsConfig ( ) ;
203
197
compiler . hooks . done . tap ( 'karma' , ( stats ) => {
204
198
if ( stats . hasErrors ( ) ) {
205
- // Print compilation errors.
206
- logger . error ( statsErrorsToString ( stats . compilation , statsConfig ) ) ;
207
199
lastCompilationHash = undefined ;
208
- // Emit a failure build event if there are compilation errors.
209
- failureCb ( ) ;
210
200
} else if ( stats . hash != lastCompilationHash ) {
211
201
// Refresh karma only when there are no webpack errors, and if the compilation changed.
212
202
lastCompilationHash = stats . hash ;
@@ -215,7 +205,7 @@ const init: any = (config: any, emitter: any) => {
215
205
unblock ( ) ;
216
206
} ) ;
217
207
218
- webpackMiddleware = new webpackDevMiddleware ( compiler , webpackMiddlewareConfig ) ;
208
+ webpackMiddleware = webpackDevMiddleware ( compiler , webpackMiddlewareConfig ) ;
219
209
220
210
emitter . on ( 'exit' , ( done : any ) => {
221
211
webpackMiddleware . close ( ) ;
@@ -244,12 +234,12 @@ function requestBlocker() {
244
234
// browser log, because it is an utility reporter,
245
235
// unless it's alone in the "reporters" option and base reporter is used.
246
236
function muteDuplicateReporterLogging ( context : any , config : any ) {
247
- context . writeCommonMsg = function ( ) { } ;
237
+ context . writeCommonMsg = ( ) => { }
248
238
const reporterName = '@angular/cli' ;
249
239
const hasTrailingReporters = config . reporters . slice ( - 1 ) . pop ( ) !== reporterName ;
250
240
251
241
if ( hasTrailingReporters ) {
252
- context . writeCommonMsg = function ( ) { } ;
242
+ context . writeCommonMsg = ( ) => { } ;
253
243
}
254
244
}
255
245
@@ -268,7 +258,7 @@ const eventReporter: any = function (this: any, baseReporterDecorator: any, conf
268
258
}
269
259
270
260
// avoid duplicate failure message
271
- this . specFailure = ( ) => { } ;
261
+ this . specFailure = ( ) => { } ;
272
262
} ;
273
263
274
264
eventReporter . $inject = [ 'baseReporterDecorator' , 'config' ] ;
@@ -287,10 +277,10 @@ const sourceMapReporter: any = function (this: any, baseReporterDecorator: any,
287
277
} ;
288
278
289
279
// avoid duplicate complete message
290
- this . onRunComplete = ( ) => { } ;
280
+ this . onRunComplete = ( ) => { } ;
291
281
292
282
// avoid duplicate failure message
293
- this . specFailure = ( ) => { } ;
283
+ this . specFailure = ( ) => { } ;
294
284
} ;
295
285
296
286
sourceMapReporter . $inject = [ 'baseReporterDecorator' , 'config' ] ;
@@ -332,7 +322,7 @@ function fallbackMiddleware() {
332
322
* @param pluginName name of the karma plugin (e.g. reporter:coverage)
333
323
*/
334
324
function isPlugin ( moduleId : string , pluginName : string ) {
335
- return ( plugin : string | { } ) : boolean => {
325
+ return ( plugin : string | { } ) : boolean => {
336
326
if ( typeof plugin === 'string' ) {
337
327
if ( ! plugin . includes ( '*' ) ) {
338
328
return plugin === moduleId ;
@@ -342,7 +332,7 @@ function isPlugin(moduleId: string, pluginName: string) {
342
332
try {
343
333
require . resolve ( moduleId ) ;
344
334
return true ;
345
- } catch { }
335
+ } catch { }
346
336
}
347
337
return false ;
348
338
}
0 commit comments