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

Commit 710cad7

Browse files
kayhadrinhankduan
authored andcommitted
feat(runner/frameworks): Change interface contract of the protractor runner instance so that it returns a promise instead of calling a callback function
1 parent 0626963 commit 710cad7

File tree

7 files changed

+110
-74
lines changed

7 files changed

+110
-74
lines changed

lib/frameworks/README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ Each file details the adapter for one test framework. Each file must export a `r
99
/**
1010
* @param {Runner} runner The Protractor runner instance.
1111
* @param {Array.<string>} specs A list of absolute filenames.
12-
* @param {Function} done A callback for when tests are finished.
12+
* @return {q.Promise} Promise resolved with the test results
1313
*/
14-
exports.run = function(runner, specs, done)
14+
exports.run = function(runner, specs)
1515
```
1616

1717
Requirements
@@ -23,4 +23,5 @@ Requirements
2323

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

26-
- When finished, `done` must be invoked and passed a results object. This object must have a `failedCount` property.
26+
- The returned promise must be resolved when tests are finished and it should return a results object.
27+
This object must have a `failedCount` property.

lib/frameworks/cucumber.js

+19-12
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
var ConfigParser = require('../configParser');
1+
var ConfigParser = require('../configParser'),
2+
q = require('q');
23

34
/**
45
* Execute the Runner's test cases through Cucumber.
56
*
67
* @param {Runner} runner The current Protractor Runner.
78
* @param {Array} specs Array of Directory Path Strings.
8-
* @param done A callback for when tests are finished.
9+
* @return {q.Promise} Promise resolved with the test results
910
*/
10-
exports.run = function(runner, specs, done) {
11+
exports.run = function(runner, specs) {
1112
// TODO - add the event interface for cucumber.
1213
var Cucumber = require('cucumber'),
1314
execOptions = ['node', 'node_modules/.bin/cucumber-js'],
@@ -57,15 +58,21 @@ exports.run = function(runner, specs, done) {
5758
}
5859
global.cucumber = Cucumber.Cli(execOptions);
5960

60-
runner.runTestPreparers().then(function() {
61-
global.cucumber.run(function(succeeded) {
62-
if (runner.getConfig().onComplete) {
63-
runner.getConfig().onComplete();
64-
}
65-
var resolvedObj = {
66-
failedCount: succeeded ? 0 : 1
67-
};
68-
done(resolvedObj);
61+
return runner.runTestPreparers().then(function () {
62+
return q.promise(function (resolve, reject) {
63+
global.cucumber.run(function (succeeded) {
64+
try {
65+
if (runner.getConfig().onComplete) {
66+
runner.getConfig().onComplete();
67+
}
68+
var resolvedObj = {
69+
failedCount: succeeded ? 0 : 1
70+
};
71+
resolve(resolvedObj);
72+
} catch (err) {
73+
reject(err);
74+
}
75+
});
6976
});
7077
});
7178
};

lib/frameworks/debugprint.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
var util = require('util');
1+
var util = require('util'),
2+
q = require('q');
23

34
/**
45
* A debug framework which does not actually run any tests, just spits
56
* out the list that would be run.
67
*
78
* @param {Runner} runner The current Protractor Runner.
89
* @param {Array} specs Array of Directory Path Strings.
9-
* @param done A callback for when tests are finished.
10+
* @return {q.Promise} Promise resolved with the test results
1011
*/
11-
exports.run = function(runner, specs, done) {
12-
console.log('Resolved spec files: ' + util.inspect(specs));
13-
done({
14-
failedCount: 0
12+
exports.run = function(runner, specs) {
13+
return q.promise(function (resolve) {
14+
console.log('Resolved spec files: ' + util.inspect(specs));
15+
resolve({
16+
failedCount: 0
17+
});
1518
});
1619
};

lib/frameworks/jasmine.js

+23-14
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
var q = require('q');
2+
13
/**
24
* Execute the Runner's test cases through Jasmine.
35
*
46
* @param {Runner} runner The current Protractor Runner.
57
* @param {Array} specs Array of Directory Path Strings.
6-
* @param done A callback for when tests are finished.
8+
* @return {q.Promise} Promise resolved with the test results
79
*/
8-
exports.run = function(runner, specs, done) {
10+
exports.run = function(runner, specs) {
911
var minijn = require('minijasminenode');
1012

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

38-
runner.runTestPreparers().then(function() {
39-
var jasmineNodeOpts = runner.getConfig().jasmineNodeOpts;
40-
var originalOnComplete = runner.getConfig().onComplete;
41-
jasmineNodeOpts.onComplete = function(jasmineRunner, log) {
42-
if (originalOnComplete) {
43-
originalOnComplete(jasmineRunner, log);
44-
}
45-
done(jasmineRunner.results());
46-
};
47-
48-
minijn.addSpecs(specs);
49-
minijn.executeSpecs(jasmineNodeOpts);
40+
return runner.runTestPreparers().then(function() {
41+
return q.promise(function (resolve, reject) {
42+
var jasmineNodeOpts = runner.getConfig().jasmineNodeOpts;
43+
var originalOnComplete = runner.getConfig().onComplete;
44+
45+
jasmineNodeOpts.onComplete = function(jasmineRunner, log) {
46+
try {
47+
if (originalOnComplete) {
48+
originalOnComplete(jasmineRunner, log);
49+
}
50+
resolve(jasmineRunner.results());
51+
} catch(err) {
52+
reject(err);
53+
}
54+
};
55+
56+
minijn.addSpecs(specs);
57+
minijn.executeSpecs(jasmineNodeOpts);
58+
});
5059
});
5160
};

lib/frameworks/mocha.js

+43-28
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,43 @@
1+
var q = require('q');
2+
13
/**
24
* Execute the Runner's test cases through Mocha.
35
*
46
* @param {Runner} runner The current Protractor Runner.
57
* @param {Array} specs Array of Directory Path Strings.
6-
* @param done A callback for when tests are finished.
8+
* @return {q.Promise} Promise resolved with the test results
79
*/
8-
exports.run = function(runner, specs, done) {
9-
10+
exports.run = function(runner, specs) {
1011
var Mocha = require('mocha'),
1112
mocha = new Mocha(runner.getConfig().mochaOpts);
1213

14+
var deferred = q.defer();
15+
1316
// Mocha doesn't set up the ui until the pre-require event, so
1417
// wait until then to load mocha-webdriver adapters as well.
1518
mocha.suite.on('pre-require', function() {
16-
// We need to re-wrap all of the global functions, which selenium-webdriver/
17-
// testing only does when it is required. So first we must remove it from
18-
// the cache.
19-
delete require.cache[require.resolve('selenium-webdriver/testing')];
20-
var mochaAdapters = require('selenium-webdriver/testing');
21-
global.after = mochaAdapters.after;
22-
global.afterEach = mochaAdapters.afterEach;
23-
global.before = mochaAdapters.before;
24-
global.beforeEach = mochaAdapters.beforeEach;
25-
26-
// The implementation of mocha's it.only uses global.it, so since that has
27-
// already been wrapped we must avoid wrapping it a second time.
28-
// See Mocha.prototype.loadFiles and bdd's context.it.only for more details.
29-
var originalOnly = global.it.only;
30-
global.it = mochaAdapters.it;
31-
global.it.only = global.iit = originalOnly;
32-
33-
global.it.skip = global.xit = mochaAdapters.xit;
19+
try {
20+
// We need to re-wrap all of the global functions, which selenium-webdriver/
21+
// testing only does when it is required. So first we must remove it from
22+
// the cache.
23+
delete require.cache[require.resolve('selenium-webdriver/testing')];
24+
var mochaAdapters = require('selenium-webdriver/testing');
25+
global.after = mochaAdapters.after;
26+
global.afterEach = mochaAdapters.afterEach;
27+
global.before = mochaAdapters.before;
28+
global.beforeEach = mochaAdapters.beforeEach;
29+
30+
// The implementation of mocha's it.only uses global.it, so since that has
31+
// already been wrapped we must avoid wrapping it a second time.
32+
// See Mocha.prototype.loadFiles and bdd's context.it.only for more details.
33+
var originalOnly = global.it.only;
34+
global.it = mochaAdapters.it;
35+
global.it.only = global.iit = originalOnly;
36+
37+
global.it.skip = global.xit = mochaAdapters.xit;
38+
}catch(err){
39+
deferred.reject(err);
40+
}
3441
});
3542

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

5259
mocha.run(function(failures) {
53-
if (runner.getConfig().onComplete) {
54-
runner.getConfig().onComplete();
55-
}
56-
var resolvedObj = {
57-
failedCount: failures
58-
};
60+
try {
61+
if (runner.getConfig().onComplete) {
62+
runner.getConfig().onComplete();
63+
}
64+
var resolvedObj = {
65+
failedCount: failures
66+
};
5967

60-
done(resolvedObj);
68+
deferred.resolve(resolvedObj);
69+
}catch(err){
70+
deferred.reject(err);
71+
}
6172
});
73+
}).catch(function(reason){
74+
deferred.reject(reason);
6275
});
76+
77+
return deferred.promise;
6378
};

lib/launcher.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@ var child = require('child_process'),
88
ConfigParser = require('./configParser'),
99
TaskScheduler = require('./taskScheduler');
1010

11-
var launcherPrefix = '[launcher] ';
11+
var launcherPrefix = '[launcher]';
1212
var RUNNERS_FAILED_EXIT_CODE = 100;
1313

14-
var log_ = function(stuff) {
15-
console.log(launcherPrefix + stuff);
14+
/**
15+
* Custom console.log proxy
16+
* @param {*} [stuff...] Any value to log
17+
* @private
18+
*/
19+
var log_ = function() {
20+
var args = [launcherPrefix].concat([].slice.call(arguments));
21+
console.log.apply(console, args);
1622
};
1723

1824
/**
@@ -137,7 +143,7 @@ var init = function(configFile, additionalConfig) {
137143
runner.run().then(function(exitCode) {
138144
process.exit(exitCode);
139145
}).catch(function(err) {
140-
log_('Error: ' + err.message);
146+
log_('Error:', err.stack || err.message || err);
141147
process.exit(1);
142148
});
143149
} else {

lib/runner.js

+2-7
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ Runner.prototype.run = function() {
228228
this.registerTestPreparer(this.config_.onPrepare);
229229

230230
// 1) Setup environment
231+
//noinspection JSValidateTypes
231232
return this.driverprovider_.setupEnv().then(function() {
232233
return q.all(
233234
[self.config_.capabilities, self.config_.multiCapabilities]).
@@ -244,7 +245,6 @@ Runner.prototype.run = function() {
244245
.setScriptTimeout(self.config_.allScriptsTimeout);
245246
// 3) Execute test cases
246247
}).then(function() {
247-
var deferred = q.defer();
248248
self.setupGlobals_.bind(self)(driver);
249249

250250
// Do the framework setup here so that jasmine and mocha globals are
@@ -262,12 +262,7 @@ Runner.prototype.run = function() {
262262
throw new Error('config.framework (' + self.config_.framework +
263263
') is not a valid framework.');
264264
}
265-
require(frameworkPath).run(self, specs, function(result) {
266-
deferred.resolve(result);
267-
});
268-
269-
return deferred.promise;
270-
265+
return require(frameworkPath).run(self, specs);
271266
// 4) Teardown
272267
}).then(function(result) {
273268
self.emit('testsDone', result.failedCount);

0 commit comments

Comments
 (0)