Comparing version 0.10.1 to 0.10.2
@@ -0,1 +1,16 @@ | ||
<a name="v0.10.2"></a> | ||
### v0.10.2 (2013-08-21) | ||
#### Bug Fixes | ||
* don't mark a browser captured if already being killed/timeouted ([21230979](http://github.com/karma-runner/karma/commit/212309795861cf599dbcc0ed60fff612ccf25cf5), closes [#88](http://github.com/karma-runner/karma/issues/88)) | ||
#### Features | ||
* sync page unload (disconnect) ([ac9b3f01](http://github.com/karma-runner/karma/commit/ac9b3f01e88ce2cf91fc86aca9cecfdb8177a6fa)) | ||
* buffer result messages when polling ([c4ad6970](http://github.com/karma-runner/karma/commit/c4ad69709103110a066ae1d9652af69e42434c6b)) | ||
* allow browser to reconnect during the test run ([cbe2851b](http://github.com/karma-runner/karma/commit/cbe2851baa55312f00be420e0345283b33326266), closes [#82](http://github.com/karma-runner/karma/issues/82), [#590](http://github.com/karma-runner/karma/issues/590)) | ||
<a name="v0.10.1"></a> | ||
@@ -2,0 +17,0 @@ ### v0.10.1 (2013-08-06) |
@@ -19,29 +19,58 @@ var helper = require('./helper'); | ||
var Browser = function(id, collection, emitter) { | ||
var log = logger.create(id); | ||
// The browser is ready to execute tests. | ||
var READY = 1; | ||
// The browser is executing the tests/ | ||
var EXECUTING = 2; | ||
// The browser is not executing, but temporarily disconnected (waiting for reconnecting). | ||
var READY_DISCONNECTED = 3; | ||
// The browser is executing the tests, but temporarily disconnect (waiting for reconnecting). | ||
var EXECUTING_DISCONNECTED = 4; | ||
// The browser got permanently disconnected (being removed from the collection and destroyed). | ||
var DISCONNECTED = 5; | ||
var Browser = function(id, fullName, /* capturedBrowsers */ collection, emitter, socket, timer, | ||
/* config.browserDisconnectTimeout */ disconnectDelay) { | ||
var name = helper.browserFullNameToShort(fullName); | ||
var log = logger.create(name); | ||
this.id = id; | ||
this.name = id; | ||
this.fullName = null; | ||
this.isReady = true; | ||
this.fullName = fullName; | ||
this.name = name; | ||
this.state = READY; | ||
this.lastResult = new Result(); | ||
this.init = function() { | ||
collection.add(this); | ||
this.toString = function() { | ||
return this.name; | ||
}; | ||
events.bindAll(this, socket); | ||
this.onRegister = function(info) { | ||
this.launchId = info.id; | ||
this.fullName = info.name; | ||
this.name = helper.browserFullNameToShort(this.fullName); | ||
log = logger.create(this.name); | ||
log.info('Connected on socket id ' + this.id); | ||
log.info('Connected on socket %s', socket.id); | ||
// TODO(vojta): remove launchId, | ||
// it's here just for WebStorm B-C. | ||
this.launchId = this.id; | ||
this.id = socket.id; | ||
// TODO(vojta): move to collection | ||
emitter.emit('browsers_change', collection); | ||
emitter.emit('browser_register', this); | ||
emitter.emit('browsers_change', collection); | ||
}; | ||
this.isReady = function() { | ||
return this.state === READY; | ||
}; | ||
this.toString = function() { | ||
return this.name; | ||
}; | ||
this.onError = function(error) { | ||
if (this.isReady) { | ||
if (this.isReady()) { | ||
return; | ||
@@ -55,3 +84,3 @@ } | ||
this.onInfo = function(info) { | ||
if (this.isReady) { | ||
if (this.isReady()) { | ||
return; | ||
@@ -75,7 +104,7 @@ } | ||
this.onComplete = function(result) { | ||
if (this.isReady) { | ||
if (this.isReady()) { | ||
return; | ||
} | ||
this.isReady = true; | ||
this.state = READY; | ||
this.lastResult.totalTimeEnd(); | ||
@@ -91,17 +120,50 @@ | ||
var self = this; | ||
var disconnect = function() { | ||
self.state = DISCONNECTED; | ||
log.warn('Disconnected'); | ||
collection.remove(self); | ||
}; | ||
var pendingDisconnect; | ||
this.onDisconnect = function() { | ||
if (!this.isReady) { | ||
this.isReady = true; | ||
this.lastResult.totalTimeEnd(); | ||
this.lastResult.disconnected = true; | ||
emitter.emit('browser_complete', this); | ||
if (this.state === READY) { | ||
disconnect(); | ||
} else if (this.state === EXECUTING) { | ||
log.debug('Disconnected during run, waiting for reconnecting.'); | ||
this.state = EXECUTING_DISCONNECTED; | ||
pendingDisconnect = timer.setTimeout(function() { | ||
self.lastResult.totalTimeEnd(); | ||
self.lastResult.disconnected = true; | ||
disconnect(); | ||
emitter.emit('browser_complete', self); | ||
}, disconnectDelay); | ||
} | ||
}; | ||
log.warn('Disconnected'); | ||
collection.remove(this); | ||
this.onReconnect = function(newSocket) { | ||
if (this.state === EXECUTING_DISCONNECTED) { | ||
this.state = EXECUTING; | ||
log.debug('Reconnected.'); | ||
} else if (this.state === EXECUTING || this.state === READY) { | ||
log.debug('New connection, forgetting the old one.'); | ||
// TODO(vojta): this should only remove this browser.onDisconnect listener | ||
socket.removeAllListeners('disconnect'); | ||
} | ||
socket = newSocket; | ||
events.bindAll(this, newSocket); | ||
if (pendingDisconnect) { | ||
timer.clearTimeout(pendingDisconnect); | ||
} | ||
}; | ||
this.onResult = function(result) { | ||
if (result.length) { | ||
return result.forEach(this.onResult, this); | ||
} | ||
// ignore - probably results from last run (after server disconnecting) | ||
if (this.isReady) { | ||
if (this.isReady()) { | ||
return; | ||
@@ -126,3 +188,3 @@ } | ||
name: this.name, | ||
isReady: this.isReady | ||
isReady: this.state === READY | ||
}; | ||
@@ -132,3 +194,9 @@ }; | ||
Browser.STATE_READY = READY; | ||
Browser.STATE_EXECUTING = EXECUTING; | ||
Browser.STATE_READY_DISCONNECTED = READY_DISCONNECTED; | ||
Browser.STATE_EXECUTING_DISCONNECTED = EXECUTING_DISCONNECTED; | ||
Browser.STATE_DISCONNECTED = DISCONNECTED; | ||
var Collection = function(emitter, browsers) { | ||
@@ -155,12 +223,19 @@ browsers = browsers || []; | ||
this.setAllIsReadyTo = function(value) { | ||
var change = false; | ||
this.getById = function(browserId) { | ||
for (var i = 0; i < browsers.length; i++) { | ||
// TODO(vojta): use id, once we fix WebStorm plugin | ||
if (browsers[i].launchId === browserId) { | ||
return browsers[i]; | ||
} | ||
} | ||
return null; | ||
}; | ||
this.setAllToExecuting = function() { | ||
browsers.forEach(function(browser) { | ||
change = change || browser.isReady !== value; | ||
browser.isReady = value; | ||
browser.state = EXECUTING; | ||
}); | ||
if (change) { | ||
emitter.emit('browsers_change', this); | ||
} | ||
emitter.emit('browsers_change', this); | ||
}; | ||
@@ -172,3 +247,3 @@ | ||
browsers.forEach(function(browser) { | ||
if (!browser.isReady) { | ||
if (!browser.isReady()) { | ||
nonReadyList.push(browser); | ||
@@ -233,10 +308,1 @@ } | ||
exports.Collection = Collection; | ||
exports.createBrowser = function(socket, collection, emitter) { | ||
var browser = new Browser(socket.id, collection, emitter); | ||
events.bindAll(browser, socket); | ||
collection.add(browser); | ||
return browser; | ||
}; |
@@ -274,2 +274,3 @@ var path = require('path'); | ||
}; | ||
this.browserDisconnectTimeout = 2000; | ||
@@ -276,0 +277,0 @@ // TODO(vojta): remove in 0.10 |
@@ -18,2 +18,37 @@ var events = require('events'); | ||
var bufferEvents = function(emitter, eventsToBuffer) { | ||
var listeners = []; | ||
var eventsToReply = []; | ||
var genericListener = function() { | ||
eventsToReply.push(Array.prototype.slice.call(arguments)); | ||
}; | ||
eventsToBuffer.forEach(function(eventName) { | ||
var listener = genericListener.bind(null, eventName); | ||
listeners.push(listener); | ||
emitter.on(eventName, listener); | ||
}); | ||
return function() { | ||
if (!eventsToReply) { | ||
return; | ||
} | ||
// remove all buffering listeners | ||
listeners.forEach(function(listener, i) { | ||
emitter.removeListener(eventsToBuffer[i], listener); | ||
}); | ||
// reply | ||
eventsToReply.forEach(function(args) { | ||
events.EventEmitter.prototype.emit.apply(emitter, args); | ||
}); | ||
// free-up | ||
listeners = eventsToReply = null; | ||
}; | ||
}; | ||
// TODO(vojta): log.debug all events | ||
@@ -42,4 +77,6 @@ var EventEmitter = function() { | ||
// PUBLISH | ||
exports.EventEmitter = EventEmitter; | ||
exports.bindAll = bindAllEvents; | ||
exports.bufferEvents = bufferEvents; |
@@ -21,4 +21,4 @@ var log = require('./logger').create(); | ||
executionScheduled = false; | ||
capturedBrowsers.setAllIsReadyTo(false); | ||
capturedBrowsers.clearResults(); | ||
capturedBrowsers.setAllToExecuting(); | ||
pendingCount = capturedBrowsers.length; | ||
@@ -25,0 +25,0 @@ runningBrowsers = capturedBrowsers.clone(); |
@@ -50,3 +50,5 @@ var spawn = require('child_process').spawn; | ||
this.markCaptured = function() { | ||
self.state = CAPTURED; | ||
if (self.state === BEING_CAPTURED) { | ||
self.state = CAPTURED; | ||
} | ||
}; | ||
@@ -53,0 +55,0 @@ |
@@ -17,3 +17,4 @@ var io = require('socket.io'); | ||
var helper = require('./helper'); | ||
var EventEmitter = require('./events').EventEmitter; | ||
var events = require('./events'); | ||
var EventEmitter = events.EventEmitter; | ||
var Executor = require('./executor'); | ||
@@ -64,2 +65,3 @@ | ||
globalEmitter.on('browser_register', function(browser) { | ||
// TODO(vojta): use just id | ||
if (browser.launchId) { | ||
@@ -83,4 +85,27 @@ launcher.markCaptured(browser.launchId); | ||
socketServer.sockets.on('connection', function (socket) { | ||
log.debug('New browser has connected on socket ' + socket.id); | ||
browser.createBrowser(socket, capturedBrowsers, globalEmitter); | ||
log.debug('A browser has connected on socket ' + socket.id); | ||
var replySocketEvents = events.bufferEvents(socket, ['info', 'error', 'result', 'complete']); | ||
socket.on('register', function(info) { | ||
var newBrowser; | ||
if (info.id) { | ||
newBrowser = capturedBrowsers.getById(info.id); | ||
} | ||
if (newBrowser) { | ||
newBrowser.onReconnect(socket); | ||
} else { | ||
newBrowser = injector.createChild([{ | ||
id: ['value', info.id || null], | ||
fullName: ['value', info.name], | ||
socket: ['value', socket] | ||
}]).instantiate(browser.Browser); | ||
newBrowser.init(); | ||
} | ||
replySocketEvents(); | ||
}); | ||
}); | ||
@@ -173,3 +198,4 @@ | ||
capturedBrowsers: ['type', browser.Collection], | ||
args: ['value', {}] | ||
args: ['value', {}], | ||
timer: ['value', {setTimeout: setTimeout, clearTimeout: clearTimeout}] | ||
}]; | ||
@@ -176,0 +202,0 @@ |
{ | ||
"name": "karma", | ||
"description": "Spectacular Test Runner for JavaScript.", | ||
"homepage": "http://karma-runner.github.com/", | ||
"homepage": "http://karma-runner.github.io/", | ||
"repository": { | ||
@@ -32,34 +32,15 @@ "type": "git", | ||
"Tim Cuthbertson <tim@gfxmonk.net>", | ||
"Andrew Martin <sublimino@gmail.com>", | ||
"Daniel Aleksandersen <code@daniel.priv.no>", | ||
"Ilya Volodin <ivolodin@vistaprint.com>", | ||
"Iristyle <Iristyle@github>", | ||
"Daniel Aleksandersen <code@daniel.priv.no>", | ||
"pavelgj <pavelgj@gmail.com>", | ||
"Andrew Martin <sublimino@gmail.com>", | ||
"Marcello Nuccio <marcello.nuccio@gmail.com>", | ||
"pavelgj <pavelgj@gmail.com>", | ||
"Bulat Shakirzyanov <mallluhuct@gmail.com>", | ||
"Ethan J. Brown <ethan_j_brown@hotmail.com>", | ||
"Igor Minar <iiminar@gmail.com>", | ||
"Hugues Malphettes <hmalphettes@gmail.com>", | ||
"Igor Minar <iiminar@gmail.com>", | ||
"ngiebel <ngiebel@starkinvestments.com>", | ||
"Roarke Gaskill <roarke.gaskill@gmail.com>", | ||
"ngiebel <ngiebel@starkinvestments.com>", | ||
"Ethan J. Brown <ethan_j_brown@hotmail.com>", | ||
"Bulat Shakirzyanov <mallluhuct@gmail.com>", | ||
"rdodev <rubenoz@gmail.com>", | ||
"Alexander Shtuchkin <ashtuchkin@gmail.com>", | ||
"Andy Joslin <andytjoslin@gmail.com>", | ||
"AvnerCohen <israbirding@gmail.com>", | ||
"Brian Ford <btford@umich.edu>", | ||
"Chad Smith <chad@configit.com>", | ||
"Chris Dawson <xrdawson@gmail.com>", | ||
"Danny Croft <danny.croft@yahoo.co.uk>", | ||
"David Jensen <david@frode.(none)>", | ||
"David Souther <davidsouther@gmail.com>", | ||
"Dillon <mdillon@reachmail.com>", | ||
"Ed Rooth <ed.rooth@rackspace.com>", | ||
"Eldar Jafarov <djkojb@gmail.com>", | ||
"Eric Baer <me@ericbaer.com>", | ||
"Franck Garcia <garcia.franck@gmail.com>", | ||
"Fred Sauer <fredsa@google.com>", | ||
"Igor Minar <igor@angularjs.org>", | ||
"James Ford <jford@psyked.co.uk>", | ||
"James Shore <jshore@jamesshore.com>", | ||
"Julian Connor <julian.connor@venmo.com>", | ||
"Kevin Ortman <kevin_ortman@msn.com>", | ||
@@ -70,2 +51,3 @@ "Marko Anastasov <marko@renderedtext.com>", | ||
"Milan Aleksic <milanaleksic@gmail.com>", | ||
"Nick Payne <nick@kurai.co.uk>", | ||
"Nish <nishantpatel611@gmail.com>", | ||
@@ -86,3 +68,24 @@ "Nuno Job <nunojobpinto@gmail.com>", | ||
"hrgdavor <hrgdavor@gmail.com>", | ||
"lanshunfang <lanshunfang@gmail.com>" | ||
"lanshunfang <lanshunfang@gmail.com>", | ||
"Alexander Shtuchkin <ashtuchkin@gmail.com>", | ||
"toran billups <toranb@gmail.com>", | ||
"Andy Joslin <andytjoslin@gmail.com>", | ||
"AvnerCohen <israbirding@gmail.com>", | ||
"Brian Ford <btford@umich.edu>", | ||
"Chad Smith <chad@configit.com>", | ||
"Chris Dawson <xrdawson@gmail.com>", | ||
"Danny Croft <danny.croft@yahoo.co.uk>", | ||
"David Jensen <david@frode.(none)>", | ||
"David Souther <davidsouther@gmail.com>", | ||
"Dillon <mdillon@reachmail.com>", | ||
"Ed Rooth <ed.rooth@rackspace.com>", | ||
"Eldar Jafarov <djkojb@gmail.com>", | ||
"Eric Baer <me@ericbaer.com>", | ||
"Franck Garcia <garcia.franck@gmail.com>", | ||
"Fred Sauer <fredsa@google.com>", | ||
"Igor Minar <igor@angularjs.org>", | ||
"James Ford <jford@psyked.co.uk>", | ||
"James Shore <jshore@jamesshore.com>", | ||
"Julian Connor <julian.connor@venmo.com>", | ||
"Karolis Narkevicius <karolis.n@gmail.com>" | ||
], | ||
@@ -150,2 +153,3 @@ "dependencies": { | ||
"karma-html2js-preprocessor": "*", | ||
"karma-browserstack-launcher": "git://github.com/karma-runner/karma-browserstack-launcher.git", | ||
"semver": "~1.1.4", | ||
@@ -161,3 +165,3 @@ "grunt-contrib-watch": "~0.5.0" | ||
}, | ||
"version": "0.10.1" | ||
"version": "0.10.2" | ||
} |
@@ -13,2 +13,3 @@ (function(window, document, io) { | ||
'resource': KARMA_URL_ROOT.substr(1) + 'socket.io', | ||
'sync disconnect on unload': true, | ||
'max reconnection attempts': Infinity | ||
@@ -56,2 +57,5 @@ }); | ||
var resultsBufferLimit = 1; | ||
var resultsBuffer = []; | ||
this.VERSION = VERSION; | ||
@@ -197,6 +201,20 @@ this.config = {}; | ||
this.result = function(result) { | ||
socket.emit('result', result); | ||
if (resultsBufferLimit === 1) { | ||
return socket.emit('result', result); | ||
} | ||
resultsBuffer.push(result); | ||
if (resultsBuffer.length === resultsBufferLimit) { | ||
socket.emit('result', resultsBuffer); | ||
resultsBuffer = []; | ||
} | ||
}; | ||
this.complete = function(result) { | ||
if (resultsBuffer.length) { | ||
socket.emit('result', resultsBuffer); | ||
resultsBuffer = []; | ||
} | ||
// give the browser some time to breath, there could be a page reload, but because a bunch of | ||
@@ -258,7 +276,13 @@ // tests could run in the same event loop, we wouldn't notice. | ||
// cancel execution | ||
socket.on('disconnect', clearContext); | ||
// report browser name, id | ||
socket.on('connect', function() { | ||
var transport = socket.socket.transport.name; | ||
// TODO(vojta): make resultsBufferLimit configurable | ||
if (transport === 'websocket' || transport === 'flashsocket') { | ||
resultsBufferLimit = 1; | ||
} else { | ||
resultsBufferLimit = 50; | ||
} | ||
socket.emit('register', { | ||
@@ -265,0 +289,0 @@ name: navigator.userAgent, |
Sorry, the diff of this file is not supported yet
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
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 website
QualityPackage does not have a website.
Found 1 instance in 1 package
870228
50
3270
1
34