karma
Version:
Spectacular Test Runner for JavaScript.
170 lines (136 loc) • 4.44 kB
JavaScript
var log = require('./logger').create('launcher')
var Promise = require('bluebird')
var baseDecorator = require('./launchers/base').decoratorFactory
var captureTimeoutDecorator = require('./launchers/capture_timeout').decoratorFactory
var retryDecorator = require('./launchers/retry').decoratorFactory
var processDecorator = require('./launchers/process').decoratorFactory
// TODO(vojta): remove once nobody uses it
var baseBrowserDecoratorFactory = function (baseLauncherDecorator, captureTimeoutLauncherDecorator,
retryLauncherDecorator, processLauncherDecorator) {
return function (launcher) {
baseLauncherDecorator(launcher)
captureTimeoutLauncherDecorator(launcher)
retryLauncherDecorator(launcher)
processLauncherDecorator(launcher)
}
}
var Launcher = function (emitter, injector) {
var browsers = []
var lastStartTime
var getBrowserById = function (id) {
for (var i = 0; i < browsers.length; i++) {
if (browsers[i].id === id) {
return browsers[i]
}
}
return null
}
this.launch = function (names, protocol, hostname, port, urlRoot) {
var browser
var url = protocol + '//' + hostname + ':' + port + urlRoot
lastStartTime = Date.now()
names.forEach(function (name) {
var locals = {
id: ['value', Launcher.generateId()],
name: ['value', name],
baseLauncherDecorator: ['factory', baseDecorator],
captureTimeoutLauncherDecorator: ['factory', captureTimeoutDecorator],
retryLauncherDecorator: ['factory', retryDecorator],
processLauncherDecorator: ['factory', processDecorator],
baseBrowserDecorator: ['factory', baseBrowserDecoratorFactory]
}
// TODO(vojta): determine script from name
if (name.indexOf('/') !== -1) {
name = 'Script'
}
try {
browser = injector.createChild([locals], ['launcher:' + name]).get('launcher:' + name)
} catch (e) {
if (e.message.indexOf('No provider for "launcher:' + name + '"') !== -1) {
log.warn('Can not load "%s", it is not registered!\n ' +
'Perhaps you are missing some plugin?', name)
} else {
log.warn('Can not load "%s"!\n ' + e.stack, name)
}
return
}
// TODO(vojta): remove in v1.0 (BC for old launchers)
if (!browser.forceKill) {
browser.forceKill = function () {
var self = this
return new Promise(function (resolve) {
self.kill(resolve)
})
}
browser.restart = function () {
var self = this
this.kill(function () {
self.start(url)
})
}
}
log.info('Starting browser %s', browser.name)
browser.start(url)
browsers.push(browser)
})
return browsers
}
this.launch.$inject = ['config.browsers', 'config.protocol', 'config.hostname', 'config.port', 'config.urlRoot']
this.kill = function (id, callback) {
var browser = getBrowserById(id)
callback = callback || function () {}
if (!browser) {
process.nextTick(callback)
return false
}
browser.forceKill().then(callback)
return true
}
this.restart = function (id) {
var browser = getBrowserById(id)
if (!browser) {
return false
}
browser.restart()
return true
}
this.killAll = function (callback) {
log.debug('Disconnecting all browsers')
var remaining = 0
var finish = function () {
remaining--
if (!remaining && callback) {
callback()
}
}
if (!browsers.length) {
return process.nextTick(callback)
}
browsers.forEach(function (browser) {
remaining++
browser.forceKill().then(finish)
})
}
this.areAllCaptured = function () {
return !browsers.some(function (browser) {
return !browser.isCaptured()
})
}
this.markCaptured = function (id) {
browsers.forEach(function (browser) {
if (browser.id === id) {
browser.markCaptured()
log.debug('%s (id %s) captured in %d secs', browser.name, browser.id,
(Date.now() - lastStartTime) / 1000)
}
})
}
// register events
emitter.on('exit', this.killAll)
}
Launcher.$inject = ['emitter', 'injector']
Launcher.generateId = function () {
return '' + Math.floor(Math.random() * 100000000)
}
// PUBLISH
exports.Launcher = Launcher