n6g7 n6g7 - 28 days ago 7
jQuery Question

Ajax : empty json response when using Karma

TL;DR : Does Karma tamper with ajax request sent while running tests ?




Context



I'm currently writing unit-tests for a front-end javascript application. I'm using Karma 0.12.31 to run the tests and the only frontend library I use that is relevant to this question is jQuery.

I have a really simple class object responsible for fetching and caching results from a backend API :

function APIReader(baseUrl) {
this.baseUrl = baseUrl;
this.cache = {};
}
APIReader.prototype.updateCache = function(uuid) {
var that = this;
$.ajax({
url : this.baseUrl+uuid,
dataType : 'json',
async : false,
success : function (data) {
that.cache[uuid] = data;
},
error : function(jqxhr, status, err) {
that.cache[uuid] = undefined;
}
});
};
APIReader.prototype.get = function(uuid) {
if (!(uuid in this.cache)) this.updateCache(uuid);
return this.cache[uuid];
};


The following snippet works like a charm on the development server :

var ar = new APIReader('http://server/api/endpoint/');
console.log(ar.get('18fc7dc1-7698-4b8e-900e-8262c1393067'));


Issue



However, when testing this with Karma using, say :

it('should work', function() {
var ar = new APIReader('http://server/api/endpoint/');
expect(ar.get('some-uuid')).toEqual({
... some object ...
});
});


I get this error :
1) Expected null to be Object({ ... some object ... }).
.

I've looked into it for a while and it seems the body of the ajax response received by the browser (Firefox 35) is empty.

Empty JSON in Firefox

I'm pretty sure the API (written with django and django-rest-framework) works well as httpie gives the correct (non-enpty) result for the same endpoint.

I've actually gone as far as to reproduce the exact same headers that Firefox uses using cURL :

Firefox cURL

And this returned the correct result as well.

Summing up




  • I'm pretty confident the API is working well

  • I'm confident the
    APIReader
    snippet works well (there's not much to it and it gives the correct results in dev)

  • I suppose there's something in Karma tampering with ajax requests (wiping the body or something) but there isn't much documentation available on their website and I couldn't find anything like that.



Any clue as to what's happening ?

Answer

Answer : CORS.

It seems all this was because the API server didn't allow the test server to to do cross-origin requests.

The django app (API) uses django-cors-headers to generate CORS headers. What I hadn't realized is that there's a distinction on host based on ports :

CORS_ORIGIN_WHITELIST = (
    'localhost',
    'other-domain',
)

doesn't allow the test server running on localhost:4000 to send CORS requests. I had to add the following :

CORS_ORIGIN_WHITELIST = (
    'localhost',
    'other-domain',
    'localhost:4000' # Karma test
)

It now works as expected.