I am creating XMLHttpRequest javascript module to get JSON data from server. Here is the code:
(function() {
var makeRequest = function(url,callback,opt) {
var xhr;
if (XMLHttpRequest) { // Mozilla, Safari, ...
xhr = new XMLHttpRequest();
} else if (ActiveXObject) { // IE
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
if (!xhr) {
callback.call(this,
'Giving up :( Cannot create an XMLHTTP instance',
null);
return false;
}
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var data = xhr.responseText;
if(opt && !opt.raw) {
try {
data = JSON.parse(data);
} catch (e) {
callback.call(this, e,null);
return;
}
}
callback.call(this,null,data);
} else {
callback.call(this,
'There was a problem with the request.',
null);
}
}
};
var params = '';
if (opt && opt.params && typeof(opt.params) == 'object') {
for( var key in opt.params) {
params += encodeURIComponent(opt.params[key]);
}
}
var method = opt && opt.method ? opt.method : 'GET';
if (method == 'GET') {
url = params.length > 0 ? url+'?'+params : url;
xhr.open('GET', url);
xhr.send();
} else if (method == 'POST') {
var data = opt && opt.data ? opt.data : params;
xhr.open('POST', url);
xhr.send(JSON.stringify(data));
}
return xhr;
}
if(typeof module !== 'undefined' && module.exports) {
module.exports = makeRequest;
}
if(typeof window!== 'undefined') {
window.getJSONData = makeRequest;
}
})();
I am writing the test case for this on nodejs with Mocha and Sinon. Using Sinon's fakeXMLHttpRequest to test the module. Here is the test code:
var expect = require('chai').expect,
getJSON = require('../'),
sinon = require('sinon');
describe('get-json-data test the request', function() {
beforeEach(function() {
this.xhr = sinon.useFakeXMLHttpRequest();
var requests = this.requests = [];
this.xhr.onCreate = function (xhr) {
requests.push(xhr);
};
});
afterEach(function() {
this.xhr.restore();
});
it('get json data', function() {
var callback = sinon.spy();
getJSON('/some/json', callback);
expect(this.requests.length).to.equal(1);
this.requests[0].respond(200,
{"Content-Type": "application/json"},
'{"id": 1, "name": "foo"}');
sinon.assert.calledWith(callback, {"id": 1, "name": "foo"});
});
});
On running the test I get error:
ReferenceError: XMLHttpRequest is not defined
And it seems correct as there is no XMLHttpRequest class/function in nodejs. But is Sinon's fakeXMLHttpRequest not supposed to do that. I thought in Sinon's setUp (Mocha's beforeEach) we are creating a fake XMLHttpRequest with fakeXMLHttpRequest. Please suggest what I am doing wrong? Or what would be the correct way to use Sinon to test my module at nodejs?
There is no "correct" way to test a module that is using DOM APIs using Node, which has no notion of DOM. But there are ways of achieving your goal. The best way to get going is probably to set up Karma to run your tests in PhantomJS or desktop browsers. That would test your code in a browser - the actual environment where it will be used!
If you do insist on testing the code _in Node_, then you could try out jsdom, which will add the DOM API to the current context. There are mocha plugins, so you could do something like this
var jsdom = require('mocha-jsdom')
var expect = require('chai').expect
describe('mocha tests', function () {
jsdom()
it('has document', function () {
var div = document.createElement('div')
expect(div.nodeName).eql('DIV')
})
})
Seems there are others using jsdom and sinon.js, so you should not have too many problems.
Thanks @fatso83 So I'll try to implement Karma with PhantomJS.
@gagan-bansal if you need some setup code to get going you can get a start here
@fatso83 thanks for the reference I'll check it.
For those who would like to test Ajax in node using just mocha and sinon, you just have to set global.XMLHttpRequest
to sinon.useFakeXMLHttpRequest()
. Here is an example: https://github.com/scriptare/compago-ajax/blob/master/tests/unit.test.js#L36
@zandaqo thanks for update.
Most helpful comment
For those who would like to test Ajax in node using just mocha and sinon, you just have to set
global.XMLHttpRequest
tosinon.useFakeXMLHttpRequest()
. Here is an example: https://github.com/scriptare/compago-ajax/blob/master/tests/unit.test.js#L36