Skip to content
This repository was archived by the owner on Jul 29, 2024. It is now read-only.

Commit f1db8b4

Browse files
committed
feat(runner): make runner an event emitter and log passes or failures from the launcher
Now, for runs with multiple capabilities, the launcher will output '.' or 'F' for each pass or fail instead of just '.' for every chunk of data. TODO - complete the event emitter API for the Cucumber runner.
1 parent 423c1a7 commit f1db8b4

File tree

3 files changed

+75
-6
lines changed

3 files changed

+75
-6
lines changed

lib/launcher.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -137,17 +137,13 @@ var init = function(argv) {
137137
childForks.forEach(function(childFork) {
138138

139139
childFork.process = child.fork(
140-
__dirname + "/runFromLauncher.js", [],
140+
__dirname + "/runFromLauncher.js", process.argv.slice(2),
141141
{silent: true, cwd: process.cwd()});
142142

143143
childFork.output = '';
144144

145145
// stdin pipe
146146
childFork.process.stdout.on('data', function(chunk) {
147-
// Output something so processes know we haven't stalled.
148-
// TODO - consider replacing this with a message system which would
149-
// output a dot per test.
150-
process.stdout.write('.');
151147
childFork.output += chunk;
152148
});
153149

@@ -156,6 +152,17 @@ var init = function(argv) {
156152
childFork.output += chunk;
157153
});
158154

155+
childFork.process.on('message', function(m) {
156+
switch (m.event) {
157+
case 'testPass':
158+
process.stdout.write('.');
159+
break;
160+
case 'testFail':
161+
process.stdout.write('F');
162+
break;
163+
}
164+
});
165+
159166
// err handler
160167
childFork.process.on('error', function(err) {
161168
log_('Runner Process(' + childFork.process.pid + ') Error: ' + err);

lib/runFromLauncher.js

+19
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,25 @@ process.on('message', function(m) {
2929

3030
// Launch test run.
3131
var runner = new Runner(config);
32+
33+
// Pipe events back to the launcher.
34+
runner.on('testPass', function() {
35+
process.send({
36+
event: 'testPass'
37+
});
38+
});
39+
runner.on('testFail', function() {
40+
process.send({
41+
event: 'testFail'
42+
});
43+
});
44+
runner.on('testsDone', function(results) {
45+
process.send({
46+
event: 'testsDone',
47+
results: results
48+
});
49+
});
50+
3251
runner.run().then(function(exitCode) {
3352
process.exit(exitCode);
3453
}).catch(function(err) {

lib/runner.js

+44-1
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@ var protractor = require('./protractor'),
44
path = require('path'),
55
util = require('util'),
66
fs = require('fs'),
7-
q = require('q');
7+
q = require('q'),
8+
EventEmitter = require('events').EventEmitter;
89

910
/*
1011
* Runner is responsible for starting the execution of a test run and triggering
1112
* setup, teardown, managing config, etc through its various dependencies.
1213
*
14+
* The Protractor Runner is a node EventEmitter with the following events:
15+
* - testPass
16+
* - testFail
17+
* - testsDone
18+
*
1319
* @param {Object} config
1420
* @constructor
1521
*/
@@ -42,6 +48,8 @@ var Runner = function(config) {
4248
this.loadDriverProvider_(config);
4349
};
4450

51+
util.inherits(Runner, EventEmitter);
52+
4553

4654
/**
4755
* Execute the Runner's test cases through Jasmine.
@@ -55,6 +63,31 @@ Runner.prototype.runJasmine_ = function(specs, done) {
5563
self = this;
5664

5765
require('../jasminewd');
66+
67+
var RunnerReporter = function(emitter) {
68+
this.emitter = emitter;
69+
};
70+
71+
RunnerReporter.prototype.reportRunnerStarting = function() {};
72+
RunnerReporter.prototype.reportRunnerResults = function() {};
73+
RunnerReporter.prototype.reportSuiteResults = function() {};
74+
RunnerReporter.prototype.reportSpecStarting = function() {};
75+
RunnerReporter.prototype.reportSpecResults = function(spec) {
76+
if (spec.results().passed()) {
77+
this.emitter.emit('testPass');
78+
} else {
79+
this.emitter.emit('testFail');
80+
}
81+
};
82+
RunnerReporter.prototype.log = function() {};
83+
84+
// On timeout, the flow should be reset. This will prevent webdriver tasks
85+
// from overflowing into the next test and causing it to fail or timeout
86+
// as well. This is done in the reporter instead of an afterEach block
87+
// to ensure that it runs after any afterEach() blocks with webdriver tasks
88+
// get to complete first.
89+
jasmine.getEnv().addReporter(new RunnerReporter(this));
90+
5891
webdriver.promise.controlFlow().execute(function() {
5992
self.runTestPreparers_();
6093
}, 'run test preparers').then(function() {
@@ -101,6 +134,14 @@ Runner.prototype.runMocha_ = function(specs, done) {
101134
global.it.skip = global.xit = mochaAdapters.xit;
102135
});
103136

137+
mocha.suite.on('pass', function() {
138+
this.emit('testPass');
139+
});
140+
141+
mocha.suite.on('fail', function() {
142+
this.emit('testFail');
143+
});
144+
104145
mocha.loadFiles();
105146

106147
webdriver.promise.controlFlow().execute(function() {
@@ -132,6 +173,7 @@ Runner.prototype.runMocha_ = function(specs, done) {
132173
* @param done A callback for when tests are finished.
133174
*/
134175
Runner.prototype.runCucumber_ = function(specs, done) {
176+
// TODO - add the event interface for cucumber.
135177
var Cucumber = require('cucumber'),
136178
self = this,
137179
execOptions = ['node', 'node_modules/.bin/cucumber-js'],
@@ -371,6 +413,7 @@ Runner.prototype.run = function() {
371413

372414
// 3) Teardown
373415
}).then(function(result) {
416+
self.emit('testsDone', result);
374417
testResult = result;
375418
if (self.driverprovider_.updateJob) {
376419
return self.driverprovider_.updateJob({

0 commit comments

Comments
 (0)