7
7
*/
8
8
9
9
/* eslint-disable import/no-extraneous-dependencies */
10
- import { Architect , BuilderRun } from '@angular-devkit/architect' ;
11
10
import { tags } from '@angular-devkit/core' ;
12
11
import { createServer } from 'http' ;
13
12
import { createProxyServer } from 'http-proxy' ;
14
13
import { AddressInfo } from 'net' ;
15
14
import puppeteer , { Browser , Page } from 'puppeteer' ;
16
- import { debounceTime , switchMap , take } from 'rxjs/operators' ;
17
- import { createArchitect , host } from '../../../testing/test-utils' ;
15
+ import { count , debounceTime , finalize , switchMap , take , timeout } from 'rxjs/operators' ;
16
+ import { serveWebpackBrowser } from '../../index' ;
17
+ import {
18
+ BASE_OPTIONS ,
19
+ BUILD_TIMEOUT ,
20
+ DEV_SERVER_BUILDER_INFO ,
21
+ describeBuilder ,
22
+ setupBrowserTarget ,
23
+ } from '../setup' ;
18
24
19
25
// eslint-disable-next-line @typescript-eslint/no-explicit-any
20
26
declare const document : any ;
@@ -132,135 +138,159 @@ async function goToPageAndWaitForWS(page: Page, url: string): Promise<void> {
132
138
} ) ,
133
139
page . goto ( url ) ,
134
140
] ) ;
141
+
135
142
await client . detach ( ) ;
136
143
}
137
144
138
- describe ( 'Dev Server Builder live-reload' , ( ) => {
139
- const target = { project : 'app' , target : 'serve' } ;
140
- // TODO: check if the below is still true.
141
- // Avoid using port `0` as these tests will behave differrently and tests will pass when they shouldn't.
142
- // Port 0 and host 0.0.0.0 have special meaning in dev-server.
143
- const overrides = { hmr : false , watch : true , port : 4202 , liveReload : true } ;
144
- let architect : Architect ;
145
- let browser : Browser ;
146
- let page : Page ;
147
- let runs : BuilderRun [ ] ;
148
-
149
- beforeAll ( async ( ) => {
150
- browser = await puppeteer . launch ( {
151
- // MacOSX users need to set the local binary manually because Chrome has lib files with
152
- // spaces in them which Bazel does not support in runfiles
153
- // See: https://github.com/angular/angular-cli/pull/17624
154
- // eslint-disable-next-line max-len
155
- // executablePath: '/Users/<USERNAME>/git/angular-cli/node_modules/puppeteer/.local-chromium/mac-818858/chrome-mac/Chromium.app/Contents/MacOS/Chromium',
156
- ignoreHTTPSErrors : true ,
157
- args : [ '--no-sandbox' , '--disable-gpu' ] ,
145
+ describeBuilder ( serveWebpackBrowser , DEV_SERVER_BUILDER_INFO , ( harness ) => {
146
+ describe ( 'Behavior: "Dev-server builder live-reload with proxies"' , ( ) => {
147
+ let browser : Browser ;
148
+ let page : Page ;
149
+
150
+ const SERVE_OPTIONS = Object . freeze ( {
151
+ ...BASE_OPTIONS ,
152
+ hmr : false ,
153
+ watch : true ,
154
+ liveReload : true ,
158
155
} ) ;
159
- } ) ;
160
156
161
- afterAll ( async ( ) => {
162
- await browser . close ( ) ;
163
- } ) ;
157
+ beforeAll ( async ( ) => {
158
+ browser = await puppeteer . launch ( {
159
+ // MacOSX users need to set the local binary manually because Chrome has lib files with
160
+ // spaces in them which Bazel does not support in runfiles
161
+ // See: https://github.com/angular/angular-cli/pull/17624
162
+ // eslint-disable-next-line max-len
163
+ // executablePath: '/Users/<USERNAME>/git/angular-cli/node_modules/puppeteer/.local-chromium/mac-818858/chrome-mac/Chromium.app/Contents/MacOS/Chromium',
164
+ ignoreHTTPSErrors : true ,
165
+ args : [ '--no-sandbox' , '--disable-gpu' ] ,
166
+ } ) ;
167
+ } ) ;
164
168
165
- beforeEach ( async ( ) => {
166
- await host . initialize ( ) . toPromise ( ) ;
167
- architect = ( await createArchitect ( host . root ( ) ) ) . architect ;
169
+ afterAll ( async ( ) => {
170
+ await browser . close ( ) ;
171
+ } ) ;
172
+
173
+ beforeEach ( async ( ) => {
174
+ setupBrowserTarget ( harness , {
175
+ polyfills : 'src/polyfills.ts' ,
176
+ } ) ;
168
177
169
- host . writeMultipleFiles ( {
170
- 'src/app/app.component.html' : `
171
- <p>{{ title }}</p>
172
- ` ,
178
+ page = await browser . newPage ( ) ;
173
179
} ) ;
174
180
175
- runs = [ ] ;
176
- page = await browser . newPage ( ) ;
177
- } ) ;
181
+ afterEach ( async ( ) => {
182
+ await page . close ( ) ;
183
+ } ) ;
178
184
179
- afterEach ( async ( ) => {
180
- await host . restore ( ) . toPromise ( ) ;
181
- await page . close ( ) ;
182
- await Promise . all ( runs . map ( ( r ) => r . stop ( ) ) ) ;
183
- } ) ;
185
+ it ( 'works without proxy' , async ( ) => {
186
+ harness . useTarget ( 'serve' , {
187
+ ...SERVE_OPTIONS ,
188
+ } ) ;
184
189
185
- it ( 'works without proxy' , async ( ) => {
186
- const run = await architect . scheduleTarget ( target , overrides ) ;
187
- runs . push ( run ) ;
188
-
189
- await run . output
190
- . pipe (
191
- debounceTime ( 1000 ) ,
192
- switchMap ( async ( buildEvent , buildCount ) => {
193
- expect ( buildEvent . success ) . toBe ( true ) ;
194
- const url = buildEvent . baseUrl as string ;
195
- switch ( buildCount ) {
196
- case 0 :
197
- await goToPageAndWaitForWS ( page , url ) ;
198
- host . replaceInFile ( 'src/app/app.component.ts' , `'app'` , `'app-live-reload'` ) ;
199
- break ;
200
- case 1 :
201
- const innerText = await page . evaluate ( ( ) => document . querySelector ( 'p' ) . innerText ) ;
202
- expect ( innerText ) . toBe ( 'app-live-reload' ) ;
203
- break ;
204
- }
205
- } ) ,
206
- take ( 2 ) ,
207
- )
208
- . toPromise ( ) ;
209
- } ) ;
190
+ await harness . writeFile ( 'src/app/app.component.html' , '<p>{{ title }}</p>' ) ;
210
191
211
- it ( 'works without http -> http proxy' , async ( ) => {
212
- const run = await architect . scheduleTarget ( target , overrides ) ;
213
- runs . push ( run ) ;
192
+ const buildCount = await harness
193
+ . execute ( )
194
+ . pipe (
195
+ debounceTime ( 1000 ) ,
196
+ timeout ( BUILD_TIMEOUT * 2 ) ,
197
+ switchMap ( async ( { result } , index ) => {
198
+ expect ( result ?. success ) . toBeTrue ( ) ;
199
+ if ( typeof result ?. baseUrl !== 'string' ) {
200
+ throw new Error ( 'Expected "baseUrl" to be a string.' ) ;
201
+ }
214
202
215
- let proxy : ProxyInstance | undefined ;
216
- let buildCount = 0 ;
217
- try {
218
- await run . output
203
+ switch ( index ) {
204
+ case 0 :
205
+ await goToPageAndWaitForWS ( page , result . baseUrl ) ;
206
+ await harness . modifyFile ( 'src/app/app.component.ts' , ( content ) =>
207
+ content . replace ( `'app'` , `'app-live-reload'` ) ,
208
+ ) ;
209
+ break ;
210
+ case 1 :
211
+ const innerText = await page . evaluate ( ( ) => document . querySelector ( 'p' ) . innerText ) ;
212
+ expect ( innerText ) . toBe ( 'app-live-reload' ) ;
213
+ break ;
214
+ }
215
+ } ) ,
216
+ take ( 2 ) ,
217
+ count ( ) ,
218
+ )
219
+ . toPromise ( ) ;
220
+
221
+ expect ( buildCount ) . toBe ( 2 ) ;
222
+ } ) ;
223
+
224
+ it ( 'works without http -> http proxy' , async ( ) => {
225
+ harness . useTarget ( 'serve' , {
226
+ ...SERVE_OPTIONS ,
227
+ } ) ;
228
+
229
+ await harness . writeFile ( 'src/app/app.component.html' , '<p>{{ title }}</p>' ) ;
230
+
231
+ let proxy : ProxyInstance | undefined ;
232
+ const buildCount = await harness
233
+ . execute ( )
219
234
. pipe (
220
235
debounceTime ( 1000 ) ,
221
- switchMap ( async ( buildEvent ) => {
222
- expect ( buildEvent . success ) . toBe ( true ) ;
223
- const url = buildEvent . baseUrl as string ;
224
- switch ( buildCount ) {
236
+ timeout ( BUILD_TIMEOUT * 2 ) ,
237
+ switchMap ( async ( { result } , index ) => {
238
+ expect ( result ?. success ) . toBeTrue ( ) ;
239
+ if ( typeof result ?. baseUrl !== 'string' ) {
240
+ throw new Error ( 'Expected "baseUrl" to be a string.' ) ;
241
+ }
242
+
243
+ switch ( index ) {
225
244
case 0 :
226
- proxy = await createProxy ( url , false ) ;
245
+ proxy = await createProxy ( result . baseUrl , false ) ;
227
246
await goToPageAndWaitForWS ( page , proxy . url ) ;
228
- host . replaceInFile ( 'src/app/app.component.ts' , `'app'` , `'app-live-reload'` ) ;
247
+ await harness . modifyFile ( 'src/app/app.component.ts' , ( content ) =>
248
+ content . replace ( `'app'` , `'app-live-reload'` ) ,
249
+ ) ;
229
250
break ;
230
251
case 1 :
231
252
const innerText = await page . evaluate ( ( ) => document . querySelector ( 'p' ) . innerText ) ;
232
253
expect ( innerText ) . toBe ( 'app-live-reload' ) ;
233
254
break ;
234
255
}
235
-
236
- buildCount ++ ;
237
256
} ) ,
238
257
take ( 2 ) ,
258
+ count ( ) ,
259
+ finalize ( ( ) => {
260
+ proxy ?. server . close ( ) ;
261
+ } ) ,
239
262
)
240
263
. toPromise ( ) ;
241
- } finally {
242
- proxy ?. server . close ( ) ;
243
- }
244
- } ) ;
245
264
246
- it ( 'works without https -> http proxy' , async ( ) => {
247
- const run = await architect . scheduleTarget ( target , overrides ) ;
248
- runs . push ( run ) ;
265
+ expect ( buildCount ) . toBe ( 2 ) ;
266
+ } ) ;
267
+
268
+ it ( 'works without https -> http proxy' , async ( ) => {
269
+ harness . useTarget ( 'serve' , {
270
+ ...SERVE_OPTIONS ,
271
+ } ) ;
249
272
250
- let proxy : ProxyInstance | undefined ;
273
+ await harness . writeFile ( 'src/app/app.component.html' , '<p>{{ title }}</p>' ) ;
251
274
252
- try {
253
- await run . output
275
+ let proxy : ProxyInstance | undefined ;
276
+ const buildCount = await harness
277
+ . execute ( )
254
278
. pipe (
255
279
debounceTime ( 1000 ) ,
256
- switchMap ( async ( buildEvent , buildCount ) => {
257
- expect ( buildEvent . success ) . toBe ( true ) ;
258
- const url = buildEvent . baseUrl as string ;
259
- switch ( buildCount ) {
280
+ timeout ( BUILD_TIMEOUT * 2 ) ,
281
+ switchMap ( async ( { result } , index ) => {
282
+ expect ( result ?. success ) . toBeTrue ( ) ;
283
+ if ( typeof result ?. baseUrl !== 'string' ) {
284
+ throw new Error ( 'Expected "baseUrl" to be a string.' ) ;
285
+ }
286
+
287
+ switch ( index ) {
260
288
case 0 :
261
- proxy = await createProxy ( url , true ) ;
289
+ proxy = await createProxy ( result . baseUrl , true ) ;
262
290
await goToPageAndWaitForWS ( page , proxy . url ) ;
263
- host . replaceInFile ( 'src/app/app.component.ts' , `'app'` , `'app-live-reload'` ) ;
291
+ await harness . modifyFile ( 'src/app/app.component.ts' , ( content ) =>
292
+ content . replace ( `'app'` , `'app-live-reload'` ) ,
293
+ ) ;
264
294
break ;
265
295
case 1 :
266
296
const innerText = await page . evaluate ( ( ) => document . querySelector ( 'p' ) . innerText ) ;
@@ -269,10 +299,14 @@ describe('Dev Server Builder live-reload', () => {
269
299
}
270
300
} ) ,
271
301
take ( 2 ) ,
302
+ count ( ) ,
303
+ finalize ( ( ) => {
304
+ proxy ?. server . close ( ) ;
305
+ } ) ,
272
306
)
273
307
. toPromise ( ) ;
274
- } finally {
275
- proxy ?. server . close ( ) ;
276
- }
308
+
309
+ expect ( buildCount ) . toBe ( 2 ) ;
310
+ } ) ;
277
311
} ) ;
278
312
} ) ;
0 commit comments