weed weed - 3 months ago 25
Javascript Question

Sinon.js fakeServer.request.respond fails when using $.getJSON with jsonp

Hello I am newbie of sinon.js. I am writing Jasmine BDD test code. I want to make a little application which get photos from flickr.

describe("with stub", function() {

beforeEach(function() {
this.server = sinon.fakeServer.create();
this.server.autoRespond = true;
this.server.respondWith(200, {
"Content-Type": "application/json"
}, '{"photos":{"page":1, "pages":726, "perpage":5, "total":"3630", "photo":[{"id":"8591804280", "owner":"77921082@N00", "secret":"da96195b4b", "server":"8526", "farm":9, "title":"Pod", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"8591810388", "owner":"77921082@N00", "secret":"d94ce346a5", "server":"8509", "farm":9, "title":"Street Plate", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"8591801040", "owner":"77921082@N00", "secret":"cb7b1e246a", "server":"8097", "farm":9, "title":"Stone pod", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"8590414659", "owner":"77921082@N00", "secret":"fb49a25607", "server":"8094", "farm":9, "title":"Street pole", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"8590411479", "owner":"77921082@N00", "secret":"9aab17d3a9", "server":"8370", "farm":9, "title":"Street plate", "ispublic":1, "isfriend":0, "isfamily":0}]}, "stat":"ok"}');
this.flickrPhotos = this.flickr.photos;
});

afterEach(function() {
this.flickrPhotos = [];
});

it("[0].title should be Pod", function() {
this.flickr.getData(5, true);
expect(this.flickrPhotos[0].title).toBe("Pod");
});
});


Below code does not pass the test. Error
TypeError: Cannot read property 'title' of undefined
is returned.

root.Flickr = (function() {

function Flickr(number) {
this.number = number;
this.photos = [];
}

Flickr.prototype.getData = function(number) {
var _this = this;
$.getJSON('http://www.flickr.com/services/rest/?jsoncallback=?', {
format: 'json',
method: 'flickr.photos.search',
api_key: '7965a8bc5a2a88908e8321f3f56c80ea',
user_id: '77921082@N00',
per_page: number
}).done(function(data) {
$.each(data.photos.photo, function(i, item) {
_this.photos.push(item);
});
});
};
})();

Answer

Sinon can't handle JSONP request, as it just stubs the XMLHttpRequest object. The problem is that JSONP has nothing to do with XMLHttpRequest. Its just an script tag that is put in to the DOM and call a global function with the returning data.

In your case you have to stub $.getJSON to return a stub that will call it callback with your result data.

var json = {"photos":{"page":1, "pages":726, "perpage":5, "total":"3630", "photo":[{"id":"8591804280", "owner":"77921082@N00", "secret":"da96195b4b", "server":"8526", "farm":9, "title":"Pod", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"8591810388", "owner":"77921082@N00", "secret":"d94ce346a5", "server":"8509", "farm":9, "title":"Street Plate", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"8591801040", "owner":"77921082@N00", "secret":"cb7b1e246a", "server":"8097", "farm":9, "title":"Stone pod", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"8590414659", "owner":"77921082@N00", "secret":"fb49a25607", "server":"8094", "farm":9, "title":"Street pole", "ispublic":1, "isfriend":0, "isfamily":0}, {"id":"8590411479", "owner":"77921082@N00", "secret":"9aab17d3a9", "server":"8370", "farm":9, "title":"Street plate", "ispublic":1, "isfriend":0, "isfamily":0}]}, "stat":"ok"};

sinon.stub($, 'getJSON').returns({done: sinon.stub().callsArgWith(0, json)})