aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Browser.js26
-rw-r--r--test/BrowserSpecs.js90
2 files changed, 93 insertions, 23 deletions
diff --git a/src/Browser.js b/src/Browser.js
index 815b6b24..a53687d5 100644
--- a/src/Browser.js
+++ b/src/Browser.js
@@ -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);
@@ -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
@@ -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;
diff --git a/test/BrowserSpecs.js b/test/BrowserSpecs.js
index ebaf0651..92e4e501 100644
--- a/test/BrowserSpecs.js
+++ b/test/BrowserSpecs.js
@@ -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');