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

Commit 20d8247

Browse files
committed
refactor(runner): split cli into cli and runner
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
1 parent 2da5abb commit 20d8247

File tree

2 files changed

+259
-182
lines changed

2 files changed

+259
-182
lines changed

lib/cli.js

+16-182
Original file line numberDiff line numberDiff line change
@@ -1,190 +1,30 @@
11
var util = require('util');
22
var path = require('path')
33
var fs = require('fs');
4-
var webdriver = require('selenium-webdriver');
5-
var remote = require('selenium-webdriver/remote');
6-
var minijn = require('minijasminenode');
7-
var protractor = require('./protractor.js');
8-
var SauceLabs = require('saucelabs');
4+
var runner = require('./runner.js');
95
var glob = require('glob');
106

11-
var args = process.argv.slice(2);
12-
var configDir, configPath;
7+
/**
8+
* The command line interface for interacting with the Protractor runner.
9+
* It takes care of parsing the config file and command line options.
10+
*/
1311

14-
var merge = function(into, from) {
15-
for (key in from) {
16-
if (into[key] instanceof Object) {
17-
merge(into[key], from[key]);
18-
} else {
19-
into[key] = from[key];
20-
}
21-
}
22-
};
23-
24-
// Default configuration.
25-
var config = {
26-
seleniumServerJar: null,
27-
seleniumArgs: [],
28-
seleniumPort: null,
29-
seleniumAddress: null,
30-
allScriptsTimeout: 11000,
31-
capabilities: {
32-
'browserName': 'chrome'
33-
},
34-
rootElement: 'body',
35-
jasmineNodeOpts: {
36-
isVerbose: false,
37-
showColors: true,
38-
includeStackTrace: true
39-
}
40-
}
41-
42-
var originalOnComplete;
43-
var server;
44-
var driver;
45-
var id;
46-
47-
var cleanUp = function(runner, log) {
48-
if (originalOnComplete) {
49-
originalOnComplete(runner, log);
50-
}
51-
52-
var passed = runner.results().failedCount == 0;
53-
var exitCode = passed ? 0 : 1;
12+
var args = process.argv.slice(2);
13+
var configPath;
5414

55-
driver.quit().then(function() {
56-
if (sauceAccount) {
57-
sauceAccount.updateJob(id, {'passed': passed}, function(err) {
58-
if (err) {
59-
throw new Error(
60-
"Error updating Sauce pass/fail status: " + util.inspect(err)
61-
);
62-
}
63-
process.exit(exitCode);
64-
});
65-
} else if (server) {
66-
util.puts('Shutting down selenium standalone server');
67-
server.stop().then(function() {
68-
process.exit(exitCode);
69-
});
70-
} else {
71-
process.exit(exitCode);
72-
}
73-
});
74-
};
7515

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

