@@ -72,105 +72,109 @@ export function execute(
72
72
assertCompatibleAngularVersion ( context . workspaceRoot , context . logger ) ;
73
73
74
74
return from ( initialize ( options , context , transforms . webpackConfiguration ) ) . pipe (
75
- switchMap (
76
- ( [ karma , webpackConfig ] ) =>
77
- new Observable < BuilderOutput > ( subscriber => {
78
- const karmaOptions : KarmaConfigOptions = { } ;
79
-
80
- if ( options . watch !== undefined ) {
81
- karmaOptions . singleRun = ! options . watch ;
82
- }
83
-
84
- // Convert browsers from a string to an array
85
- if ( options . browsers ) {
86
- karmaOptions . browsers = options . browsers . split ( ',' ) ;
87
- }
88
-
89
- if ( options . reporters ) {
90
- // Split along commas to make it more natural, and remove empty strings.
91
- const reporters = options . reporters
92
- . reduce < string [ ] > ( ( acc , curr ) => acc . concat ( curr . split ( ',' ) ) , [ ] )
93
- . filter ( x => ! ! x ) ;
94
-
95
- if ( reporters . length > 0 ) {
96
- karmaOptions . reporters = reporters ;
97
- }
98
- }
99
-
100
- // prepend special webpack loader that will transform test.ts
101
- if ( options . include && options . include . length > 0 ) {
102
- const mainFilePath = getSystemPath (
103
- join ( normalize ( context . workspaceRoot ) , options . main ) ,
104
- ) ;
105
- const files = findTests ( options . include , dirname ( mainFilePath ) , context . workspaceRoot ) ;
106
- // early exit, no reason to start karma
107
- if ( ! files . length ) {
108
- subscriber . error (
109
- `Specified patterns: "${ options . include . join ( ', ' ) } " did not match any spec files` ,
110
- ) ;
111
-
112
- return ;
113
- }
114
-
115
- // Get the rules and ensure the Webpack configuration is setup properly
116
- const rules = webpackConfig . module ?. rules || [ ] ;
117
- if ( ! webpackConfig . module ) {
118
- webpackConfig . module = { rules } ;
119
- } else if ( ! webpackConfig . module . rules ) {
120
- webpackConfig . module . rules = rules ;
121
- }
122
-
123
- rules . unshift ( {
124
- test : mainFilePath ,
125
- use : {
126
- // cannot be a simple path as it differs between environments
127
- loader : SingleTestTransformLoader ,
128
- options : {
129
- files,
130
- logger : context . logger ,
131
- } ,
132
- } ,
133
- } ) ;
134
- }
135
-
136
- // Assign additional karmaConfig options to the local ngapp config
137
- karmaOptions . configFile = resolve ( context . workspaceRoot , options . karmaConfig ) ;
138
-
139
- karmaOptions . buildWebpack = {
140
- options,
141
- webpackConfig,
142
- // Pass onto Karma to emit BuildEvents.
143
- successCb : ( ) => subscriber . next ( { success : true } ) ,
144
- failureCb : ( ) => subscriber . next ( { success : false } ) ,
145
- // Workaround for https://github.com/karma-runner/karma/issues/3154
146
- // When this workaround is removed, user projects need to be updated to use a Karma
147
- // version that has a fix for this issue.
148
- toJSON : ( ) => { } ,
149
- logger : context . logger ,
150
- } ;
151
-
152
- // Complete the observable once the Karma server returns.
153
- const karmaServer = new karma . Server (
154
- transforms . karmaOptions ? transforms . karmaOptions ( karmaOptions ) : karmaOptions ,
155
- ( exitCode : number ) => {
156
- subscriber . next ( { success : exitCode === 0 } ) ;
157
- subscriber . complete ( ) ;
158
- } ,
75
+ switchMap ( async ( [ karma , webpackConfig ] ) => {
76
+ const karmaOptions : KarmaConfigOptions = { } ;
77
+
78
+ if ( options . watch !== undefined ) {
79
+ karmaOptions . singleRun = ! options . watch ;
80
+ }
81
+
82
+ // Convert browsers from a string to an array
83
+ if ( options . browsers ) {
84
+ karmaOptions . browsers = options . browsers . split ( ',' ) ;
85
+ }
86
+
87
+ if ( options . reporters ) {
88
+ // Split along commas to make it more natural, and remove empty strings.
89
+ const reporters = options . reporters
90
+ . reduce < string [ ] > ( ( acc , curr ) => acc . concat ( curr . split ( ',' ) ) , [ ] )
91
+ . filter ( x => ! ! x ) ;
92
+
93
+ if ( reporters . length > 0 ) {
94
+ karmaOptions . reporters = reporters ;
95
+ }
96
+ }
97
+
98
+ // prepend special webpack loader that will transform test.ts
99
+ if ( options . include && options . include . length > 0 ) {
100
+ const mainFilePath = getSystemPath (
101
+ join ( normalize ( context . workspaceRoot ) , options . main ) ,
102
+ ) ;
103
+ const files = findTests ( options . include , dirname ( mainFilePath ) , context . workspaceRoot ) ;
104
+ // early exit, no reason to start karma
105
+ if ( ! files . length ) {
106
+ throw new Error (
107
+ `Specified patterns: "${ options . include . join ( ', ' ) } " did not match any spec files.` ,
159
108
) ;
160
- // karma typings incorrectly define start's return value as void
161
- // tslint:disable-next-line:no-use-of-empty-return-value
162
- const karmaStart = ( karmaServer . start ( ) as unknown ) as Promise < void > ;
163
-
164
- // Cleanup, signal Karma to exit.
165
- return ( ) => {
166
- // Karma only has the `stop` method start with 3.1.1, so we must defensively check.
167
- const karmaServerWithStop = ( karmaServer as unknown ) as { stop : ( ) => Promise < void > } ;
168
- if ( typeof karmaServerWithStop . stop === 'function' ) {
169
- return karmaStart . then ( ( ) => karmaServerWithStop . stop ( ) ) ;
170
- }
171
- } ;
172
- } ) ,
173
- ) ,
109
+ }
110
+
111
+ // Get the rules and ensure the Webpack configuration is setup properly
112
+ const rules = webpackConfig . module ?. rules || [ ] ;
113
+ if ( ! webpackConfig . module ) {
114
+ webpackConfig . module = { rules } ;
115
+ } else if ( ! webpackConfig . module . rules ) {
116
+ webpackConfig . module . rules = rules ;
117
+ }
118
+
119
+ rules . unshift ( {
120
+ test : mainFilePath ,
121
+ use : {
122
+ // cannot be a simple path as it differs between environments
123
+ loader : SingleTestTransformLoader ,
124
+ options : {
125
+ files,
126
+ logger : context . logger ,
127
+ } ,
128
+ } ,
129
+ } ) ;
130
+ }
131
+
132
+ karmaOptions . buildWebpack = {
133
+ options,
134
+ webpackConfig,
135
+ logger : context . logger ,
136
+ } ;
137
+
138
+ // @types /karma doesn't include the last parameter.
139
+ // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/52286
140
+ // tslint:disable-next-line: no-any
141
+ const config = await ( karma . config . parseConfig as any ) (
142
+ resolve ( context . workspaceRoot , options . karmaConfig ) ,
143
+ transforms . karmaOptions ? transforms . karmaOptions ( karmaOptions ) : karmaOptions ,
144
+ { promiseConfig : true , throwErrors : true } ,
145
+ ) as Promise < KarmaConfigOptions > ;
146
+
147
+ return [ karma , config ] as [ typeof karma , KarmaConfigOptions ] ;
148
+ } ) ,
149
+ switchMap ( ( [ karma , karmaConfig ] ) => new Observable < BuilderOutput > ( subscriber => {
150
+ // Pass onto Karma to emit BuildEvents.
151
+ karmaConfig . buildWebpack ??= { } ;
152
+ if ( typeof karmaConfig . buildWebpack === 'object' ) {
153
+ // tslint:disable-next-line: no-any
154
+ ( karmaConfig . buildWebpack as any ) . failureCb ??= ( ) => subscriber . next ( { success : false } ) ;
155
+ // tslint:disable-next-line: no-any
156
+ ( karmaConfig . buildWebpack as any ) . successCb ??= ( ) => subscriber . next ( { success : true } ) ;
157
+ }
158
+
159
+ // Complete the observable once the Karma server returns.
160
+ const karmaServer = new karma . Server (
161
+ karmaConfig ,
162
+ ( exitCode : number ) => {
163
+ subscriber . next ( { success : exitCode === 0 } ) ;
164
+ subscriber . complete ( ) ;
165
+ } ,
166
+ ) ;
167
+ // karma typings incorrectly define start's return value as void
168
+ // tslint:disable-next-line:no-use-of-empty-return-value
169
+ const karmaStart = ( karmaServer . start ( ) as unknown ) as Promise < void > ;
170
+
171
+ // Cleanup, signal Karma to exit.
172
+ return ( ) => {
173
+ const karmaServerWithStop = ( karmaServer as unknown ) as { stop : ( ) => Promise < void > } ;
174
+
175
+ return karmaStart . then ( ( ) => karmaServerWithStop . stop ( ) ) ;
176
+ } ;
177
+ } ) ) ,
174
178
defaultIfEmpty ( { success : false } ) ,
175
179
) ;
176
180
}
0 commit comments