karma-sauce-launcher
Advanced tools
Comparing version 0.1.5 to 0.2.0
248
index.js
@@ -1,244 +0,16 @@ | ||
// TODO(vojta): | ||
// - add concrete browsers | ||
// - more config (+ global config) | ||
var SauceConnect = require('./lib/sauce_connect'); | ||
var SauceLauncher = require('./lib/sauce_launcher'); | ||
var SauceReporter = require('./lib/sauce_reporter'); | ||
var q = require('q'); | ||
var wd = require('wd'); | ||
var launchSauceConnect = require('sauce-connect-launcher'); | ||
// SauceLabs is a wrapper around the Sauce Labs REST API | ||
var SauceLabs = require('saucelabs'); | ||
// We keep a mapping from Karma launch IDs to Sauce job IDs here, to report the pass/fail results. | ||
// We also keep the Sauce credentials here - theoretically different credentials can be used for | ||
// different browsers in the same session. | ||
var jobMapping = {}; | ||
var SauceConnect = function(emitter, logger) { | ||
var log = logger.create('launcher.sauce'); | ||
var alreadyRunningDefered; | ||
var alreadyRunningProces; | ||
this.start = function(username, accessKey, tunnelIdentifier, done) { | ||
var options = { | ||
username: username, | ||
accessKey: accessKey, | ||
verbose: false, | ||
logfile: null, | ||
logger: log.debug.bind(log), | ||
no_progress: false, | ||
tunnelIdentifier: tunnelIdentifier | ||
}; | ||
// TODO(vojta): if different username/accessKey, start a new process | ||
if (alreadyRunningDefered) { | ||
log.debug('Sauce Connect is already running or starting'); | ||
return alreadyRunningDefered.promise; | ||
} | ||
alreadyRunningDefered = q.defer(); | ||
launchSauceConnect(options, function(err, p) { | ||
if (err) { | ||
return alreadyRunningDefered.reject(err); | ||
} | ||
alreadyRunningProces = p; | ||
alreadyRunningDefered.resolve(); | ||
}); | ||
return alreadyRunningDefered.promise; | ||
}; | ||
emitter.on('exit', function(done) { | ||
if (alreadyRunningProces) { | ||
log.info('Shutting down Sauce Connect'); | ||
alreadyRunningProces.close(done); | ||
alreadyRunningProces = null; | ||
} else { | ||
done(); | ||
} | ||
}); | ||
}; | ||
var SauceLabsBrowser = function(id, args, sauceConnect, /* config.sauceLabs */ config, logger, emitter, helper) { | ||
config = config || {}; | ||
var username = process.env.SAUCE_USERNAME || args.username || config.username; | ||
var accessKey = process.env.SAUCE_ACCESS_KEY || args.accessKey || config.accessKey; | ||
var tunnelIdentifier = args.tunnelIdentifier || config.tunnelIdentifier; | ||
var browserName = args.browserName + (args.version ? ' ' + args.version : '') + | ||
(args.platform ? ' (' + args.platform + ')' : '') + ' on SauceLabs'; | ||
var startConnect = config.startConnect !== false; | ||
var log = logger.create('launcher.sauce'); | ||
var self = this; | ||
var driver; | ||
var captured = false; | ||
if (startConnect && !tunnelIdentifier) { | ||
tunnelIdentifier = 'karma' + Math.round(new Date().getTime() / 1000); | ||
} | ||
this.id = id; | ||
this.name = browserName; | ||
var pendingHeartBeat; | ||
var heartbeat = function() { | ||
pendingHeartBeat = setTimeout(function() { | ||
log.debug('Heartbeat to Sauce Labs - fetching title'); | ||
driver.title(); | ||
heartbeat(); | ||
}, 60000); | ||
}; | ||
var formatSauceError = function(err) { | ||
return err.message + '\n ' + err.data.split('\n').shift(); | ||
}; | ||
var start = function(url) { | ||
var options = helper.merge(config.options, args, { | ||
browserName: args.browserName, | ||
version: args.version || '', | ||
platform: args.platform || 'ANY', | ||
tags: args.tags || config.tags || [], | ||
name: args.testName || config.testName || 'Karma test', | ||
'tunnel-identifier': tunnelIdentifier, | ||
'record-video': args.recordVideo || config.recordVideo || false, | ||
'record-screenshots': args.recordScreenshots || config.recordScreenshots || true, | ||
'build': args.build || config.build || process.env.TRAVIS_BUILD_NUMBER || | ||
process.env.BUILD_NUMBER || process.env.BUILD_TAG || | ||
process.env.CIRCLE_BUILD_NUM || null, | ||
'device-orientation': args.deviceOrientation || null | ||
}); | ||
// Adding any other option that was specified in args, but not consumed from above | ||
// Useful for supplying chromeOptions, firefoxProfile, etc. | ||
for (var key in args){ | ||
if (typeof options[key] === 'undefined') { | ||
options[key] = args[key]; | ||
} | ||
} | ||
url = url + '?id=' + id; | ||
driver = wd.remote('ondemand.saucelabs.com', 80, username, accessKey); | ||
driver.init(options, function(err, jobId) { | ||
if (err) { | ||
log.error('Can not start %s\n %s', browserName, formatSauceError(err)); | ||
return emitter.emit('browser_process_failure', self); | ||
} | ||
// Record the job details, so we can access it later with the reporter | ||
jobMapping[id] = { | ||
jobId: jobId, | ||
credentials: { | ||
username: username, | ||
password: accessKey | ||
} | ||
}; | ||
log.info('%s session at https://saucelabs.com/tests/%s', browserName, driver.sessionID); | ||
log.debug('WebDriver channel instantiated, opening ' + url); | ||
driver.get(url, heartbeat); | ||
}); | ||
}; | ||
this.start = function(url) { | ||
if (startConnect) { | ||
sauceConnect.start(username, accessKey, tunnelIdentifier).then(function() { | ||
start(url); | ||
}, function(err) { | ||
log.error('Can not start %s\n Failed to start Sauce Connect:\n %s', browserName, err.message); | ||
emitter.emit('browser_process_failure', self); | ||
}); | ||
} else { | ||
start(url); | ||
} | ||
}; | ||
this.kill = function(done) { | ||
if (!driver) { | ||
return process.nextTick(done); | ||
} | ||
clearTimeout(pendingHeartBeat); | ||
log.debug('Shutting down Sauce Labs driver'); | ||
// workaround - navigate to other page to avoid re-connection | ||
driver.get('about:blank', function() { | ||
driver.quit(done); | ||
}); | ||
}; | ||
this.markCaptured = function() { | ||
captured = true; | ||
}; | ||
this.isCaptured = function() { | ||
return captured; | ||
}; | ||
this.toString = function() { | ||
return this.name; | ||
}; | ||
}; | ||
var SauceLabsReporter = function(baseReporterDecorator, emitter, logger) { | ||
var log = logger.create('reporter.sauce'); | ||
baseReporterDecorator(this); | ||
var pendingUpdates = 0; | ||
var updatesFinished = function() {}; | ||
// We're only interested in the final results per browser | ||
this.onBrowserComplete = function(browser) { | ||
var result = browser.lastResult; | ||
// browser.launchId was used until v0.10.2, but changed to just browser.id in v0.11.0 | ||
var browserId = browser.launchId || browser.id; | ||
if(browserId in jobMapping) { | ||
var jobDetails = jobMapping[browserId]; | ||
var sauceApi = new SauceLabs(jobDetails.credentials); | ||
// We record pass/fail status, as well as the full results in "custom-data". | ||
var payload = { | ||
passed: !(result.failed || result.error), | ||
'custom-data': result | ||
}; | ||
pendingUpdates++; | ||
sauceApi.updateJob(jobDetails.jobId, payload, function(err) { | ||
pendingUpdates--; | ||
if (err) { | ||
log.error('Failed record pass/fail status: %s', err.error); | ||
} | ||
if (pendingUpdates == 0) { | ||
updatesFinished(); | ||
} | ||
}); | ||
} | ||
}; | ||
// Wait until all updates have been pushed to SauceLabs | ||
emitter.on('exit', function(done) { | ||
if (pendingUpdates) { | ||
updatesFinished = done; | ||
} else { | ||
done(); | ||
} | ||
}); | ||
}; | ||
SauceLabsReporter.$inject = ['baseReporterDecorator', 'emitter', 'logger']; | ||
// PUBLISH DI MODULE | ||
module.exports = { | ||
'sauceConnect': ['type', SauceConnect], | ||
'launcher:SauceLabs': ['type', SauceLabsBrowser], | ||
'reporter:saucelabs': ['type', SauceLabsReporter] | ||
'launcher:SauceLabs': ['type', SauceLauncher], | ||
'reporter:saucelabs': ['type', SauceReporter], | ||
// We keep a mapping from Karma launch IDs to Sauce job IDs here, to report the pass/fail results. | ||
// We also keep the Sauce credentials here - theoretically different credentials can be used for | ||
// different browsers in the same session. | ||
'sauce:jobMapping': ['value', {}] | ||
}; |
{ | ||
"name": "karma-sauce-launcher", | ||
"version": "0.1.5", | ||
"version": "0.2.0", | ||
"description": "A Karma plugin. Launch any browser on SauceLabs!", | ||
@@ -22,4 +22,4 @@ "main": "index.js", | ||
"dependencies": { | ||
"wd": "~0.1.5", | ||
"sauce-connect-launcher": "~0.1.10", | ||
"wd": "~0.2.8", | ||
"sauce-connect-launcher": "~0.2.2", | ||
"q": "~0.9.6", | ||
@@ -29,3 +29,3 @@ "saucelabs": "~0.1.0" | ||
"peerDependencies": { | ||
"karma": ">=0.9" | ||
"karma": ">=0.11.11" | ||
}, | ||
@@ -32,0 +32,0 @@ "license": "MIT", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
12234
7
220
0
76
1
+ Addedarchiver@0.10.1(transitive)
+ Addedassert-plus@0.1.5(transitive)
+ Addedasync@0.9.2(transitive)
+ Addedaws-sign2@0.5.0(transitive)
+ Addedbl@0.9.5(transitive)
+ Addedbuffer-crc32@0.2.13(transitive)
+ Addedcrc32-stream@0.2.0(transitive)
+ Addedctype@0.5.3(transitive)
+ Addeddebug@1.0.5(transitive)
+ Addeddeflate-crc32-stream@0.1.2(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedfile-utils@0.2.2(transitive)
+ Addedfindup-sync@0.2.1(transitive)
+ Addedform-data@0.1.4(transitive)
+ Addedglob@4.3.54.5.3(transitive)
+ Addedhawk@1.0.0(transitive)
+ Addedhttp-signature@0.10.1(transitive)
+ Addedisbinaryfile@2.0.4(transitive)
+ Addedjson-stringify-safe@5.0.1(transitive)
+ Addedlazystream@0.1.0(transitive)
+ Addedlodash@2.4.2(transitive)
+ Addedminimatch@2.0.10(transitive)
+ Addedq@1.0.1(transitive)
+ Addedrequest@2.36.0(transitive)
+ Addedrimraf@2.7.1(transitive)
+ Addedsauce-connect-launcher@0.2.2(transitive)
+ Addedtar-stream@0.4.7(transitive)
+ Addedtldts@6.1.50(transitive)
+ Addedtldts-core@6.1.50(transitive)
+ Addedtough-cookie@5.0.0(transitive)
+ Addedtunnel-agent@0.4.3(transitive)
+ Addedunderscore.string@2.3.3(transitive)
+ Addedwd@0.2.27(transitive)
+ Addedxtend@4.0.2(transitive)
+ Addedzip-stream@0.3.7(transitive)
- Removedarchiver@0.4.10(transitive)
- Removedassert-plus@0.1.2(transitive)
- Removedaws-sign@0.3.0(transitive)
- Removedcookie-jar@0.3.0(transitive)
- Removedctype@0.5.2(transitive)
- Removedform-data@0.0.8(transitive)
- Removedhawk@0.13.1(transitive)
- Removedhoek@0.8.5(transitive)
- Removedhttp-signature@0.9.11(transitive)
- Removediconv-lite@0.2.11(transitive)
- Removedjson-stringify-safe@4.0.0(transitive)
- Removedrequest@2.21.0(transitive)
- Removedsauce-connect-launcher@0.1.11(transitive)
- Removedtunnel-agent@0.3.0(transitive)
- Removedwd@0.1.5(transitive)
Updatedwd@~0.2.8