Skip to content

Commit 119256f

Browse files
clydinalan-agius4
authored andcommitted
test(@angular-devkit/build-angular): add dev-server builder port option tests
This change adds expanded unit tests for the dev-server builder's `port` option using the builder test harness.
1 parent c9a002c commit 119256f

File tree

2 files changed

+102
-36
lines changed

2 files changed

+102
-36
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import { URL } from 'url';
9+
import { serveWebpackBrowser } from '../../index';
10+
import { executeOnceAndFetch } from '../execute-fetch';
11+
import {
12+
BASE_OPTIONS,
13+
DEV_SERVER_BUILDER_INFO,
14+
describeBuilder,
15+
setupBrowserTarget,
16+
} from '../setup';
17+
18+
function getResultPort(result: Record<string, unknown> | undefined): string | undefined {
19+
if (typeof result?.baseUrl !== 'string') {
20+
fail(`Expected builder result with a string 'baseUrl' property. Received: ${result?.baseUrl}`);
21+
22+
return;
23+
}
24+
25+
try {
26+
return new URL(result.baseUrl).port;
27+
} catch {
28+
fail(`Expected a valid URL in builder result 'baseUrl' property. Received: ${result.baseUrl}`);
29+
}
30+
}
31+
32+
describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => {
33+
describe('option: "port"', () => {
34+
beforeEach(async () => {
35+
setupBrowserTarget(harness);
36+
37+
// Application code is not needed for these tests
38+
await harness.writeFile('src/main.ts', '');
39+
});
40+
41+
it('uses default port (4200) when not present', async () => {
42+
harness.useTarget('serve', {
43+
...BASE_OPTIONS,
44+
// Base options set port to zero
45+
port: undefined,
46+
});
47+
48+
const { result, response, logs } = await executeOnceAndFetch(harness, '/');
49+
50+
expect(result?.success).toBeTrue();
51+
expect(getResultPort(result)).toBe('4200');
52+
expect(await response?.text()).toContain('<title>');
53+
54+
expect(logs).toContain(
55+
jasmine.objectContaining({
56+
message: jasmine.stringMatching(/:4200/),
57+
}),
58+
);
59+
});
60+
61+
it('uses a random free port when set to 0 (zero)', async () => {
62+
harness.useTarget('serve', {
63+
...BASE_OPTIONS,
64+
port: 0,
65+
});
66+
67+
const { result, response, logs } = await executeOnceAndFetch(harness, '/');
68+
69+
expect(result?.success).toBeTrue();
70+
const port = getResultPort(result);
71+
expect(port).not.toBe('4200');
72+
expect(port).toMatch(/\d{4,6}/);
73+
expect(await response?.text()).toContain('<title>');
74+
75+
expect(logs).toContain(
76+
jasmine.objectContaining({
77+
message: jasmine.stringMatching(':' + port),
78+
}),
79+
);
80+
});
81+
82+
it('uses specific port when a non-zero number is specified', async () => {
83+
harness.useTarget('serve', {
84+
...BASE_OPTIONS,
85+
port: 8000,
86+
});
87+
88+
const { result, response, logs } = await executeOnceAndFetch(harness, '/');
89+
90+
expect(result?.success).toBeTrue();
91+
expect(getResultPort(result)).toBe('8000');
92+
expect(await response?.text()).toContain('<title>');
93+
94+
expect(logs).toContain(
95+
jasmine.objectContaining({
96+
message: jasmine.stringMatching(':8000'),
97+
}),
98+
);
99+
});
100+
});
101+
});

packages/angular_devkit/build_angular/src/dev-server/works_spec.ts

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
import { Architect, BuilderRun } from '@angular-devkit/architect';
99
import { DevServerBuilderOutput } from '@angular-devkit/build-angular';
10-
import { logging, normalize, virtualFs } from '@angular-devkit/core';
10+
import { normalize, virtualFs } from '@angular-devkit/core';
1111
import fetch from 'node-fetch'; // tslint:disable-line:no-implicit-dependencies
1212
import { createArchitect, host } from '../test-utils';
1313

@@ -27,17 +27,6 @@ describe('Dev Server Builder', () => {
2727
await Promise.all(runs.map(r => r.stop()));
2828
});
2929

30-
it('works', async () => {
31-
const run = await architect.scheduleTarget(target);
32-
runs.push(run);
33-
const output = await run.result as DevServerBuilderOutput;
34-
expect(output.success).toBe(true);
35-
expect(output.baseUrl).toBe('http://localhost:4200/');
36-
37-
const response = await fetch('http://localhost:4200/index.html');
38-
expect(await response.text()).toContain('<title>HelloWorldApp</title>');
39-
});
40-
4130
it(`doesn't serve files on the cwd directly`, async () => {
4231
const run = await architect.scheduleTarget(target);
4332
runs.push(run);
@@ -56,30 +45,6 @@ describe('Dev Server Builder', () => {
5645
expect(res).toContain('<title>HelloWorldApp</title>');
5746
});
5847

59-
it('works with port 0', async () => {
60-
const logger = new logging.Logger('');
61-
const logs: string[] = [];
62-
logger.subscribe(e => logs.push(e.message));
63-
64-
const run = await architect.scheduleTarget(target, { port: 0 }, { logger });
65-
runs.push(run);
66-
const output = await run.result as DevServerBuilderOutput;
67-
expect(output.success).toBe(true);
68-
69-
const groups = logs.join().match(/\:(\d+){4,6}/g);
70-
if (!groups) {
71-
throw new Error('Expected log to contain port number.');
72-
}
73-
74-
// tests that both the ports in the logs are the same.
75-
const [firstPort, secondPort] = groups;
76-
expect(firstPort).toBe(secondPort);
77-
78-
expect(output.baseUrl).toBe(`http://localhost${firstPort}/`);
79-
const response = await fetch(`http://localhost${firstPort}/index.html`);
80-
expect(await response.text()).toContain('<title>HelloWorldApp</title>');
81-
});
82-
8348
it('should not generate sourcemaps when running prod build', async () => {
8449
// Production builds have sourcemaps turned off.
8550
const run = await architect.scheduleTarget({ ...target, configuration: 'production' });

0 commit comments

Comments
 (0)