Skip to content

Commit

Permalink
feat: buffer result messages when polling
Browse files Browse the repository at this point in the history
Some browsers (Safari) starts loosing messages when sending too often (using xhr/html polling). Batching solves the issue.
  • Loading branch information
vojtajina committed Aug 21, 2013
1 parent 72da3fb commit c4ad697
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 3 deletions.
4 changes: 4 additions & 0 deletions lib/browser.js
Expand Up @@ -151,6 +151,10 @@ var Browser = function(id, fullName, /* capturedBrowsers */ collection, emitter,
};

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()) {
return;
Expand Down
28 changes: 27 additions & 1 deletion static/karma.src.js
Expand Up @@ -50,6 +50,9 @@ var Karma = function(socket, context, navigator, location) {
var store = {};
var self = this;

var resultsBufferLimit = 1;
var resultsBuffer = [];

this.VERSION = VERSION;
this.config = {};

Expand Down Expand Up @@ -190,10 +193,24 @@ var Karma = function(socket, context, navigator, location) {
};

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
// tests could run in the same event loop, we wouldn't notice.
setTimeout(function() {
Expand Down Expand Up @@ -252,6 +269,15 @@ var Karma = function(socket, context, navigator, location) {

// 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', {
name: navigator.userAgent,
id: parseInt((location.search.match(/\?id=(.*)/) || [])[1], 10) || null
Expand Down
47 changes: 46 additions & 1 deletion test/client/karma.spec.js
Expand Up @@ -6,10 +6,16 @@
describe('karma', function() {
var socket, k, spyStart, windowNavigator, windowLocation;

var setTransportTo = function(transportName) {
socket._setTransportNameTo(transportName);
socket.emit('connect');
};


beforeEach(function() {
socket = new MockSocket();
windowNavigator = {};
windowLocation = {};
windowLocation = {search: ''};
k = new Karma(socket, {}, windowNavigator, windowLocation);
spyStart = spyOn(k, 'start');
});
Expand Down Expand Up @@ -84,6 +90,45 @@ describe('karma', function() {
});


describe('result', function() {
var spyResult;

beforeEach(function() {
spyResult = jasmine.createSpy('onResult');
socket.on('result', spyResult);
});

it('should buffer results when polling', function() {
setTransportTo('xhr-polling');

// emit 49 results
for (var i = 1; i < 50; i++) {
k.result({id: i});
}

expect(spyResult).not.toHaveBeenCalled();

k.result('result', {id: 50});
expect(spyResult).toHaveBeenCalled();
expect(spyResult.argsForCall[0][0].length).toBe(50);
});


it('should buffer results when polling', function() {
setTransportTo('xhr-polling');

// emit 40 results
for (var i = 1; i <= 40; i++) {
k.result({id: i});
}

k.complete();
expect(spyResult).toHaveBeenCalled();
expect(spyResult.argsForCall[0][0].length).toBe(40);
});
});


describe('setupContext', function() {
it('should capture alert', function() {
spyOn(k, 'log');
Expand Down
13 changes: 12 additions & 1 deletion test/client/mocks.js
Expand Up @@ -27,7 +27,18 @@ var Emitter = function() {
};
};

var MockSocket = Emitter;

var MockSocket = function() {
Emitter.call(this);

this.socket = {transport: {name: 'websocket'}};

// MOCK API
this._setTransportNameTo = function(transportName) {
this.socket.transport.name = transportName;
};
};


var io = {
connect: function() {
Expand Down
10 changes: 10 additions & 0 deletions test/unit/browser.spec.coffee
Expand Up @@ -329,6 +329,16 @@ describe 'browser', ->
expect(browser.lastResult.netTime).to.equal 9


it 'should accept array of results', ->
browser.state = b.Browser.STATE_EXECUTING
browser.onResult [createSuccessResult(), createSuccessResult(),
createFailedResult(), createSkippedResult()]

expect(browser.lastResult.success).to.equal 2
expect(browser.lastResult.failed).to.equal 1
expect(browser.lastResult.skipped).to.equal 1


#==========================================================================
# browser.Browser.serialize
#==========================================================================
Expand Down

0 comments on commit c4ad697

Please sign in to comment.