feat(mocks.$httpBackend): add $httpBackend mock

$httpBackend mock allows:
- expecting (asserting) requests
- stubbing (responding without asserting)

Add empty $httpBackend service (currently just wrapper for $browser.xhr)
This commit is contained in:
Vojta Jina 2011-08-16 21:24:53 +02:00 committed by Igor Minar
parent 59adadca08
commit cd28a2e952
8 changed files with 944 additions and 444 deletions

1
angularFiles.js vendored
View file

@ -33,6 +33,7 @@ angularFiles = {
'src/service/sniffer.js',
'src/service/window.js',
'src/service/http.js',
'src/service/httpBackend.js',
'src/service/locale.js',
'src/directives.js',
'src/markups.js',

View file

@ -78,6 +78,7 @@ function ngModule($provide, $injector) {
$provide.service('$filter', $FilterProvider);
$provide.service('$formFactory', $FormFactoryProvider);
$provide.service('$http', $HttpProvider);
$provide.service('$httpBackend', $HttpBackendProvider);
$provide.service('$location', $LocationProvider);
$provide.service('$log', $LogProvider);
$provide.service('$parse', $ParseProvider);

167
src/angular-mocks.js vendored
View file

@ -21,6 +21,7 @@ angular.module.ngMock = function($provide){
$provide.service('$browser', angular.module.ngMock.$BrowserProvider);
$provide.service('$exceptionHandler', angular.module.ngMock.$ExceptionHandlerProvider);
$provide.service('$log', angular.module.ngMock.$LogProvider);
$provide.service('$httpBackend', angular.module.ngMock.$HttpBackendProvider);
};
angular.module.ngMock.$inject = ['$provide'];
@ -38,8 +39,6 @@ angular.module.ngMock.$inject = ['$provide'];
*
* The following apis can be used in tests:
*
* - {@link #xhr} enables testing of code that uses
* the {@link angular.module.ng.$xhr $xhr service} to make XmlHttpRequests.
* - $browser.defer enables testing of code that uses
* {@link angular.module.ng.$defer $defer} for executing functions via the `setTimeout` api.
*/
@ -720,6 +719,170 @@ angular.module.ngMock.dump = function(object){
}
};
/**
* @ngdoc object
* @name angular.module.ngMock.$httpBackend
*/
angular.module.ngMock.$HttpBackendProvider = function() {
this.$get = function() {
var definitions = [],
expectations = [],
responses = [];
function createResponse(status, data, headers) {
return angular.isNumber(status) ? [status, data, headers] : [200, status, data];
}
// TODO(vojta): change params to: method, url, data, headers, callback
function $httpBackend(method, url, data, callback, headers) {
var xhr = new MockXhr(),
expectation = expectations[0],
wasExpected = false;
if (expectation && expectation.match(method, url)) {
if (!expectation.matchData(data))
throw Error('Expected ' + method + ' ' + url + ' with different data');
if (!expectation.matchHeaders(headers))
throw Error('Expected ' + method + ' ' + url + ' with different headers');
expectations.shift();
if (expectation.response) {
responses.push(function() {
xhr.$$headers = expectation.response[2];
callback(expectation.response[0], expectation.response[1]);
});
return method == 'JSONP' ? undefined : xhr;
}
wasExpected = true;
}
var i = -1, definition;
while ((definition = definitions[++i])) {
if (definition.match(method, url, data, headers || {})) {
if (!definition.response) throw Error('No response defined !');
responses.push(function() {
var response = angular.isFunction(definition.response) ?
definition.response(method, url, data, headers) : definition.response;
xhr.$$headers = response[2];
callback(response[0], response[1]);
});
return method == 'JSONP' ? undefined : xhr;
}
}
throw wasExpected ? Error('No response defined !') :
Error('Unexpected request: ' + method + ' ' + url);
}
$httpBackend.when = function(method, url, data, headers) {
var definition = new MockHttpExpectation(method, url, data, headers);
definitions.push(definition);
return {
then: function(status, data, headers) {
definition.response = angular.isFunction(status) ? status : createResponse(status, data, headers);
}
};
};
$httpBackend.expect = function(method, url, data, headers) {
var expectation = new MockHttpExpectation(method, url, data, headers);
expectations.push(expectation);
return {
respond: function(status, data, headers) {
expectation.response = createResponse(status, data, headers);
}
};
};
$httpBackend.flush = function(count) {
count = count || responses.length;
while (count--) {
if (!responses.length) throw Error('No more pending requests');
responses.shift()();
}
};
$httpBackend.verifyExpectations = function() {
if (expectations.length) {
throw Error('Unsatisfied requests: ' + expectations.join(', '));
}
};
$httpBackend.resetExpectations = function() {
expectations = [];
responses = [];
};
return $httpBackend;
};
};
function MockHttpExpectation(method, url, data, headers) {
this.match = function(m, u, d, h) {
if (method != m) return false;
if (!this.matchUrl(u)) return false;
if (angular.isDefined(d) && !this.matchData(d)) return false;
if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
return true;
};
this.matchUrl = function(u) {
if (!url) return true;
if (angular.isFunction(url.test)) {
if (!url.test(u)) return false;
} else if (url != u) return false;
return true;
};
this.matchHeaders = function(h) {
if (angular.isUndefined(headers)) return true;
if (angular.isFunction(headers)) {
if (!headers(h)) return false;
} else if (!angular.equals(headers, h)) return false;
return true;
};
this.matchData = function(d) {
if (angular.isUndefined(data)) return true;
if (data && angular.isFunction(data.test)) {
if (!data.test(d)) return false;
} else if (data != d) return false;
return true;
};
this.toString = function() {
return method + ' ' + url;
};
}
function MockXhr() {
// hack for testing $http
MockXhr.$$lastInstance = this;
this.getResponseHeader = function(name) {
return this.$$headers[name];
};
this.getAllResponseHeaders = function() {
var lines = [];
angular.forEach(this.$$headers, function(value, key) {
lines.push(key + ': ' + value);
});
return lines.join('\n');
};
this.abort = noop;
}
window.jstestdriver && (function(window){
/**
* Global method to output any number of objects into JSTD console. Useful for debugging.

View file

@ -51,6 +51,7 @@ function transform(data, fns, param) {
/**
* @ngdoc object
* @name angular.module.ng.$http
* @requires $httpBacked
* @requires $browser
* @requires $exceptionHandler
* @requires $cacheFactory
@ -85,8 +86,8 @@ function $HttpProvider() {
}
};
this.$get = ['$browser', '$exceptionHandler', '$cacheFactory', '$rootScope',
function($browser, $exceptionHandler, $cacheFactory, $rootScope) {
this.$get = ['$httpBackend', '$browser', '$exceptionHandler', '$cacheFactory', '$rootScope',
function($httpBackend, $browser, $exceptionHandler, $cacheFactory, $rootScope) {
var cache = $cacheFactory('$http'),
pendingRequestsCount = 0;
@ -235,7 +236,7 @@ function $HttpProvider() {
/**
* Represents Request object, returned by $http()
*
* !!! ACCESS CLOSURE VARS: $browser, $config, $log, $rootScope, cache, pendingRequestsCount
* !!! ACCESS CLOSURE VARS: $httpBackend, $browser, $config, $log, $rootScope, cache, pendingRequestsCount
*/
function XhrFuture() {
var rawRequest, cfg = {}, callbacks = [],
@ -243,7 +244,7 @@ function $HttpProvider() {
parsedHeaders;
/**
* Callback registered to $browser.xhr:
* Callback registered to $httpBackend():
* - caches the response if desired
* - calls fireCallbacks()
* - clears the reference to raw request object
@ -265,7 +266,7 @@ function $HttpProvider() {
* Fire all registered callbacks for given status code
*
* This method when:
* - serving response from real request ($browser.xhr callback)
* - serving response from real request
* - serving response from cache
*
* It does:
@ -368,7 +369,7 @@ function $HttpProvider() {
fireCallbacks(fromCache[1], fromCache[0]);
});
} else {
rawRequest = $browser.xhr(cfg.method, cfg.url, data, done, headers, cfg.timeout);
rawRequest = $httpBackend(cfg.method, cfg.url, data, done, headers, cfg.timeout);
}
pendingRequestsCount++;

View file

@ -0,0 +1,6 @@
function $HttpBackendProvider() {
this.$get = ['$browser', function($browser) {
return $browser.xhr;
}];
}

View file

@ -342,4 +342,401 @@ describe('mocks', function() {
expect(count).toBe(2);
});
});
describe('$httpBackend', function() {
var hb, callback;
beforeEach(inject(function($httpBackend) {
callback = jasmine.createSpy('callback');
hb = $httpBackend;
}));
it('should respond with first matched definition', function() {
hb.when('GET', '/url1').then(200, 'content', {});
hb.when('GET', '/url1').then(201, 'another', {});
callback.andCallFake(function(status, response) {
expect(status).toBe(200);
expect(response).toBe('content');
});
hb('GET', '/url1', null, callback);
expect(callback).not.toHaveBeenCalled();
hb.flush();
expect(callback).toHaveBeenCalledOnce();
});
it('should throw error when unexpected request', function() {
hb.when('GET', '/url1').then(200, 'content');
expect(function() {
hb('GET', '/xxx');
}).toThrow('Unexpected request: GET /xxx');
});
it('should match headers if specified', function() {
hb.when('GET', '/url', null, {'X': 'val1'}).then(201, 'content1');
hb.when('GET', '/url', null, {'X': 'val2'}).then(202, 'content2');
hb.when('GET', '/url').then(203, 'content3');
hb('GET', '/url', null, function(status, response) {
expect(status).toBe(203);
expect(response).toBe('content3');
});
hb('GET', '/url', null, function(status, response) {
expect(status).toBe(201);
expect(response).toBe('content1');
}, {'X': 'val1'});
hb('GET', '/url', null, function(status, response) {
expect(status).toBe(202);
expect(response).toBe('content2');
}, {'X': 'val2'});
hb.flush();
});
it('should match data if specified', function() {
hb.when('GET', '/a/b', '{a: true}').then(201, 'content1');
hb.when('GET', '/a/b').then(202, 'content2');
hb('GET', '/a/b', '{a: true}', function(status, response) {
expect(status).toBe(201);
expect(response).toBe('content1');
});
hb('GET', '/a/b', null, function(status, response) {
expect(status).toBe(202);
expect(response).toBe('content2');
});
hb.flush();
});
it('should match only method', function() {
hb.when('GET').then(202, 'c');
callback.andCallFake(function(status, response) {
expect(status).toBe(202);
expect(response).toBe('c');
});
hb('GET', '/some', null, callback, {});
hb('GET', '/another', null, callback, {'X-Fake': 'Header'});
hb('GET', '/third', 'some-data', callback, {});
hb.flush();
expect(callback).toHaveBeenCalled();
});
it('should expose given headers', function() {
hb.when('GET', '/u1').then(200, null, {'X-Fake': 'Header', 'Content-Type': 'application/json'});
var xhr = hb('GET', '/u1', null, noop, {});
hb.flush();
expect(xhr.getResponseHeader('X-Fake')).toBe('Header');
expect(xhr.getAllResponseHeaders()).toBe('X-Fake: Header\nContent-Type: application/json');
});
it('should preserve the order of requests', function() {
hb.when('GET', '/url1').then(200, 'first');
hb.when('GET', '/url2').then(201, 'second');
hb('GET', '/url2', null, callback);
hb('GET', '/url1', null, callback);
hb.flush();
expect(callback.callCount).toBe(2);
expect(callback.argsForCall[0]).toEqual([201, 'second']);
expect(callback.argsForCall[1]).toEqual([200, 'first']);
});
it('then() should take function', function() {
hb.when('GET', '/some').then(function(m, u, d, h) {
return [301, m + u + ';' + d + ';a=' + h.a, {'Connection': 'keep-alive'}];
});
var xhr = hb('GET', '/some', 'data', callback, {a: 'b'});
hb.flush();
expect(callback).toHaveBeenCalledOnce();
expect(callback.mostRecentCall.args[0]).toBe(301);
expect(callback.mostRecentCall.args[1]).toBe('GET/some;data;a=b');
expect(xhr.getResponseHeader('Connection')).toBe('keep-alive');
});
it('expect() should require specified order', function() {
hb.expect('GET', '/url1').respond(200, '');
hb.expect('GET', '/url2').respond(200, '');
expect(function() {
hb('GET', '/url2', null, noop, {});
}).toThrow('Unexpected request: GET /url2');
});
it('expect() should have precendence over when()', function() {
callback.andCallFake(function(status, response) {
expect(status).toBe(300);
expect(response).toBe('expect');
});
hb.when('GET', '/url').then(200, 'when');
hb.expect('GET', '/url').respond(300, 'expect');
hb('GET', '/url', null, callback, {});
hb.flush();
expect(callback).toHaveBeenCalledOnce();
});
it ('should throw exception when only headers differes from expectation', function() {
hb.when('GET').then(200, '', {});
hb.expect('GET', '/match', undefined, {'Content-Type': 'application/json'});
expect(function() {
hb('GET', '/match', null, noop, {});
}).toThrow('Expected GET /match with different headers');
});
it ('should throw exception when only data differes from expectation', function() {
hb.when('GET').then(200, '', {});
hb.expect('GET', '/match', 'some-data');
expect(function() {
hb('GET', '/match', 'different', noop, {});
}).toThrow('Expected GET /match with different data');
});
it('expect() should without respond() and use then()', function() {
callback.andCallFake(function(status, response) {
expect(status).toBe(201);
expect(response).toBe('data');
});
hb.when('GET', '/some').then(201, 'data');
hb.expect('GET', '/some');
hb('GET', '/some', null, callback);
hb.flush();
expect(callback).toHaveBeenCalled();
expect(function() { hb.verifyExpectations(); }).not.toThrow();
});
it('flush() should not flush requests fired during callbacks', function() {
// regression
hb.when('GET').then(200, '');
hb('GET', '/some', null, function() {
hb('GET', '/other', null, callback);
});
hb.flush();
expect(callback).not.toHaveBeenCalled();
});
it('flush() should flush given number of pending requests', function() {
hb.when('GET').then(200, '');
hb('GET', '/some', null, callback);
hb('GET', '/some', null, callback);
hb('GET', '/some', null, callback);
hb.flush(2);
expect(callback).toHaveBeenCalled();
expect(callback.callCount).toBe(2);
});
it('flush() should throw exception when flushing more requests than pending', function() {
hb.when('GET').then(200, '');
hb('GET', '/url', null, callback);
expect(function() {hb.flush(2);}).toThrow('No more pending requests');
expect(callback).toHaveBeenCalledOnce();
});
it('respond() should set default status 200 if not defined', function() {
callback.andCallFake(function(status, response) {
expect(status).toBe(200);
expect(response).toBe('some-data');
});
hb.expect('GET', '/url1').respond('some-data');
hb.expect('GET', '/url2').respond('some-data', {'X-Header': 'true'});
hb('GET', '/url1', null, callback);
hb('GET', '/url2', null, callback);
hb.flush();
expect(callback).toHaveBeenCalled();
expect(callback.callCount).toBe(2);
});
it('then() should set default status 200 if not defined', function() {
callback.andCallFake(function(status, response) {
expect(status).toBe(200);
expect(response).toBe('some-data');
});
hb.when('GET', '/url1').then('some-data');
hb.when('GET', '/url2').then('some-data', {'X-Header': 'true'});
hb('GET', '/url1', null, callback);
hb('GET', '/url2', null, callback);
hb.flush();
expect(callback).toHaveBeenCalled();
expect(callback.callCount).toBe(2);
});
it('should respond with definition if no response for expectation', function() {
callback.andCallFake(function(status, response) {
expect(status).toBe(201);
expect(response).toBe('def-response');
});
hb.when('GET').then(201, 'def-response');
hb.expect('GET', '/some-url');
hb('GET', '/some-url', null, callback);
hb.flush();
expect(callback).toHaveBeenCalledOnce();
hb.verifyExpectations();
});
it('should throw an exception if no response defined', function() {
hb.when('GET', '/test');
expect(function() {
hb('GET', '/test', null, callback);
}).toThrow('No response defined !');
});
it('should throw an exception if no response for expection and no definition', function() {
hb.expect('GET', '/url');
expect(function() {
hb('GET', '/url', null, callback);
}).toThrow('No response defined !');
});
it('should respond undefined when JSONP method', function() {
hb.when('JSONP', '/url1').then(200);
hb.expect('JSONP', '/url2').respond(200);
expect(hb('JSONP', '/url1')).toBeUndefined();
expect(hb('JSONP', '/url2')).toBeUndefined();
});
describe('verify', function() {
it('should throw exception if not all expectations were satisfied', function() {
hb.expect('POST', '/u1', 'ddd').respond(201, '', {});
hb.expect('GET', '/u2').respond(200, '', {});
hb.expect('POST', '/u3').respond(201, '', {});
hb('POST', '/u1', 'ddd', noop, {});
expect(function() {hb.verifyExpectations();})
.toThrow('Unsatisfied requests: GET /u2, POST /u3');
});
it('should do nothing when no expectation', function() {
hb.when('DELETE', '/some').then(200, '');
expect(function() {hb.verifyExpectations();}).not.toThrow();
});
it('should do nothing when all expectations satisfied', function() {
hb.expect('GET', '/u2').respond(200, '', {});
hb.expect('POST', '/u3').respond(201, '', {});
hb.when('DELETE', '/some').then(200, '');
hb('GET', '/u2', noop);
hb('POST', '/u3', noop);
expect(function() {hb.verifyExpectations();}).not.toThrow();
});
});
describe('reset', function() {
it('should remove all expectations', function() {
hb.expect('GET', '/u2').respond(200, '', {});
hb.expect('POST', '/u3').respond(201, '', {});
hb.resetExpectations();
expect(function() {hb.verifyExpectations();}).not.toThrow();
});
it('should remove all responses', function() {
hb.expect('GET', '/url').respond(200, '', {});
hb('GET', '/url', null, callback, {});
hb.resetExpectations();
hb.flush();
expect(callback).not.toHaveBeenCalled();
});
});
describe('MockHttpExpectation', function() {
it('should accept url as regexp', function() {
var exp = new MockHttpExpectation('GET', /^\/x/);
expect(exp.match('GET', '/x')).toBe(true);
expect(exp.match('GET', '/xxx/x')).toBe(true);
expect(exp.match('GET', 'x')).toBe(false);
expect(exp.match('GET', 'a/x')).toBe(false);
});
it('should accept data as regexp', function() {
var exp = new MockHttpExpectation('POST', '/url', /\{.*?\}/);
expect(exp.match('POST', '/url', '{"a": "aa"}')).toBe(true);
expect(exp.match('POST', '/url', '{"one": "two"}')).toBe(true);
expect(exp.match('POST', '/url', '{"one"')).toBe(false);
});
it('should ignore data only if undefined (not null or false)', function() {
var exp = new MockHttpExpectation('POST', '/url', null);
expect(exp.matchData(null)).toBe(true);
expect(exp.matchData('some-data')).toBe(false);
exp = new MockHttpExpectation('POST', '/url', undefined);
expect(exp.matchData(null)).toBe(true);
expect(exp.matchData('some-data')).toBe(true);
});
it('should accept headers as function', function() {
var exp = new MockHttpExpectation('GET', '/url', undefined, function(h) {
return h['Content-Type'] == 'application/json';
});
expect(exp.matchHeaders({})).toBe(false);
expect(exp.matchHeaders({'Content-Type': 'application/json', 'X-Another': 'true'})).toBe(true);
});
});
});
});

File diff suppressed because it is too large Load diff

View file

@ -134,14 +134,13 @@ describe("widget", function() {
expect($rootScope.$$childHead).toBeFalsy();
}));
it('should do xhr request and cache it', inject(function($rootScope, $browser, $compile) {
it('should do xhr request and cache it', inject(function($rootScope, $httpBackend, $compile) {
var element = $compile('<ng:include src="url"></ng:include>')($rootScope);
var $browserXhr = $browser.xhr;
$browserXhr.expectGET('myUrl').respond('my partial');
$httpBackend.expect('GET', 'myUrl').respond('my partial');
$rootScope.url = 'myUrl';
$rootScope.$digest();
$browserXhr.flush();
$httpBackend.flush();
expect(element.text()).toEqual('my partial');
$rootScope.url = null;
@ -155,14 +154,13 @@ describe("widget", function() {
}));
it('should clear content when error during xhr request',
inject(function($browser, $compile, $rootScope) {
inject(function($httpBackend, $compile, $rootScope) {
var element = $compile('<ng:include src="url">content</ng:include>')($rootScope);
var $browserXhr = $browser.xhr;
$browserXhr.expectGET('myUrl').respond(404, '');
$httpBackend.expect('GET', 'myUrl').respond(404, '');
$rootScope.url = 'myUrl';
$rootScope.$digest();
$browserXhr.flush();
$httpBackend.flush();
expect(element.text()).toBe('');
}));
@ -500,33 +498,33 @@ describe("widget", function() {
it('should load content via xhr when route changes',
inject(function($rootScope, $compile, $browser, $location, $route) {
inject(function($rootScope, $compile, $httpBackend, $location, $route) {
$route.when('/foo', {template: 'myUrl1'});
$route.when('/bar', {template: 'myUrl2'});
expect(element.text()).toEqual('');
$location.path('/foo');
$browser.xhr.expectGET('myUrl1').respond('<div>{{1+3}}</div>');
$httpBackend.expect('GET', 'myUrl1').respond('<div>{{1+3}}</div>');
$rootScope.$digest();
$browser.xhr.flush();
$httpBackend.flush();
expect(element.text()).toEqual('4');
$location.path('/bar');
$browser.xhr.expectGET('myUrl2').respond('angular is da best');
$httpBackend.expect('GET', 'myUrl2').respond('angular is da best');
$rootScope.$digest();
$browser.xhr.flush();
$httpBackend.flush();
expect(element.text()).toEqual('angular is da best');
}));
it('should remove all content when location changes to an unknown route',
inject(function($rootScope, $compile, $location, $browser, $route) {
inject(function($rootScope, $compile, $location, $httpBackend, $route) {
$route.when('/foo', {template: 'myUrl1'});
$location.path('/foo');
$browser.xhr.expectGET('myUrl1').respond('<div>{{1+3}}</div>');
$httpBackend.expect('GET', 'myUrl1').respond('<div>{{1+3}}</div>');
$rootScope.$digest();
$browser.xhr.flush();
$httpBackend.flush();
expect(element.text()).toEqual('4');
$location.path('/unknown');
@ -535,14 +533,14 @@ describe("widget", function() {
}));
it('should chain scopes and propagate evals to the child scope',
inject(function($rootScope, $compile, $location, $browser, $route) {
inject(function($rootScope, $compile, $location, $httpBackend, $route) {
$route.when('/foo', {template: 'myUrl1'});
$rootScope.parentVar = 'parent';
$location.path('/foo');
$browser.xhr.expectGET('myUrl1').respond('<div>{{parentVar}}</div>');
$httpBackend.expect('GET', 'myUrl1').respond('<div>{{parentVar}}</div>');
$rootScope.$digest();
$browser.xhr.flush();
$httpBackend.flush();
expect(element.text()).toEqual('parent');
$rootScope.parentVar = 'new parent';
@ -551,10 +549,11 @@ describe("widget", function() {
}));
it('should be possible to nest ng:view in ng:include', inject(function() {
// TODO(vojta): refactor this test
var injector = angular.injector('ng', 'ngMock');
var myApp = injector.get('$rootScope');
var $browser = injector.get('$browser');
$browser.xhr.expectGET('includePartial.html').respond('view: <ng:view></ng:view>');
var $httpBackend = injector.get('$httpBackend');
$httpBackend.expect('GET', 'includePartial.html').respond('view: <ng:view></ng:view>');
injector.get('$location').path('/foo');
var $route = injector.get('$route');
@ -566,9 +565,10 @@ describe("widget", function() {
'</div>')(myApp);
myApp.$apply();
$browser.xhr.expectGET('viewPartial.html').respond('content');
$httpBackend.expect('GET', 'viewPartial.html').respond('content');
$httpBackend.flush();
myApp.$digest();
$browser.xhr.flush();
$httpBackend.flush();
expect(myApp.$element.text()).toEqual('include: view: content');
expect($route.current.template).toEqual('viewPartial.html');
@ -576,11 +576,10 @@ describe("widget", function() {
}));
it('should initialize view template after the view controller was initialized even when ' +
'templates were cached', inject(function($rootScope, $compile, $location, $browser, $route) {
'templates were cached', inject(function($rootScope, $compile, $location, $httpBackend, $route) {
//this is a test for a regression that was introduced by making the ng:view cache sync
$route.when('/foo', {controller: ParentCtrl, template: 'viewPartial.html'});
$rootScope.log = [];
function ParentCtrl() {
@ -592,12 +591,12 @@ describe("widget", function() {
};
$location.path('/foo');
$browser.xhr.expectGET('viewPartial.html').
$httpBackend.expect('GET', 'viewPartial.html').
respond('<div ng:init="log.push(\'init\')">' +
'<div ng:controller="ChildCtrl"></div>' +
'</div>');
$rootScope.$apply();
$browser.xhr.flush();
$httpBackend.flush();
expect($rootScope.log).toEqual(['parent', 'init', 'child']);
@ -608,13 +607,12 @@ describe("widget", function() {
$rootScope.log = [];
$location.path('/foo');
$rootScope.$apply();
$browser.defer.flush();
expect($rootScope.log).toEqual(['parent', 'init', 'child']);
}));
it('should discard pending xhr callbacks if a new route is requested before the current ' +
'finished loading', inject(function($route, $rootScope, $location, $browser) {
'finished loading', inject(function($route, $rootScope, $location, $httpBackend) {
// this is a test for a bad race condition that affected feedback
$route.when('/foo', {template: 'myUrl1'});
@ -623,26 +621,26 @@ describe("widget", function() {
expect($rootScope.$element.text()).toEqual('');
$location.path('/foo');
$browser.xhr.expectGET('myUrl1').respond('<div>{{1+3}}</div>');
$httpBackend.expect('GET', 'myUrl1').respond('<div>{{1+3}}</div>');
$rootScope.$digest();
$location.path('/bar');
$browser.xhr.expectGET('myUrl2').respond('<div>{{1+1}}</div>');
$httpBackend.expect('GET', 'myUrl2').respond('<div>{{1+1}}</div>');
$rootScope.$digest();
$browser.xhr.flush(); // now that we have to requests pending, flush!
$httpBackend.flush(); // now that we have to requests pending, flush!
expect($rootScope.$element.text()).toEqual('2');
}));
it('should clear the content when error during xhr request',
inject(function($route, $location, $rootScope, $browser) {
inject(function($route, $location, $rootScope, $httpBackend) {
$route.when('/foo', {controller: noop, template: 'myUrl1'});
$location.path('/foo');
$browser.xhr.expectGET('myUrl1').respond(404, '');
$httpBackend.expect('GET', 'myUrl1').respond(404, '');
$rootScope.$element.text('content');
$rootScope.$digest();
$browser.xhr.flush();
$httpBackend.flush();
expect($rootScope.$element.text()).toBe('');
}));