7
7
*/
8
8
9
9
import { BuilderContext , BuilderOutput , createBuilder } from '@angular-devkit/architect' ;
10
- import { Config , ConfigOptions } from 'karma' ;
10
+ import { strings } from '@angular-devkit/core' ;
11
+ import { Config , ConfigOptions , config , constants } from 'karma' ;
12
+ import { createRequire } from 'module' ;
11
13
import * as path from 'path' ;
12
14
import { Observable , from } from 'rxjs' ;
13
15
import { defaultIfEmpty , switchMap } from 'rxjs/operators' ;
@@ -90,9 +92,17 @@ export function execute(
90
92
91
93
return from ( initialize ( options , context , transforms . webpackConfiguration ) ) . pipe (
92
94
switchMap ( async ( [ karma , webpackConfig ] ) => {
93
- const karmaOptions : KarmaConfigOptions = {
94
- singleRun,
95
- } ;
95
+ // Determine project name from builder context target
96
+ const projectName = context . target ?. project ;
97
+ if ( ! projectName ) {
98
+ throw new Error ( `The 'karma' builder requires a target to be specified.` ) ;
99
+ }
100
+
101
+ const karmaOptions : KarmaConfigOptions = options . main
102
+ ? getBuiltInKarmaConfig ( context . workspaceRoot , projectName )
103
+ : { } ;
104
+
105
+ karmaOptions . singleRun = singleRun ;
96
106
97
107
// Convert browsers from a string to an array
98
108
if ( options . browsers ) {
@@ -112,11 +122,6 @@ export function execute(
112
122
113
123
// prepend special webpack loader that will transform test.ts
114
124
if ( options . include ?. length ) {
115
- const projectName = context . target ?. project ;
116
- if ( ! projectName ) {
117
- throw new Error ( 'The builder requires a target.' ) ;
118
- }
119
-
120
125
const projectMetadata = await context . getProjectMetadata ( projectName ) ;
121
126
const sourceRoot = ( projectMetadata . sourceRoot ?? projectMetadata . root ?? '' ) as string ;
122
127
const projectSourceRoot = path . join ( context . workspaceRoot , sourceRoot ) ;
@@ -156,13 +161,13 @@ export function execute(
156
161
logger : context . logger ,
157
162
} ;
158
163
159
- const config = await karma . config . parseConfig (
160
- path . resolve ( context . workspaceRoot , options . karmaConfig ) ,
164
+ const parsedKarmaConfig = await config . parseConfig (
165
+ options . karmaConfig && path . resolve ( context . workspaceRoot , options . karmaConfig ) ,
161
166
transforms . karmaOptions ? transforms . karmaOptions ( karmaOptions ) : karmaOptions ,
162
167
{ promiseConfig : true , throwErrors : true } ,
163
168
) ;
164
169
165
- return [ karma , config ] as [ typeof karma , KarmaConfigOptions ] ;
170
+ return [ karma , parsedKarmaConfig ] as [ typeof karma , KarmaConfigOptions ] ;
166
171
} ) ,
167
172
switchMap (
168
173
( [ karma , karmaConfig ] ) =>
@@ -194,5 +199,47 @@ export function execute(
194
199
) ;
195
200
}
196
201
202
+ function getBuiltInKarmaConfig (
203
+ workspaceRoot : string ,
204
+ projectName : string ,
205
+ ) : ConfigOptions & Record < string , unknown > {
206
+ let coverageFolderName = projectName . charAt ( 0 ) === '@' ? projectName . slice ( 1 ) : projectName ;
207
+ if ( / [ A - Z ] / . test ( coverageFolderName ) ) {
208
+ coverageFolderName = strings . dasherize ( coverageFolderName ) ;
209
+ }
210
+
211
+ const workspaceRootRequire = createRequire ( workspaceRoot + '/' ) ;
212
+
213
+ return {
214
+ basePath : '' ,
215
+ frameworks : [ 'jasmine' , '@angular-devkit/build-angular' ] ,
216
+ plugins : [
217
+ 'karma-jasmine' ,
218
+ 'karma-chrome-launcher' ,
219
+ 'karma-jasmine-html-reporter' ,
220
+ 'karma-coverage' ,
221
+ '@angular-devkit/build-angular/plugins/karma' ,
222
+ ] . map ( ( p ) => workspaceRootRequire ( p ) ) ,
223
+ client : {
224
+ clearContext : false , // leave Jasmine Spec Runner output visible in browser
225
+ } ,
226
+ jasmineHtmlReporter : {
227
+ suppressAll : true , // removes the duplicated traces
228
+ } ,
229
+ coverageReporter : {
230
+ dir : path . join ( workspaceRoot , 'coverage' , coverageFolderName ) ,
231
+ subdir : '.' ,
232
+ reporters : [ { type : 'html' } , { type : 'text-summary' } ] ,
233
+ } ,
234
+ reporters : [ 'progress' , 'kjhtml' ] ,
235
+ port : 9876 ,
236
+ colors : true ,
237
+ logLevel : constants . LOG_INFO ,
238
+ autoWatch : true ,
239
+ browsers : [ 'Chrome' ] ,
240
+ restartOnFileChange : true ,
241
+ } ;
242
+ }
243
+
197
244
export { KarmaBuilderOptions } ;
198
245
export default createBuilder < Record < string , string > & KarmaBuilderOptions > ( execute ) ;
0 commit comments