UNPKG

chimpy

Version:

Develop acceptance tests & end-to-end tests with realtime feedback.

159 lines (138 loc) 4.9 kB
"use strict"; var request = require('request'), log = require('./log'), _ = require('underscore'); /** * SessionManager Constructor * * @param {Object} options * @api public */ function SauceLabsSessionManager(options) { log.debug('[chimp][saucelabs-session-manager] options are', options); var host = options.host.replace('ondemand.', ''); var sauceLabsBaseUrl = 'https://' + options.user + ':' + options.key + '@' + host + '/rest/v1/' + options.user; options.sauceLabsUrl = sauceLabsBaseUrl; this.options = options; this.maxRetries = 30; this.retryDelay = 3000; this.retry = 0; this.build = null; log.debug('[chimp][saucelabs-session-manager] created a new SessionManager', options); } SauceLabsSessionManager.prototype.webdriver = require('xolvio-sync-webdriverio'); /** * Wraps the webdriver remote method and allows reuse options * * @api public */ SauceLabsSessionManager.prototype.remote = function (webdriverOptions, callback) { var self = this; log.debug('[chimp][saucelabs-session-manager] creating webdriver remote '); var browser = this.webdriver.remote(webdriverOptions); this.build = webdriverOptions.desiredCapabilities.build; log.debug('[chimp][saucelabs-session-manager] build: ' + this.build); callback(null, browser); return; }; var DEFAULT_LIMIT = 100; /** * Gets a list of sessions from the SauceLabs API based on Build ID * * @api private */ SauceLabsSessionManager.prototype._getJobs = function (callback, limit, skip) { var hub = this.options.sauceLabsUrl + '/jobs?full=true&limit=' + limit; if (skip > 0) { hub += '&skip=' + skip; } log.debug('[chimp][saucelabs-session-manager]', 'requesting sessions from', hub); request(hub, function (error, response, body) { if (!error && response.statusCode === 200) { log.debug('[chimp][saucelabs-session-manager]', 'received data', body); callback(null, JSON.parse(body)); } else { log.error('[chimp][saucelabs-session-manager]', 'received error', error); callback(error); } }); }; /** * @api public */ SauceLabsSessionManager.prototype.killCurrentSession = function (callback) { var self = this; var killSession = function (job) { // This will stop the session, causing a 'User terminated' error. // If we don't manually stop the session, we get a timed-out error. var options = { url: this.options.sauceLabsUrl + '/jobs/' + job.id + '/stop', method: 'PUT' }; request(options, function (error, response) { if (!error && response.statusCode === 200) { log.debug('[chimp][saucelabs-session-manager]', 'stopped session'); callback(); } else { log.error('[chimp][saucelabs-session-manager]', 'received error', error); callback(error); } }); // This will set the session to passing or else it will show as Errored out // even though we stop it. options = { url: this.options.sauceLabsUrl + '/jobs/' + job.id, method: 'PUT', json: true, body: { passed: true } }; request(options, function (error, response) { if (!error && response.statusCode === 200) { log.debug('[chimp][saucelabs-session-manager]', 'updated session to passing state'); callback(); } else { log.error('[chimp][saucelabs-session-manager]', 'received error', error); callback(error); } }); }.bind(this); var getJobForBuild = function (cb, skip) { if (!self.build) { // get one and kill it, this is the (flawed) default of chimp which will just randomly // terminate sessions and you get an odd `Error: The test with session id XXX has already finished, and can't receive further commands.` error console.warn('You should really consider setting a build, otherwise random sessions will be terminated!'); this._getJobs(function (err, jobs) { if (jobs.length) { killSession(jobs[0]); } }, 1); return; } this._getJobs(function (err, jobs) { // the original code never uses this error, // probably because if we don't find anything we just leave the session alone // we might want to revisit this behavior // if (err) { // cb(err); // } if (!jobs.length) { // no more jobs found, let's exit console.warn("Couldn't find a job to terminate for build ".concat(self.build)); callback(); return; } var currentJob = _.find(jobs, function (b) { return b.build === self.build; }); if (!currentJob) { // maybe it's in the next batch? getJobForBuild(cb, skip + DEFAULT_LIMIT); } else { killSession(currentJob); } }, DEFAULT_LIMIT, skip); }.bind(this); getJobForBuild(killSession, 0); }; module.exports = SauceLabsSessionManager;