Skip to content

Commit 9685dde

Browse files
committed
feat(@angular/cli): ng e2e defaults to random port
1 parent a22474e commit 9685dde

File tree

5 files changed

+61
-12
lines changed

5 files changed

+61
-12
lines changed

packages/@angular/cli/commands/e2e.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
const SilentError = require('silent-error');
22

3+
import { overrideOptions } from '../utilities/override-options';
34
import { CliConfig } from '../models/config';
45
import { ServeTaskOptions, baseServeCommandOptions } from './serve';
6+
import { checkPort } from '../utilities/check-port';
57
const Command = require('../ember-cli/lib/models/command');
68

79

@@ -13,14 +15,17 @@ export interface E2eTaskOptions extends ServeTaskOptions {
1315
elementExplorer: boolean;
1416
}
1517

16-
export const e2eCommandOptions = baseServeCommandOptions.concat([
17-
{ name: 'config', type: String, aliases: ['c'] },
18-
{ name: 'specs', type: Array, default: [], aliases: ['sp'] },
19-
{ name: 'element-explorer', type: Boolean, default: false, aliases: ['ee'] },
20-
{ name: 'webdriver-update', type: Boolean, default: true, aliases: ['wu'] },
21-
{ name: 'serve', type: Boolean, default: true, aliases: ['s'] }
22-
]);
23-
18+
export const e2eCommandOptions = overrideOptions(
19+
baseServeCommandOptions.concat([
20+
{ name: 'config', type: String, aliases: ['c'] },
21+
{ name: 'specs', type: Array, default: [], aliases: ['sp'] },
22+
{ name: 'element-explorer', type: Boolean, default: false, aliases: ['ee'] },
23+
{ name: 'webdriver-update', type: Boolean, default: true, aliases: ['wu'] },
24+
{ name: 'serve', type: Boolean, default: true, aliases: ['s'] }
25+
]), [
26+
{ name: 'port', default: 0, aliases: ['p'] },
27+
]
28+
);
2429

2530
const E2eCommand = Command.extend({
2631
name: 'e2e',
@@ -66,7 +71,9 @@ const E2eCommand = Command.extend({
6671
}
6772
}
6873

69-
serve.run(commandOptions, rebuildCb)
74+
checkPort(commandOptions.port, commandOptions.host)
75+
.then((port: number) => commandOptions.port = port)
76+
.then(() => serve.run(commandOptions, rebuildCb))
7077
.catch(reject);
7178
});
7279
} else {

packages/@angular/cli/commands/serve.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { baseBuildCommandOptions } from './build';
44
import { CliConfig } from '../models/config';
55
import { Version } from '../upgrade/version';
66
import { ServeTaskOptions } from './serve';
7+
import { checkPort } from '../utilities/check-port';
78

89
const SilentError = require('silent-error');
910
const PortFinder = require('portfinder');
@@ -100,7 +101,8 @@ const ServeCommand = Command.extend({
100101
Version.assertAngularVersionIs2_3_1OrHigher(this.project.root);
101102
commandOptions.liveReloadHost = commandOptions.liveReloadHost || commandOptions.host;
102103

103-
return checkExpressPort(commandOptions)
104+
return checkPort(commandOptions.port, commandOptions.host)
105+
.then((port: number) => commandOptions.port = port)
104106
.then(() => autoFindLiveReloadPort(commandOptions))
105107
.then((opts: ServeTaskOptions) => {
106108
const serve = new ServeTask({
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import * as denodeify from 'denodeify';
2+
3+
const SilentError = require('silent-error');
4+
const PortFinder = require('portfinder');
5+
const getPort = <any>denodeify(PortFinder.getPort);
6+
7+
PortFinder.basePort = 49152;
8+
9+
10+
export function checkPort(port: number, host: string) {
11+
return getPort({ port, host })
12+
.then((foundPort: number) => {
13+
14+
// If the port isn't available and we weren't looking for any port, throw error.
15+
if (port !== foundPort && port !== 0) {
16+
throw new SilentError(
17+
`Port ${port} is already in use. Use '--port' to specify a different port.`
18+
);
19+
}
20+
21+
// Otherwise, our found port is good.
22+
return foundPort;
23+
});
24+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const cloneDeep = require('lodash/cloneDeep');
2+
3+
export function overrideOptions(original: any[], overrides: any[]) {
4+
let copy = cloneDeep(original);
5+
overrides.forEach(override => {
6+
const option = copy.find((opt: any) => opt.name == override.name);
7+
if (option) {
8+
Object.assign(option, override);
9+
}
10+
});
11+
return copy;
12+
}

tests/e2e/tests/test/e2e.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
ng,
33
npm,
44
execAndWaitForOutputToMatch,
5+
silentExecAndWaitForOutputToMatch,
56
killAllProcesses
67
} from '../../utils/process';
78
import { updateJsonFile } from '../../utils/project';
@@ -40,6 +41,9 @@ export default function () {
4041
.then(() => killAllProcesses(), (err: any) => {
4142
killAllProcesses();
4243
throw err;
43-
});
44-
44+
})
45+
// Should run side-by-side with `ng serve`
46+
.then(() => silentExecAndWaitForOutputToMatch('ng', ['serve'],
47+
/webpack: Compiled successfully./))
48+
.then(() => ng('e2e'));
4549
}

0 commit comments

Comments
 (0)