Skip to content

Commit 0b062dd

Browse files
committed
test: add live-reload test
1 parent b087a10 commit 0b062dd

File tree

2 files changed

+156
-39
lines changed

2 files changed

+156
-39
lines changed

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

+38-39
Original file line numberDiff line numberDiff line change
@@ -31,51 +31,50 @@ export interface ServeTaskOptions extends BuildOptions {
3131
}
3232

3333
// Expose options unrelated to live-reload to other commands that need to run serve
34-
export const baseServeCommandOptions: any = baseBuildCommandOptions.concat([
35-
{ name: 'port', type: Number, default: defaultPort, aliases: ['p'] },
36-
{
37-
name: 'host',
38-
type: String,
39-
default: defaultHost,
40-
aliases: ['H'],
41-
description: `Listens only on ${defaultHost} by default`
42-
},
43-
{ name: 'proxy-config', type: 'Path', aliases: ['pc'] },
44-
{ name: 'ssl', type: Boolean, default: false },
45-
{ name: 'ssl-key', type: String, default: 'ssl/server.key' },
46-
{ name: 'ssl-cert', type: String, default: 'ssl/server.crt' },
47-
{
48-
name: 'open',
49-
type: Boolean,
50-
default: false,
51-
aliases: ['o'],
52-
description: 'Opens the url in default browser',
53-
}
54-
]);
34+
export const baseServeCommandOptions: any = overrideOptions(
35+
baseBuildCommandOptions.concat([
36+
{ name: 'port', type: Number, default: defaultPort, aliases: ['p'] },
37+
{
38+
name: 'host',
39+
type: String,
40+
default: defaultHost,
41+
aliases: ['H'],
42+
description: `Listens only on ${defaultHost} by default`
43+
},
44+
{ name: 'proxy-config', type: 'Path', aliases: ['pc'] },
45+
{ name: 'ssl', type: Boolean, default: false },
46+
{ name: 'ssl-key', type: String, default: 'ssl/server.key' },
47+
{ name: 'ssl-cert', type: String, default: 'ssl/server.crt' },
48+
{
49+
name: 'open',
50+
type: Boolean,
51+
default: false,
52+
aliases: ['o'],
53+
description: 'Opens the url in default browser',
54+
},
55+
{ name: 'live-reload', type: Boolean, default: true, aliases: ['lr'] },
56+
{
57+
name: 'live-reload-client',
58+
type: String,
59+
description: 'specify the URL that the live reload browser client will use'
60+
},
61+
{
62+
name: 'hmr',
63+
type: Boolean,
64+
default: false,
65+
description: 'Enable hot module replacement',
66+
}
67+
]), [
68+
{ name: 'watch', default: true },
69+
]
70+
);
5571

