diff --git a/src/ng/compile.js b/src/ng/compile.js
index 6606dc6c6586..68a3dca1e841 100644
--- a/src/ng/compile.js
+++ b/src/ng/compile.js
@@ -1018,10 +1018,10 @@ function $CompileProvider($provide) {
while(linkQueue.length) {
- var controller = linkQueue.pop(),
- linkRootElement = linkQueue.pop(),
- beforeTemplateLinkNode = linkQueue.pop(),
- scope = linkQueue.pop(),
+ var scope = linkQueue.shift(),
+ beforeTemplateLinkNode = linkQueue.shift(),
+ linkRootElement = linkQueue.shift(),
+ controller = linkQueue.shift(),
linkNode = compileNode;
if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
diff --git a/src/ng/http.js b/src/ng/http.js
index e4d695c460a0..d54e8bd31599 100644
--- a/src/ng/http.js
+++ b/src/ng/http.js
@@ -155,20 +155,52 @@ function $HttpProvider() {
xsrfHeaderName: 'X-XSRF-TOKEN'
};
- var providerResponseInterceptors = this.responseInterceptors = [];
+ /**
+ * Are order by request. I.E. they are applied in the same order as
+ * array on request, but revers order on response.
+ */
+ var interceptorFactories = this.interceptors = [];
+ /**
+ * For historical reasons, response interceptors ordered by the order in which
+ * they are applied to response. (This is in revers to interceptorFactories)
+ */
+ var responseInterceptorFactories = this.responseInterceptors = [];
this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
- var defaultCache = $cacheFactory('$http'),
- responseInterceptors = [];
+ var defaultCache = $cacheFactory('$http');
- forEach(providerResponseInterceptors, function(interceptor) {
- responseInterceptors.push(
- isString(interceptor)
- ? $injector.get(interceptor)
- : $injector.invoke(interceptor)
- );
+ /**
+ * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
+ * The reversal is needed so that we can build up the interception chain around the
+ * server request.
+ */
+ var reversedInterceptors = [];
+
+ forEach(interceptorFactories, function(interceptorFactory) {
+ reversedInterceptors.unshift(isString(interceptorFactory)
+ ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
+ });
+
+ forEach(responseInterceptorFactories, function(interceptorFactory, index) {
+ var responseFn = isString(interceptorFactory)
+ ? $injector.get(interceptorFactory)
+ : $injector.invoke(interceptorFactory);
+
+ /**
+ * Response interceptors go before "around" interceptors (no real reason, just
+ * had to pick one.) But they are already revesed, so we can't use unshift, hence
+ * the splice.
+ */
+ reversedInterceptors.splice(index, 0, {
+ response: function(response) {
+ return responseFn($q.when(response));
+ },
+ responseError: function(response) {
+ return responseFn($q.reject(response));
+ }
+ });
});
@@ -310,7 +342,90 @@ function $HttpProvider() {
* To skip it, set configuration property `cache` to `false`.
*
*
- * # Response interceptors
+ * # Interceptors
+ *
+ * Before you start creating interceptors, be sure to understand the
+ * {@link ng.$q $q and deferred/promise APIs}.
+ *
+ * For purposes of global error handling, authentication or any kind of synchronous or
+ * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
+ * able to intercept requests before they are handed to the server and
+ * responses before they are handed over to the application code that
+ * initiated these requests. The interceptors leverage the {@link ng.$q
+ * promise APIs} to fulfil this need for both synchronous and asynchronous pre-processing.
+ *
+ * The interceptors are service factories that are registered with the $httpProvider by
+ * adding them to the `$httpProvider.interceptors` array. The factory is called and
+ * injected with dependencies (if specified) and returns the interceptor.
+ *
+ * There are two kinds of interceptors (and two kinds of rejection interceptors):
+ *
+ * * `request`: interceptors get called with http `config` object. The function is free to modify
+ * the `config` or create a new one. The function needs to return the `config` directly or as a
+ * promise.
+ * * `requestError`: interceptor gets called when a previous interceptor threw an error or resolved
+ * with a rejection.
+ * * `response`: interceptors get called with http `response` object. The function is free to modify
+ * the `response` or create a new one. The function needs to return the `response` directly or as a
+ * promise.
+ * * `responseError`: interceptor gets called when a previous interceptor threw an error or resolved
+ * with a rejection.
+ *
+ *
+ *
+ * // register the interceptor as a service
+ * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
+ * return {
+ * // optional method
+ * 'request': function(config) {
+ * // do something on success
+ * return config || $q.when(config);
+ * },
+ *
+ * // optional method
+ * 'requestError': function(rejection) {
+ * // do something on error
+ * if (canRecover(rejection)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(rejection);
+ * },
+ *
+ *
+ *
+ * // optional method
+ * 'response': function(response) {
+ * // do something on success
+ * return response || $q.when(response);
+ * },
+ *
+ * // optional method
+ * 'responseError': function(rejection) {
+ * // do something on error
+ * if (canRecover(rejection)) {
+ * return responseOrNewPromise
+ * }
+ * return $q.reject(rejection);
+ * };
+ * }
+ * });
+ *
+ * $httpProvider.interceptors.push('myHttpInterceptor');
+ *
+ *
+ * // register the interceptor via an anonymous factory
+ * $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
+ * return {
+ * 'request': function(config) {
+ * // same as above
+ * },
+ * 'response': function(response) {
+ * // same as above
+ * }
+ * });
+ *
+ *
+ * # Response interceptors (DEPRECATED)
*
* Before you start creating interceptors, be sure to understand the
* {@link ng.$q $q and deferred/promise APIs}.
@@ -526,45 +641,66 @@ function $HttpProvider() {
*/
- function $http(config) {
+ function $http(requestConfig) {
+ var config = {
+ transformRequest: defaults.transformRequest,
+ transformResponse: defaults.transformResponse
+ };
+ var headers = {};
+
+ extend(config, requestConfig);
+ config.headers = headers;
config.method = uppercase(config.method);
- var xsrfHeader = {},
- xsrfCookieName = config.xsrfCookieName || defaults.xsrfCookieName,
- xsrfHeaderName = config.xsrfHeaderName || defaults.xsrfHeaderName,
- xsrfToken = isSameDomain(config.url, $browser.url()) ?
- $browser.cookies()[xsrfCookieName] : undefined;
- xsrfHeader[xsrfHeaderName] = xsrfToken;
-
- var reqTransformFn = config.transformRequest || defaults.transformRequest,
- respTransformFn = config.transformResponse || defaults.transformResponse,
- defHeaders = defaults.headers,
- reqHeaders = extend(xsrfHeader,
- defHeaders.common, defHeaders[lowercase(config.method)], config.headers),
- reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),
- promise;
-
- // strip content-type if data is undefined
- if (isUndefined(config.data)) {
- delete reqHeaders['Content-Type'];
- }
+ extend(headers,
+ defaults.headers.common,
+ defaults.headers[lowercase(config.method)],
+ requestConfig.headers);
- if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
- config.withCredentials = defaults.withCredentials;
+ var xsrfValue = isSameDomain(config.url, $browser.url())
+ ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
+ : undefined;
+ if (xsrfValue) {
+ headers[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
}
- // send request
- promise = sendReq(config, reqData, reqHeaders);
+ var serverRequest = function(config) {
+ var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
- // transform future response
- promise = promise.then(transformResponse, transformResponse);
+ // strip content-type if data is undefined
+ if (isUndefined(config.data)) {
+ delete headers['Content-Type'];
+ }
+
+ if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
+ config.withCredentials = defaults.withCredentials;
+ }
+
+ // send request
+ return sendReq(config, reqData, headers).then(transformResponse, transformResponse);
+ };
+
+ var chain = [serverRequest, undefined];
+ var promise = $q.when(config);
// apply interceptors
- forEach(responseInterceptors, function(interceptor) {
- promise = interceptor(promise);
+ forEach(reversedInterceptors, function(interceptor) {
+ if (interceptor.request || interceptor.requestError) {
+ chain.unshift(interceptor.request, interceptor.requestError);
+ }
+ if (interceptor.response || interceptor.responseError) {
+ chain.push(interceptor.response, interceptor.responseError);
+ }
});
+ while(chain.length) {
+ var thenFn = chain.shift();
+ var rejectFn = chain.shift();
+
+ promise = promise.then(thenFn, rejectFn);
+ };
+
promise.success = function(fn) {
promise.then(function(response) {
fn(response.data, response.status, response.headers, config);
@@ -584,7 +720,7 @@ function $HttpProvider() {
function transformResponse(response) {
// make a copy since the response must be cacheable
var resp = extend({}, response, {
- data: transformData(response.data, response.headers, respTransformFn)
+ data: transformData(response.data, response.headers, config.transformResponse)
});
return (isSuccess(response.status))
? resp
diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js
index 8c91e62801d3..3980a391add4 100644
--- a/src/ngMock/angular-mocks.js
+++ b/src/ngMock/angular-mocks.js
@@ -826,7 +826,7 @@ angular.mock.dump = function(object) {
*/
angular.mock.$HttpBackendProvider = function() {
- this.$get = [createHttpBackendMock];
+ this.$get = ['$rootScope', createHttpBackendMock];
};
/**
@@ -843,7 +843,7 @@ angular.mock.$HttpBackendProvider = function() {
* @param {Object=} $browser Auto-flushing enabled if specified
* @return {Object} Instance of $httpBackend mock
*/
-function createHttpBackendMock($delegate, $browser) {
+function createHttpBackendMock($rootScope, $delegate, $browser) {
var definitions = [],
expectations = [],
responses = [],
@@ -1173,6 +1173,7 @@ function createHttpBackendMock($delegate, $browser) {
* is called an exception is thrown (as this typically a sign of programming error).
*/
$httpBackend.flush = function(count) {
+ $rootScope.$digest();
if (!responses.length) throw Error('No pending request to flush !');
if (angular.isDefined(count)) {
@@ -1205,6 +1206,7 @@ function createHttpBackendMock($delegate, $browser) {
*
*/
$httpBackend.verifyNoOutstandingExpectation = function() {
+ $rootScope.$digest();
if (expectations.length) {
throw Error('Unsatisfied requests: ' + expectations.join(', '));
}
@@ -1606,7 +1608,7 @@ angular.module('ngMockE2E', ['ng']).config(function($provide) {
* control how a matched request is handled.
*/
angular.mock.e2e = {};
-angular.mock.e2e.$httpBackendDecorator = ['$delegate', '$browser', createHttpBackendMock];
+angular.mock.e2e.$httpBackendDecorator = ['$rootScope', '$delegate', '$browser', createHttpBackendMock];
angular.mock.clearDataCache = function() {
diff --git a/test/ng/directive/ngIncludeSpec.js b/test/ng/directive/ngIncludeSpec.js
index 7c94a70ec5ba..dce803b52c31 100644
--- a/test/ng/directive/ngIncludeSpec.js
+++ b/test/ng/directive/ngIncludeSpec.js
@@ -178,25 +178,23 @@ describe('ngInclude', function() {
it('should discard pending xhr callbacks if a new template is requested before the current ' +
'finished loading', inject(function($rootScope, $compile, $httpBackend) {
element = jqLite("");
- var log = [];
+ var log = {};
$rootScope.templateUrl = 'myUrl1';
$rootScope.logger = function(msg) {
- log.push(msg);
+ log[msg] = true;
}
$compile(element)($rootScope);
- expect(log.join('; ')).toEqual('');
+ expect(log).toEqual({});
$httpBackend.expect('GET', 'myUrl1').respond('{{logger("url1")}}
');
$rootScope.$digest();
- expect(log.join('; ')).toEqual('');
+ expect(log).toEqual({});
$rootScope.templateUrl = 'myUrl2';
$httpBackend.expect('GET', 'myUrl2').respond('{{logger("url2")}}
');
- $rootScope.$digest();
$httpBackend.flush(); // now that we have two requests pending, flush!
- expect(log.join('; ')).toEqual('url2; url2'); // it's here twice because we go through at
- // least two digest cycles
+ expect(log).toEqual({ url2 : true });
}));
diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js
index 2dd141925789..e6d1cf4fb0f8 100644
--- a/test/ng/httpSpec.js
+++ b/test/ng/httpSpec.js
@@ -12,7 +12,7 @@ describe('$http', function() {
$exceptionHandlerProvider.mode('log');
}));
- afterEach(inject(function($exceptionHandler, $httpBackend) {
+ afterEach(inject(function($exceptionHandler, $httpBackend, $rootScope) {
forEach($exceptionHandler.errors, function(e) {
dump('Unhandled exception: ', e)
});
@@ -21,13 +21,150 @@ describe('$http', function() {
throw 'Unhandled exceptions trapped in $exceptionHandler!';
}
+ $rootScope.$digest();
$httpBackend.verifyNoOutstandingExpectation();
}));
describe('$httpProvider', function() {
-
describe('interceptors', function() {
+ it('should accept injected rejected response interceptor', function() {
+ var wasCalled = false;
+ module(function($httpProvider, $provide) {
+ $httpProvider.responseInterceptors.push('injectedInterceptor');
+ $provide.factory('injectedInterceptor', ['$q', function($q) {
+ return function(promise) {
+ return promise.then(null, function authInterceptor(response) {
+ wasCalled = true;
+ expect(response.status).toEqual(401);
+ return $q.reject(response);
+ });
+ };
+ }]);
+ });
+ inject(function($http, $httpBackend) {
+ $httpBackend.expect('GET', '/url').respond(401);
+ $http({method: 'GET', url: '/url'});
+ $httpBackend.flush();
+ expect(wasCalled).toEqual(true);
+ });
+ });
+
+
+ it('should chain request, requestReject, response and responseReject interceptors', function() {
+ module(function($httpProvider) {
+ var savedConfig, savedResponse;
+ $httpProvider.interceptors.push(function($q) {
+ return {
+ request: function(config) {
+ config.url += '/1';
+ savedConfig = config;
+ return $q.reject('/2');
+ }
+ };
+ });
+ $httpProvider.interceptors.push(function($q) {
+ return {
+ requestError: function(error) {
+ savedConfig.url += error;
+ return $q.when(savedConfig);
+ }
+ };
+ });
+ $httpProvider.interceptors.push(function() {
+ return {
+ responseError: function(rejection) {
+ savedResponse.data += rejection;
+ return savedResponse;
+ }
+ };
+ });
+ $httpProvider.interceptors.push(function($q) {
+ return {
+ response: function(response) {
+ response.data += ':1';
+ savedResponse = response
+ return $q.reject(':2');
+ }
+ };
+ });
+ });
+ inject(function($http, $httpBackend, $rootScope) {
+ var response;
+ $httpBackend.expect('GET', '/url/1/2').respond('response');
+ $http({method: 'GET', url: '/url'}).then(function(r) {
+ response = r;
+ });
+ $rootScope.$apply();
+ $httpBackend.flush();
+ expect(response.data).toEqual('response:1:2');
+ });
+ });
+
+
+ it('should verify order of execution', function() {
+ module(function($httpProvider) {
+ $httpProvider.interceptors.push(function($q) {
+ return {
+ request: function(config) {
+ config.url += '/outer';
+ return config;
+ },
+ response: function(response) {
+ response.data = '{' + response.data + '} outer';
+ return response;
+ }
+ };
+ });
+ $httpProvider.interceptors.push(function($q) {
+ return {
+ request: function(config) {
+ config.url += '/inner';
+ return config;
+ },
+ response: function(response) {
+ response.data = '{' + response.data + '} inner';
+ return response;
+ }
+ };
+ });
+ $httpProvider.responseInterceptors.push(function($q) {
+ return function(promise) {
+ var defer = $q.defer();
+
+ promise.then(function(response) {
+ response.data = '[' + response.data + '] legacy-1';
+ defer.resolve(response);
+ });
+ return defer.promise;
+ };
+ });
+ $httpProvider.responseInterceptors.push(function($q) {
+ return function(promise) {
+ var defer = $q.defer();
+
+ promise.then(function(response) {
+ response.data = '[' + response.data + '] legacy-2';
+ defer.resolve(response);
+ });
+ return defer.promise;
+ };
+ });
+ });
+ inject(function($http, $httpBackend) {
+ var response;
+ $httpBackend.expect('GET', '/url/outer/inner').respond('response');
+ $http({method: 'GET', url: '/url'}).then(function(r) {
+ response = r;
+ });
+ $httpBackend.flush();
+ expect(response.data).toEqual('{{[[response] legacy-1] legacy-2} inner} outer');
+ });
+ });
+ });
+
+
+ describe('response interceptors', function() {
it('should default to an empty array', module(function($httpProvider) {
expect($httpProvider.responseInterceptors).toEqual([]);
@@ -44,7 +181,7 @@ describe('$http', function() {
data: response.data + '?',
status: 209,
headers: response.headers,
- config: response.config
+ request: response.config
});
return deferred.promise;
});
@@ -100,6 +237,136 @@ describe('$http', function() {
});
});
});
+
+
+ describe('request interceptors', function() {
+ it('should pass request config as a promise', function() {
+ var run = false;
+ module(function($httpProvider) {
+ $httpProvider.interceptors.push(function() {
+ return {
+ request: function(config) {
+ expect(config.url).toEqual('/url');
+ expect(config.data).toEqual({one: "two"});
+ expect(config.headers.foo).toEqual('bar');
+ run = true;
+ return config;
+ }
+ };
+ });
+ });
+ inject(function($http, $httpBackend, $rootScope) {
+ $httpBackend.expect('POST', '/url').respond('');
+ $http({method: 'POST', url: '/url', data: {one: 'two'}, headers: {foo: 'bar'}});
+ $rootScope.$apply();
+ expect(run).toEqual(true);
+ });
+ });
+
+ it('should allow manipulation of request', function() {
+ module(function($httpProvider) {
+ $httpProvider.interceptors.push(function() {
+ return {
+ request: function(config) {
+ config.url = '/intercepted';
+ config.headers.foo = 'intercepted';
+ return config;
+ }
+ };
+ });
+ });
+ inject(function($http, $httpBackend, $rootScope) {
+ $httpBackend.expect('GET', '/intercepted', null, function (headers) {
+ return headers.foo === 'intercepted';
+ }).respond('');
+ $http.get('/url');
+ $rootScope.$apply();
+ });
+ });
+
+ it('should reject the http promise if an interceptor fails', function() {
+ var reason = new Error('interceptor failed');
+ module(function($httpProvider) {
+ $httpProvider.interceptors.push(function($q) {
+ return {
+ request: function(promise) {
+ return $q.reject(reason);
+ }
+ };
+ });
+ });
+ inject(function($http, $httpBackend, $rootScope) {
+ var success = jasmine.createSpy(), error = jasmine.createSpy();
+ $http.get('/url').then(success, error);
+ $rootScope.$apply();
+ expect(success).not.toHaveBeenCalled();
+ expect(error).toHaveBeenCalledWith(reason);
+ });
+ });
+
+ it('should not manipulate the passed-in config', function() {
+ module(function($httpProvider) {
+ $httpProvider.interceptors.push(function() {
+ return {
+ request: function(config) {
+ config.url = '/intercepted';
+ config.headers.foo = 'intercepted';
+ return config;
+ }
+ };
+ });
+ });
+ inject(function($http, $httpBackend, $rootScope) {
+ var config = { method: 'get', url: '/url', headers: { foo: 'bar'} };
+ $httpBackend.expect('GET', '/intercepted').respond('');
+ $http.get('/url');
+ $rootScope.$apply();
+ expect(config.method).toEqual('get');
+ expect(config.url).toEqual('/url');
+ expect(config.headers.foo).toEqual('bar')
+ });
+ });
+
+ it('should support interceptors defined as services', function() {
+ module(function($provide, $httpProvider) {
+ $provide.factory('myInterceptor', function() {
+ return {
+ request: function(config) {
+ config.url = '/intercepted';
+ return config;
+ }
+ };
+ });
+ $httpProvider.interceptors.push('myInterceptor');
+ });
+ inject(function($http, $httpBackend, $rootScope) {
+ $httpBackend.expect('POST', '/intercepted').respond('');
+ $http.post('/url');
+ $rootScope.$apply();
+ });
+ });
+
+ it('should support complex interceptors based on promises', function() {
+ module(function($provide, $httpProvider) {
+ $provide.factory('myInterceptor', function($q, $rootScope) {
+ return {
+ request: function(config) {
+ return $q.when('/intercepted').then(function(intercepted) {
+ config.url = intercepted;
+ return config;
+ });
+ }
+ };
+ });
+ $httpProvider.interceptors.push('myInterceptor');
+ });
+ inject(function($http, $httpBackend, $rootScope) {
+ $httpBackend.expect('POST', '/intercepted').respond('');
+ $http.post('/two');
+ $rootScope.$apply();
+ });
+ });
+ });
});
@@ -938,7 +1205,7 @@ describe('$http', function() {
$http({method: 'GET', url: '/url'}); // Notice no cache given in config.
$httpBackend.flush();
- // Second should be served from cache, without sending request to server.
+ // Second should be served from cache, without sending request to server.
$http({method: 'get', url: '/url'}).success(callback);
$rootScope.$digest();
@@ -1004,6 +1271,7 @@ describe('$http', function() {
expect($http.pendingRequests.length).toBe(0);
$http({method: 'get', url: '/some'});
+ $rootScope.$digest();
expect($http.pendingRequests.length).toBe(1);
$httpBackend.flush();
@@ -1016,13 +1284,16 @@ describe('$http', function() {
$http({method: 'get', url: '/cached', cache: true});
$http({method: 'get', url: '/cached', cache: true});
+ $rootScope.$digest();
expect($http.pendingRequests.length).toBe(2);
$httpBackend.flush();
expect($http.pendingRequests.length).toBe(0);
$http({method: 'get', url: '/cached', cache: true});
- expect($http.pendingRequests.length).toBe(1);
+ spyOn($http.pendingRequests, 'push').andCallThrough();
+ $rootScope.$digest();
+ expect($http.pendingRequests.push).toHaveBeenCalledOnce();
$rootScope.$apply();
expect($http.pendingRequests.length).toBe(0);
@@ -1035,6 +1306,7 @@ describe('$http', function() {
expect($http.pendingRequests.length).toBe(0);
});
+ $rootScope.$digest();
expect($http.pendingRequests.length).toBe(1);
$httpBackend.flush();
});
@@ -1071,10 +1343,11 @@ describe('$http', function() {
$provide.value('$httpBackend', $httpBackend);
});
- inject(function($http) {
+ inject(function($http, $rootScope) {
$http({
method: 'GET', url: 'some.html', timeout: 12345, withCredentials: true, responseType: 'json'
});
+ $rootScope.$digest();
expect($httpBackend).toHaveBeenCalledOnce();
});
@@ -1093,11 +1366,12 @@ describe('$http', function() {
$provide.value('$httpBackend', $httpBackend);
});
- inject(function($http) {
+ inject(function($http, $rootScope) {
$http.defaults.withCredentials = true;
$http({
method: 'GET', url: 'some.html', timeout: 12345, responseType: 'json'
});
+ $rootScope.$digest();
expect($httpBackend).toHaveBeenCalledOnce();
});
diff --git a/test/ngResource/resourceSpec.js b/test/ngResource/resourceSpec.js
index 1112473937bc..225f96a165ba 100644
--- a/test/ngResource/resourceSpec.js
+++ b/test/ngResource/resourceSpec.js
@@ -468,12 +468,9 @@ describe("resource", function() {
var response = callback.mostRecentCall.args[0];
- expect(response).toEqualData({
- data: {id: 123, number: '9876'},
- status: 200,
- config: {method: 'GET', data: undefined, url: '/CreditCard/123'},
- resource: {id: 123, number: '9876', $resolved: true}
- });
+ expect(response.data).toEqual({id: 123, number: '9876'});
+ expect(response.status).toEqual(200);
+ expect(response.resource).toEqualData({id: 123, number: '9876', $resolved: true});
expect(typeof response.resource.$save).toBe('function');
});
@@ -516,11 +513,8 @@ describe("resource", function() {
var response = callback.mostRecentCall.args[0];
- expect(response).toEqualData({
- data : 'resource not found',
- status : 404,
- config : { method : 'GET', data : undefined, url : '/CreditCard/123' }
- });
+ expect(response.data).toEqual('resource not found');
+ expect(response.status).toEqual(404);
});
@@ -564,12 +558,9 @@ describe("resource", function() {
var response = callback.mostRecentCall.args[0];
- expect(response).toEqualData({
- data: [{id: 1}, {id :2}],
- status: 200,
- config: {method: 'GET', data: undefined, url: '/CreditCard', params: {key: 'value'}},
- resource: [ { id : 1 }, { id : 2 } ]
- });
+ expect(response.data).toEqual([{id: 1}, {id :2}]);
+ expect(response.status).toEqual(200);
+ expect(response.resource).toEqualData([ { id : 1 }, { id : 2 } ]);
expect(typeof response.resource[0].$save).toBe('function');
expect(typeof response.resource[1].$save).toBe('function');
});
@@ -613,11 +604,8 @@ describe("resource", function() {
var response = callback.mostRecentCall.args[0];
- expect(response).toEqualData({
- data : 'resource not found',
- status : 404,
- config : { method : 'GET', data : undefined, url : '/CreditCard', params: {key: 'value'}}
- });
+ expect(response.data).toEqual('resource not found');
+ expect(response.status).toEqual(404);
});