saucelabs.js (lodash-3.0.0) | : | saucelabs.js (lodash-4.0.0) | ||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
} | } | |||
/** 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'), | |||
util = require('util'); | util = require('util'); | |||
/** Load other modules. */ | /** Load other modules. */ | |||
var _ = require('../lodash.src.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'); | SauceTunnel = require('sauce-tunnel'); | |||
/** 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 default maximum number of times to retry a job and tunnel. */ | /** Used as the default maximum number of times to retry a job and tunnel. */ | |||
skipping to change at line 79 | skipping to change at line 79 | |||
*/ | */ | |||
var advisor = getOption('advisor', false), | var advisor = getOption('advisor', false), | |||
build = getOption('build', (env.TRAVIS_COMMIT || '').slice(0, 10)), | build = getOption('build', (env.TRAVIS_COMMIT || '').slice(0, 10)), | |||
commandTimeout = getOption('commandTimeout', 90), | commandTimeout = getOption('commandTimeout', 90), | |||
compatMode = getOption('compatMode', null), | compatMode = getOption('compatMode', null), | |||
customData = Function('return {' + getOption('customData', '').replace(/^\{| }$/g, '') + '}')(), | customData = Function('return {' + getOption('customData', '').replace(/^\{| }$/g, '') + '}')(), | |||
deviceOrientation = getOption('deviceOrientation', 'portrait'), | deviceOrientation = getOption('deviceOrientation', 'portrait'), | |||
framework = getOption('framework', 'qunit'), | framework = getOption('framework', 'qunit'), | |||
idleTimeout = getOption('idleTimeout', 60), | idleTimeout = getOption('idleTimeout', 60), | |||
jobName = getOption('name', 'unit tests'), | jobName = getOption('name', 'unit tests'), | |||
maxDuration = getOption('maxDuration', 120), | maxDuration = getOption('maxDuration', 180), | |||
port = ports[Math.min(_.sortedIndex(ports, getOption('port', 9001)), ports.l ength - 1)], | port = ports[Math.min(_.sortedIndex(ports, getOption('port', 9001)), ports.l ength - 1)], | |||
publicAccess = getOption('public', true), | publicAccess = getOption('public', true), | |||
queueTimeout = getOption('queueTimeout', 240), | queueTimeout = getOption('queueTimeout', 240), | |||
recordVideo = getOption('recordVideo', true), | recordVideo = getOption('recordVideo', true), | |||
recordScreenshots = getOption('recordScreenshots', false), | recordScreenshots = getOption('recordScreenshots', false), | |||
runner = getOption('runner', 'test/index.html').replace(/^\W+/, ''), | runner = getOption('runner', 'test/index.html').replace(/^\W+/, ''), | |||
runnerUrl = getOption('runnerUrl', 'http://localhost:' + port + '/' + runner ), | runnerUrl = getOption('runnerUrl', 'http://localhost:' + port + '/' + runner ), | |||
statusInterval = getOption('statusInterval', 5), | statusInterval = getOption('statusInterval', 5), | |||
tags = getOption('tags', []), | tags = getOption('tags', []), | |||
throttled = getOption('throttled', 10), | throttled = getOption('throttled', 10), | |||
skipping to change at line 105 | skipping to change at line 105 | |||
/** 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', | |||
'ipad': 'iPad', | 'ipad': 'iPad', | |||
'iphone': 'iPhone' | 'iphone': 'iPhone' | |||
}; | }; | |||
/** 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', '5.1'], | |||
['Linux', 'android', '4.0'], | ['Windows 10', 'chrome', '47'], | |||
['Windows 8.1', 'firefox', '35'], | ['Windows 10', 'chrome', '46'], | |||
['Windows 8.1', 'firefox', '34'], | ['Windows 10', 'firefox', '43'], | |||
['Windows 8.1', 'firefox', '20'], | ['Windows 10', 'firefox', '42'], | |||
['Windows 8.1', 'chrome', '39'], | ['Windows 10', 'microsoftedge', '20.10240'], | |||
['Windows 8.1', 'chrome', '38'], | ['Windows 10', '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'], | // ['OS X 10.10', 'ipad', '9.1'], | |||
['Windows XP', 'internet explorer', '7'], | ['OS X 10.11', 'safari', '9'], | |||
['Windows XP', 'internet explorer', '6'], | ['OS X 10.10', 'safari', '8'] | |||
['Windows 7', 'opera', '12'], | ||||
['Windows 7', 'opera', '11'], | ||||
['OS X 10.9', 'ipad', '8.1'], | ||||
['OS X 10.6', 'ipad', '4'], | ||||
['OS X 10.10', 'safari', '8'], | ||||
['OS X 10.9', 'safari', '7'], | ||||
['OS X 10.8', 'safari', '6'], | ||||
['OS X 10.6', 'safari', '5'] | ||||
]; | ]; | |||
/** Used to tailor the `platforms` array. */ | /** Used to tailor the `platforms` array. */ | |||
var isAMD = _.includes(tags, 'amd'), | var isAMD = _.includes(tags, 'amd'), | |||
isBackbone = _.includes(tags, 'backbone'), | isBackbone = _.includes(tags, 'backbone'), | |||
isModern = _.includes(tags, 'modern'); | isModern = _.includes(tags, 'modern'); | |||
// The platforms to test IE compatibility modes. | // The platforms to test IE compatibility modes. | |||
if (compatMode) { | if (compatMode) { | |||
platforms = [ | platforms = [ | |||
['Windows 8.1', 'internet explorer', '11'], | ['Windows 10', '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'] | |||
]; | ]; | |||
} | } | |||
// The platforms for AMD tests. | // The platforms for AMD tests. | |||
if (isAMD) { | if (isAMD) { | |||
platforms = _.filter(platforms, function(platform) { | platforms = _.filter(platforms, function(platform) { | |||
var browser = browserName(platform[1]), | var browser = browserName(platform[1]), | |||
version = +platform[2]; | version = +platform[2]; | |||
skipping to change at line 163 | skipping to change at line 154 | |||
}); | }); | |||
} | } | |||
// The platforms for Backbone tests. | // The platforms for Backbone tests. | |||
if (isBackbone) { | if (isBackbone) { | |||
platforms = _.filter(platforms, function(platform) { | platforms = _.filter(platforms, function(platform) { | |||
var browser = browserName(platform[1]), | var browser = browserName(platform[1]), | |||
version = +platform[2]; | version = +platform[2]; | |||
switch (browser) { | switch (browser) { | |||
case 'Firefox': return version >= 4; | case 'Firefox': return version >= 4; | |||
case 'Internet Explorer': return version >= 7; | ||||
case 'iPad': return version >= 5; | case 'iPad': return version >= 5; | |||
case 'Opera': return version >= 12; | case 'Opera': return version >= 12; | |||
} | } | |||
return true; | return true; | |||
}); | }); | |||
} | } | |||
// The platforms for modern builds. | // The platforms for modern builds. | |||
if (isModern) { | if (isModern) { | |||
platforms = _.filter(platforms, function(platform) { | platforms = _.filter(platforms, function(platform) { | |||
var browser = browserName(platform[1]), | var browser = browserName(platform[1]), | |||
skipping to change at line 279 | skipping to change at line 271 | |||
} | } | |||
/** | /** | |||
* 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 = _.trunc(text, 40); | prevLine = text = _.truncate(text, { 'length': 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)); | |||
skipping to change at line 301 | skipping to change at line 293 | |||
/** | /** | |||
* Converts a comma separated option value into an array. | * Converts a comma separated option value into an array. | |||
* | * | |||
* @private | * @private | |||
* @param {string} name The name of the option to inspect. | * @param {string} name The name of the option to inspect. | |||
* @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(/, */), 't rim')); | return _.compact(_.invokeMap((optionToValue(name, string) || '').split(/, */), 'trim')); | |||
} | } | |||
/** | /** | |||
* Extracts the option value from an option string. | * Extracts the option value from an option string. | |||
* | * | |||
* @private | * @private | |||
* @param {string} name The name of the option to inspect. | * @param {string} name The name of the option to inspect. | |||
* @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`. | |||
*/ | */ | |||
skipping to change at line 545 | skipping to change at line 537 | |||
/** | /** | |||
* The Job constructor. | * The Job constructor. | |||
* | * | |||
* @private | * @private | |||
* @param {Object} [properties] The properties to initialize a job with. | * @param {Object} [properties] The properties to initialize a job with. | |||
*/ | */ | |||
function Job(properties) { | function Job(properties) { | |||
EventEmitter.call(this); | EventEmitter.call(this); | |||
this.options = {}; | this.options = {}; | |||
this.retries = maxJobRetries; | ||||
this.statusInterval = statusInterval; | ||||
_.merge(this, properties); | _.merge(this, properties); | |||
_.defaults(this.options, _.cloneDeep(jobOptions)); | _.defaults(this.options, _.cloneDeep(jobOptions)); | |||
this.attempts = 0; | this.attempts = 0; | |||
this.checking = this.failed = this.removing = this.resetting = this.restarting = this.running = this.starting = this.stopping = false; | this.checking = this.failed = this.removing = this.resetting = this.restarting = this.running = this.starting = this.stopping = false; | |||
this._pollerId = this.id = this.result = this.taskId = this.url = null; | this._pollerId = this.id = this.result = this.taskId = this.url = null; | |||
} | } | |||
util.inherits(Job, EventEmitter); | util.inherits(Job, EventEmitter); | |||
/** | /** | |||
* Removes the job. | * Removes the job. | |||
* | * | |||
* @memberOf Job | * @memberOf Job | |||
* @param {Function} callback The function called once the job is removed. | * @param {Function} callback The function called once the job is removed. | |||
* @param {Object} Returns the job instance. | * @param {Object} Returns the job instance. | |||
*/ | */ | |||
Job.prototype.remove = function(callback) { | Job.prototype.remove = function(callback) { | |||
this.once('remove', _.callback(callback)); | this.once('remove', _.iteratee(callback)); | |||
if (this.removing) { | if (this.removing) { | |||
return this; | return this; | |||
} | } | |||
this.removing = true; | this.removing = true; | |||
return this.stop(function() { | return this.stop(function() { | |||
var onRemove = _.bind(onJobRemove, this); | var onRemove = _.bind(onJobRemove, this); | |||
if (!this.id) { | if (!this.id) { | |||
_.defer(onRemove); | _.defer(onRemove); | |||
return; | return; | |||
} | } | |||
skipping to change at line 591 | skipping to change at line 580 | |||
}; | }; | |||
/** | /** | |||
* Resets the job. | * Resets the job. | |||
* | * | |||
* @memberOf Job | * @memberOf Job | |||
* @param {Function} callback The function called once the job is reset. | * @param {Function} callback The function called once the job is reset. | |||
* @param {Object} Returns the job instance. | * @param {Object} Returns the job instance. | |||
*/ | */ | |||
Job.prototype.reset = function(callback) { | Job.prototype.reset = function(callback) { | |||
this.once('reset', _.callback(callback)); | this.once('reset', _.iteratee(callback)); | |||
if (this.resetting) { | if (this.resetting) { | |||
return this; | return this; | |||
} | } | |||
this.resetting = true; | this.resetting = true; | |||
return this.remove(onJobReset); | return this.remove(onJobReset); | |||
}; | }; | |||
/** | /** | |||
* Restarts the job. | * Restarts the job. | |||
* | * | |||
* @memberOf Job | * @memberOf Job | |||
* @param {Function} callback The function called once the job is restarted. | * @param {Function} callback The function called once the job is restarted. | |||
* @param {Object} Returns the job instance. | * @param {Object} Returns the job instance. | |||
*/ | */ | |||
Job.prototype.restart = function(callback) { | Job.prototype.restart = function(callback) { | |||
this.once('restart', _.callback(callback)); | this.once('restart', _.iteratee(callback)); | |||
if (this.restarting) { | if (this.restarting) { | |||
return this; | return this; | |||
} | } | |||
this.restarting = true; | this.restarting = true; | |||
var options = this.options, | var options = this.options, | |||
platform = options.platforms[0], | platform = options.platforms[0], | |||
description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + capi talizeWords(platform[0]), | description = browserName(platform[1]) + ' ' + platform[2] + ' on ' + capi talizeWords(platform[0]), | |||
label = options.name + ':'; | label = options.name + ':'; | |||
skipping to change at line 632 | skipping to change at line 621 | |||
}; | }; | |||
/** | /** | |||
* Starts the job. | * Starts the job. | |||
* | * | |||
* @memberOf Job | * @memberOf Job | |||
* @param {Function} callback The function called once the job is started. | * @param {Function} callback The function called once the job is started. | |||
* @param {Object} Returns the job instance. | * @param {Object} Returns the job instance. | |||
*/ | */ | |||
Job.prototype.start = function(callback) { | Job.prototype.start = function(callback) { | |||
this.once('start', _.callback(callback)); | this.once('start', _.iteratee(callback)); | |||
if (this.starting || this.running) { | if (this.starting || this.running) { | |||
return this; | return this; | |||
} | } | |||
this.starting = true; | this.starting = true; | |||
request.post(_.template('https://saucelabs.com/rest/v1/${user}/js-tests')(this ), { | request.post(_.template('https://saucelabs.com/rest/v1/${user}/js-tests')(this ), { | |||
'auth': { 'user': this.user, 'pass': this.pass }, | 'auth': { 'user': this.user, 'pass': this.pass }, | |||
'json': this.options | 'json': this.options | |||
}, _.bind(onJobStart, this)); | }, _.bind(onJobStart, this)); | |||
return this; | return this; | |||
}; | }; | |||
/** | /** | |||
* Checks the status of a job. | * Checks the status of a job. | |||
* | * | |||
* @memberOf Job | * @memberOf Job | |||
* @param {Function} callback The function called once the status is resolved. | * @param {Function} callback The function called once the status is resolved. | |||
* @param {Object} Returns the job instance. | * @param {Object} Returns the job instance. | |||
*/ | */ | |||
Job.prototype.status = function(callback) { | Job.prototype.status = function(callback) { | |||
this.once('status', _.callback(callback)); | this.once('status', _.iteratee(callback)); | |||
if (this.checking || this.removing || this.resetting || this.restarting || thi s.starting || this.stopping) { | if (this.checking || this.removing || this.resetting || this.restarting || thi s.starting || this.stopping) { | |||
return this; | return this; | |||
} | } | |||
this._pollerId = null; | this._pollerId = null; | |||
this.checking = true; | this.checking = true; | |||
request.post(_.template('https://saucelabs.com/rest/v1/${user}/js-tests/status ')(this), { | request.post(_.template('https://saucelabs.com/rest/v1/${user}/js-tests/status ')(this), { | |||
'auth': { 'user': this.user, 'pass': this.pass }, | 'auth': { 'user': this.user, 'pass': this.pass }, | |||
'json': { 'js tests': [this.taskId] } | 'json': { 'js tests': [this.taskId] } | |||
}, _.bind(onJobStatus, this)); | }, _.bind(onJobStatus, this)); | |||
skipping to change at line 675 | skipping to change at line 664 | |||
}; | }; | |||
/** | /** | |||
* Stops the job. | * Stops the job. | |||
* | * | |||
* @memberOf Job | * @memberOf Job | |||
* @param {Function} callback The function called once the job is stopped. | * @param {Function} callback The function called once the job is stopped. | |||
* @param {Object} Returns the job instance. | * @param {Object} Returns the job instance. | |||
*/ | */ | |||
Job.prototype.stop = function(callback) { | Job.prototype.stop = function(callback) { | |||
this.once('stop', _.callback(callback)); | this.once('stop', _.iteratee(callback)); | |||
if (this.stopping) { | if (this.stopping) { | |||
return this; | return this; | |||
} | } | |||
this.stopping = true; | this.stopping = true; | |||
if (this._pollerId) { | if (this._pollerId) { | |||
clearTimeout(this._pollerId); | clearTimeout(this._pollerId); | |||
this._pollerId = null; | this._pollerId = null; | |||
this.checking = false; | this.checking = false; | |||
} | } | |||
var onStop = _.bind(onGenericStop, this); | var onStop = _.bind(onGenericStop, this); | |||
skipping to change at line 708 | skipping to change at line 697 | |||
/** | /** | |||
* The Tunnel constructor. | * The Tunnel constructor. | |||
* | * | |||
* @private | * @private | |||
* @param {Object} [properties] The properties to initialize the tunnel with. | * @param {Object} [properties] The properties to initialize the tunnel with. | |||
*/ | */ | |||
function Tunnel(properties) { | function Tunnel(properties) { | |||
EventEmitter.call(this); | EventEmitter.call(this); | |||
this.retries = maxTunnelRetries; | ||||
_.merge(this, properties); | _.merge(this, properties); | |||
var active = [], | var active = [], | |||
queue = []; | queue = []; | |||
var all = _.map(this.platforms, function(platform) { | var all = _.map(this.platforms, _.bind(function(platform) { | |||
return new Job(_.merge({ | return new Job(_.merge({ | |||
'user': this.user, | 'user': this.user, | |||
'pass': this.pass, | 'pass': this.pass, | |||
'tunnel': this, | 'tunnel': this, | |||
'options': { 'platforms': [platform] } | 'options': { 'platforms': [platform] } | |||
}, this.job)); | }, this.job)); | |||
}, this); | }, this)); | |||
var completed = 0, | var completed = 0, | |||
restarted = [], | restarted = [], | |||
success = true, | success = true, | |||
total = all.length, | total = all.length, | |||
tunnel = this; | tunnel = this; | |||
_.invoke(all, 'on', 'complete', function() { | _.invokeMap(all, 'on', 'complete', function() { | |||
_.pull(active, this); | _.pull(active, this); | |||
if (success) { | if (success) { | |||
success = !this.failed; | success = !this.failed; | |||
} | } | |||
if (++completed == total) { | if (++completed == total) { | |||
tunnel.stop(_.partial(tunnel.emit, 'complete', success)); | tunnel.stop(_.partial(tunnel.emit, 'complete', success)); | |||
return; | return; | |||
} | } | |||
tunnel.dequeue(); | tunnel.dequeue(); | |||
}); | }); | |||
_.invoke(all, 'on', 'restart', function() { | _.invokeMap(all, 'on', 'restart', function() { | |||
if (!_.includes(restarted, this)) { | if (!_.includes(restarted, this)) { | |||
restarted.push(this); | restarted.push(this); | |||
} | } | |||
// Restart tunnel if all active jobs have restarted. | // Restart tunnel if all active jobs have restarted. | |||
var threshold = Math.min(all.length, _.isFinite(throttled) ? throttled : 3); | var threshold = Math.min(all.length, _.isFinite(throttled) ? throttled : 3); | |||
if (tunnel.attempts < tunnel.retries && | if (tunnel.attempts < tunnel.retries && | |||
active.length >= threshold && _.isEmpty(_.difference(active, restarted)) ) { | active.length >= threshold && _.isEmpty(_.difference(active, restarted)) ) { | |||
tunnel.restart(); | tunnel.restart(); | |||
} | } | |||
}); | }); | |||
skipping to change at line 775 | skipping to change at line 763 | |||
util.inherits(Tunnel, EventEmitter); | util.inherits(Tunnel, EventEmitter); | |||
/** | /** | |||
* Restarts the tunnel. | * Restarts the tunnel. | |||
* | * | |||
* @memberOf Tunnel | * @memberOf Tunnel | |||
* @param {Function} callback The function called once the tunnel is restarted. | * @param {Function} callback The function called once the tunnel is restarted. | |||
*/ | */ | |||
Tunnel.prototype.restart = function(callback) { | Tunnel.prototype.restart = function(callback) { | |||
this.once('restart', _.callback(callback)); | this.once('restart', _.iteratee(callback)); | |||
if (this.restarting) { | if (this.restarting) { | |||
return this; | return this; | |||
} | } | |||
this.restarting = true; | this.restarting = true; | |||
logInline(); | logInline(); | |||
console.log('Tunnel %s: restart %d of %d', this.id, ++this.attempts, this.retr ies); | console.log('Tunnel %s: restart %d of %d', this.id, ++this.attempts, this.retr ies); | |||
var jobs = this.jobs, | var jobs = this.jobs, | |||
active = jobs.active, | active = jobs.active, | |||
all = jobs.all; | all = jobs.all; | |||
var reset = _.after(all.length, _.bind(this.stop, this, onGenericRestart)), | var reset = _.after(all.length, _.bind(this.stop, this, onGenericRestart)), | |||
stop = _.after(active.length, _.partial(_.invoke, all, 'reset', reset)); | stop = _.after(active.length, _.partial(_.invokeMap, all, 'reset', reset)) ; | |||
if (_.isEmpty(active)) { | if (_.isEmpty(active)) { | |||
_.defer(stop); | _.defer(stop); | |||
} | } | |||
if (_.isEmpty(all)) { | if (_.isEmpty(all)) { | |||
_.defer(reset); | _.defer(reset); | |||
} | } | |||
_.invoke(active, 'stop', function() { | _.invokeMap(active, 'stop', function() { | |||
_.pull(active, this); | _.pull(active, this); | |||
stop(); | stop(); | |||
}); | }); | |||
if (this._timeoutId) { | if (this._timeoutId) { | |||
clearTimeout(this._timeoutId); | clearTimeout(this._timeoutId); | |||
this._timeoutId = null; | this._timeoutId = null; | |||
} | } | |||
return this; | return this; | |||
}; | }; | |||
/** | /** | |||
* Starts the tunnel. | * Starts the tunnel. | |||
* | * | |||
* @memberOf Tunnel | * @memberOf Tunnel | |||
* @param {Function} callback The function called once the tunnel is started. | * @param {Function} callback The function called once the tunnel is started. | |||
* @param {Object} Returns the tunnel instance. | * @param {Object} Returns the tunnel instance. | |||
*/ | */ | |||
Tunnel.prototype.start = function(callback) { | Tunnel.prototype.start = function(callback) { | |||
this.once('start', _.callback(callback)); | this.once('start', _.iteratee(callback)); | |||
if (this.starting || this.running) { | if (this.starting || this.running) { | |||
return this; | return this; | |||
} | } | |||
this.starting = true; | this.starting = true; | |||
logInline(); | logInline(); | |||
console.log('Opening Sauce Connect tunnel...'); | console.log('Opening Sauce Connect tunnel...'); | |||
var onStart = _.bind(onTunnelStart, this); | var onStart = _.bind(onTunnelStart, this); | |||
if (this.timeout) { | if (this.timeout) { | |||
skipping to change at line 860 | skipping to change at line 848 | |||
}; | }; | |||
/** | /** | |||
* Stops the tunnel. | * Stops the tunnel. | |||
* | * | |||
* @memberOf Tunnel | * @memberOf Tunnel | |||
* @param {Function} callback The function called once the tunnel is stopped. | * @param {Function} callback The function called once the tunnel is stopped. | |||
* @param {Object} Returns the tunnel instance. | * @param {Object} Returns the tunnel instance. | |||
*/ | */ | |||
Tunnel.prototype.stop = function(callback) { | Tunnel.prototype.stop = function(callback) { | |||
this.once('stop', _.callback(callback)); | this.once('stop', _.iteratee(callback)); | |||
if (this.stopping) { | if (this.stopping) { | |||
return this; | return this; | |||
} | } | |||
this.stopping = true; | this.stopping = true; | |||
logInline(); | logInline(); | |||
console.log('Shutting down Sauce Connect tunnel...'); | console.log('Shutting down Sauce Connect tunnel...'); | |||
var jobs = this.jobs, | var jobs = this.jobs, | |||
active = jobs.active; | active = jobs.active; | |||
skipping to change at line 885 | skipping to change at line 873 | |||
this.connection.stop(onStop); | this.connection.stop(onStop); | |||
} else { | } else { | |||
onStop(); | onStop(); | |||
} | } | |||
}, this)); | }, this)); | |||
jobs.queue.length = 0; | jobs.queue.length = 0; | |||
if (_.isEmpty(active)) { | if (_.isEmpty(active)) { | |||
_.defer(stop); | _.defer(stop); | |||
} | } | |||
_.invoke(active, 'stop', function() { | _.invokeMap(active, 'stop', function() { | |||
_.pull(active, this); | _.pull(active, this); | |||
stop(); | stop(); | |||
}); | }); | |||
if (this._timeoutId) { | if (this._timeoutId) { | |||
clearTimeout(this._timeoutId); | clearTimeout(this._timeoutId); | |||
this._timeoutId = null; | this._timeoutId = null; | |||
} | } | |||
return this; | return this; | |||
}; | }; | |||
End of changes. 26 change blocks. | ||||
44 lines changed or deleted | 32 lines changed or added |