82-
var run = function() {
83-
if (config.jasmineNodeOpts.specFolders) {
84-
throw new Error('Using config.jasmineNodeOpts.specFolders is deprecated ' +
85-
'in Protractor 0.6.0. Please switch to config.specs.');
86-
}
87-
var specs = config.specs;
88-
var resolvedSpecs = [];
89-
for (var i = 0; i < specs.length; ++i) {
90-
var matches = glob.sync(specs[i], {cwd: configDir});
91-
if (!matches.length) {
92-
throw new Error('Test file ' + specs[i] + ' did not match any files.');
93-
}
94-
for (var j = 0; j < matches.length; ++j) {
95-
resolvedSpecs.push(path.resolve(configDir, matches[j]));
96-
}
97-
}
98-
minijn.addSpecs(resolvedSpecs);
99-
100-
if (config.sauceUser && config.sauceKey) {
101-
config.capabilities.username = config.sauceUser;
102-
config.capabilities.accessKey = config.sauceKey;
103-
if (!config.jasmineNodeOpts.defaultTimeoutInterval) {
104-
config.jasmineNodeOpts.defaultTimeoutInterval = 30 * 1000;
105-
}
106-
config.seleniumAddress = 'http://' + config.sauceUser + ':' +
107-
config.sauceKey + '@ondemand.saucelabs.com:80/wd/hub';
108-
109-
util.puts('Using SauceLabs selenium server at ' + config.seleniumAddress);
110-
startJasmineTests();
111-
} else if (config.seleniumAddress) {
112-
113-
util.puts('Using the selenium server at ' + config.seleniumAddress);
114-
startJasmineTests();
115-
} else if (config.seleniumServerJar) {
116-
util.puts('Starting selenium standalone server...');
117-
if (config.chromeDriver) {
118-
if (!fs.existsSync(config.chromeDriver)) {
119-
if (fs.existsSync(config.chromeDriver + '.exe')) {
120-
config.chromeDriver += '.exe';
121-
} else {
122-
throw 'Could not find chromedriver at ' + config.chromeDriver;
123-
}
124-
}
125-
config.seleniumArgs.push(
126-
'-Dwebdriver.chrome.driver=' + config.chromeDriver);
127-
}
128-
server = new remote.SeleniumServer(config.seleniumServerJar, {
129-
args: config.seleniumArgs,
130-
port: config.seleniumPort
131-
});
132-
server.start().then(function(url) {
133-
134-
util.puts('Selenium standalone server started at ' + url);
135-
config.seleniumAddress = server.address();
136-
startJasmineTests();
137-
});
138-
} else {
139-
throw new Error('You must specify either a seleniumAddress, ' +
140-
'seleniumServerJar, or saucelabs account.');
141-
}
142-
}
143-
144-
var startJasmineTests = function() {
145-
driver = new webdriver.Builder().
146-
usingServer(config.seleniumAddress).
147-
withCapabilities(config.capabilities).build();
148-
149-
driver.getSession().then(function(session) {
150-
driver.manage().timeouts().setScriptTimeout(config.allScriptsTimeout);
151-
152-
id = session.getId();
153-
154-
protractor.setInstance(protractor.wrapDriver(driver, config.baseUrl, config.rootElement));
155-
156-
// Export protractor to the global namespace to be used in tests.
157-
global.protractor = protractor;
158-
159-
// Set up the Jasmine WebDriver Adapter.
160-
require('../jasminewd');
161-
162-
var options = config.jasmineNodeOpts;
163-
originalOnComplete = options.onComplete;
164-
options.onComplete = cleanUp;
165-
166-
// Let the configuration configure the protractor instance before running
167-
// the tests.
168-
webdriver.promise.controlFlow().execute(function() {
169-
if (config.onPrepare) {
170-
if (typeof config.onPrepare == 'function') {
171-
config.onPrepare();
172-
} else if (typeof config.onPrepare == 'string') {
173-
require(path.resolve(process.cwd(), config.onPrepare));
174-
} else {
175-
throw 'config.onPrepare must be a string or function';
176-
}
177-
}
178-
}).then(function() {
179-
minijn.executeSpecs(options);
180-
});
181-
});
182-
}
18322

18423
if (!args.length) {
185-
util.puts('USAGE: protractor configFile [options]');
24+
util.puts('USAGE: protractor [configFile] [options]');
18625
util.puts('Options:');
18726
util.puts(' --version: Print Protractor version');
27+
util.puts(' --browser <string>: Browsername, e.g. chrome or firefox');
18828
util.puts(' --seleniumAddress <string>: A running selenium address to use');
18929
util.puts(' --seleniumServerJar <string>: Location of the standalone selenium server .jar file');
19030
util.puts(' --seleniumPort <string>: Optional port for the standalone selenium server');
@@ -232,6 +72,9 @@ while(args.length) {
23272
case '--seleniumPort':
23373
commandLineConfig.seleniumPort = args.shift();
23474
break;
75+
case '--chromeDriver':
76+
commandLineConfig.chromeDriver = args.shift();
77+
break;
23578
case '--sauceUser':
23679
commandLineConfig.sauceUser = args.shift();
23780
break;
@@ -262,24 +105,15 @@ while(args.length) {
262105
break;
263106
default:
264107
configPath = path.resolve(process.cwd(), arg);
265-
configDir = path.dirname(configPath);
266108
break;
267109
}
268110
}
269111

270112
if (configPath) {
271-
merge(config, require(configPath).config);
272-
} else {
273-
configDir = "./";
113+
runner.addConfig(require(configPath).config);
114+
runner.addConfig({specFileBase: path.dirname(configPath)})
274115
}
275-
merge(config, commandLineConfig);
276116

277-
var sauceAccount;
278-
if (config.sauceUser && config.sauceKey) {
279-
sauceAccount = new SauceLabs({
280-
username: config.sauceUser,
281-
password: config.sauceKey
282-
});
283-
}
117+
runner.addConfig(commandLineConfig);
284118

285-
run();
119+
runner.runOnce();

0 commit comments

Comments
 (0)