5672
const ServeCommand = Command.extend({
5773
name: 'serve',
5874
description: 'Builds and serves your app, rebuilding on file changes.',
5975
aliases: ['server', 's'],
6076

61-
availableOptions: overrideOptions(
62-
baseServeCommandOptions.concat([
63-
{ name: 'live-reload', type: Boolean, default: true, aliases: ['lr'] },
64-
{
65-
name: 'live-reload-client',
66-
type: String,
67-
description: 'specify the URL that the live reload browser client will use'
68-
},
69-
{
70-
name: 'hmr',
71-
type: Boolean,
72-
default: false,
73-
description: 'Enable hot module replacement',
74-
}
75-
]), [
76-
{ name: 'watch', default: true },
77-
]
78-
),
77+
availableOptions: baseServeCommandOptions,
7978

8079
run: function (commandOptions: ServeTaskOptions) {
8180
const ServeTask = require('../tasks/serve').default;

tests/e2e/tests/misc/live-reload.ts

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import * as express from 'express';
2+
import * as http from 'http';
3+
4+
import { appendToFile, writeMultipleFiles } from '../../utils/fs';
5+
import {
6+
killAllProcesses,
7+
silentExecAndWaitForOutputToMatch,
8+
waitForAnyProcessOutputToMatch
9+
} from '../../utils/process';
10+
import { wait } from '../../utils/utils';
11+
12+
13+
export default function () {
14+
const protractorGoodRegEx = /Spec started/;
15+
const webpackGoodRegEx = /webpack: Compiled successfully./;
16+
17+
// Create an express api for the Angular app to call.
18+
const app = express();
19+
const server = http.createServer(app);
20+
let liveReloadCount = 0;
21+
let liveReloadClientCalled = false;
22+
function resetApiVars() {
23+
liveReloadCount = 0;
24+
liveReloadClientCalled = false;
25+
}
26+
27+
server.listen(0);
28+
app.set('port', server.address().port);
29+
const apiUrl = `http://localhost:${server.address().port}`;
30+
31+
// This endpoint will be pinged by the main app on each reload.
32+
app.get('/live-reload-count', _ => liveReloadCount++);
33+
// This endpoint will be pinged by webpack to check for live reloads.
34+
app.get('/sockjs-node/info', _ => liveReloadClientCalled = true);
35+
36+
37+
return Promise.resolve()
38+
.then(_ => writeMultipleFiles({
39+
// e2e test that just opens the page and waits, so that the app runs.
40+
'./e2e/app.e2e-spec.ts': `
41+
import { browser } from 'protractor';
42+
43+
describe('master-project App', function() {
44+
it('should wait', _ => {
45+
browser.get('/');
46+
browser.sleep(30000);
47+
});
48+
});
49+
`,
50+
// App that calls the express server once.
51+
'./src/app/app.component.ts': `
52+
import { Component } from '@angular/core';
53+
import { Http } from '@angular/http';
54+
55+
@Component({
56+
selector: 'app-root',
57+
template: '<h1>Live reload test</h1>'
58+
})
59+
export class AppComponent {
60+
constructor(private http: Http) {
61+
http.get('${apiUrl + '/live-reload-count'}').subscribe(res => null);
62+
}
63+
}
64+
`
65+
}))
66+
.then(_ => silentExecAndWaitForOutputToMatch(
67+
'ng',
68+
['e2e', '--watch', '--live-reload'],
69+
protractorGoodRegEx
70+
))
71+
// Let app run.
72+
.then(_ => wait(1000))
73+
.then(_ => appendToFile('src/main.ts', 'console.log(1);'))
74+
.then(_ => waitForAnyProcessOutputToMatch(webpackGoodRegEx, 5000))
75+
.then(_ => wait(1000))
76+
.then(_ => {
77+
if (liveReloadCount != 2) {
78+
throw new Error(
79+
`Expected API to have been called 2 times but it was called ${liveReloadCount} times.`
80+
);
81+
}
82+
})
83+
.then(_ => killAllProcesses(), (err) => { killAllProcesses(); throw err; })
84+
.then(_ => resetApiVars())
85+
// Serve with live reload off should call api only once.
86+
.then(_ => silentExecAndWaitForOutputToMatch(
87+
'ng',
88+
['e2e', '--watch', '--no-live-reload'],
89+
protractorGoodRegEx
90+
))
91+
.then(_ => wait(1000))
92+
.then(_ => appendToFile('src/main.ts', 'console.log(1);'))
93+
.then(_ => waitForAnyProcessOutputToMatch(webpackGoodRegEx, 5000))
94+
.then(_ => wait(1000))
95+
.then(_ => {
96+
if (liveReloadCount != 1) {
97+
throw new Error(
98+
`Expected API to have been called 1 time but it was called ${liveReloadCount} times.`
99+
);
100+
}
101+
})
102+
.then(_ => killAllProcesses(), (err) => { killAllProcesses(); throw err; })
103+
.then(_ => resetApiVars())
104+
// Serve with live reload client set to api should call api.
105+
.then(_ => silentExecAndWaitForOutputToMatch(
106+
'ng',
107+
['e2e', '--watch', `--live-reload-client=${apiUrl}`],
108+
protractorGoodRegEx
109+
))
110+
.then(_ => wait(2000))
111+
.then(_ => {
112+
if (!liveReloadClientCalled) {
113+
throw new Error(`Expected live-reload client to have been called but it was not.`);
114+
}
115+
})
116+
.then(_ => killAllProcesses(), (err) => { killAllProcesses(); throw err; })
117+
.then(_ => server.close(), (err) => { server.close(); throw err; });
118+
}

0 commit comments

Comments
 (0)