karma
Version:
Spectacular Test Runner for JavaScript.
171 lines (131 loc) • 4.33 kB
JavaScript
var log = require('./logger').create('launcher');
var q = require('q');
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, hostname, port, urlRoot) {
var browser;
var url = 'http://' + 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 deferred = q.defer();
this.kill(function() {
deferred.resolve();
});
return deferred.promise;
};
}
log.info('Starting browser %s', browser.name);
browser.start(url);
browsers.push(browser);
});
return browsers;
};
this.launch.$inject = ['config.browsers', '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;