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

Commit

Permalink
refactor(runner): split cli into cli and runner
Browse files Browse the repository at this point in the history
Split the cli.js file into a file which actually ony handles
command line processing and a runner.js file which handles
starting up selenium, running the tests, interacting with
minijasminenode, and test shutdown. Closes #17
  • Loading branch information
juliemr committed Oct 21, 2013
1 parent 2da5abb commit 20d8247
Show file tree
Hide file tree
Showing 2 changed files with 259 additions and 182 deletions.
198 changes: 16 additions & 182 deletions lib/cli.js
Original file line number Diff line number Diff line change
@@ -1,190 +1,30 @@
var util = require('util');
var path = require('path')
var fs = require('fs');
var webdriver = require('selenium-webdriver');
var remote = require('selenium-webdriver/remote');
var minijn = require('minijasminenode');
var protractor = require('./protractor.js');
var SauceLabs = require('saucelabs');
var runner = require('./runner.js');
var glob = require('glob');

var args = process.argv.slice(2);
var configDir, configPath;
/**
* The command line interface for interacting with the Protractor runner.
* It takes care of parsing the config file and command line options.
*/

var merge = function(into, from) {
for (key in from) {
if (into[key] instanceof Object) {
merge(into[key], from[key]);
} else {
into[key] = from[key];
}
}
};

// Default configuration.
var config = {
seleniumServerJar: null,
seleniumArgs: [],
seleniumPort: null,
seleniumAddress: null,
allScriptsTimeout: 11000,
capabilities: {
'browserName': 'chrome'
},
rootElement: 'body',
jasmineNodeOpts: {
isVerbose: false,
showColors: true,
includeStackTrace: true
}
}

var originalOnComplete;
var server;
var driver;
var id;

var cleanUp = function(runner, log) {
if (originalOnComplete) {
originalOnComplete(runner, log);
}

var passed = runner.results().failedCount == 0;
var exitCode = passed ? 0 : 1;
var args = process.argv.slice(2);
var configPath;

driver.quit().then(function() {
if (sauceAccount) {
sauceAccount.updateJob(id, {'passed': passed}, function(err) {
if (err) {
throw new Error(
"Error updating Sauce pass/fail status: " + util.inspect(err)
);
}
process.exit(exitCode);
});
} else if (server) {
util.puts('Shutting down selenium standalone server');
server.stop().then(function() {
process.exit(exitCode);
});
} else {
process.exit(exitCode);
}
});
};

var printVersion = function () {
util.puts('Version ' + JSON.parse(
fs.readFileSync(__dirname + '/../package.json', 'utf8')).version);
process.exit(0);
};

var run = function() {
if (config.jasmineNodeOpts.specFolders) {
throw new Error('Using config.jasmineNodeOpts.specFolders is deprecated ' +
'in Protractor 0.6.0. Please switch to config.specs.');
}
var specs = config.specs;
var resolvedSpecs = [];
for (var i = 0; i < specs.length; ++i) {
var matches = glob.sync(specs[i], {cwd: configDir});
if (!matches.length) {
throw new Error('Test file ' + specs[i] + ' did not match any files.');
}
for (var j = 0; j < matches.length; ++j) {
resolvedSpecs.push(path.resolve(configDir, matches[j]));
}
}
minijn.addSpecs(resolvedSpecs);

if (config.sauceUser && config.sauceKey) {
config.capabilities.username = config.sauceUser;
config.capabilities.accessKey = config.sauceKey;
if (!config.jasmineNodeOpts.defaultTimeoutInterval) {
config.jasmineNodeOpts.defaultTimeoutInterval = 30 * 1000;
}
config.seleniumAddress = 'http://' + config.sauceUser + ':' +
config.sauceKey + '@ondemand.saucelabs.com:80/wd/hub';

util.puts('Using SauceLabs selenium server at ' + config.seleniumAddress);
startJasmineTests();
} else if (config.seleniumAddress) {

util.puts('Using the selenium server at ' + config.seleniumAddress);
startJasmineTests();
} else if (config.seleniumServerJar) {
util.puts('Starting selenium standalone server...');
if (config.chromeDriver) {
if (!fs.existsSync(config.chromeDriver)) {
if (fs.existsSync(config.chromeDriver + '.exe')) {
config.chromeDriver += '.exe';
} else {
throw 'Could not find chromedriver at ' + config.chromeDriver;
}
}
config.seleniumArgs.push(
'-Dwebdriver.chrome.driver=' + config.chromeDriver);
}
server = new remote.SeleniumServer(config.seleniumServerJar, {
args: config.seleniumArgs,
port: config.seleniumPort
});
server.start().then(function(url) {

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

var startJasmineTests = function() {
driver = new webdriver.Builder().
usingServer(config.seleniumAddress).
withCapabilities(config.capabilities).build();

driver.getSession().then(function(session) {
driver.manage().timeouts().setScriptTimeout(config.allScriptsTimeout);

id = session.getId();

protractor.setInstance(protractor.wrapDriver(driver, config.baseUrl, config.rootElement));

// Export protractor to the global namespace to be used in tests.
global.protractor = protractor;

// Set up the Jasmine WebDriver Adapter.
require('../jasminewd');

var options = config.jasmineNodeOpts;
originalOnComplete = options.onComplete;
options.onComplete = cleanUp;

// Let the configuration configure the protractor instance before running
// the tests.
webdriver.promise.controlFlow().execute(function() {
if (config.onPrepare) {
if (typeof config.onPrepare == 'function') {
config.onPrepare();
} else if (typeof config.onPrepare == 'string') {
require(path.resolve(process.cwd(), config.onPrepare));
} else {
throw 'config.onPrepare must be a string or function';
}
}
}).then(function() {
minijn.executeSpecs(options);
});
});
}

if (!args.length) {
util.puts('USAGE: protractor configFile [options]');
util.puts('USAGE: protractor [configFile] [options]');
util.puts('Options:');
util.puts(' --version: Print Protractor version');
util.puts(' --browser <string>: Browsername, e.g. chrome or firefox');
util.puts(' --seleniumAddress <string>: A running selenium address to use');
util.puts(' --seleniumServerJar <string>: Location of the standalone selenium server .jar file');
util.puts(' --seleniumPort <string>: Optional port for the standalone selenium server');
Expand Down Expand Up @@ -232,6 +72,9 @@ while(args.length) {
case '--seleniumPort':
commandLineConfig.seleniumPort = args.shift();
break;
case '--chromeDriver':
commandLineConfig.chromeDriver = args.shift();
break;
case '--sauceUser':
commandLineConfig.sauceUser = args.shift();
break;
Expand Down Expand Up @@ -262,24 +105,15 @@ while(args.length) {
break;
default:
configPath = path.resolve(process.cwd(), arg);
configDir = path.dirname(configPath);
break;
}
}

if (configPath) {
merge(config, require(configPath).config);
} else {
configDir = "./";
runner.addConfig(require(configPath).config);
runner.addConfig({specFileBase: path.dirname(configPath)})
}
merge(config, commandLineConfig);

var sauceAccount;
if (config.sauceUser && config.sauceKey) {
sauceAccount = new SauceLabs({
username: config.sauceUser,
password: config.sauceKey
});
}
runner.addConfig(commandLineConfig);

run();
runner.runOnce();
Loading

0 comments on commit 20d8247

Please sign in to comment.