angular.js/test/service/httpBackendSpec.js
Vojta Jina 5ad0c7d0e4 feat($httpBackend): extract $browser.xhr into separate service
- remove whole $browser.xhr stuff
- remove whole mock $browser.xhr stuff
- add $httpBackend service + migrate unit tests from $browser
- add temporary API to access $browser's outstandingRequests count
2011-11-30 11:17:22 -05:00

179 lines
4.9 KiB
JavaScript

describe('$httpBackend', function() {
var $backend, $browser, $window,
xhr, fakeBody, callback;
// TODO(vojta): should be replaced by $defer mock
function fakeTimeout(fn, delay) {
fakeTimeout.fns.push(fn);
fakeTimeout.delays.push(delay);
}
fakeTimeout.fns = [];
fakeTimeout.delays = [];
fakeTimeout.flush = function() {
var len = fakeTimeout.fns.length;
fakeTimeout.delays = [];
while (len--) fakeTimeout.fns.shift()();
};
beforeEach(inject(function($injector) {
$window = {};
$browser = $injector.get('$browser');
fakeBody = {removeChild: jasmine.createSpy('body.removeChild')};
$backend = createHttpBackend($browser, MockXhr, fakeTimeout, $window, fakeBody);
callback = jasmine.createSpy('done');
}));
it('should do basics - open async xhr and send data', function() {
$backend('GET', '/some-url', 'some-data', noop);
xhr = MockXhr.$$lastInstance;
expect(xhr.$$method).toBe('GET');
expect(xhr.$$url).toBe('/some-url');
expect(xhr.$$data).toBe('some-data');
expect(xhr.$$async).toBe(true);
});
it('should normalize IE\'s 1223 status code into 204', function() {
callback.andCallFake(function(status) {
expect(status).toBe(204);
});
$backend('GET', 'URL', null, callback);
xhr = MockXhr.$$lastInstance;
xhr.status = 1223;
xhr.readyState = 4;
xhr.onreadystatechange();
expect(callback).toHaveBeenCalledOnce();
});
it('should set only the requested headers', function() {
$backend('POST', 'URL', null, noop, {'X-header1': 'value1', 'X-header2': 'value2'});
xhr = MockXhr.$$lastInstance;
expect(xhr.$$headers).toEqual({
'X-header1': 'value1',
'X-header2': 'value2'
});
});
it('should return raw xhr object', function() {
expect($backend('GET', '/url', null, noop)).toBe(MockXhr.$$lastInstance);
});
it('should abort request on timeout', function() {
callback.andCallFake(function(status, response) {
expect(status).toBe(-1);
});
$backend('GET', '/url', null, callback, {}, 2000);
xhr = MockXhr.$$lastInstance;
spyOn(xhr, 'abort');
expect(fakeTimeout.delays[0]).toBe(2000);
fakeTimeout.flush();
expect(xhr.abort).toHaveBeenCalledOnce();
xhr.status = 0;
xhr.readyState = 4;
xhr.onreadystatechange();
expect(callback).toHaveBeenCalledOnce();
});
it('should be async even if xhr.send() is sync', function() {
// IE6, IE7 is sync when serving from cache
function SyncXhr() {
xhr = this;
this.open = this.setRequestHeader = noop;
this.send = function() {
this.status = 200;
this.responseText = 'response';
this.readyState = 4;
};
}
callback.andCallFake(function(status, response) {
expect(status).toBe(200);
expect(response).toBe('response');
});
$backend = createHttpBackend($browser, SyncXhr, fakeTimeout);
$backend('GET', '/url', null, callback);
expect(callback).not.toHaveBeenCalled();
fakeTimeout.flush();
expect(callback).toHaveBeenCalledOnce();
(xhr.onreadystatechange || noop)();
expect(callback).toHaveBeenCalledOnce();
});
describe('JSONP', function() {
it('should add script tag for JSONP request', function() {
callback.andCallFake(function(status, response) {
expect(status).toBe(200);
expect(response).toBe('some-data');
});
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
expect($browser.$$scripts.length).toBe(1);
var script = $browser.$$scripts.shift(),
url = script.url.split('?cb=');
expect(url[0]).toBe('http://example.org/path');
$window[url[1]]('some-data');
script.done();
expect(callback).toHaveBeenCalledOnce();
});
it('should clean up the callback and remove the script', function() {
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
expect($browser.$$scripts.length).toBe(1);
var script = $browser.$$scripts.shift(),
callbackId = script.url.split('?cb=')[1];
$window[callbackId]('some-data');
script.done();
expect($window[callbackId]).toBeUndefined();
expect(fakeBody.removeChild).toHaveBeenCalledOnce();
expect(fakeBody.removeChild).toHaveBeenCalledWith(script);
});
it('should call callback with status -2 when script fails to load', function() {
callback.andCallFake(function(status, response) {
expect(status).toBe(-2);
expect(response).toBeUndefined();
});
$backend('JSONP', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
expect($browser.$$scripts.length).toBe(1);
$browser.$$scripts.shift().done();
expect(callback).toHaveBeenCalledOnce();
});
// TODO(vojta): test whether it fires "async-start"
// TODO(vojta): test whether it fires "async-end" on both success and error
});
});