Skip to content

Commit f09e3e4

Browse files
committed
adding tests libs for runing an ember server and tear it down
1 parent 3d04916 commit f09e3e4

8 files changed

Lines changed: 295 additions & 0 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
3+
const RSVP = require('rsvp');
4+
const request = RSVP.denodeify(require('request'));
5+
const expect = require('chai').use(require('chai-string')).expect;
6+
const { startServer, stopServer } = require('../../test-libs/index');
7+
8+
describe.only('simple acceptance', function() {
9+
this.timeout(5000);
10+
11+
before(function() {
12+
return startServer({
13+
command: 'serve'
14+
});
15+
16+
});
17+
18+
after(function() {
19+
return stopServer();
20+
});
21+
22+
it('/ HTML contents', async () => {
23+
const response = await request({
24+
url: 'http://localhost:49741/',
25+
headers: {
26+
'Accept': 'text/html'
27+
}
28+
})
29+
30+
expect(response.statusCode).to.equal(200);
31+
expect(response.headers["content-type"]).to.equalIgnoreCase("text/html; charset=utf-8");
32+
expect(response.body).to.contain("Basic fastboot ember app");
33+
});
34+
});

test-packages/test-libs/debug.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
const debug = require('debug')('ember-cli-fastboot');
4+
5+
module.exports = debug;

