Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat($browser): JSONP error handling
Browse files Browse the repository at this point in the history
since we don't know if the error was due to a client error (4xx) or
server error (5xx), we leave the status code as undefined.
  • Loading branch information
Di Peng authored and IgorMinar committed Aug 19, 2011
1 parent 718ebf1 commit 05e2c31
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 23 deletions.
26 changes: 21 additions & 5 deletions src/Browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,19 @@ function Browser(window, document, body, XHR, $log) {
outstandingRequestCount ++;
if (lowercase(method) == 'json') {
var callbackId = ("angular_" + Math.random() + '_' + (idCounter++)).replace(/\d\./, '');
var script = self.addJs(url.replace('JSON_CALLBACK', callbackId));
window[callbackId] = function(data){
window[callbackId] = function(data) {
window[callbackId].data = data;
};

var script = self.addJs(url.replace('JSON_CALLBACK', callbackId), null, function() {
if (window[callbackId].data) {
completeOutstandingRequest(callback, 200, window[callbackId].data);
} else {
completeOutstandingRequest(callback);
}
delete window[callbackId];
body[0].removeChild(script);
completeOutstandingRequest(callback, 200, data);
};
});
} else {
var xhr = new XHR();
xhr.open(method, url, true);
Expand Down Expand Up @@ -452,7 +459,7 @@ function Browser(window, document, body, XHR, $log) {
* @description
* Adds a script tag to the head.
*/
self.addJs = function(url, domId) {
self.addJs = function(url, domId, done) {
// we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
// - fetches local scripts via XHR and evals them
// - adds and immediately removes script elements from the document
Expand All @@ -465,6 +472,15 @@ function Browser(window, document, body, XHR, $log) {
script.type = 'text/javascript';
script.src = url;
if (domId) script.id = domId;

if (msie) {
script.onreadystatechange = function() {
/loaded|complete/.test(script.readyState) && done && done();
}
} else {
if (done) script.onload = script.onerror = done;
}

body[0].appendChild(script);

return script;
Expand Down
90 changes: 72 additions & 18 deletions test/BrowserSpecs.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,27 +87,81 @@ describe('browser', function(){

describe('xhr', function(){
describe('JSON', function(){
it('should add script tag for request', function() {
var callback = jasmine.createSpy('callback');
var log = "";
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, function(code, data){
log += code + ':' + data + ';';
});
browser.notifyWhenNoOutstandingRequests(callback);
expect(callback).not.toHaveBeenCalled();
expect(scripts.length).toEqual(1);
var script = scripts[0];
var url = script.src.split('?cb=');
expect(url[0]).toEqual('http://example.org/path');
expect(typeof fakeWindow[url[1]]).toEqual($function);
fakeWindow[url[1]]('data');
expect(callback).toHaveBeenCalled();
expect(log).toEqual('200:data;');
expect(scripts).toEqual(removedScripts);
expect(fakeWindow[url[1]]).toBeUndefined();
var log;

function callback(code, data) {
log += code + ':' + data + ';';
}

beforeEach(function() {
log = "";
});


// We don't have unit tests for IE because script.readyState is readOnly.
// Instead we run e2e tests on all browsers - see e2e for $xhr.
if (!msie) {

it('should add script tag for JSONP request', function() {
var notify = jasmine.createSpy('notify');
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
browser.notifyWhenNoOutstandingRequests(notify);
expect(notify).not.toHaveBeenCalled();
expect(scripts.length).toEqual(1);
var script = scripts[0];
var url = script.src.split('?cb=');
expect(url[0]).toEqual('http://example.org/path');
expect(typeof fakeWindow[url[1]]).toEqual($function);
fakeWindow[url[1]]('data');
script.onload();

expect(notify).toHaveBeenCalled();
expect(log).toEqual('200:data;');
expect(scripts).toEqual(removedScripts);
expect(fakeWindow[url[1]]).toBeUndefined();
});


it('should call callback when script fails to load', function() {
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
var script = scripts[0];
expect(typeof script.onload).toBe($function);
expect(typeof script.onerror).toBe($function);
script.onerror();

expect(log).toEqual('undefined:undefined;');
});


it('should update the outstandingRequests counter for successful requests', function() {
var notify = jasmine.createSpy('notify');
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
browser.notifyWhenNoOutstandingRequests(notify);
expect(notify).not.toHaveBeenCalled();

var script = scripts[0];
var url = script.src.split('?cb=');
fakeWindow[url[1]]('data');
script.onload();

expect(notify).toHaveBeenCalled();
});


it('should update the outstandingRequests counter for failed requests', function() {
var notify = jasmine.createSpy('notify');
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
browser.notifyWhenNoOutstandingRequests(notify);
expect(notify).not.toHaveBeenCalled();

scripts[0].onerror();

expect(notify).toHaveBeenCalled();
});
}
});


it('should normalize IE\'s 1223 status code into 204', function() {
var callback = jasmine.createSpy('XHR');

Expand Down

0 comments on commit 05e2c31

Please sign in to comment.