-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[BUGFIX release] Fixes #3603 - Validate JSON API documents returned b…
…y serializer#normalizeResponse
- Loading branch information
1 parent
fb79a08
commit 353889a
Showing
2 changed files
with
253 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
185 changes: 185 additions & 0 deletions
185
packages/ember-data/tests/integration/store/json-api-validation-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
var Person, store, env; | ||
var run = Ember.run; | ||
|
||
module("integration/store/json-validation", { | ||
setup: function() { | ||
Person = DS.Model.extend({ | ||
updatedAt: DS.attr('string'), | ||
name: DS.attr('string'), | ||
firstName: DS.attr('string'), | ||
lastName: DS.attr('string') | ||
}); | ||
|
||
env = setupStore({ | ||
person: Person | ||
}); | ||
store = env.store; | ||
}, | ||
|
||
teardown: function() { | ||
run(store, 'destroy'); | ||
} | ||
}); | ||
|
||
test("when normalizeResponse returns undefined (or doesn't return), throws an error", function() { | ||
|
||
env.registry.register('serializer:person', DS.Serializer.extend({ | ||
normalizeResponse() {} | ||
})); | ||
|
||
env.registry.register('adapter:person', DS.Adapter.extend({ | ||
findRecord() { | ||
return Ember.RSVP.resolve({}); | ||
} | ||
})); | ||
|
||
throws(function () { | ||
run(function() { | ||
store.find('person', 1); | ||
}); | ||
}, /Top level of a JSON API document must be an object/); | ||
}); | ||
|
||
test("when normalizeResponse returns null, throws an error", function() { | ||
|
||
env.registry.register('serializer:person', DS.Serializer.extend({ | ||
normalizeResponse() {return null;} | ||
})); | ||
|
||
env.registry.register('adapter:person', DS.Adapter.extend({ | ||
findRecord() { | ||
return Ember.RSVP.resolve({}); | ||
} | ||
})); | ||
|
||
throws(function () { | ||
run(function() { | ||
store.find('person', 1); | ||
}); | ||
}, /Top level of a JSON API document must be an object/); | ||
}); | ||
|
||
|
||
test("when normalizeResponse returns an empty object, throws an error", function() { | ||
|
||
env.registry.register('serializer:person', DS.Serializer.extend({ | ||
normalizeResponse() {return {};} | ||
})); | ||
|
||
env.registry.register('adapter:person', DS.Adapter.extend({ | ||
findRecord() { | ||
return Ember.RSVP.resolve({}); | ||
} | ||
})); | ||
|
||
throws(function () { | ||
run(function() { | ||
store.find('person', 1); | ||
}); | ||
}, /One or more of the following keys must be present/); | ||
}); | ||
|
||
test("when normalizeResponse returns a document with both data and errors, throws an error", function() { | ||
|
||
env.registry.register('serializer:person', DS.Serializer.extend({ | ||
normalizeResponse() { | ||
return { | ||
data: [], | ||
errors: [] | ||
}; | ||
} | ||
})); | ||
|
||
env.registry.register('adapter:person', DS.Adapter.extend({ | ||
findRecord() { | ||
return Ember.RSVP.resolve({}); | ||
} | ||
})); | ||
|
||
throws(function () { | ||
run(function() { | ||
store.find('person', 1); | ||
}); | ||
}, /cannot both be present/); | ||
}); | ||
|
||
function testPayloadError(payload, expectedError) { | ||
env.registry.register('serializer:person', DS.Serializer.extend({ | ||
normalizeResponse(store, type, pld) { | ||
return pld; | ||
} | ||
})); | ||
env.registry.register('adapter:person', DS.Adapter.extend({ | ||
findRecord() { | ||
return Ember.RSVP.resolve(payload); | ||
} | ||
})); | ||
throws(function () { | ||
run(function() { | ||
store.find('person', 1); | ||
}); | ||
}, expectedError, `Payload ${JSON.stringify(payload)} should throw error ${expectedError}`); | ||
env.registry.unregister('serializer:person'); | ||
env.registry.unregister('adapter:person'); | ||
} | ||
|
||
test("normalizeResponse 'data' cannot be undefined, a number, a string or a boolean", function() { | ||
|
||
testPayloadError({ data: undefined }, /data must be/); | ||
testPayloadError({ data: 1 }, /data must be/); | ||
testPayloadError({ data: 'lollerskates' }, /data must be/); | ||
testPayloadError({ data: true }, /data must be/); | ||
|
||
}); | ||
|
||
test("normalizeResponse 'meta' cannot be an array, undefined, a number, a string or a boolean", function() { | ||
|
||
testPayloadError({ meta: undefined }, /meta must be an object/); | ||
testPayloadError({ meta: [] }, /meta must be an object/); | ||
testPayloadError({ meta: 1 }, /meta must be an object/); | ||
testPayloadError({ meta: 'lollerskates' }, /meta must be an object/); | ||
testPayloadError({ meta: true }, /meta must be an object/); | ||
|
||
}); | ||
|
||
test("normalizeResponse 'links' cannot be an array, undefined, a number, a string or a boolean", function() { | ||
|
||
testPayloadError({ data: [], links: undefined }, /links must be an object/); | ||
testPayloadError({ data: [], links: [] }, /links must be an object/); | ||
testPayloadError({ data: [], links: 1 }, /links must be an object/); | ||
testPayloadError({ data: [], links: 'lollerskates' }, /links must be an object/); | ||
testPayloadError({ data: [], links: true }, /links must be an object/); | ||
|
||
}); | ||
|
||
test("normalizeResponse 'jsonapi' cannot be an array, undefined, a number, a string or a boolean", function() { | ||
|
||
testPayloadError({ data: [], jsonapi: undefined }, /jsonapi must be an object/); | ||
testPayloadError({ data: [], jsonapi: [] }, /jsonapi must be an object/); | ||
testPayloadError({ data: [], jsonapi: 1 }, /jsonapi must be an object/); | ||
testPayloadError({ data: [], jsonapi: 'lollerskates' }, /jsonapi must be an object/); | ||
testPayloadError({ data: [], jsonapi: true }, /jsonapi must be an object/); | ||
|
||
}); | ||
|
||
test("normalizeResponse 'included' cannot be an object, undefined, a number, a string or a boolean", function() { | ||
|
||
testPayloadError({ included: undefined }, /included must be an array/); | ||
testPayloadError({ included: {} }, /included must be an array/); | ||
testPayloadError({ included: 1 }, /included must be an array/); | ||
testPayloadError({ included: 'lollerskates' }, /included must be an array/); | ||
testPayloadError({ included: true }, /included must be an array/); | ||
|
||
}); | ||
|
||
test("normalizeResponse 'errors' cannot be an object, undefined, a number, a string or a boolean", function() { | ||
|
||
testPayloadError({ errors: undefined }, /errors must be an array/); | ||
testPayloadError({ errors: {} }, /errors must be an array/); | ||
testPayloadError({ errors: 1 }, /errors must be an array/); | ||
testPayloadError({ errors: 'lollerskates' }, /errors must be an array/); | ||
testPayloadError({ errors: true }, /errors must be an array/); | ||
|
||
}); | ||
|
||
|