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

Commit

Permalink
feat(runner): make runner an event emitter and log passes or failures…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
juliemr committed Mar 13, 2014
1 parent 423c1a7 commit f1db8b4
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 6 deletions.
17 changes: 12 additions & 5 deletions lib/launcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,13 @@ var init = function(argv) {
childForks.forEach(function(childFork) {

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

childFork.output = '';

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

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

childFork.process.on('message', function(m) {
switch (m.event) {
case 'testPass':
process.stdout.write('.');
break;
case 'testFail':
process.stdout.write('F');
break;
}
});

// err handler
childFork.process.on('error', function(err) {
log_('Runner Process(' + childFork.process.pid + ') Error: ' + err);
Expand Down
19 changes: 19 additions & 0 deletions lib/runFromLauncher.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ process.on('message', function(m) {

// Launch test run.
var runner = new Runner(config);

// Pipe events back to the launcher.
runner.on('testPass', function() {
process.send({
event: 'testPass'
});
});
runner.on('testFail', function() {
process.send({
event: 'testFail'
});
});
runner.on('testsDone', function(results) {
process.send({
event: 'testsDone',
results: results
});
});

runner.run().then(function(exitCode) {
process.exit(exitCode);
}).catch(function(err) {
Expand Down
45 changes: 44 additions & 1 deletion lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ var protractor = require('./protractor'),
path = require('path'),
util = require('util'),
fs = require('fs'),
q = require('q');
q = require('q'),
EventEmitter = require('events').EventEmitter;

/*
* Runner is responsible for starting the execution of a test run and triggering
* setup, teardown, managing config, etc through its various dependencies.
*
* The Protractor Runner is a node EventEmitter with the following events:
* - testPass
* - testFail
* - testsDone
*
* @param {Object} config
* @constructor
*/
Expand Down Expand Up @@ -42,6 +48,8 @@ var Runner = function(config) {
this.loadDriverProvider_(config);
};

util.inherits(Runner, EventEmitter);


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

require('../jasminewd');

var RunnerReporter = function(emitter) {
this.emitter = emitter;
};

RunnerReporter.prototype.reportRunnerStarting = function() {};
RunnerReporter.prototype.reportRunnerResults = function() {};
RunnerReporter.prototype.reportSuiteResults = function() {};
RunnerReporter.prototype.reportSpecStarting = function() {};
RunnerReporter.prototype.reportSpecResults = function(spec) {
if (spec.results().passed()) {
this.emitter.emit('testPass');
} else {
this.emitter.emit('testFail');
}
};
RunnerReporter.prototype.log = function() {};

// On timeout, the flow should be reset. This will prevent webdriver tasks
// from overflowing into the next test and causing it to fail or timeout
// as well. This is done in the reporter instead of an afterEach block
// to ensure that it runs after any afterEach() blocks with webdriver tasks
// get to complete first.
jasmine.getEnv().addReporter(new RunnerReporter(this));

webdriver.promise.controlFlow().execute(function() {
self.runTestPreparers_();
}, 'run test preparers').then(function() {
Expand Down Expand Up @@ -101,6 +134,14 @@ Runner.prototype.runMocha_ = function(specs, done) {
global.it.skip = global.xit = mochaAdapters.xit;
});

mocha.suite.on('pass', function() {
this.emit('testPass');
});

mocha.suite.on('fail', function() {
this.emit('testFail');
});

mocha.loadFiles();

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

// 3) Teardown
}).then(function(result) {
self.emit('testsDone', result);
testResult = result;
if (self.driverprovider_.updateJob) {
return self.driverprovider_.updateJob({
Expand Down

0 comments on commit f1db8b4

Please sign in to comment.