Skip to content

Commit

Permalink
fix(resource): check whether response matches action.isArray
Browse files Browse the repository at this point in the history
When using $resource you must setup your actions carefully based on what the server returns.
If the server responds to a request with an array then you must configure the action with
`isArray:true` and vice versa.  The built-in `get` action defaults to `isArray:false` and the
`query` action defaults to `isArray:true`, which is must be changed if the server does not do this.
Before the error message was an exception inside angular.copy, which didn't explain what the
real problem was. Rather than changing the way that angular.copy works, this change ensures that
a better error message is provided to the programmer if they do not set up their resource actions
correctly.

Closes angular#2255, angular#1044
  • Loading branch information
petebacondarwin committed Jul 30, 2013
1 parent e1fe2ac commit 544ce8c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
4 changes: 4 additions & 0 deletions docs/content/error/ngResource/badcfg.ngdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@ngdoc error
@name ngResource:badcfg
@fullName Response does not match configured parameter
@description
5 changes: 5 additions & 0 deletions src/ngResource/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,11 @@ angular.module('ngResource', ['ng']).
promise = value.$promise;

if (data) {
if ( angular.isArray(data) != !!action.isArray ) {
throw ngResourceMinErr('badcfg', 'Error in resource configuration. Expected response' +
' to contain an {0} but got an {1}',
action.isArray?'array':'object', angular.isArray(data)?'array':'object');
}
if (action.isArray) {
value.length = 0;
forEach(data, function(item) {
Expand Down
49 changes: 48 additions & 1 deletion test/ngResource/resourceSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,6 @@ describe("resource", function() {
});
});


it('should transform request/response', function() {
var Person = $resource('/Person/:id', {}, {
save: {
Expand Down Expand Up @@ -1034,3 +1033,51 @@ describe("resource", function() {
});
});
});

describe('resource', function() {
var $httpBackend, $resource;

beforeEach(module(function($exceptionHandlerProvider) {
$exceptionHandlerProvider.mode('log');
}));

beforeEach(module('ngResource'));

beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
$resource = $injector.get('$resource');
}));


it('should fail if action expects an object but response is an array', function() {
var successSpy = jasmine.createSpy('successSpy');
var failureSpy = jasmine.createSpy('failureSpy');

$httpBackend.expect('GET', '/Customer/123').respond({id: 'abc'});

$resource('/Customer/123').query()
.$promise.then(successSpy, function(e) { failureSpy(e.message); });
$httpBackend.flush();

expect(successSpy).not.toHaveBeenCalled();
expect(failureSpy).toHaveBeenCalledWith(
'[ngResource:badcfg] Error in resource configuration. Expected response to contain an array but got an object');
});

it('should fail if action expects an array but response is an object', function() {
var successSpy = jasmine.createSpy('successSpy');
var failureSpy = jasmine.createSpy('failureSpy');

$httpBackend.expect('GET', '/Customer/123').respond([1,2,3]);

$resource('/Customer/123').get()
.$promise.then(successSpy, function(e) { failureSpy(e.message); });
$httpBackend.flush();

expect(successSpy).not.toHaveBeenCalled();
expect(failureSpy).toHaveBeenCalledWith(
'[ngResource:badcfg] Error in resource configuration. Expected response to contain an object but got an array');
});


});

0 comments on commit 544ce8c

Please sign in to comment.