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

Commit

Permalink
feat(runner/frameworks): Change interface contract of the protractor …
Browse files Browse the repository at this point in the history
…runner instance so that it returns a promise instead of calling a callback function
  • Loading branch information
kayhadrin authored and hankduan committed Oct 2, 2014
1 parent 0626963 commit 710cad7
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 74 deletions.
7 changes: 4 additions & 3 deletions lib/frameworks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ Each file details the adapter for one test framework. Each file must export a `r
/**
* @param {Runner} runner The Protractor runner instance.
* @param {Array.<string>} specs A list of absolute filenames.
* @param {Function} done A callback for when tests are finished.
* @return {q.Promise} Promise resolved with the test results
*/
exports.run = function(runner, specs, done)
exports.run = function(runner, specs)
```

Requirements
Expand All @@ -23,4 +23,5 @@ Requirements

- `runner.getConfig().onComplete` must be called when tests are finished.

- When finished, `done` must be invoked and passed a results object. This object must have a `failedCount` property.
- The returned promise must be resolved when tests are finished and it should return a results object.
This object must have a `failedCount` property.
31 changes: 19 additions & 12 deletions lib/frameworks/cucumber.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
var ConfigParser = require('../configParser');
var ConfigParser = require('../configParser'),
q = require('q');

/**
* Execute the Runner's test cases through Cucumber.
*
* @param {Runner} runner The current Protractor Runner.
* @param {Array} specs Array of Directory Path Strings.
* @param done A callback for when tests are finished.
* @return {q.Promise} Promise resolved with the test results
*/
exports.run = function(runner, specs, done) {
exports.run = function(runner, specs) {
// TODO - add the event interface for cucumber.
var Cucumber = require('cucumber'),
execOptions = ['node', 'node_modules/.bin/cucumber-js'],
Expand Down Expand Up @@ -57,15 +58,21 @@ exports.run = function(runner, specs, done) {
}
global.cucumber = Cucumber.Cli(execOptions);

runner.runTestPreparers().then(function() {
global.cucumber.run(function(succeeded) {
if (runner.getConfig().onComplete) {
runner.getConfig().onComplete();
}
var resolvedObj = {
failedCount: succeeded ? 0 : 1
};
done(resolvedObj);
return runner.runTestPreparers().then(function () {
return q.promise(function (resolve, reject) {
global.cucumber.run(function (succeeded) {
try {
if (runner.getConfig().onComplete) {
runner.getConfig().onComplete();
}
var resolvedObj = {
failedCount: succeeded ? 0 : 1
};
resolve(resolvedObj);
} catch (err) {
reject(err);
}
});
});
});
};
15 changes: 9 additions & 6 deletions lib/frameworks/debugprint.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
var util = require('util');
var util = require('util'),
q = require('q');

/**
* A debug framework which does not actually run any tests, just spits
* out the list that would be run.
*
* @param {Runner} runner The current Protractor Runner.
* @param {Array} specs Array of Directory Path Strings.
* @param done A callback for when tests are finished.
* @return {q.Promise} Promise resolved with the test results
*/
exports.run = function(runner, specs, done) {
console.log('Resolved spec files: ' + util.inspect(specs));
done({
failedCount: 0
exports.run = function(runner, specs) {
return q.promise(function (resolve) {
console.log('Resolved spec files: ' + util.inspect(specs));
resolve({
failedCount: 0
});
});
};
37 changes: 23 additions & 14 deletions lib/frameworks/jasmine.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
var q = require('q');

/**
* Execute the Runner's test cases through Jasmine.
*
* @param {Runner} runner The current Protractor Runner.
* @param {Array} specs Array of Directory Path Strings.
* @param done A callback for when tests are finished.
* @return {q.Promise} Promise resolved with the test results
*/
exports.run = function(runner, specs, done) {
exports.run = function(runner, specs) {
var minijn = require('minijasminenode');

require('jasminewd');
Expand Down Expand Up @@ -35,17 +37,24 @@ exports.run = function(runner, specs, done) {
// get to complete first.
jasmine.getEnv().addReporter(new RunnerReporter(runner));

runner.runTestPreparers().then(function() {
var jasmineNodeOpts = runner.getConfig().jasmineNodeOpts;
var originalOnComplete = runner.getConfig().onComplete;
jasmineNodeOpts.onComplete = function(jasmineRunner, log) {
if (originalOnComplete) {
originalOnComplete(jasmineRunner, log);
}
done(jasmineRunner.results());
};

minijn.addSpecs(specs);
minijn.executeSpecs(jasmineNodeOpts);
return runner.runTestPreparers().then(function() {
return q.promise(function (resolve, reject) {
var jasmineNodeOpts = runner.getConfig().jasmineNodeOpts;
var originalOnComplete = runner.getConfig().onComplete;

jasmineNodeOpts.onComplete = function(jasmineRunner, log) {
try {
if (originalOnComplete) {
originalOnComplete(jasmineRunner, log);
}
resolve(jasmineRunner.results());
} catch(err) {
reject(err);
}
};

minijn.addSpecs(specs);
minijn.executeSpecs(jasmineNodeOpts);
});
});
};
71 changes: 43 additions & 28 deletions lib/frameworks/mocha.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,43 @@
var q = require('q');

/**
* Execute the Runner's test cases through Mocha.
*
* @param {Runner} runner The current Protractor Runner.
* @param {Array} specs Array of Directory Path Strings.
* @param done A callback for when tests are finished.
* @return {q.Promise} Promise resolved with the test results
*/
exports.run = function(runner, specs, done) {

exports.run = function(runner, specs) {
var Mocha = require('mocha'),
mocha = new Mocha(runner.getConfig().mochaOpts);

var deferred = q.defer();

// Mocha doesn't set up the ui until the pre-require event, so
// wait until then to load mocha-webdriver adapters as well.
mocha.suite.on('pre-require', function() {
// We need to re-wrap all of the global functions, which selenium-webdriver/
// testing only does when it is required. So first we must remove it from
// the cache.
delete require.cache[require.resolve('selenium-webdriver/testing')];
var mochaAdapters = require('selenium-webdriver/testing');
global.after = mochaAdapters.after;
global.afterEach = mochaAdapters.afterEach;
global.before = mochaAdapters.before;
global.beforeEach = mochaAdapters.beforeEach;

// The implementation of mocha's it.only uses global.it, so since that has
// already been wrapped we must avoid wrapping it a second time.
// See Mocha.prototype.loadFiles and bdd's context.it.only for more details.
var originalOnly = global.it.only;
global.it = mochaAdapters.it;
global.it.only = global.iit = originalOnly;

global.it.skip = global.xit = mochaAdapters.xit;
try {
// We need to re-wrap all of the global functions, which selenium-webdriver/
// testing only does when it is required. So first we must remove it from
// the cache.
delete require.cache[require.resolve('selenium-webdriver/testing')];
var mochaAdapters = require('selenium-webdriver/testing');
global.after = mochaAdapters.after;
global.afterEach = mochaAdapters.afterEach;
global.before = mochaAdapters.before;
global.beforeEach = mochaAdapters.beforeEach;

// The implementation of mocha's it.only uses global.it, so since that has
// already been wrapped we must avoid wrapping it a second time.
// See Mocha.prototype.loadFiles and bdd's context.it.only for more details.
var originalOnly = global.it.only;
global.it = mochaAdapters.it;
global.it.only = global.iit = originalOnly;

global.it.skip = global.xit = mochaAdapters.xit;
}catch(err){
deferred.reject(err);
}
});

mocha.suite.on('pass', function() {
Expand All @@ -50,14 +57,22 @@ exports.run = function(runner, specs, done) {
});

mocha.run(function(failures) {
if (runner.getConfig().onComplete) {
runner.getConfig().onComplete();
}
var resolvedObj = {
failedCount: failures
};
try {
if (runner.getConfig().onComplete) {
runner.getConfig().onComplete();
}
var resolvedObj = {
failedCount: failures
};

done(resolvedObj);
deferred.resolve(resolvedObj);
}catch(err){
deferred.reject(err);
}
});
}).catch(function(reason){
deferred.reject(reason);
});

return deferred.promise;
};
14 changes: 10 additions & 4 deletions lib/launcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@ var child = require('child_process'),
ConfigParser = require('./configParser'),
TaskScheduler = require('./taskScheduler');

var launcherPrefix = '[launcher] ';
var launcherPrefix = '[launcher]';
var RUNNERS_FAILED_EXIT_CODE = 100;

var log_ = function(stuff) {
console.log(launcherPrefix + stuff);
/**
* Custom console.log proxy
* @param {*} [stuff...] Any value to log
* @private
*/
var log_ = function() {
var args = [launcherPrefix].concat([].slice.call(arguments));
console.log.apply(console, args);
};

/**
Expand Down Expand Up @@ -137,7 +143,7 @@ var init = function(configFile, additionalConfig) {
runner.run().then(function(exitCode) {
process.exit(exitCode);
}).catch(function(err) {
log_('Error: ' + err.message);
log_('Error:', err.stack || err.message || err);
process.exit(1);
});
} else {
Expand Down
9 changes: 2 additions & 7 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ Runner.prototype.run = function() {
this.registerTestPreparer(this.config_.onPrepare);

// 1) Setup environment
//noinspection JSValidateTypes
return this.driverprovider_.setupEnv().then(function() {
return q.all(
[self.config_.capabilities, self.config_.multiCapabilities]).
Expand All @@ -244,7 +245,6 @@ Runner.prototype.run = function() {
.setScriptTimeout(self.config_.allScriptsTimeout);
// 3) Execute test cases
}).then(function() {
var deferred = q.defer();
self.setupGlobals_.bind(self)(driver);

// Do the framework setup here so that jasmine and mocha globals are
Expand All @@ -262,12 +262,7 @@ Runner.prototype.run = function() {
throw new Error('config.framework (' + self.config_.framework +
') is not a valid framework.');
}
require(frameworkPath).run(self, specs, function(result) {
deferred.resolve(result);
});

return deferred.promise;

return require(frameworkPath).run(self, specs);
// 4) Teardown
}).then(function(result) {
self.emit('testsDone', result.failedCount);
Expand Down

0 comments on commit 710cad7

Please sign in to comment.