Skip to content

Commit cdbb48f

Browse files
alan-agius4dgp1130
authored andcommitted
test(@angular-devkit/build-angular): re-write live-reload tests to use new test harness.
With this change we replace the live-reload proxy tests to use the new test harness. This is an effort to reduce the flakiness of these tests.
1 parent f57cb75 commit cdbb48f

File tree

1 file changed

+135
-101
lines changed

1 file changed

+135
-101
lines changed

packages/angular_devkit/build_angular/src/builders/dev-server/specs/live-reload_spec.ts renamed to packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/serve-live-reload-proxies_spec.ts

+135-101
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@
77
*/
88

99
/* eslint-disable import/no-extraneous-dependencies */
10-
import { Architect, BuilderRun } from '@angular-devkit/architect';
1110
import { tags } from '@angular-devkit/core';
1211
import { createServer } from 'http';
1312
import { createProxyServer } from 'http-proxy';
1413
import { AddressInfo } from 'net';
1514
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';
1824

1925
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2026
declare const document: any;
@@ -132,135 +138,159 @@ async function goToPageAndWaitForWS(page: Page, url: string): Promise<void> {
132138
}),
133139
page.goto(url),
134140
]);
141+
135142
await client.detach();
136143
}
137144

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,
158155
});
159-
});
160156

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+
});
164168

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+
});
168177

169-
host.writeMultipleFiles({
170-
'src/app/app.component.html': `
171-
<p>{{ title }}</p>
172-
`,
178+
page = await browser.newPage();
173179
});
174180

175-
runs = [];
176-
page = await browser.newPage();
177-
});
181+
afterEach(async () => {
182+
await page.close();
183+
});
178184

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+
});
184189

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>');
210191

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+
}
214202

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()
219234
.pipe(
220235
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) {
225244
case 0:
226-
proxy = await createProxy(url, false);
245+
proxy = await createProxy(result.baseUrl, false);
227246
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+
);
229250
break;
230251
case 1:
231252
const innerText = await page.evaluate(() => document.querySelector('p').innerText);
232253
expect(innerText).toBe('app-live-reload');
233254
break;
234255
}
235-
236-
buildCount++;
237256
}),
238257
take(2),
258+
count(),
259+
finalize(() => {
260+
proxy?.server.close();
261+
}),
239262
)
240263
.toPromise();
241-
} finally {
242-
proxy?.server.close();
243-
}
244-
});
245264

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+
});
249272

250-
let proxy: ProxyInstance | undefined;
273+
await harness.writeFile('src/app/app.component.html', '<p>{{ title }}</p>');
251274

252-
try {
253-
await run.output
275+
let proxy: ProxyInstance | undefined;
276+
const buildCount = await harness
277+
.execute()
254278
.pipe(
255279
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) {
260288
case 0:
261-
proxy = await createProxy(url, true);
289+
proxy = await createProxy(result.baseUrl, true);
262290
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+
);
264294
break;
265295
case 1:
266296
const innerText = await page.evaluate(() => document.querySelector('p').innerText);
@@ -269,10 +299,14 @@ describe('Dev Server Builder live-reload', () => {
269299
}
270300
}),
271301
take(2),
302+
count(),
303+
finalize(() => {
304+
proxy?.server.close();
305+
}),
272306
)
273307
.toPromise();
274-
} finally {
275-
proxy?.server.close();
276-
}
308+
309+
expect(buildCount).toBe(2);
310+
});
277311
});
278312
});

0 commit comments

Comments
 (0)