Remove IIFE in test/saucelabs.js.

This commit is contained in:
John-David Dalton
2014-04-28 08:41:24 -07:00
parent 2c4657355f
commit 3efa9d2030

View File

@@ -1,63 +1,61 @@
#!/usr/bin/env node #!/usr/bin/env node
;(function() { 'use strict';
'use strict';
/** Environment shortcut */ /** Environment shortcut */
var env = process.env; var env = process.env;
if (isFinite(env.TRAVIS_PULL_REQUEST)) { if (isFinite(env.TRAVIS_PULL_REQUEST)) {
console.log('Skipping Sauce Labs jobs for pull requests'); console.log('Skipping Sauce Labs jobs for pull requests');
process.exit(0); process.exit(0);
} }
/** Load Node.js modules */ /** Load Node.js modules */
var EventEmitter = require('events').EventEmitter, var EventEmitter = require('events').EventEmitter,
http = require('http'), http = require('http'),
path = require('path'), path = require('path'),
url = require('url'); url = require('url');
/** Load other modules */ /** Load other modules */
var _ = require('../lodash.js'), var _ = require('../lodash.js'),
chalk = require('chalk'), chalk = require('chalk'),
ecstatic = require('ecstatic'), ecstatic = require('ecstatic'),
request = require('request'), request = require('request'),
SauceTunnel = require('sauce-tunnel-sc3-1'); SauceTunnel = require('sauce-tunnel-sc3-1');
/** Used for Sauce Labs credentials */ /** Used for Sauce Labs credentials */
var accessKey = env.SAUCE_ACCESS_KEY, var accessKey = env.SAUCE_ACCESS_KEY,
username = env.SAUCE_USERNAME; username = env.SAUCE_USERNAME;
/** Used as the maximum number of times to retry a job */ /** Used as the maximum number of times to retry a job */
var maxRetries = 3; var maxRetries = 3;
/** Used as the static file server middleware */ /** Used as the static file server middleware */
var mount = ecstatic({ var mount = ecstatic({
'cache': false, 'cache': false,
'root': process.cwd() 'root': process.cwd()
}); });
/** Used as the list of ports supported by Sauce Connect */ /** Used as the list of ports supported by Sauce Connect */
var ports = [ var ports = [
80, 443, 888, 2000, 2001, 2020, 2109, 2222, 2310, 3000, 3001, 3030, 3210, 80, 443, 888, 2000, 2001, 2020, 2109, 2222, 2310, 3000, 3001, 3030, 3210,
3333, 4000, 4001, 4040, 4321, 4502, 4503, 4567, 5000, 5001, 5050, 5555, 5432, 3333, 4000, 4001, 4040, 4321, 4502, 4503, 4567, 5000, 5001, 5050, 5555, 5432,
6000, 6001, 6060, 6666, 6543, 7000, 7070, 7774, 7777, 8000, 8001, 8003, 8031, 6000, 6001, 6060, 6666, 6543, 7000, 7070, 7774, 7777, 8000, 8001, 8003, 8031,
8080, 8081, 8765, 8777, 8888, 9000, 9001, 9080, 9090, 9876, 9877, 9999, 49221, 8080, 8081, 8765, 8777, 8888, 9000, 9001, 9080, 9090, 9876, 9877, 9999, 49221,
55001 55001
]; ];
/** Used by `logInline` to clear previously logged messages */ /** Used by `logInline` to clear previously logged messages */
var prevLine = ''; var prevLine = '';
/** Used to detect error messages */ /** Used to detect error messages */
var reError = /\berror\b/i; var reError = /\berror\b/i;
/** Used to display the wait throbber */ /** Used to display the wait throbber */
var throbberId, var throbberDelay = 500,
throbberDelay = 500,
waitCount = -1; waitCount = -1;
/** Used as Sauce Labs config values */ /** Used as Sauce Labs config values */
var advisor = getOption('advisor', true), var advisor = getOption('advisor', true),
build = getOption('build', env.TRAVIS_COMMIT.slice(0, 10)), build = getOption('build', env.TRAVIS_COMMIT.slice(0, 10)),
compatMode = getOption('compatMode', null), compatMode = getOption('compatMode', null),
customData = Function('return {' + getOption('customData', '').replace(/^\{|}$/g, '') + '}')(), customData = Function('return {' + getOption('customData', '').replace(/^\{|}$/g, '') + '}')(),
@@ -78,14 +76,14 @@
tunnelTimeout = getOption('tunnelTimeout', 10000), tunnelTimeout = getOption('tunnelTimeout', 10000),
videoUploadOnPass = getOption('videoUploadOnPass', false); videoUploadOnPass = getOption('videoUploadOnPass', false);
/** Used to convert Sauce Labs browser identifiers to their formal names */ /** Used to convert Sauce Labs browser identifiers to their formal names */
var browserNameMap = { var browserNameMap = {
'googlechrome': 'Chrome', 'googlechrome': 'Chrome',
'iehta': 'Internet Explorer' 'iehta': 'Internet Explorer'
}; };
/** List of platforms to load the runner on */ /** List of platforms to load the runner on */
var platforms = [ var platforms = [
['Linux', 'android', '4.3'], ['Linux', 'android', '4.3'],
['OS X 10.9', 'iphone', '7.1'], ['OS X 10.9', 'iphone', '7.1'],
['OS X 10.9', 'ipad', '7.1'], ['OS X 10.9', 'ipad', '7.1'],
@@ -106,25 +104,25 @@
['OS X 10.9', 'safari', '7'], ['OS X 10.9', 'safari', '7'],
['OS X 10.8', 'safari', '6'], ['OS X 10.8', 'safari', '6'],
['OS X 10.6', 'safari', '5'] ['OS X 10.6', 'safari', '5']
]; ];
/** Used to tailor the `platforms` array */ /** Used to tailor the `platforms` array */
var runnerQuery = url.parse(runner, true).query, var runnerQuery = url.parse(runner, true).query,
isBackbone = /\bbackbone\b/i.test(runner), isBackbone = /\bbackbone\b/i.test(runner),
isMobile = /\bmobile\b/i.test(runnerQuery.build), isMobile = /\bmobile\b/i.test(runnerQuery.build),
isModern = /\bmodern\b/i.test(runnerQuery.build); isModern = /\bmodern\b/i.test(runnerQuery.build);
// platforms to test IE compat mode // platforms to test IE compat mode
if (compatMode) { if (compatMode) {
platforms = [ platforms = [
['Windows 8.1', 'internet explorer', '11'], ['Windows 8.1', 'internet explorer', '11'],
['Windows 8', 'internet explorer', '10'], ['Windows 8', 'internet explorer', '10'],
['Windows 7', 'internet explorer', '9'], ['Windows 7', 'internet explorer', '9'],
['Windows 7', 'internet explorer', '8'] ['Windows 7', 'internet explorer', '8']
]; ];
} }
// platforms for AMD tests // platforms for AMD tests
if (_.contains(tags, 'amd')) { if (_.contains(tags, 'amd')) {
platforms = platforms.filter(function(platform) { platforms = platforms.filter(function(platform) {
var browser = platform[1], var browser = platform[1],
version = +platform[2]; version = +platform[2];
@@ -134,9 +132,9 @@
} }
return true; return true;
}); });
} }
// platforms for Backbone tests // platforms for Backbone tests
if (isBackbone) { if (isBackbone) {
platforms = platforms.filter(function(platform) { platforms = platforms.filter(function(platform) {
var browser = platform[1], var browser = platform[1],
version = +platform[2]; version = +platform[2];
@@ -147,9 +145,9 @@
} }
return true; return true;
}); });
} }
// platforms for mobile and modern builds // platforms for mobile and modern builds
if (isMobile || isModern) { if (isMobile || isModern) {
platforms = platforms.filter(function(platform) { platforms = platforms.filter(function(platform) {
var browser = platform[1], var browser = platform[1],
version = +platform[2]; version = +platform[2];
@@ -162,10 +160,10 @@
} }
return true; return true;
}); });
} }
/** Used as the default `Job` options object */ /** Used as the default `Job` options object */
var defaultOptions = { var defaultOptions = {
'build': build, 'build': build,
'custom-data': customData, 'custom-data': customData,
'framework': framework, 'framework': framework,
@@ -180,40 +178,40 @@
'tags': tags, 'tags': tags,
'url': runnerUrl, 'url': runnerUrl,
'video-upload-on-pass': videoUploadOnPass 'video-upload-on-pass': videoUploadOnPass
}; };
if (publicAccess === true) { if (publicAccess === true) {
defaultOptions['public'] = 'public'; defaultOptions['public'] = 'public';
} }
if (tunneled) { if (tunneled) {
defaultOptions['tunnel-identifier'] = tunnelId; defaultOptions['tunnel-identifier'] = tunnelId;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
* Resolves the formal browser name for a given Sauce Labs browser identifier. * Resolves the formal browser name for a given Sauce Labs browser identifier.
* *
* @private * @private
* @param {string} identifier The browser identifier. * @param {string} identifier The browser identifier.
* @returns {string} Returns the formal browser name. * @returns {string} Returns the formal browser name.
*/ */
function browserName(identifier) { function browserName(identifier) {
return capitalizeWords(browserNameMap[identifier] || identifier); return capitalizeWords(browserNameMap[identifier] || identifier);
} }
/** /**
* Capitalizes the first character of each word in `string`. * Capitalizes the first character of each word in `string`.
* *
* @private * @private
* @param {string} string The string to augment. * @param {string} string The string to augment.
* @returns {string} Returns the augmented string. * @returns {string} Returns the augmented string.
*/ */
function capitalizeWords(string) { function capitalizeWords(string) {
return _.map(string.split(' '), _.capitalize).join(' '); return _.map(string.split(' '), _.capitalize).join(' ');
} }
/** /**
* Gets the value for the given option name. If no value is available the * Gets the value for the given option name. If no value is available the
* `defaultValue` is returned. * `defaultValue` is returned.
* *
@@ -222,7 +220,7 @@
* @param {*} defaultValue The default option value. * @param {*} defaultValue The default option value.
* @returns {*} Returns the option value. * @returns {*} Returns the option value.
*/ */
function getOption(name, defaultValue) { function getOption(name, defaultValue) {
var isArr = _.isArray(defaultValue); var isArr = _.isArray(defaultValue);
return _.reduce(process.argv, function(result, value) { return _.reduce(process.argv, function(result, value) {
if (isArr) { if (isArr) {
@@ -233,30 +231,30 @@
return value == null ? result : value; return value == null ? result : value;
}, defaultValue); }, defaultValue);
} }
/** /**
* Writes an inline message to standard output. * Writes an inline message to standard output.
* *
* @private * @private
* @param {string} text The text to log. * @param {string} text The text to log.
*/ */
function logInline(text) { function logInline(text) {
var blankLine = _.repeat(' ', _.size(prevLine)); var blankLine = _.repeat(' ', _.size(prevLine));
prevLine = text = _.truncate(text, 40); prevLine = text = _.truncate(text, 40);
process.stdout.write(text + blankLine.slice(text.length) + '\r'); process.stdout.write(text + blankLine.slice(text.length) + '\r');
} }
/** /**
* Writes the wait throbber to standard output. * Writes the wait throbber to standard output.
* *
* @private * @private
*/ */
function logThrobber() { function logThrobber() {
logInline('Please wait' + _.repeat('.', (++waitCount % 3) + 1)); logInline('Please wait' + _.repeat('.', (++waitCount % 3) + 1));
} }
/** /**
* Converts a comma separated option value into an array. * Converts a comma separated option value into an array.
* *
* @private * @private
@@ -264,11 +262,11 @@
* @param {string} string The options string. * @param {string} string The options string.
* @returns {Array} Returns the new converted array. * @returns {Array} Returns the new converted array.
*/ */
function optionToArray(name, string) { function optionToArray(name, string) {
return _.compact(_.invoke((optionToValue(name, string) || '').split(/, */), 'trim')); return _.compact(_.invoke((optionToValue(name, string) || '').split(/, */), 'trim'));
} }
/** /**
* Extracts the option value from an option string. * Extracts the option value from an option string.
* *
* @private * @private
@@ -276,29 +274,29 @@
* @param {string} string The options string. * @param {string} string The options string.
* @returns {string|undefined} Returns the option value, else `undefined`. * @returns {string|undefined} Returns the option value, else `undefined`.
*/ */
function optionToValue(name, string) { function optionToValue(name, string) {
var result = (result = string.match(RegExp('^' + name + '(?:=([\\s\\S]+))?$'))) && (result[1] ? result[1].trim() : true); var result = (result = string.match(RegExp('^' + name + '(?:=([\\s\\S]+))?$'))) && (result[1] ? result[1].trim() : true);
if (result === 'false') { if (result === 'false') {
return false; return false;
} }
return result || undefined; return result || undefined;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
* Used by the `onRun` callback to check the status of a job. * Used by the `onRun` callback to check the status of a job.
* *
* @private * @private
*/ */
function check() { function check() {
request.post('https://saucelabs.com/rest/v1/' + this.user + '/js-tests/status', { request.post('https://saucelabs.com/rest/v1/' + this.user + '/js-tests/status', {
'auth': { 'user': this.user, 'pass': this.pass }, 'auth': { 'user': this.user, 'pass': this.pass },
'json': { 'js tests': [this.id] } 'json': { 'js tests': [this.id] }
}, onCheck.bind(this)); }, onCheck.bind(this));
} }
/** /**
* The `request.post` callback used by `check`. * The `request.post` callback used by `check`.
* *
* @private * @private
@@ -306,7 +304,7 @@
* @param {Object} response The response data object. * @param {Object} response The response data object.
* @param {Object} body The response body JSON object. * @param {Object} body The response body JSON object.
*/ */
function onCheck(error, response, body) { function onCheck(error, response, body) {
var data = _.result(body, 'js tests', [{}])[0], var data = _.result(body, 'js tests', [{}])[0],
options = this.options, options = this.options,
platform = options.platforms[0], platform = options.platforms[0],
@@ -341,9 +339,9 @@
console.log(label, description, chalk.green('passed')); console.log(label, description, chalk.green('passed'));
} }
this.emit('complete'); this.emit('complete');
} }
/** /**
* The `request.post` callback used by `Jobs#run`. * The `request.post` callback used by `Jobs#run`.
* *
* @private * @private
@@ -351,7 +349,7 @@
* @param {Object} response The response data object. * @param {Object} response The response data object.
* @param {Object} body The response body JSON object. * @param {Object} body The response body JSON object.
*/ */
function onRun(error, response, body) { function onRun(error, response, body) {
var id = _.result(body, 'js tests', [])[0], var id = _.result(body, 'js tests', [])[0],
statusCode = _.result(response, 'statusCode'); statusCode = _.result(response, 'statusCode');
@@ -364,46 +362,46 @@
} }
this.id = id; this.id = id;
check.call(this); check.call(this);
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
* The Job constructor. * The Job constructor.
* *
* @private * @private
* @param {Object} [properties] The properties to initial a job with. * @param {Object} [properties] The properties to initial a job with.
*/ */
function Job(properties) { function Job(properties) {
EventEmitter.call(this); EventEmitter.call(this);
_.merge(this, { 'attempts': 0, 'options': {} }, properties); _.merge(this, { 'attempts': 0, 'options': {} }, properties);
_.defaults(this.options, _.cloneDeep(defaultOptions)); _.defaults(this.options, _.cloneDeep(defaultOptions));
} }
Job.prototype = _.create(EventEmitter.prototype); Job.prototype = _.create(EventEmitter.prototype);
/** /**
* Runs the job on Sauce Labs. * Runs the job on Sauce Labs.
* *
* @private * @private
*/ */
Job.prototype.run = function() { Job.prototype.run = function() {
request.post('https://saucelabs.com/rest/v1/' + this.user + '/js-tests', { request.post('https://saucelabs.com/rest/v1/' + this.user + '/js-tests', {
'auth': { 'user': this.user, 'pass': this.pass }, 'auth': { 'user': this.user, 'pass': this.pass },
'json': this.options 'json': this.options
}, onRun.bind(this)); }, onRun.bind(this));
}; };
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
* Runs jobs for the given platforms. * Runs jobs for the given platforms.
* *
* @private * @private
* @param {Array} platforms The platforms to run jobs for. * @param {Array} platforms The platforms to run jobs for.
* @param {Function} onComplete The function called once all jobs have completed. * @param {Function} onComplete The function called once all jobs have completed.
*/ */
function run(platforms, onComplete) { function run(platforms, onComplete) {
var jobs = _.map(platforms, function(platform) { var jobs = _.map(platforms, function(platform) {
return new Job({ return new Job({
'user': username, 'user': username,
@@ -426,29 +424,29 @@
console.log('Starting jobs...'); console.log('Starting jobs...');
_.invoke(jobs, 'run'); _.invoke(jobs, 'run');
} }
// cleanup any inline logs when exited via `ctrl+c` // cleanup any inline logs when exited via `ctrl+c`
process.on('SIGINT', function() { process.on('SIGINT', function() {
logInline(''); logInline('');
process.exit(); process.exit();
}); });
// create a web server for the local dir // create a web server for the local dir
http.createServer(function(req, res) { http.createServer(function(req, res) {
// see http://msdn.microsoft.com/en-us/library/ff955275(v=vs.85).aspx // see http://msdn.microsoft.com/en-us/library/ff955275(v=vs.85).aspx
if (compatMode && path.extname(url.parse(req.url).pathname) == '.html') { if (compatMode && path.extname(url.parse(req.url).pathname) == '.html') {
res.setHeader('X-UA-Compatible', 'IE=' + compatMode); res.setHeader('X-UA-Compatible', 'IE=' + compatMode);
} }
mount(req, res); mount(req, res);
}).listen(port); }).listen(port);
// set up Sauce Connect so we can use this server from Sauce Labs // set up Sauce Connect so we can use this server from Sauce Labs
var tunnel = new SauceTunnel(username, accessKey, tunnelId, tunneled, tunnelTimeout); var tunnel = new SauceTunnel(username, accessKey, tunnelId, tunneled, tunnelTimeout);
console.log('Opening Sauce Connect tunnel...'); console.log('Opening Sauce Connect tunnel...');
tunnel.start(function(success) { tunnel.start(function(success) {
if (!success) { if (!success) {
console.error('Failed to open Sauce Connect tunnel'); console.error('Failed to open Sauce Connect tunnel');
process.exit(2); process.exit(2);
@@ -457,11 +455,8 @@
run(platforms, function(success) { run(platforms, function(success) {
console.log('Shutting down Sauce Connect tunnel...'); console.log('Shutting down Sauce Connect tunnel...');
clearInterval(throbberId);
tunnel.stop(function() { process.exit(success ? 0 : 1); }); tunnel.stop(function() { process.exit(success ? 0 : 1); });
}); });
throbberId = setInterval(logThrobber, throbberDelay); setInterval(logThrobber, throbberDelay);
logThrobber(); });
});
}());