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

Commit

Permalink
fix(runner): exit with proper code when tests fail
Browse files Browse the repository at this point in the history
When errors with messages matching /timeout/ were created, Protractor
clears the control flow so that the remainder of the tasks scheduled
for that spec don't bleed over into the next spec. This was messing up
the promises used in the runner, since they are also webdriver promises.
Long term, the runner should _not_ use webdriver promises. For now, fix by
having the runner resolve promises directly rather than through chaining,
and add a TODO to use promises which aren't connected to WebDriver's
control flow in the runner.

Closes #214.
  • Loading branch information
juliemr committed Nov 4, 2013
1 parent ebc528f commit 8ff4787
Showing 1 changed file with 19 additions and 11 deletions.
30 changes: 19 additions & 11 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ var cleanUp = function(runner) {
* the value of the selenium address that will be used.
*/
var setUpSelenium = function() {
var promise = webdriver.promise.defer();
// TODO: This should not be tied to the webdriver promise loop, it should use
// another promise system instead.
var deferred = webdriver.promise.defer();

if (config.sauceUser && config.sauceKey) {
sauceAccount = new SauceLabs({
Expand All @@ -110,7 +112,7 @@ var setUpSelenium = function() {

if (config.seleniumAddress) {
util.puts('Using the selenium server at ' + config.seleniumAddress);
promise.fulfill(config.seleniumAddress);
deferred.fulfill(config.seleniumAddress);
} else if (sauceAccount) {
config.capabilities.username = config.sauceUser;
config.capabilities.accessKey = config.sauceKey;
Expand All @@ -121,7 +123,7 @@ var setUpSelenium = function() {
config.sauceKey + '@ondemand.saucelabs.com:80/wd/hub';

util.puts('Using SauceLabs selenium server at ' + config.seleniumAddress);
promise.fulfill(config.seleniumAddress);
deferred.fulfill(config.seleniumAddress);
} else if (config.seleniumServerJar) {
util.puts('Starting selenium standalone server...');
if (config.chromeDriver) {
Expand All @@ -143,14 +145,14 @@ var setUpSelenium = function() {

util.puts('Selenium standalone server started at ' + url);
config.seleniumAddress = server.address();
promise.fulfill(config.seleniumAddress);
deferred.fulfill(config.seleniumAddress);
});
} else {
throw new Error('You must specify either a seleniumAddress, ' +
'seleniumServerJar, or saucelabs account.');
}

return promise;
return deferred.promise;
}

/**
Expand Down Expand Up @@ -181,7 +183,9 @@ var runJasmineTests = function() {
}

minijn.addSpecs(resolvedSpecs);
var runPromise = webdriver.promise.defer();
// TODO: This should not be tied to the webdriver promise loop, it should use
// another promise system instead.
var runDeferred = webdriver.promise.defer();
driver = new webdriver.Builder().
usingServer(config.seleniumAddress).
withCapabilities(config.capabilities).build();
Expand Down Expand Up @@ -227,25 +231,29 @@ var runJasmineTests = function() {
originalOnComplete(runner, log);
}
driver.quit().then(function() {
runPromise.fulfill(runner);
runDeferred.fulfill(runner);
});
};

minijn.executeSpecs(options);
});
});

return runPromise;
return runDeferred.promise;
};


/**
* Run Protractor once.
*/
var runOnce = function() {
setUpSelenium().
then(runJasmineTests).
then(cleanUp);
setUpSelenium().then(function() {
// cleanUp must be registered directly onto runJasmineTests, not onto
// the chained promise, so that cleanUp is still called in case of a
// timeout error. Timeout errors need to clear the control flow, which
// would mess up chaining promises.
runJasmineTests().then(cleanUp);
});
};

exports.addConfig = addConfig;
Expand Down

0 comments on commit 8ff4787

Please sign in to comment.