test-packages/test-libs/index.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use strict';
2+
3+
const runServer = require('./run-server');
4+
const killCliProcess = require('./kill-cli-process');
5+
6+
let server;
7+
let longRunningServerPromise;
8+
9+
const startServer = function(options) {
10+
return runServer(options)
11+
.then(result => {
12+
server = result.server;
13+
longRunningServerPromise = result.longRunningServerPromise;
14+
});
15+
};
16+
17+
const stopServer = function() {
18+
if (!server) {
19+
throw new Error('You must call `startServer()` before calling `stopServer()`.');
20+
}
21+
22+
killCliProcess(server);
23+
24+
return longRunningServerPromise.catch(() => {
25+
server = null;
26+
});
27+
};
28+
29+
module.exports = {
30+
startServer,
31+
stopServer,
32+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
3+
module.exports = function(childProcess) {
4+
if (process.platform === 'win32') {
5+
childProcess.send({ kill: true });
6+
} else {
7+
childProcess.kill('SIGINT');
8+
}
9+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* global beforeEach, afterEach */
2+
'use strict';
3+
4+
let logSink = [];
5+
6+
if (typeof beforeEach !== 'undefined') {
7+
beforeEach(function() {
8+
logSink = [];
9+
});
10+
}
11+
12+
if (typeof afterEach !== 'undefined') {
13+
afterEach(function() {
14+
if (this.currentTest.state !== 'passed') {
15+
// It would be preferable to attach the log output to the error object
16+
// (this.currentTest.err) and have Mocha report it somehow, so that the
17+
// error message and log output show up in the same place. This doesn't
18+
// seem to be possible though.
19+
console.log(logSink.join('\n')); // eslint-disable-line no-console
20+
}
21+
logSink = [];
22+
});
23+
}
24+
25+
function logOnFailure(s) {
26+
logSink.push(s);
27+
}
28+
29+
module.exports = logOnFailure;
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
'use strict';
2+
3+
const denodeify = require('denodeify');
4+
const chalk = require('chalk');
5+
const childProcess = require('child_process');
6+
const spawn = childProcess.spawn;
7+
const defaults = require('lodash/defaults');
8+
const killCliProcess = require('./kill-cli-process');
9+
const debug = require('./debug');
10+
const logOnFailure = require('./log-on-failure');
11+
const exec = denodeify(childProcess.exec);
12+
13+
const isWindows = process.platform === 'win32';
14+
15+
module.exports = function run(/* command, args, options */) {
16+
let command = arguments[0];
17+
let args = Array.prototype.slice.call(arguments, 1);
18+
let options = {};
19+
20+
if (typeof args[args.length - 1] === 'object') {
21+
options = args.pop();
22+
}
23+
24+
debug('running command=' + command + '; args=' + args + '; cwd=' + process.cwd());
25+
26+
if (isWindows && (command === 'npm' || command === 'bower')) {
27+
return exec(command + ' ' + args.join(' '));
28+
}
29+
30+
options = defaults(options, {
31+
32+
onOutput(string) {
33+
options.log(string);
34+
},
35+
36+
onError(string) {
37+
options.log(chalk.red(string));
38+
},
39+
40+
log(string) {
41+
debug(string);
42+
43+
logOnFailure(string);
44+
}
45+
});
46+
47+
return new Promise((resolve, reject) => {
48+
let opts = {};
49+
if (isWindows) {
50+
args = ['"' + command + '"'].concat(args);
51+
command = 'node';
52+
opts.windowsVerbatimArguments = true;
53+
opts.stdio = [null, null, null, 'ipc'];
54+
}
55+
let child = spawn(command, args, opts);
56+
let result = {
57+
output: [],
58+
errors: [],
59+
code: null
60+
};
61+
62+
if (options.onChildSpawned) {
63+
let onChildSpawnedPromise = new Promise((childSpawnedResolve, childSpawnedReject) => {
64+
try {
65+
options.onChildSpawned(child).then(childSpawnedResolve, childSpawnedReject);
66+
} catch (err) {
67+
childSpawnedReject(err);
68+
}
69+
});
70+
onChildSpawnedPromise
71+
.then(() => {
72+
if (options.killAfterChildSpawnedPromiseResolution) {
73+
killCliProcess(child);
74+
}
75+
}, err => {
76+
result.testingError = err;
77+
if (options.killAfterChildSpawnedPromiseResolution) {
78+
killCliProcess(child);
79+
}
80+
});
81+
}
82+
83+
child.stdout.on('data', data => {
84+
let string = data.toString();
85+
86+
options.onOutput(string, child);
87+
88+
result.output.push(string);
89+
});
90+
91+
child.stderr.on('data', data => {
92+
let string = data.toString();
93+
94+
options.onError(string, child);
95+
96+
result.errors.push(string);
97+
});
98+
99+
child.on('close', (code, signal) => {
100+
result.code = code;
101+
result.signal = signal;
102+
103+
if (code === 0) {
104+
resolve(result);
105+
} else {
106+
reject(result);
107+
}
108+
});
109+
});
110+
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
3+
const path = require('path');
4+
const findup = require('findup-sync');
5+
const runCommand = require('./run-command');
6+
7+
module.exports = function(command, options) {
8+
let emberCLIPath = findup('node_modules/ember-cli');
9+
10+
let args = [path.join(emberCLIPath, 'bin', 'ember'), command].concat(options);
11+
12+
return runCommand.apply(undefined, args);
13+
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
'use strict';
2+
3+
const debug = require('./debug');
4+
const runEmber = require('./run-ember');
5+
const defaults = require('lodash/defaults');
6+
7+
module.exports = function runServer(options) {
8+
return new Promise((resolve, reject) => {
9+
options = options || { };
10+
11+
defaults(options, {
12+
port: '49741',
13+
command: 'server',
14+
detectServerStart
15+
});
16+
17+
let args = [
18+
'--port', options.port
19+
];
20+
21+
if (options.additionalArguments) {
22+
args = args.concat(options.additionalArguments);
23+
}
24+
25+
let longRunningServerPromise;
26+
27+
let commandOptions = {
28+
verbose: true,
29+
30+
onOutput(output, child) {
31+
if (options.detectServerStart(output)) {
32+
resolve({
33+
server: child,
34+
longRunningServerPromise
35+
});
36+
}
37+
}
38+
};
39+
40+
args.push(commandOptions);
41+
42+
debug('starting server; command=%s; port=%s', options.command, options.port);
43+
44+
longRunningServerPromise = runEmber(options.command, args)
45+
.then(() => {
46+
throw new Error('The server should not have exited successfully.');
47+
})
48+
.catch(reject);
49+
});
50+
};
51+
52+
function detectServerStart(output) {
53+
let indicators = [
54+
'Ember FastBoot running at',
55+
'Build successful'
56+
];
57+
58+
for (let indicator of indicators) {
59+
if (output.indexOf(indicator) > -1) {
60+
return true;
61+
}
62+
}
63+
}

0 commit comments

Comments
 (0)