I'm testing a function that makes AJAX requests, allowing retries when the network is not working or there are timeouts because the connection is unstable (I'm thinking about mobile devices).
I'm sure it works because I've used it integrated with other code, but I want to have a proper test.
However I haven't been able to create a unit test to ensure it formally. I'm using jasmine 2.3 along with karma and here is my code so far:
var RETRIES=2;
var TIMEOUT=1000;
function doRequest(method, url, successFn, errorFn, body, retries) {
var request = new XMLHttpRequest();
retries = retries === undefined ? RETRIES : retries;
request.open(method, url);
request.setRequestHeader('Accept', 'application/json');
request.setRequestHeader('Content-Type', 'application/json');
request.onload = function () {
if (request.status < 300 && request.status >= 200) {
successFn(JSON.parse(request.responseText));
} else {
if (errorFn) {
errorFn(this.status, this.responseText);
}
}
};
request.onerror = function () {
if (this.readyState === 4 && this.status === 0) {
//there is no connection
errorFn('NO_NETWORK');
} else {
errorFn(this.status, this.responseText);
}
};
if (retries > 0) {
request.ontimeout = function () {
doRequest(method, url, successFn, errorFn, body, retries - 1);
};
} else {
request.ontimeout = function () {
errorFn('timeout');
};
}
request.timeout = TIMEOUT;
if (body) {
request.send(body);
} else {
request.send();
}
}
And this is my test:
describe('Ajax request', function () {
'use strict';
var RETRIES=2;
var TIMEOUT=1000;
beforeEach(function () {
jasmine.Ajax.install();
jasmine.clock().install();
});
afterEach(function () {
jasmine.Ajax.uninstall();
jasmine.clock().uninstall();
});
it(' should call error callback function when a tiemout happens', function () {
var doneFn = jasmine.createSpy('onLoad');
var errorFn=jasmine.createSpy('onTimeout');
doRequest('GET','http://www.mockedaddress.com', doneFn, errorFn,null,RETRIES);
var request = jasmine.Ajax.requests.mostRecent();
expect(request.method).toBe('GET');
jasmine.clock().tick(TIMEOUT*(RETRIES+1)+50); //first attempt and then 2 retries
expect(errorFn).toHaveBeenCalled(); // assertion failed
});
});
And this is the output of the test:
Expected spy onTimeout to have been called.
at Object.<anonymous> (js/test/doRequest_test.js:75:0)
Chrome 42.0.2311 (Windows 7): Executed 1 of 1 (1 FAILED) ERROR (0.007 secs / 0.008 secs)