From fb444c74c48687704bb8baa14551f1c49ea1064b Mon Sep 17 00:00:00 2001 From: Lisa Backer Date: Tue, 30 May 2017 14:18:32 -0400 Subject: [PATCH 1/2] Change setupStore helper default serializer to JSONAPISerializer #4754 --- tests/helpers/store.js | 5 +- tests/integration/adapter/find-all-test.js | 20 +- tests/integration/adapter/find-test.js | 29 +- tests/integration/adapter/queries-test.js | 27 +- .../adapter/record-persistence-test.js | 12 +- .../integration/adapter/store-adapter-test.js | 119 +++-- .../integration/client-id-generation-test.js | 2 +- tests/integration/filter-test.js | 117 +++- tests/integration/lifecycle-hooks-test.js | 2 +- tests/integration/record-array-test.js | 21 +- .../adapter-populated-record-array-test.js | 48 +- .../records/collection-save-test.js | 6 +- .../records/property-changes-test.js | 2 +- tests/integration/records/reload-test.js | 55 +- tests/integration/records/save-test.js | 4 +- .../integration/references/belongs-to-test.js | 30 +- tests/integration/references/has-many-test.js | 18 +- tests/integration/references/record-test.js | 32 +- .../relationships/belongs-to-test.js | 179 +++++-- .../relationships/has-many-test.js | 500 ++++++++++++------ .../relationships/one-to-one-test.js | 4 +- .../serializers/json-api-serializer-test.js | 2 +- .../serializers/json-serializer-test.js | 35 +- .../serializers/rest-serializer-test.js | 11 + tests/integration/snapshot-test.js | 18 +- tests/integration/store-test.js | 7 +- tests/integration/store/query-record-test.js | 2 +- tests/unit/model-test.js | 20 +- tests/unit/model/lifecycle-callbacks-test.js | 8 +- tests/unit/model/merge-test.js | 8 +- .../model/relationships/belongs-to-test.js | 29 +- .../unit/model/relationships/has-many-test.js | 29 +- tests/unit/store/adapter-interop-test.js | 84 +-- tests/unit/store/finders-test.js | 14 +- tests/unit/store/push-test.js | 63 ++- tests/unit/store/unload-test.js | 13 +- 36 files changed, 1093 insertions(+), 482 deletions(-) diff --git a/tests/helpers/store.js b/tests/helpers/store.js index 4948ab027f9..d76792e08be 100644 --- a/tests/helpers/store.js +++ b/tests/helpers/store.js @@ -49,13 +49,12 @@ export default function setupStore(options) { registry.optionsForType('adapter', { singleton: false }); registry.register('adapter:-default', DS.Adapter); - registry.register('serializer:-default', DS.JSONSerializer); + registry.register('serializer:-default', DS.JSONAPISerializer); + registry.register('serializer:-json', DS.JSONSerializer); registry.register('serializer:-rest', DS.RESTSerializer); registry.register('adapter:-rest', DS.RESTAdapter); - registry.register('adapter:-json-api', DS.JSONAPIAdapter); - registry.register('serializer:-json-api', DS.JSONAPISerializer); env.restSerializer = container.lookup('serializer:-rest'); env.store = container.lookup('service:store'); diff --git a/tests/integration/adapter/find-all-test.js b/tests/integration/adapter/find-all-test.js index ce836f680ac..914a4652e9d 100644 --- a/tests/integration/adapter/find-all-test.js +++ b/tests/integration/adapter/find-all-test.js @@ -45,7 +45,13 @@ test("When all records for a type are requested, the store should call the adapt // this will get called twice assert.ok(true, "the adapter's findAll method should be invoked"); - return resolve([{ id: 1, name: "Braaaahm Dale" }]); + return resolve({ data: [{ + id: 1, + type: 'person', + attributes: { + name: "Braaaahm Dale" + } + }]}); } })); @@ -75,7 +81,13 @@ test("When all records for a type are requested, a rejection should reject the p if (count++ === 0) { return reject(); } else { - return resolve([{ id: 1, name: "Braaaahm Dale" }]); + return resolve({ data: [{ + id: 1, + type: 'person', + attributes: { + name: "Braaaahm Dale" + } + }]}); } } })); @@ -185,7 +197,7 @@ test("isUpdating is true while records are fetched", function(assert) { assert.equal(persons.get("isUpdating"), true); - findAllDeferred.resolve([{ id: 2 }]); + findAllDeferred.resolve({ data: [{ id: 2, type: 'person' }] }); }); test("isUpdating is true while records are fetched in the background", function(assert) { @@ -223,7 +235,7 @@ test("isUpdating is true while records are fetched in the background", function( assert.equal(persons.get("isUpdating"), true); run(function() { - findAllDeferred.resolve([{ id: 2 }]); + findAllDeferred.resolve({ data: [{ id: 2, type: 'person' }] }); }); run(function() { diff --git a/tests/integration/adapter/find-test.js b/tests/integration/adapter/find-test.js index 8e6b7f97e08..2dd54dfb1ee 100644 --- a/tests/integration/adapter/find-test.js +++ b/tests/integration/adapter/find-test.js @@ -51,7 +51,15 @@ test("When a single record is requested, the adapter's find method should be cal assert.equal(count, 0, "the find method is only called once"); count++; - return { id: 1, name: "Braaaahm Dale" }; + return { + data: { + id: 1, + type: "person", + attributes: { + name: "Braaaahm Dale" + } + } + }; } })); @@ -101,7 +109,14 @@ test("When a single record is requested multiple times, all .findRecord() calls })); }); - run(() => deferred.resolve({ id: 1, name: "Braaaahm Dale" })); + run(() => deferred.resolve({ + data: { + id: 1, + type: "person", + attributes: { + name: "Braaaahm Dale" + } + }})); }); test("When a single record is requested, and the promise is rejected, .findRecord() is rejected.", (assert) => { @@ -158,7 +173,15 @@ testInDebug('When multiple records are requested, and the payload is blank', (as testInDebug("warns when returned record has different id", function(assert) { env.registry.register('adapter:person', DS.Adapter.extend({ findRecord() { - return { id: 1, name: "Braaaahm Dale" }; + return { + data: { + id: 1, + type: "person", + attributes: { + name: "Braaaahm Dale" + } + } + }; } })); diff --git a/tests/integration/adapter/queries-test.js b/tests/integration/adapter/queries-test.js index fcc354a5196..7797127e98c 100644 --- a/tests/integration/adapter/queries-test.js +++ b/tests/integration/adapter/queries-test.js @@ -45,8 +45,25 @@ test("When a query is made, the adapter should receive a record array it can pop adapter.query = function(store, type, query, recordArray) { assert.equal(type, Person, "the query method is called with the correct type"); - return Ember.RSVP.resolve([{ id: 1, name: "Peter Wagenet" }, { id: 2, name: "Brohuda Katz" }]); - }; + return Ember.RSVP.resolve({ + data: [ + { + id: 1, + type: 'person', + attributes: { + name: "Peter Wagenet" + } + }, + { + id: 2, + type: "person", + attributes: { + name: "Brohuda Katz" + } + } + ] + }); + } store.query('person', { page: 1 }).then(assert.wait(function(queryResults) { assert.equal(get(queryResults, 'length'), 2, "the record array has a length of 2 after the results are loaded"); @@ -59,7 +76,7 @@ test("When a query is made, the adapter should receive a record array it can pop test("a query can be updated via `update()`", function(assert) { adapter.query = function() { - return Ember.RSVP.resolve([{ id: 'first' }]); + return Ember.RSVP.resolve({ data: [{ id: 'first', type: 'person' }] }); }; run(function() { @@ -70,7 +87,7 @@ test("a query can be updated via `update()`", function(assert) { adapter.query = function() { assert.ok('query is called a second time'); - return Ember.RSVP.resolve([{ id: 'second' }]); + return Ember.RSVP.resolve({data: [{ id: 'second', type: 'person' }] }); }; let updateQuery = query.update(); @@ -96,7 +113,7 @@ testInDebug("The store asserts when query is made and the adapter responses with adapter.query = function(store, type, query, recordArray) { assert.equal(type, Person, "the query method is called with the correct type"); - return Ember.RSVP.resolve({ people: { id: 1, name: "Peter Wagenet" } }); + return Ember.RSVP.resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Peter Wagenet" } }] }); }; assert.expectAssertion(function() { diff --git a/tests/integration/adapter/record-persistence-test.js b/tests/integration/adapter/record-persistence-test.js index 289976dac5f..3a4091bd5e3 100644 --- a/tests/integration/adapter/record-persistence-test.js +++ b/tests/integration/adapter/record-persistence-test.js @@ -78,7 +78,7 @@ test("When a store is committed, the adapter's `commit` method should be called assert.equal(type, Person, "the type is correct"); assert.equal(snapshot.record, tom, "the record is correct"); - return Ember.RSVP.resolve({ id: 1, name: "Tom Dale" }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale" } } }); }; run(function() { @@ -92,7 +92,7 @@ test("After a created record has been assigned an ID, finding a record by that I var tom; env.adapter.createRecord = function(store, type, snapshot) { - return Ember.RSVP.resolve({ id: 1, name: "Tom Dale" }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale" } } }); }; run(function() { @@ -178,9 +178,9 @@ test("An adapter can notify the store that records were updated by calling `didS test("An adapter can notify the store that records were updated and provide new data by calling `didSaveRecords`.", function(assert) { env.adapter.updateRecord = function(store, type, snapshot) { if (snapshot.id === "1") { - return Ember.RSVP.resolve({ id: 1, name: "Tom Dale", updatedAt: "now" }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale", "updated-at": "now" } } }); } else if (snapshot.id === "2") { - return Ember.RSVP.resolve({ id: 2, name: "Yehuda Katz", updatedAt: "now!" }); + return Ember.RSVP.resolve({ data: { id: 2, type: "person", attributes: { name: "Yehuda Katz", "updated-at": "now!" } } }); } }; @@ -249,9 +249,9 @@ test("An adapter can notify the store that a record was updated and provide new env.adapter.updateRecord = function(store, type, snapshot) { switch (snapshot.id) { case "1": - return Ember.RSVP.resolve({ id: 1, name: "Tom Dale", updatedAt: "now" }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale", "updated-at": "now" } } }); case "2": - return Ember.RSVP.resolve({ id: 2, name: "Yehuda Katz", updatedAt: "now!" }); + return Ember.RSVP.resolve({ data: { id: 2, type: "person", attributes: { name: "Yehuda Katz", "updated-at": "now!" } } }); } }; diff --git a/tests/integration/adapter/store-adapter-test.js b/tests/integration/adapter/store-adapter-test.js index 3348ca6a9ca..fe114a08d69 100644 --- a/tests/integration/adapter/store-adapter-test.js +++ b/tests/integration/adapter/store-adapter-test.js @@ -58,13 +58,23 @@ module("integration/adapter/store-adapter - DS.Store and DS.Adapter integration test("Records loaded multiple times and retrieved in recordArray are ready to send state events", function(assert) { adapter.query = function(store, type, query, recordArray) { - return Ember.RSVP.resolve([{ - id: 1, - name: "Mickael Ramírez" - }, { - id: 2, - name: "Johny Fontana" - }]); + return Ember.RSVP.resolve({ + data: [ + { + id: 1, + type: "person", + attributes: { + name: "Mickael Ramírez" + } + }, { + id: 2, + type: "person", + attributes: { + name: "Johny Fontana" + } + } + ] + }); }; run(store, 'query', 'person', { q: 'bla' }).then(assert.wait(function(people) { @@ -99,11 +109,17 @@ test("by default, createRecords calls createRecord once per record", function(as } var hash = snapshot.attributes(); - hash.id = count; - hash.updatedAt = "now"; + var recordId = count; + hash['updated-at'] = "now"; count++; - return Ember.RSVP.resolve(hash); + return Ember.RSVP.resolve({ + data: { + id: recordId, + type: "person", + attributes: hash + } + }); }; var tom, yehuda; @@ -206,10 +222,10 @@ test("calling store.didSaveRecord can provide an optional hash", function(assert count++; if (count === 1) { assert.equal(snapshot.attr('name'), "Tom Dale"); - return Ember.RSVP.resolve({ id: 1, name: "Tom Dale", updatedAt: "now" }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale", "updated-at": "now" } } }); } else if (count === 2) { assert.equal(snapshot.attr('name'), "Yehuda Katz"); - return Ember.RSVP.resolve({ id: 2, name: "Yehuda Katz", updatedAt: "now!" }); + return Ember.RSVP.resolve({ data: { id: 2, type: "person", attributes: { name: "Yehuda Katz", "updated-at": "now!" } } }); } else { assert.ok(false, "should not get here"); } @@ -866,7 +882,7 @@ test("can be created after the DS.Store", function(assert) { adapter.findRecord = function(store, type, id, snapshot) { assert.equal(type, Person, "the type is correct"); - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person" } }); }; run(function() { @@ -877,10 +893,24 @@ test("can be created after the DS.Store", function(assert) { test("the filter method can optionally take a server query as well", function(assert) { adapter.shouldBackgroundReloadRecord = () => false; adapter.query = function(store, type, query, array) { - return Ember.RSVP.resolve([ - { id: 1, name: "Yehuda Katz" }, - { id: 2, name: "Tom Dale" } - ]); + return Ember.RSVP.resolve({ + data: [ + { + id: 1, + type: "person", + attributes: { + name: "Yehuda Katz" + } + }, + { + id: 2, + type: "person", + attributes: { + name: "Tom Dale" + } + } + ] + }); }; var asyncFilter = store.filter('person', { page: 1 }, function(data) { @@ -916,7 +946,18 @@ test("relationships returned via `commit` do not trigger additional findManys", }); adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, name: "Tom Dale", dogs: [1] }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: "person", + attributes: { name: "Tom Dale" }, + relationships: { + dogs: { + data: [{ id: 1, type: "dog" }] + } + } + } + }); }; adapter.updateRecord = function(store, type, snapshot) { @@ -946,7 +987,7 @@ test("relationships returned via `commit` do not trigger additional findManys", }] }); - resolve({ id: 1, name: "Scruffy" }); + resolve({ data: { id: 1, type: "dog", attributes: { name: "Scruffy" } } }); }); }; @@ -977,7 +1018,7 @@ test("relationships don't get reset if the links is the same", function(assert) adapter.findHasMany = function(store, snapshot, link, relationship) { assert.ok(count++ === 0, "findHasMany is only called once"); - return Ember.RSVP.resolve([{ id: 1, name: "Scruffy" }]); + return Ember.RSVP.resolve({ data: [{ id: 1, type: "dog", attributes: { name: "Scruffy" } }] }); }; run(function() { @@ -1036,10 +1077,18 @@ test("async hasMany always returns a promise", function(assert) { }); adapter.createRecord = function(store, type, snapshot) { - var hash = { name: "Tom Dale" }; - hash.dogs = []; - hash.id = 1; - return Ember.RSVP.resolve(hash); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: "person", + attributes: { + name: "Tom Dale" + }, + relationships: { + dogs: [] + } + } + }); }; var tom; @@ -1137,7 +1186,7 @@ test("findRecord receives a snapshot", function(assert) { adapter.findRecord = function(store, type, id, snapshot) { assert.ok(snapshot instanceof DS.Snapshot, "snapshot is an instance of DS.Snapshot"); - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person" } }); }; run(function() { @@ -1156,7 +1205,7 @@ test("findMany receives an array of snapshots", function(assert) { adapter.findMany = function(store, type, ids, snapshots) { assert.ok(snapshots[0] instanceof DS.Snapshot, "snapshots[0] is an instance of DS.Snapshot"); assert.ok(snapshots[1] instanceof DS.Snapshot, "snapshots[1] is an instance of DS.Snapshot"); - return Ember.RSVP.resolve([{ id: 2 }, { id: 3 }]); + return Ember.RSVP.resolve({ data: [{ id: 2, type: "dog" }, { id: 3, type: "dog" }] }); }; var person; @@ -1193,7 +1242,7 @@ test("findHasMany receives a snapshot", function(assert) { env.adapter.findHasMany = function(store, snapshot, link, relationship) { assert.ok(snapshot instanceof DS.Snapshot, "snapshot is an instance of DS.Snapshot"); - return Ember.RSVP.resolve([{ id: 2 }, { id: 3 }]); + return Ember.RSVP.resolve({ data: [{ id: 2, type: "dog" }, { id: 3, type: "dog" }] }); }; var person; @@ -1229,7 +1278,7 @@ test("findBelongsTo receives a snapshot", function(assert) { env.adapter.findBelongsTo = assert.wait(function(store, snapshot, link, relationship) { assert.ok(snapshot instanceof DS.Snapshot, "snapshot is an instance of DS.Snapshot"); - return Ember.RSVP.resolve({ id: 2 }); + return Ember.RSVP.resolve({ data: { id: 2, type: "dog" } }); }); var person; @@ -1261,7 +1310,7 @@ test("record.save should pass adapterOptions to the updateRecord method", functi env.adapter.updateRecord = assert.wait(function(store, type, snapshot) { assert.deepEqual(snapshot.adapterOptions, { subscribe: true }); - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person" } }); }); run(function() { @@ -1284,7 +1333,7 @@ test("record.save should pass adapterOptions to the createRecord method", functi env.adapter.createRecord = assert.wait(function(store, type, snapshot) { assert.deepEqual(snapshot.adapterOptions, { subscribe: true }); - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person" } }); }); run(function() { @@ -1298,7 +1347,7 @@ test("record.save should pass adapterOptions to the deleteRecord method", functi env.adapter.deleteRecord = assert.wait(function(store, type, snapshot) { assert.deepEqual(snapshot.adapterOptions, { subscribe: true }); - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person" } }); }); run(function() { @@ -1322,7 +1371,7 @@ test("store.findRecord should pass adapterOptions to adapter.findRecord", functi env.adapter.findRecord = assert.wait(function(store, type, id, snapshot) { assert.deepEqual(snapshot.adapterOptions, { query: { embed: true } }); - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person" } }); }); run(function() { @@ -1335,7 +1384,7 @@ test("store.findRecord should pass 'include' to adapter.findRecord", function(as env.adapter.findRecord = assert.wait((store, type, id, snapshot) => { assert.equal(snapshot.include, 'books', 'include passed to adapter.findRecord'); - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: "person" } }); }); run(() => store.findRecord('person', 1, { include: 'books' })); @@ -1347,7 +1396,7 @@ test("store.findAll should pass adapterOptions to the adapter.findAll method", f env.adapter.findAll = assert.wait(function(store, type, sinceToken, arraySnapshot) { var adapterOptions = arraySnapshot.adapterOptions; assert.deepEqual(adapterOptions, { query: { embed: true } }); - return Ember.RSVP.resolve([{ id: 1 }]); + return Ember.RSVP.resolve({ data: [{ id: 1, type: "person" }] }); }); run(function() { @@ -1360,7 +1409,7 @@ test("store.findAll should pass 'include' to adapter.findAll", function(assert) env.adapter.findAll = assert.wait((store, type, sinceToken, arraySnapshot) => { assert.equal(arraySnapshot.include, 'books', 'include passed to adapter.findAll'); - return Ember.RSVP.resolve([{ id: 1 }]); + return Ember.RSVP.resolve({ data: [{ id: 1, type: "person" }] }); }); run(() => store.findAll('person', { include: 'books' })); diff --git a/tests/integration/client-id-generation-test.js b/tests/integration/client-id-generation-test.js index 4d30afcf9f5..f55d93c95b7 100644 --- a/tests/integration/client-id-generation-test.js +++ b/tests/integration/client-id-generation-test.js @@ -87,7 +87,7 @@ test("empty string and undefined ids should coerce to null", function(assert) { env.adapter.createRecord = function(store, type, record) { assert.equal(typeof get(record, 'id'), 'object', 'correct type'); - return Ember.RSVP.resolve({ id: id++ }); + return Ember.RSVP.resolve({ data: { id: id++, type: type.modelName } }); }; run(function() { diff --git a/tests/integration/filter-test.js b/tests/integration/filter-test.js index 8ac10a0d18d..07c36a637c6 100644 --- a/tests/integration/filter-test.js +++ b/tests/integration/filter-test.js @@ -449,12 +449,17 @@ test('a filter created after a record is already loaded works', function(assert) test('filter with query persists query on the resulting filteredRecordArray', function(assert) { customAdapter(env, DS.Adapter.extend({ query(store, type, id) { - return [ - { - id: id, - name: 'Tom Dale' - } - ]; + return { + data: [ + { + id: id, + type: 'person', + attributes: { + name: 'Tom Dale' + } + } + ] + }; } })); @@ -473,8 +478,13 @@ test('it is possible to filter by state flags', function(assert) { customAdapter(env, DS.Adapter.extend({ findRecord(store, type, id, snapshot) { return { - id, - name: 'Tom Dale' + data: { + id, + type: 'person', + attributes: { + name: 'Tom Dale' + } + } }; } })); @@ -504,7 +514,7 @@ test('it is possible to filter by state flags', function(assert) { test('it is possible to filter loaded records by dirtiness', function(assert) { customAdapter(env, DS.Adapter.extend({ updateRecord(type, model, snapshot) { - return { id: snapshot.id }; + return { data: { id: snapshot.id, type: model.modelName } }; }, shouldBackgroundReloadRecord() { return false; @@ -544,7 +554,13 @@ test('it is possible to filter created records by dirtiness', function(assert) { run(() => { customAdapter(env, DS.Adapter.extend({ createRecord(type, model, snapshot) { - return Ember.merge(Ember.merge({}, snapshot._attributes), { id: snapshot.id} ) + return { + data: { + id: snapshot.id, + type: model.modelName, + attributes: Ember.merge(Ember.merge({}, snapshot._attributes)) + } + } }, shouldBackgroundReloadRecord() { return false; } })); @@ -574,8 +590,13 @@ test('it is possible to filter created records by isReloading', function(assert) customAdapter(env, DS.Adapter.extend({ findRecord(store, type, id, snapshot) { return { - id: 1, - name: 'Tom Dalle' + data: { + id: 1, + type: 'person', + attributes: { + name: 'Tom Dalle' + } + } }; } })); @@ -644,8 +665,13 @@ test('a Record Array can update its filter after server-side updates one record' setup(assert, { updateRecord(store, type, snapshot) { return { - id: 1, - name: 'Scumbag Server-side Dale' + data: { + id: 1, + type: 'person', + attributes: { + name: 'Scumbag Server-side Dale' + } + } }; }, shouldBackgroundReloadRecord() { return false; } @@ -664,13 +690,23 @@ test('a Record Array can update its filter after server-side updates multiple re switch (snapshot.id) { case '1': return { - id: 1, - name: 'Scumbag Server-side Dale' + data: { + id: 1, + type: 'person', + attributes: { + name: 'Scumbag Server-side Dale' + } + } }; case '2': return { - id: 2, - name: 'Scumbag Server-side Katz' + data: { + id: 2, + type: 'person', + attributes: { + name: 'Scumbag Server-side Katz' + } + } }; } }, @@ -688,8 +724,13 @@ test('a Record Array can update its filter after server-side creates one record' setup(assert, { createRecord(store, type, snapshot) { return { - id: 4, - name: 'Scumbag Server-side Tim' + data: { + id: 4, + type: 'person', + attributes: { + name: 'Scumbag Server-side Tim' + } + } }; } }); @@ -707,13 +748,23 @@ test('a Record Array can update its filter after server-side creates multiple re switch (snapshot.attr('name')) { case 'Client-side Mike': return { - id: 4, - name: 'Scumbag Server-side Mike' + data: { + id: 4, + type: 'person', + attributes: { + name: 'Scumbag Server-side Mike' + } + } }; case 'Client-side David': return { - id: 5, - name: 'Scumbag Server-side David' + data: { + id: 5, + type: 'person', + attributes: { + name: 'Scumbag Server-side David' + } + } }; } } @@ -732,13 +783,23 @@ test('a Record Array can update its filter after server-side creates multiple re switch (snapshot.attr('name')) { case 'Client-side Mike': return { - id: 4, - name: 'Scumbag Server-side Mike' + data: { + id: 4, + type: 'person', + attributes: { + name: 'Scumbag Server-side Mike' + } + } }; case 'Client-side David': return { - id: 5, - name: 'Scumbag Server-side David' + data: { + id: 5, + type: 'person', + attributes: { + name: 'Scumbag Server-side David' + } + } }; } } diff --git a/tests/integration/lifecycle-hooks-test.js b/tests/integration/lifecycle-hooks-test.js index 35ad90e0823..69f06b8143b 100644 --- a/tests/integration/lifecycle-hooks-test.js +++ b/tests/integration/lifecycle-hooks-test.js @@ -31,7 +31,7 @@ test("When the adapter acknowledges that a record has been created, a `didCreate assert.expect(3); env.adapter.createRecord = function(store, type, snapshot) { - return resolve({ id: 99, name: "Yehuda Katz" }); + return resolve({ data: { id: 99, type: "person", attributes: { name: "Yehuda Katz" } } }); }; var person; diff --git a/tests/integration/record-array-test.js b/tests/integration/record-array-test.js index cd801ced50b..ed45e4e21d5 100644 --- a/tests/integration/record-array-test.js +++ b/tests/integration/record-array-test.js @@ -8,7 +8,7 @@ import DS from 'ember-data'; const { get, run, RSVP: { Promise }} = Ember; -let array; +let results; const Person = DS.Model.extend({ name: DS.attr('string'), @@ -25,11 +25,13 @@ const Tool = DS.Model.extend({ module('unit/record_array - DS.RecordArray', { beforeEach() { - array = Ember.A([ - { id: '1', name: 'Scumbag Dale' }, - { id: '2', name: 'Scumbag Katz' }, - { id: '3', name: 'Scumbag Bryn' } - ]); + results = { + data: [ + { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, + { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } }, + { id: '3', type: 'person', attributes: { name: 'Scumbag Bryn' } } + ] + }; } }); @@ -74,8 +76,9 @@ test('a record array is backed by records', function(assert) { return run(() => { return store.findByIds('person', [1,2,3]).then(records => { - for (let i=0, l = get(array, 'length'); i { diff --git a/tests/integration/record-arrays/adapter-populated-record-array-test.js b/tests/integration/record-arrays/adapter-populated-record-array-test.js index ce0273964b4..6264ed285e2 100644 --- a/tests/integration/record-arrays/adapter-populated-record-array-test.js +++ b/tests/integration/record-arrays/adapter-populated-record-array-test.js @@ -165,10 +165,12 @@ test('pass record array to adapter.query based on arity', function(assert) { let env = setupStore({ person: Person }); let store = env.store; - let payload = [ - { id: '1', name: 'Scumbag Dale' }, - { id: '2', name: 'Scumbag Katz' } - ]; + let payload = { + data: [ + { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, + { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } } + ] + }; env.adapter.query = function(store, type, query) { assert.equal(arguments.length, 3); @@ -188,10 +190,12 @@ test('pass record array to adapter.query based on arity', function(assert) { let env = setupStore({ person: Person }); let store = env.store; - let payload = [ - { id: '1', name: 'Scumbag Dale' }, - { id: '2', name: 'Scumbag Katz' } - ]; + let payload = { + data: [ + { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, + { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } } + ] + }; let actualQuery = { }; @@ -234,10 +238,12 @@ test('loadRecord re-syncs internalModels recordArrays', function(assert) { let env = setupStore({ person: Person }); let store = env.store; - let payload = [ - { id: '1', name: 'Scumbag Dale' }, - { id: '2', name: 'Scumbag Katz' } - ]; + let payload = { + data: [ + { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, + { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } } + ] + }; env.adapter.query = function(store, type, query, recordArray) { return payload; @@ -247,10 +253,12 @@ test('loadRecord re-syncs internalModels recordArrays', function(assert) { return recordArray.update().then(recordArray => { assert.deepEqual(recordArray.getEach('name'), ['Scumbag Dale', 'Scumbag Katz'], 'expected query to contain specific records'); - payload = [ - { id: '1', name: 'Scumbag Dale' }, - { id: '3', name: 'Scumbag Penner' } - ]; + payload = { + data: [ + { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, + { id: '3', type: 'person', attributes: { name: 'Scumbag Penner' } } + ] + }; return recordArray.update(); }).then(recordArray => { @@ -265,17 +273,17 @@ test('when an adapter populated record gets updated the array contents are also let filteredPromise, filteredArr, findPromise, findArray; let env = setupStore({ person: Person }); let store = env.store; - let array = [{ id: '1', name: 'Scumbag Dale' }]; + let array = [{ id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }]; // resemble server side filtering env.adapter.query = function(store, type, query, recordArray) { - return array.slice(query.slice); + return { data: array.slice(query.slice) }; }; // implement findAll to further test that query updates won't muddle // with the non-query record arrays env.adapter.findAll = function(store, type, sinceToken) { - return array.slice(0); + return { data: array.slice(0) }; }; run(() => { @@ -298,7 +306,7 @@ test('when an adapter populated record gets updated the array contents are also // a new element gets pushed in record array run(() => { - array.push({ id: '2', name: 'Scumbag Katz' }); + array.push({ id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } }); filteredArr.update().then(() => { assert.equal(filteredArr.get('length'), 1, 'The new record is returned and added in adapter populated array'); assert.equal(filteredArr.get('isUpdating'), false, 'Record array isUpdating state updated'); diff --git a/tests/integration/records/collection-save-test.js b/tests/integration/records/collection-save-test.js index 83460722740..2ea23b0b647 100644 --- a/tests/integration/records/collection-save-test.js +++ b/tests/integration/records/collection-save-test.js @@ -33,7 +33,7 @@ test("Collection will resolve save on success", function(assert) { var posts = env.store.peekAll('post'); env.adapter.createRecord = function(store, type, snapshot) { - return Ember.RSVP.resolve({ id: id++ }); + return Ember.RSVP.resolve({ data: { id: id++ , type: 'post' } }); }; run(function() { @@ -77,12 +77,12 @@ test("Retry is allowed in a failure handler", function(assert) { if (count++ === 0) { return Ember.RSVP.reject(); } else { - return Ember.RSVP.resolve({ id: id++ }); + return Ember.RSVP.resolve({ data: { id: id++, type: 'post' } }); } }; env.adapter.updateRecord = function(store, type, snapshot) { - return Ember.RSVP.resolve({ id: snapshot.id }); + return Ember.RSVP.resolve({ data: { id: snapshot.id, type: 'post' } }); }; run(function() { diff --git a/tests/integration/records/property-changes-test.js b/tests/integration/records/property-changes-test.js index 55c688c85bf..a6374c7ce7d 100644 --- a/tests/integration/records/property-changes-test.js +++ b/tests/integration/records/property-changes-test.js @@ -115,7 +115,7 @@ test('Saving a record trigger observers for locally changed attributes with the var person; env.adapter.updateRecord = function(store, type, snapshot) { - return Ember.RSVP.resolve({ id: 'wat', lastName: 'Katz' }); + return Ember.RSVP.resolve({ data: { id: 'wat', type: 'person', attributes: { 'last-name': 'Katz' } } }); }; run(function() { diff --git a/tests/integration/records/reload-test.js b/tests/integration/records/reload-test.js index c5aedf2f05c..76bc76b4b36 100644 --- a/tests/integration/records/reload-test.js +++ b/tests/integration/records/reload-test.js @@ -33,10 +33,10 @@ test("When a single record is requested, the adapter's find method should be cal env.adapter.findRecord = function(store, type, id, snapshot) { if (count === 0) { count++; - return Ember.RSVP.resolve({ id: id, name: "Tom Dale" }); + return Ember.RSVP.resolve({ data: { id: id, type: 'person', attributes: { name: "Tom Dale" } } }); } else if (count === 1) { count++; - return Ember.RSVP.resolve({ id: id, name: "Braaaahm Dale" }); + return Ember.RSVP.resolve({ data: { id: id, type: 'person', attributes: { name: "Braaaahm Dale" } } }); } else { assert.ok(false, "Should not get here"); } @@ -77,7 +77,7 @@ test("When a record is reloaded and fails, it can try again", function(assert) { if (count++ === 0) { return Ember.RSVP.reject(); } else { - return Ember.RSVP.resolve({ id: 1, name: "Thomas Dale" }); + return Ember.RSVP.resolve({ data: { id: 1, type: 'person', attributes: { name: "Thomas Dale" } } }); } }; @@ -96,19 +96,20 @@ test("When a record is reloaded and fails, it can try again", function(assert) { }); test("When a record is loaded a second time, isLoaded stays true", function(assert) { + let record = { + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + } + } + }; env.adapter.findRecord = function(store, type, id, snapshot) { - return { id: 1, name: "Tom Dale" }; + return record; }; run(function() { - env.store.push({ - data: { - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' - } - } - }); + env.store.push(record); }); run(function() { @@ -117,15 +118,7 @@ test("When a record is loaded a second time, isLoaded stays true", function(asse person.addObserver('isLoaded', isLoadedDidChange); // Reload the record - env.store.push({ - data: { - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' - } - } - }); + env.store.push(record); assert.equal(get(person, 'isLoaded'), true, "The person is still loaded after load"); @@ -154,9 +147,23 @@ test("When a record is reloaded, its async hasMany relationships still work", fu env.adapter.findRecord = function(store, type, id, snapshot) { switch (type.modelName) { case 'person': - return Ember.RSVP.resolve({ id: 1, name: "Tom", tags: [1, 2] }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'person', + attributes: { name: "Tom" }, + relationships: { + tags: { + data: [ + { id: 1, type: 'tag' }, + { id: 2, type: 'tag' } + ] + } + } + } + }); case 'tag': - return Ember.RSVP.resolve({ id: id, name: tags[id] }); + return Ember.RSVP.resolve({ data: { id: id, type: 'tag', attributes: { name: tags[id] } } }); } }; diff --git a/tests/integration/records/save-test.js b/tests/integration/records/save-test.js index 99125f1413a..397906fba22 100644 --- a/tests/integration/records/save-test.js +++ b/tests/integration/records/save-test.js @@ -40,7 +40,7 @@ test("Will resolve save on success", function(assert) { // `save` returns a PromiseObject which allows to call get on it assert.equal(saved.get('id'), undefined); - deferred.resolve({ id: 123 }); + deferred.resolve({ data: { id: 123, type: 'post' } }); saved.then(function(model) { assert.ok(true, 'save operation was resolved'); assert.equal(saved.get('id'), 123); @@ -82,7 +82,7 @@ test("Retry is allowed in a failure handler", function(assert) { if (count++ === 0) { return Ember.RSVP.reject(error); } else { - return Ember.RSVP.resolve({ id: 123 }); + return Ember.RSVP.resolve({ data: { id: 123, type: 'post' } }); } }; diff --git a/tests/integration/references/belongs-to-test.js b/tests/integration/references/belongs-to-test.js index af3cc59f451..9ba234c1ff8 100644 --- a/tests/integration/references/belongs-to-test.js +++ b/tests/integration/references/belongs-to-test.js @@ -410,7 +410,11 @@ test("load() fetches the record", function(assert) { env.adapter.findRecord = function(store, type, id) { return Ember.RSVP.resolve({ - id: 1, name: "Coreleone" + data: { + id: 1, + type: 'family', + attributes: { name: "Coreleone" } + } }); }; @@ -447,7 +451,11 @@ test("load() fetches link when remoteType is link", function(assert) { assert.equal(link, "/families/1"); return Ember.RSVP.resolve({ - id: 1, name: "Coreleone" + data: { + id: 1, + type: 'family', + attributes: { name: "Coreleone" } + } }); }; @@ -487,7 +495,11 @@ test("reload() - loads the record when not yet loaded", function(assert) { assert.equal(count, 1); return Ember.RSVP.resolve({ - id: 1, name: "Coreleone" + data: { + id: 1, + type: 'family', + attributes: { name: "Coreleone" } + } }); }; @@ -526,7 +538,11 @@ test("reload() - reloads the record when already loaded", function(assert) { assert.equal(count, 1); return Ember.RSVP.resolve({ - id: 1, name: "Coreleone" + data: { + id: 1, + type: 'family', + attributes: { name: "Coreleone" } + } }); }; @@ -569,7 +585,11 @@ test("reload() - uses link to reload record", function(assert) { assert.equal(link, "/families/1"); return Ember.RSVP.resolve({ - id: 1, name: "Coreleone" + data: { + id: 1, + type: 'family', + attributes: { name: "Coreleone" } + } }); }; diff --git a/tests/integration/references/has-many-test.js b/tests/integration/references/has-many-test.js index 374747cad17..a2ad4339254 100644 --- a/tests/integration/references/has-many-test.js +++ b/tests/integration/references/has-many-test.js @@ -588,7 +588,7 @@ test("load() fetches the referenced records", function(assert) { var done = assert.async(); env.adapter.findMany = function(store, type, id) { - return Ember.RSVP.resolve([{ id: 1, name: "Vito" }, { id: 2, name: "Michael" }]); + return Ember.RSVP.resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito" } }, { id: 2, type: 'person', attributes: { name: "Michael" } }] }); }; var family; @@ -629,7 +629,7 @@ test("load() fetches link when remoteType is link", function(assert) { env.adapter.findHasMany = function(store, snapshot, link) { assert.equal(link, "/families/1/persons"); - return Ember.RSVP.resolve([{ id: 1, name: "Vito" }, { id: 2, name: "Michael" }]); + return Ember.RSVP.resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito" } }, { id: 2, type: 'person', attributes: { name: "Michael" } }] }); }; var family; @@ -703,7 +703,7 @@ test("load() - only a single find is triggered", function(assert) { }); run(function() { - deferred.resolve([{ id: 1, name: "Vito" }, { id: 2, name: "Michael" }]); + deferred.resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito" } }, { id: 2, type: 'person', attributes: { name: "Michael" } }] }); }); run(function() { @@ -719,10 +719,7 @@ test("reload()", function(assert) { var done = assert.async(); env.adapter.findMany = function(store, type, id) { - return Ember.RSVP.resolve([ - { id: 1, name: "Vito Coreleone" }, - { id: 2, name: "Michael Coreleone" } - ]); + return Ember.RSVP.resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito Coreleone" } }, { id: 2, type: 'person', attributes: { name: "Michael Coreleone" } }] }); }; var family; @@ -768,12 +765,9 @@ test("reload() fetches link when remoteType is link", function(assert) { assert.equal(link, "/families/1/persons"); if (count === 1) { - return Ember.RSVP.resolve([{ id: 1, name: "Vito" }, { id: 2, name: "Michael" }]); + return Ember.RSVP.resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito" } }, { id: 2, type: 'person', attributes: { name: "Michael" } }] }); } else { - return Ember.RSVP.resolve([ - { id: 1, name: "Vito Coreleone" }, - { id: 2, name: "Michael Coreleone" } - ]); + return Ember.RSVP.resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito Coreleone" } }, { id: 2, type: 'person', attributes: { name: "Michael Coreleone" } }] }); } }; diff --git a/tests/integration/references/record-test.js b/tests/integration/references/record-test.js index 7f66074d8f4..d29d547e093 100644 --- a/tests/integration/references/record-test.js +++ b/tests/integration/references/record-test.js @@ -122,7 +122,13 @@ test("load() fetches the record", function(assert) { env.adapter.findRecord = function(store, type, id) { return Ember.RSVP.resolve({ - id: 1, name: "Vito" + data: { + id: 1, + type: 'person', + attributes: { + name: 'Vito' + } + } }); }; @@ -162,7 +168,13 @@ test("load() only a single find is triggered", function(assert) { run(function() { deferred.resolve({ - id: 1, name: "Vito" + data: { + id: 1, + type: 'person', + attributes: { + name: 'Vito' + } + } }); }); @@ -184,7 +196,13 @@ test("reload() loads the record if not yet loaded", function(assert) { assert.equal(count, 1); return Ember.RSVP.resolve({ - id: 1, name: "Vito Coreleone" + data: { + id: 1, + type: 'person', + attributes: { + name: 'Vito Coreleone' + } + } }); }; @@ -204,7 +222,13 @@ test("reload() fetches the record", function(assert) { env.adapter.findRecord = function(store, type, id) { return Ember.RSVP.resolve({ - id: 1, name: "Vito Coreleone" + data: { + id: 1, + type: 'person', + attributes: { + name: 'Vito Coreleone' + } + } }); }; diff --git a/tests/integration/relationships/belongs-to-test.js b/tests/integration/relationships/belongs-to-test.js index f2e44830546..7cc2b0c9fbf 100644 --- a/tests/integration/relationships/belongs-to-test.js +++ b/tests/integration/relationships/belongs-to-test.js @@ -67,7 +67,7 @@ module("integration/relationship/belongs_to Belongs-To Relationships", { env.registry.optionsForType('serializer', { singleton: false }); env.registry.optionsForType('adapter', { singleton: false }); - env.registry.register('serializer:user', DS.JSONSerializer.extend({ + env.registry.register('serializer:user', DS.JSONAPISerializer.extend({ attrs: { favouriteMessage: { embedded: 'always' } } @@ -102,7 +102,10 @@ test("The store can materialize a non loaded monomorphic belongsTo association", env.adapter.findRecord = function(store, type, id, snapshot) { assert.ok(true, "The adapter's find method should be called"); return Ember.RSVP.resolve({ - id + data: { + id, + type: snapshot.modelName + } }); }; @@ -280,8 +283,8 @@ test("The store can serialize a polymorphic belongsTo association", function(ass store.findRecord('comment', 2).then(function(comment) { var serialized = comment.serialize({ includeId: true }); - assert.equal(serialized['message'], 1); - assert.equal(serialized['message_type'], 'post'); + assert.equal(serialized.data.relationships.message.data.id, 1); + assert.equal(serialized.data.relationships.message.data.type, 'posts'); }); }); }); @@ -325,7 +328,17 @@ test("A serializer can materialize a belongsTo as a link that gets sent back to assert.equal(relationship.key, 'group'); assert.equal(link, "/people/1/group"); - return Ember.RSVP.resolve({ id: 1, people: [1] }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'group', + relationships: { + people: { + data: [{ id: 1, type: 'person' }] + } + } + } + }); }); run(function() { @@ -374,7 +387,7 @@ test('A record with an async belongsTo relationship always returns a promise for }; env.adapter.findBelongsTo = assert.wait(function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: 'seat' } }); }); run(function() { @@ -426,7 +439,7 @@ test("A record with an async belongsTo relationship returning null should resolv }; env.adapter.findBelongsTo = assert.wait(function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve(null); + return Ember.RSVP.resolve({ data: null }); }); env.store.findRecord('person', '1').then(assert.wait(function(person) { @@ -716,10 +729,22 @@ test("Destroying a record with an unloaded aync belongsTo association does not f assert.ok(snapshot.record instanceof type); assert.equal(snapshot.id, 1, 'should first post'); return { - id: '1', - title: null, - created_at: null, - user: "2" + data: { + id: '1', + type: 'post', + attributes: { + title: null, + 'created-at': null + }, + relationships: { + user: { + data: { + id: '2', + type: 'user' + } + } + } + } }; }; @@ -852,7 +877,16 @@ test("belongsTo hasData async loaded", function(assert) { }); env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, name: 'The Greatest Book', author: 2 }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: 'The Greatest Book' }, + relationships: { + author: { data: { id: 2, type: 'author'} } + } + } + }); }; run(function() { @@ -867,7 +901,16 @@ test("belongsTo hasData sync loaded", function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, name: 'The Greatest Book', author: 2 }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: 'The Greatest Book' }, + relationships: { + author: { data: { id: 2, type: 'author'} } + } + } + }); }; run(function() { @@ -886,7 +929,16 @@ test("belongsTo hasData async not loaded", function(assert) { }); env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, name: 'The Greatest Book', links: { author: 'author' } }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: 'The Greatest Book' }, + relationships: { + author: { links: { related: 'author'} } + } + } + }); }; run(function() { @@ -901,8 +953,14 @@ test("belongsTo hasData sync not loaded", function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, name: 'The Greatest Book' }); - }; + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: 'The Greatest Book' } + } + }); + } run(function() { store.findRecord('book', 1).then(function(book) { @@ -991,9 +1049,13 @@ test("Related link should be fetched when no local data is present", function(as env.adapter.findBelongsTo = function(store, snapshot, url, relationship) { assert.equal(url, 'author', 'url is correct'); assert.ok(true, "The adapter's findBelongsTo method should be called"); - return Ember.RSVP.resolve( - { id: 1, name: 'This is author' } - ); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'author', + attributes: { name: 'This is author' } + } + }); }; run(function() { @@ -1028,7 +1090,13 @@ test("Local data should take precedence over related link", function(assert) { }; env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, name: 'This is author' }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'author', + attributes: { name: 'This is author' } + } + }); }; run(function() { @@ -1062,9 +1130,13 @@ test("New related link should take precedence over local data", function(assert) env.adapter.findBelongsTo = function(store, snapshot, url, relationship) { assert.equal(url, 'author-new-link', 'url is correct'); assert.ok(true, "The adapter's findBelongsTo method should be called"); - return Ember.RSVP.resolve( - { id: 1, name: 'This is author' } - ); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'author', + attributes: { name: 'This is author' } + } + }); }; env.adapter.findRecord = function(store, type, id, snapshot) { @@ -1117,9 +1189,13 @@ test("Updated related link should take precedence over local data", function(ass env.adapter.findBelongsTo = function(store, snapshot, url, relationship) { assert.equal(url, 'author-updated-link', 'url is correct'); assert.ok(true, "The adapter's findBelongsTo method should be called"); - return Ember.RSVP.resolve( - { id: 1, name: 'This is updated author' } - ); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'author', + attributes: { name: 'This is updated author' } + } + }); }; env.adapter.findRecord = function(store, type, id, snapshot) { @@ -1244,13 +1320,26 @@ test("A belongsTo relationship can be reloaded using the reference if it was fet env.adapter.findRecord = function() { return Ember.RSVP.resolve({ - id: 1, - links: { book: '/books/1' } + data: { + id: 1, + type: 'chapter', + relationships: { + book: { + links: { related: '/books/1' } + } + } + } }); }; env.adapter.findBelongsTo = function() { - return Ember.RSVP.resolve({ id: 1, name: "book title" }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: "book title" } + } + }); }; run(function() { @@ -1263,7 +1352,13 @@ test("A belongsTo relationship can be reloaded using the reference if it was fet assert.equal(book.get('name'), "book title"); env.adapter.findBelongsTo = function() { - return Ember.RSVP.resolve({ id: 1, name: "updated book title" }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: "updated book title" } + } + }); }; return chapter.belongsTo('book').reload(); @@ -1307,7 +1402,13 @@ test("A sync belongsTo relationship can be reloaded using a reference if it was }); env.adapter.findRecord = function() { - return Ember.RSVP.resolve({ id: 1, name: "updated book title" }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: 'updated book title' } + } + }); }; run(function() { @@ -1345,7 +1446,13 @@ test("A belongsTo relationship can be reloaded using a reference if it was fetch }); env.adapter.findRecord = function() { - return Ember.RSVP.resolve({ id: 1, name: "book title" }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: "book title" } + } + }); }; run(function() { @@ -1353,7 +1460,13 @@ test("A belongsTo relationship can be reloaded using a reference if it was fetch assert.equal(book.get('name'), "book title"); env.adapter.findRecord = function() { - return Ember.RSVP.resolve({ id: 1, name: "updated book title" }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: "updated book title" } + } + }); }; return chapter.belongsTo('book').reload(); diff --git a/tests/integration/relationships/has-many-test.js b/tests/integration/relationships/has-many-test.js index 27aa6c40d84..b7534447b16 100644 --- a/tests/integration/relationships/has-many-test.js +++ b/tests/integration/relationships/has-many-test.js @@ -102,27 +102,29 @@ module("integration/relationships/has_many - Has-Many Relationships", { test("When a hasMany relationship is accessed, the adapter's findMany method should not be called if all the records in the relationship are already loaded", function(assert) { assert.expect(0); + let postData = { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' } + ] + } + } + }; + env.adapter.findMany = function(store, type, ids, snapshots) { assert.ok(false, "The adapter's find method should not be called"); }; env.adapter.findRecord = function(store, type, ids, snapshots) { - return { id: 1, comments: [1] }; + return { data: postData }; }; run(function() { env.store.push({ - data: { - type: 'post', - id: '1', - relationships: { - comments: { - data: [ - { type: 'comment', id: '1' } - ] - } - } - }, + data: postData, included: [{ type: 'comment', id: '1' @@ -137,35 +139,39 @@ test("When a hasMany relationship is accessed, the adapter's findMany method sho test("adapter.findMany only gets unique IDs even if duplicate IDs are present in the hasMany relationship", function(assert) { assert.expect(2); + let bookData = { + type: 'book', + id: '1', + relationships: { + chapters: { + data: [ + { type: 'chapter', id: '2' }, + { type: 'chapter', id: '3' }, + { type: 'chapter', id: '3' } + ] + } + } + }; + env.adapter.findMany = function(store, type, ids, snapshots) { assert.equal(type, Chapter, 'type passed to adapter.findMany is correct'); assert.deepEqual(ids, ['2', '3'], 'ids passed to adapter.findMany are unique'); - return Ember.RSVP.resolve([ - { id: 2, title: 'Chapter One' }, - { id: 3, title: 'Chapter Two' } - ]); + return Ember.RSVP.resolve({ + data: [ + { id: 2, type: 'chapter', attributes: { title: 'Chapter One' } }, + { id: 3, type: 'chapter', attributes: { title: 'Chapter Two' } } + ] + }); }; env.adapter.findRecord = function(store, type, ids, snapshots) { - return { id: 1, chapters: [2, 3, 3] }; + return { data: bookData }; }; run(function() { env.store.push({ - data: { - type: 'book', - id: '1', - relationships: { - chapters: { - data: [ - { type: 'chapter', id: '2' }, - { type: 'chapter', id: '3' }, - { type: 'chapter', id: '3' } - ] - } - } - } + data: bookData }); env.store.findRecord('book', 1).then(function(book) { return book.get('chapters'); @@ -188,8 +194,21 @@ test("A serializer can materialize a hasMany as an opaque token that can be lazi assert.equal(type, Post, "find type was Post"); assert.equal(id, "1", "find id was 1"); - return Ember.RSVP.resolve({ id: 1, links: { comments: "/posts/1/comments" } }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'post', + relationships: { + comments: { + links: { + related: "/posts/1/comments" + } + } + } + } + }); }; + //({ id: 1, links: { comments: "/posts/1/comments" } }); env.adapter.findMany = function(store, type, ids, snapshots) { throw new Error("Adapter's findMany should not be called"); @@ -199,10 +218,12 @@ test("A serializer can materialize a hasMany as an opaque token that can be lazi assert.equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments"); assert.equal(relationship.type, "comment", "relationship was passed correctly"); - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ] + }); }; run(function() { @@ -251,10 +272,12 @@ test("Accessing a hasMany backed by a link multiple times triggers only one requ assert.equal(count, 1, "findHasMany has only been called once"); return new Ember.RSVP.Promise(function(resolve, reject) { setTimeout(function() { - var value = [ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]; + var value = { + data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ] + }; resolve(value); }, 100); }); @@ -294,10 +317,12 @@ test("A hasMany backed by a link remains a promise after a record has been added }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ] + }); }; var post; run(function() { @@ -347,14 +372,19 @@ test("A hasMany updated link should not remove new children", function(assert) { }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve([]); + return Ember.RSVP.resolve({ data: [] }); }; env.adapter.createRecord = function(store, snapshot, link, relationship) { return Ember.RSVP.resolve({ - id: 1, - links: { - comments: '/some/link' + data: { + id: 1, + type: 'post', + relationships: { + comments: { + links: { related: '/some/link' } + } + } } }); }; @@ -388,14 +418,21 @@ test("A hasMany updated link should not remove new children when the parent reco }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve([{ id: 5, body: 'hello' }]); + return Ember.RSVP.resolve({ data: [ + { id: 5, type: 'comment', attributes: { body: 'hello' } } + ]}); }; env.adapter.createRecord = function(store, snapshot, link, relationship) { return Ember.RSVP.resolve({ - id: 1, - links: { - comments: '/some/link' + data: { + id: 1, + type: 'post', + relationships: { + comments: { + links: { related: '/some/link' } + } + } } }); }; @@ -430,9 +467,7 @@ test("A hasMany relationship doesn't contain duplicate children, after the canon }); env.adapter.createRecord = function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve({ - id: 1 - }); + return Ember.RSVP.resolve({ data: { id: 1, type: 'post' } }); }; run(function() { @@ -498,7 +533,17 @@ test("A hasMany relationship can be reloaded if it was fetched via a link", func assert.equal(type, Post, "find type was Post"); assert.equal(id, "1", "find id was 1"); - return Ember.RSVP.resolve({ id: 1, links: { comments: "/posts/1/comments" } }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'post', + relationships: { + comments: { + links: { related: "/posts/1/comments" } + } + } + } + }); }; env.adapter.findHasMany = function(store, snapshot, link, relationship) { @@ -506,10 +551,10 @@ test("A hasMany relationship can be reloaded if it was fetched via a link", func assert.equal(relationship.key, 'comments', "findHasMany relationship key was comments"); assert.equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments"); - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; run(function() { @@ -524,11 +569,11 @@ test("A hasMany relationship can be reloaded if it was fetched via a link", func assert.equal(relationship.key, 'comments', "findHasMany relationship key was comments"); assert.equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments"); - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" }, - { id: 3, body: "Thirds" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } }, + { id: 3, type: 'comment', attributes: { body: "Thirds" } } + ]}); }; return comments.reload(); @@ -547,7 +592,20 @@ test("A sync hasMany relationship can be reloaded if it was fetched via ids", fu assert.equal(type, Post, "find type was Post"); assert.equal(id, "1", "find id was 1"); - return Ember.RSVP.resolve({ id: 1, comments: [1, 2] }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'post', + relationships: { + comments: { + data: [ + { id: 1, type: 'comment' }, + { id: 2, type: 'comment' } + ] + } + } + } + }); }; run(function() { @@ -573,10 +631,10 @@ test("A sync hasMany relationship can be reloaded if it was fetched via ids", fu assert.equal(comments.get('length'), 2, "comments have a length of 2"); env.adapter.findMany = function(store, type, ids, snapshots) { - return Ember.RSVP.resolve([ - { id: 1, body: "FirstUpdated" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; return comments.reload(); @@ -595,14 +653,24 @@ test("A hasMany relationship can be reloaded if it was fetched via ids", functio assert.equal(type, Post, "find type was Post"); assert.equal(id, "1", "find id was 1"); - return Ember.RSVP.resolve({ id: 1, comments: [1,2] }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'post', + relationships: { + comments: { + data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }] + } + } + } + }); }; env.adapter.findMany = function(store, type, ids, snapshots) { - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; run(function() { @@ -613,10 +681,10 @@ test("A hasMany relationship can be reloaded if it was fetched via ids", functio assert.equal(comments.get('length'), 2, "comments have 2 length"); env.adapter.findMany = function(store, type, ids, snapshots) { - return Ember.RSVP.resolve([ - { id: 1, body: "FirstUpdated" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; return comments.reload(); @@ -634,7 +702,17 @@ test("A hasMany relationship can be reloaded even if it failed at the first time }); env.adapter.findRecord = function(store, type, id) { - return Ember.RSVP.resolve({ id: 1, links: { comments: "/posts/1/comments" } }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'post', + relationships: { + comments: { + links: { related: "/posts/1/comments" } + } + } + } + }); }; var loadingCount = -1; @@ -643,10 +721,10 @@ test("A hasMany relationship can be reloaded even if it failed at the first time if (loadingCount % 2 === 0) { return Ember.RSVP.reject(); } else { - return Ember.RSVP.resolve([ - { id: 1, body: "FirstUpdated" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); } }; run(function() { @@ -679,16 +757,26 @@ test("A hasMany relationship can be directly reloaded if it was fetched via link assert.equal(type, Post, "find type was Post"); assert.equal(id, "1", "find id was 1"); - return Ember.RSVP.resolve({ id: 1, links: { comments: "/posts/1/comments" } }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'post', + relationships: { + comments: { + links: { related: "/posts/1/comments" } + } + } + } + }); }; env.adapter.findHasMany = function(store, record, link, relationship) { assert.equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments"); - return Ember.RSVP.resolve([ - { id: 1, body: "FirstUpdated" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; run(function() { env.store.findRecord('post', 1).then(function(post) { @@ -710,16 +798,26 @@ test("Has many via links - Calling reload multiple times does not send a new req }); env.adapter.findRecord = function(store, type, id) { - return Ember.RSVP.resolve({ id: 1, links: { comments: "/posts/1/comments" } }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'post', + relationships: { + comments: { + links: { related: "/posts/1/comments" } + } + } + } + }); }; let count = 0; env.adapter.findHasMany = function(store, record, link, relationship) { count++; - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; run(function() { env.store.findRecord('post', 1).then(function(post) { @@ -742,14 +840,24 @@ test("A hasMany relationship can be directly reloaded if it was fetched via ids" assert.equal(type, Post, "find type was Post"); assert.equal(id, "1", "find id was 1"); - return Ember.RSVP.resolve({ id: 1, comments: [1,2] }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'post', + relationships: { + comments: { + data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }] + } + } + } + }); }; env.adapter.findMany = function(store, type, ids, snapshots) { - return Ember.RSVP.resolve([ - { id: 1, body: "FirstUpdated" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; run(function() { @@ -772,16 +880,26 @@ test("Has many via ids - Calling reload multiple times does not send a new reque }); env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, comments: [1,2] }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'post', + relationships: { + comments: { + data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }] + } + } + } + }); }; let count = 0; env.adapter.findMany = function(store, type, ids, snapshots) { count++; - return Ember.RSVP.resolve([ - { id: 1, body: "FirstUpdated" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; run(function() { @@ -804,10 +922,10 @@ test("PromiseArray proxies createRecord to its ManyArray once the hasMany is loa }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; var post; @@ -848,10 +966,10 @@ test("PromiseArray proxies evented methods to its ManyArray", function(assert) { }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; var post, comments; @@ -915,16 +1033,16 @@ test("An updated `links` value should invalidate a relationship cache", function assert.equal(relationship.type, "comment", "relationship was passed correctly"); if (link === '/first') { - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); } else if (link === '/second') { - return Ember.RSVP.resolve([ - { id: 3, body: "Third" }, - { id: 4, body: "Fourth" }, - { id: 5, body: "Fifth" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 3, type: 'comment', attributes: { body: "Third" } }, + { id: 4, type: 'comment', attributes: { body: "Fourth" } }, + { id: 5, type: 'comment', attributes: { body: "Fifth" } } + ]}); } }; var post; @@ -976,28 +1094,30 @@ test("An updated `links` value should invalidate a relationship cache", function test("When a polymorphic hasMany relationship is accessed, the adapter's findMany method should not be called if all the records in the relationship are already loaded", function(assert) { assert.expect(1); + let userData = { + type: 'user', + id: '1', + relationships: { + messages: { + data: [ + { type: 'post', id: '1' }, + { type: 'comment', id: '3' } + ] + } + } + }; + env.adapter.findMany = function(store, type, ids, snapshots) { assert.ok(false, "The adapter's find method should not be called"); }; env.adapter.findRecord = function(store, type, ids, snapshots) { - return { id: 1, messages: [{ id: 1, type: 'post' }, { id: 3, type: 'comment' }] }; + return { data: userData }; }; run(function() { env.store.push({ - data: { - type: 'user', - id: '1', - relationships: { - messages: { - data: [ - { type: 'post', id: '1' }, - { type: 'comment', id: '3' } - ] - } - } - }, + data: userData, included: [{ type: 'post', id: '1' @@ -1023,9 +1143,9 @@ test("When a polymorphic hasMany relationship is accessed, the store can call mu env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.findRecord = function(store, type, id, snapshot) { if (type === Post) { - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: 'post' } }); } else if (type === Comment) { - return Ember.RSVP.resolve({ id: 3 }); + return Ember.RSVP.resolve({ data: { id: 3, type: 'comment' } }); } }; @@ -1081,7 +1201,17 @@ test("Type can be inferred from the key of a hasMany relationship", function(ass assert.expect(1); env.adapter.findRecord = function(store, type, ids, snapshots) { - return { id: 1, contacts: [1] }; + return { + data: { + id: 1, + type: 'user', + relationships: { + contacts: { + data: [{ id: 1, type: 'contact' }] + } + } + } + }; }; run(function() { @@ -1120,7 +1250,17 @@ test("Type can be inferred from the key of an async hasMany relationship", funct }); env.adapter.findRecord = function(store, type, ids, snapshots) { - return { id: 1, contacts: [1] }; + return { + data: { + id: 1, + type: 'user', + relationships: { + contacts: { + data: [{ id: 1, type: 'contact' }] + } + } + } + }; }; run(function() { @@ -1157,7 +1297,7 @@ test("Polymorphic relationships work with a hasMany whose type is inferred", fun }); env.adapter.findRecord = function(store, type, ids, snapshots) { - return { id: 1 }; + return { data: { id: 1, type: 'user' } }; }; assert.expect(1); @@ -1489,7 +1629,7 @@ test("When a record is saved, its unsaved hasMany records should be kept", funct var post, comment; env.adapter.createRecord = function(store, type, snapshot) { - return Ember.RSVP.resolve({ id: 1 }); + return Ember.RSVP.resolve({ data: { id: 1, type: snapshot.modelName } }); }; run(function () { @@ -1512,9 +1652,9 @@ test("dual non-async HM <-> BT", function(assert) { }); env.adapter.createRecord = function(store, type, snapshot) { - var data = snapshot.record.serialize(); - data.id = 2; - return Ember.RSVP.resolve(data); + var serialized = snapshot.record.serialize(); + serialized.data.id = 2; + return Ember.RSVP.resolve(serialized); }; var post, firstComment; @@ -1568,11 +1708,14 @@ test("When an unloaded record is added to the hasMany, it gets fetched once the }); env.adapter.findMany = function(store, type, ids, snapshots) { - return resolve([{ id: 1, body: 'first' }, { id: 2, body: 'second' }]); + return resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: 'first' } }, + { id: 2, type: 'comment', attributes: { body: 'second' } } + ]}); }; env.adapter.findRecord = function(store, type, id, snapshot) { - return resolve({ id: 3, body: 'third' }); + return resolve({ data: { id: 3, type: 'comment', attributes: { body: 'third' } } }); }; var post; @@ -2304,7 +2447,18 @@ test("hasMany hasData async loaded", function(assert) { }); env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, title: 'The Story Begins', pages: [2, 3] }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'chapter', + attributes: { title: 'The Story Begins' }, + relationships: { + pages: { + data: [{ id: 2, type: 'page' }, { id: 3, type: 'page' }] + } + } + } + }); }; run(function() { @@ -2319,7 +2473,18 @@ test("hasMany hasData sync loaded", function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, title: 'The Story Begins', pages: [2, 3] }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'chapter', + attributes: { title: 'The Story Begins' }, + relationships: { + pages: { + data: [{ id: 2, type: 'page' }, { id: 3, type: 'page' }] + } + } + } + }); }; run(function() { @@ -2338,7 +2503,18 @@ test("hasMany hasData async not loaded", function(assert) { }); env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, title: 'The Story Begins', links: { pages: 'pages' } }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'chapter', + attributes: { title: 'The Story Begins' }, + relationships: { + pages: { + links: { related: 'pages' } + } + } + } + }); }; run(function() { @@ -2353,7 +2529,13 @@ test("hasMany hasData sync not loaded", function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, title: 'The Story Begins' }); + return Ember.RSVP.resolve({ + data: { + id: 1, + type: 'chapter', + attributes: { title: 'The Story Begins' } + } + }); }; run(function() { @@ -2577,9 +2759,9 @@ test("Related link should be fetched when no local data is present", function(as env.adapter.findHasMany = function(store, snapshot, url, relationship) { assert.equal(url, 'comments', 'url is correct'); assert.ok(true, "The adapter's findHasMany method should be called"); - return Ember.RSVP.resolve([ - { id: 1, body: 'This is comment' } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: 'This is comment' } } + ]}); }; run(function() { @@ -2614,7 +2796,7 @@ test("Local data should take precedence over related link", function(assert) { }; env.adapter.findRecord = function(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: 1, body: 'This is comment' }); + return Ember.RSVP.resolve({ data: { id: 1, type: 'comment', attributes: { body: 'This is comment' } } }); }; run(function() { @@ -2650,9 +2832,9 @@ test("Updated related link should take precedence over local data", function(ass env.adapter.findHasMany = function(store, snapshot, url, relationship) { assert.equal(url, 'comments-updated-link', 'url is correct'); assert.ok(true, "The adapter's findHasMany method should be called"); - return Ember.RSVP.resolve([ - { id: 1, body: 'This is comment' } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: 'This is comment' } } + ]}); }; env.adapter.findRecord = function(store, type, id, snapshot) { @@ -2705,10 +2887,10 @@ test("PromiseArray proxies createRecord to its ManyArray before the hasMany is l }); env.adapter.findHasMany = function(store, record, link, relationship) { - return Ember.RSVP.resolve([ - { id: 1, body: "First" }, - { id: 2, body: "Second" } - ]); + return Ember.RSVP.resolve({ data: [ + { id: 1, type: 'comment', attributes: { body: "First" } }, + { id: 2, type: 'comment', attributes: { body: "Second" } } + ]}); }; run(function() { diff --git a/tests/integration/relationships/one-to-one-test.js b/tests/integration/relationships/one-to-one-test.js index 1ae4d48eecb..a4b9038aed1 100644 --- a/tests/integration/relationships/one-to-one-test.js +++ b/tests/integration/relationships/one-to-one-test.js @@ -588,13 +588,13 @@ test("Setting a BelongsTo to a promise multiple times is resistant to race condi env.adapter.findRecord = function(store, type, id, snapshot) { if (id === '5') { - return Ember.RSVP.resolve({ id: 5, name: "Igor's friend" }); + return Ember.RSVP.resolve({ data: { id: 5, type: 'user', attributes: { name: "Igor's friend" } } }); } else if (id === '2') { let done = assert.async(); return new Ember.RSVP.Promise(function(resolve, reject) { setTimeout(function() { done(); - resolve({ id: 2, name: "Stanley's friend" }); + resolve({ data: { id: 2, type: 'user', attributes: { name: "Stanley's friend" } } }); }, 1); }); } diff --git a/tests/integration/serializers/json-api-serializer-test.js b/tests/integration/serializers/json-api-serializer-test.js index 8c294ba4951..a597ca058c8 100644 --- a/tests/integration/serializers/json-api-serializer-test.js +++ b/tests/integration/serializers/json-api-serializer-test.js @@ -59,7 +59,7 @@ module('integration/serializers/json-api-serializer - JSONAPISerializer', { }); store = env.store; - serializer = store.serializerFor('-json-api'); + serializer = env.serializer; }, afterEach() { diff --git a/tests/integration/serializers/json-serializer-test.js b/tests/integration/serializers/json-serializer-test.js index c5548b82757..a020766303c 100644 --- a/tests/integration/serializers/json-serializer-test.js +++ b/tests/integration/serializers/json-serializer-test.js @@ -7,7 +7,7 @@ import {module, test} from 'qunit'; import DS from 'ember-data'; -var Post, post, Comment, comment, Favorite, favorite, env; +var Post, post, Comment, comment, Favorite, favorite, env, serializer; var run = Ember.run; module("integration/serializer/json - JSONSerializer", { @@ -31,6 +31,7 @@ module("integration/serializer/json - JSONSerializer", { env.store.modelFor('post'); env.store.modelFor('comment'); env.store.modelFor('favorite'); + serializer = env.store.serializerFor('-json'); }, afterEach() { @@ -44,7 +45,7 @@ test("serialize doesn't include ID when includeId is false", function(assert) { }); var json = {}; - json = env.serializer.serialize(post._createSnapshot(), { includeId: false }); + json = serializer.serialize(post._createSnapshot(), { includeId: false }); assert.deepEqual(json, { title: "Rails is omakase", @@ -59,7 +60,7 @@ test("serialize includes id when includeId is true", function(assert) { }); var json = {}; - json = env.serializer.serialize(post._createSnapshot(), { includeId: true }); + json = serializer.serialize(post._createSnapshot(), { includeId: true }); assert.deepEqual(json, { id: 'test', @@ -76,7 +77,7 @@ if (isEnabled("ds-serialize-id")) { }); var json = {}; - env.serializer.serializeId(post._createSnapshot(), json, 'id'); + serializer.serializeId(post._createSnapshot(), json, 'id'); assert.deepEqual(json, { id: 'test' @@ -134,7 +135,7 @@ test("serializeAttribute", function(assert) { }); var json = {}; - env.serializer.serializeAttribute(post._createSnapshot(), json, "title", { type: "string" }); + serializer.serializeAttribute(post._createSnapshot(), json, "title", { type: "string" }); assert.deepEqual(json, { title: "Rails is omakase" @@ -166,7 +167,7 @@ test("serializeBelongsTo", function(assert) { var json = {}; - env.serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); + serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); assert.deepEqual(json, { post: "1" }); }); @@ -177,7 +178,7 @@ test("serializeBelongsTo with null", function(assert) { }); var json = {}; - env.serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); + serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); assert.deepEqual(json, { post: null @@ -193,7 +194,7 @@ test("async serializeBelongsTo with null", function(assert) { }); var json = {}; - env.serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); + serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); assert.deepEqual(json, { post: null @@ -294,7 +295,7 @@ test("serializeIntoHash", function(assert) { var json = {}; - env.serializer.serializeIntoHash(json, Post, post._createSnapshot()); + serializer.serializeIntoHash(json, Post, post._createSnapshot()); assert.deepEqual(json, { title: "Rails is omakase", @@ -441,6 +442,7 @@ test('Serializer should respect the attrs hash when serializing records', functi }); test('Serializer respects if embedded model has an attribute named "type" - #3726', function(assert) { + env.registry.register("serializer:child", DS.JSONSerializer); env.registry.register("serializer:parent", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { attrs: { child: { embedded: 'always' } @@ -476,6 +478,7 @@ test('Serializer respects if embedded model has an attribute named "type" - #372 }); test('Serializer respects if embedded model has a relationship named "type" - #3726', function(assert) { + env.registry.register("serializer:child", DS.JSONSerializer); env.registry.register("serializer:parent", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { attrs: { child: { embedded: 'always' } @@ -919,6 +922,7 @@ test('normalizeResponse returns empty `included` payload when relationship is un }); test('normalizeResponse respects `included` items (single response)', function(assert) { + env.registry.register("serializer:comment", DS.JSONSerializer); env.registry.register("serializer:post", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { attrs: { comments: { embedded: 'always' } @@ -943,6 +947,7 @@ test('normalizeResponse respects `included` items (single response)', function(a }); test('normalizeResponse respects `included` items (array response)', function(assert) { + env.registry.register("serializer:comment", DS.JSONSerializer); env.registry.register("serializer:post", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { attrs: { comments: { embedded: 'always' } @@ -1013,7 +1018,7 @@ test('options are passed to transform for serialization', function(assert) { post = env.store.createRecord('post', { custom: 'value' }); }); - env.serializer.serialize(post._createSnapshot()); + serializer.serialize(post._createSnapshot()); }); test('options are passed to transform for normalization', function(assert) { @@ -1031,7 +1036,7 @@ test('options are passed to transform for normalization', function(assert) { }) }); - env.serializer.normalize(Post, { + serializer.normalize(Post, { custom: 'value' }); }); @@ -1060,7 +1065,7 @@ test('Serializer should respect the attrs hash in links', function(assert) { if (isEnabled("ds-payload-type-hooks")) { test("mapping of model name can be customized via modelNameFromPayloadType", function(assert) { - env.serializer.modelNameFromPayloadType = function(payloadType) { + serializer.modelNameFromPayloadType = function(payloadType) { return payloadType.replace("api::v1::", ""); }; @@ -1074,7 +1079,7 @@ if (isEnabled("ds-payload-type-hooks")) { assert.expectNoDeprecation(); - let normalized = env.serializer.normalizeSingleResponse(env.store, Favorite, jsonHash); + let normalized = serializer.normalizeSingleResponse(env.store, Favorite, jsonHash); assert.deepEqual(normalized, { data: { @@ -1095,7 +1100,7 @@ if (isEnabled("ds-payload-type-hooks")) { }); testInDebug("DEPRECATED - mapping of model name can be customized via modelNameFromPayloadKey", function(assert) { - env.serializer.modelNameFromPayloadKey = function(payloadType) { + serializer.modelNameFromPayloadKey = function(payloadType) { return payloadType.replace("api::v1::", ""); }; @@ -1109,7 +1114,7 @@ if (isEnabled("ds-payload-type-hooks")) { assert.expectDeprecation("You used modelNameFromPayloadKey to customize how a type is normalized. Use modelNameFromPayloadType instead"); - let normalized = env.serializer.normalizeSingleResponse(env.store, Favorite, jsonHash); + let normalized = serializer.normalizeSingleResponse(env.store, Favorite, jsonHash); assert.deepEqual(normalized, { data: { diff --git a/tests/integration/serializers/rest-serializer-test.js b/tests/integration/serializers/rest-serializer-test.js index 4adc1591bf4..5767f4b7f93 100644 --- a/tests/integration/serializers/rest-serializer-test.js +++ b/tests/integration/serializers/rest-serializer-test.js @@ -106,6 +106,8 @@ test("normalizeResponse with custom modelNameFromPayloadKey", function(assert) { var camelized = Ember.String.camelize(root); return Ember.String.singularize(camelized); }; + env.registry.register('serializer:home-planet', DS.JSONSerializer); + env.registry.register('serializer:super-villain', DS.JSONSerializer); var jsonHash = { home_planets: [{ @@ -201,6 +203,8 @@ testInDebug("normalizeResponse with type and custom modelNameFromPayloadKey", fu testInDebug("normalizeResponse warning with custom modelNameFromPayloadKey", function(assert) { var homePlanet; var oldModelNameFromPayloadKey = env.restSerializer.modelNameFromPayloadKey; + env.registry.register('serializer:super-villain', DS.JSONSerializer); + env.registry.register('serializer:home-planet', DS.JSONSerializer); env.restSerializer.modelNameFromPayloadKey = function(root) { //return some garbage that won"t resolve in the container return "garbage"; @@ -235,6 +239,8 @@ testInDebug("normalizeResponse warning with custom modelNameFromPayloadKey", fun testInDebug("normalizeResponse warning with custom modelNameFromPayloadKey", function(assert) { var homePlanets; + env.registry.register('serializer:super-villain', DS.JSONSerializer); + env.registry.register('serializer:home-planet', DS.JSONSerializer); env.restSerializer.modelNameFromPayloadKey = function(root) { //return some garbage that won"t resolve in the container return "garbage"; @@ -310,6 +316,7 @@ test("serialize polymorphic when associated object is null", function(assert) { test("normalizeResponse loads secondary records with correct serializer", function(assert) { var superVillainNormalizeCount = 0; + env.registry.register('serializer:evil-minion', DS.JSONSerializer); env.registry.register('serializer:super-villain', DS.RESTSerializer.extend({ normalize() { superVillainNormalizeCount++; @@ -347,6 +354,7 @@ test("normalizeResponse returns null if payload contains null", function(assert) test("normalizeResponse loads secondary records with correct serializer", function(assert) { var superVillainNormalizeCount = 0; + env.registry.register('serializer:evil-minion', DS.JSONSerializer); env.registry.register('serializer:super-villain', DS.RESTSerializer.extend({ normalize() { superVillainNormalizeCount++; @@ -776,6 +784,7 @@ test("normalizeResponse can load secondary records of the same type without affe ] }; var array; + env.registry.register('serializer:comment', DS.JSONSerializer); run(function() { array = env.restSerializer.normalizeResponse(env.store, Comment, jsonHash, '1', 'findRecord'); @@ -905,6 +914,7 @@ test('Serializer should respect the attrs hash in links', function(assert) { // https://github.com/emberjs/data/issues/3805 test('normalizes sideloaded single record so that it sideloads correctly - belongsTo - GH-3805', function(assert) { + env.registry.register('serializer:evil-minion', DS.JSONSerializer); env.registry.register("serializer:doomsday-device", DS.RESTSerializer.extend()); let payload = { doomsdayDevice: { @@ -937,6 +947,7 @@ test('normalizes sideloaded single record so that it sideloads correctly - belon // https://github.com/emberjs/data/issues/3805 test('normalizes sideloaded single record so that it sideloads correctly - hasMany - GH-3805', function(assert) { + env.registry.register('serializer:super-villain', DS.JSONSerializer); env.registry.register("serializer:home-planet", DS.RESTSerializer.extend()); let payload = { homePlanet: { diff --git a/tests/integration/snapshot-test.js b/tests/integration/snapshot-test.js index 6bb11f9e20c..cf125d7d797 100644 --- a/tests/integration/snapshot-test.js +++ b/tests/integration/snapshot-test.js @@ -372,7 +372,7 @@ test("snapshot.belongsTo() returns a snapshot if relationship link has been fetc assert.expect(2); env.adapter.findBelongsTo = function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve({ id: 1, title: 'Hello World' }); + return Ember.RSVP.resolve({ data: { id: 1, type: 'post', attributes: { title: 'Hello World' } } }); }; run(function() { @@ -804,7 +804,7 @@ test("snapshot.hasMany() returns array of snapshots if relationship link has bee assert.expect(2); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return Ember.RSVP.resolve([{ id: 2, body: 'This is comment' }]); + return Ember.RSVP.resolve({ data: [{ id: 2, type: 'comment', attributes: { body: 'This is comment' } }]}); }; run(function() { @@ -1055,7 +1055,17 @@ test("snapshot.serialize() serializes itself", function(assert) { post.set('title', 'New Title'); - assert.deepEqual(snapshot.serialize(), { author: undefined, title: 'Hello World' }, 'shapshot serializes correctly'); - assert.deepEqual(snapshot.serialize({ includeId: true }), { id: "1", author: undefined, title: 'Hello World' }, 'serialize takes options'); + var expected = { + data: { + attributes: { + author: undefined, + title: 'Hello World' + }, + type: 'posts' + } + }; + assert.deepEqual(snapshot.serialize(), expected, 'shapshot serializes correctly'); + expected.data.id = '1'; + assert.deepEqual(snapshot.serialize({ includeId: true }), expected, 'serialize takes options'); }); }); diff --git a/tests/integration/store-test.js b/tests/integration/store-test.js index 4d9266ee147..4af6741d664 100644 --- a/tests/integration/store-test.js +++ b/tests/integration/store-test.js @@ -162,10 +162,11 @@ test("destroying the store correctly cleans everything up", function(assert) { }); env.adapter.query = function() { - return [{ + return { data: [{ id: 2, - name: 'Yehuda' - }]; + type: 'person', + attributes: { name: 'Yehuda' } + }]}; }; var adapterPopulatedPeople, filterdPeople; diff --git a/tests/integration/store/query-record-test.js b/tests/integration/store/query-record-test.js index 76376e5792a..a712c6ef5c3 100644 --- a/tests/integration/store/query-record-test.js +++ b/tests/integration/store/query-record-test.js @@ -47,7 +47,7 @@ test("When a record is requested, the adapter's queryRecord method should be cal env.registry.register('adapter:person', DS.Adapter.extend({ queryRecord(store, type, query) { assert.equal(type, Person, "the query method is called with the correct type"); - return Ember.RSVP.resolve({ id: 1, name: "Peter Wagenet" }); + return Ember.RSVP.resolve({ data: { id: 1, type: 'person', attributes: { name: "Peter Wagenet" } } }); } })); diff --git a/tests/unit/model-test.js b/tests/unit/model-test.js index 1340ea94cc7..da70733455d 100644 --- a/tests/unit/model-test.js +++ b/tests/unit/model-test.js @@ -6,7 +6,7 @@ import {module, test} from 'qunit'; import DS from 'ember-data'; import { isEnabled } from 'ember-data/-private'; -const { get, set, run } = Ember; +const { get, getOwner, set, run } = Ember; let Person, store, env; @@ -360,7 +360,7 @@ test('changedAttributes() works while the record is being saved', function(asser likes: [undefined, 'Cheese'] }); - return { id: 1 }; + return { data: { id: 1, type: 'mascot' } }; } }); @@ -396,7 +396,7 @@ test('changedAttributes() works while the record is being updated', function(ass likes: ['Cheese', 'Mussels'] }); - return { id: '1', type: 'mascot' }; + return { data: { id: '1', type: 'mascot' } }; } }); @@ -1006,6 +1006,7 @@ function converts(assert, type, provided, expected, options = {}) { let testStore = createStore({ model: Model }); + getOwner(testStore).register('serializer:model', DS.JSONSerializer); run(() => { testStore.push(testStore.normalize('model', { id: 1, name: provided })); @@ -1041,6 +1042,7 @@ function convertsFromServer(assert, type, provided, expected) { shouldBackgroundReloadRecord() { return false; } }) }); + getOwner(testStore).register('serializer:model', DS.JSONSerializer); return run(() => { testStore.push(testStore.normalize('model', { @@ -1141,6 +1143,7 @@ function convertsWhenSet(assert, type, provided, expected) { } }) }); + getOwner(testStore).register('serializer:model', DS.JSONSerializer); return run(() => { testStore.push({ @@ -1180,8 +1183,11 @@ test('ensure model exits loading state, materializes data and fulfills promise o adapter: DS.Adapter.extend({ findRecord(store, type, id, snapshot) { return Ember.RSVP.resolve({ - id: 1, - name: 'John' + data: { + id: 1, + type: 'person', + attributes: { name: 'John' } + } }); } }), @@ -1204,7 +1210,7 @@ test('A DS.Model can be JSONified', function(assert) { let store = createStore({ person: Person }); let record = run(() => store.createRecord('person', { name: 'TomHuda' })); - assert.deepEqual(record.toJSON(), { name: 'TomHuda' }); + assert.deepEqual(record.toJSON(), { data: { type: 'people', attributes: { name: 'TomHuda' } } }); }); testInDebug('A subclass of DS.Model can not use the `data` property', function(assert) { @@ -1325,7 +1331,7 @@ test('toJSON looks up the JSONSerializer using the store instead of using JSONSe } assert.ok(!errorThrown, 'error not thrown due to missing store'); - assert.deepEqual(json, {}); + assert.deepEqual(json, { data: { type: 'people' }}); }); test('internalModel is ready by `init`', function(assert) { diff --git a/tests/unit/model/lifecycle-callbacks-test.js b/tests/unit/model/lifecycle-callbacks-test.js index c7dbd9fa820..13257dd728d 100644 --- a/tests/unit/model/lifecycle-callbacks-test.js +++ b/tests/unit/model/lifecycle-callbacks-test.js @@ -21,7 +21,7 @@ test('a record receives a didLoad callback when it has finished loading', functi const Adapter = DS.Adapter.extend({ findRecord(store, type, id, snapshot) { - return { id: 1, name: 'Foo' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Foo' } } }; } }); @@ -78,7 +78,7 @@ test('a record receives a didUpdate callback when it has finished updating', fun const Adapter = DS.Adapter.extend({ findRecord(store, type, id, snapshot) { - return { id: 1, name: 'Foo' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Foo' } } }; }, updateRecord(store, type, snapshot) { @@ -165,7 +165,7 @@ test('a record receives a didDelete callback when it has finished deleting', fun const Adapter = DS.Adapter.extend({ findRecord(store, type, id, snapshot) { - return { id: 1, name: 'Foo' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Foo' } } }; }, deleteRecord(store, type, snapshot) { @@ -244,7 +244,7 @@ test('a record receives a becameInvalid callback when it became invalid', functi const Adapter = DS.Adapter.extend({ findRecord(store, type, id, snapshot) { - return { id: 1, name: "Foo" }; + return { data: { id: 1, type: 'person', attributes: { name: 'Foo' } } }; }, updateRecord(store, type, snapshot) { diff --git a/tests/unit/model/merge-test.js b/tests/unit/model/merge-test.js index 26e93f8aac1..c2f865dd5d9 100644 --- a/tests/unit/model/merge-test.js +++ b/tests/unit/model/merge-test.js @@ -22,7 +22,7 @@ test('When a record is in flight, changes can be made', function(assert) { const Adapter = DS.Adapter.extend({ createRecord(store, type, snapshot) { - return { id: 1, name: 'Tom Dale' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Tom Dale' } } }; } }); @@ -98,7 +98,7 @@ test("When a record is in flight, pushes are applied underneath the in flight ch updateRecord(store, type, snapshot) { // Make sure saving isn't resolved synchronously return new Ember.RSVP.Promise(resolve => { - run.next(null, resolve, { id: 1, name: 'Senor Thomas Dale, Esq.', city: 'Portland' }); + run.next(null, resolve, { data: { id: 1, type: 'person', attributes: { name: 'Senor Thomas Dale, Esq.', city: 'Portland' } } }); }); } }); @@ -245,7 +245,7 @@ test('A record with no changes can still be saved', function(assert) { const Adapter = DS.Adapter.extend({ updateRecord(store, type, snapshot) { - return { id: 1, name: 'Thomas Dale' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Thomas Dale' } } }; } }); @@ -277,7 +277,7 @@ test('A dirty record can be reloaded', function(assert) { const Adapter = DS.Adapter.extend({ findRecord(store, type, id, snapshot) { - return { id: 1, name: 'Thomas Dale', city: 'Portland' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Thomas Dale', city: 'Portland' } } }; } }); diff --git a/tests/unit/model/relationships/belongs-to-test.js b/tests/unit/model/relationships/belongs-to-test.js index a6c0919dbf2..32606b21674 100644 --- a/tests/unit/model/relationships/belongs-to-test.js +++ b/tests/unit/model/relationships/belongs-to-test.js @@ -151,11 +151,11 @@ test('async belongsTo relationships work when the data hash has not been loaded' if (type === Person) { assert.equal(id, 1, 'id should be 1'); - return { id: 1, name: 'Tom Dale', tag: 2 }; + return { data: { id: 1, type: 'person', attributes: { name: 'Tom Dale' }, relationships: { tag: { data: { id: 2, type: 'tag' } } } } }; } else if (type === Tag) { assert.equal(id, 2, 'id should be 2'); - return { id: 2, name: 'friendly' }; + return { data: { id: 2, type: 'tag', attributes: { name: 'friendly' } } }; } }; @@ -252,9 +252,18 @@ test('when response to saving a belongsTo is a success but includes changes that env.adapter.updateRecord = function() { return { - type: 'user', - id: '1', - tag: { type: 'tag', id: '1' } + data: { + type: 'user', + id: '1', + relationships: { + tag: { + data: { + id: '1', + type: 'tag' + } + } + } + } }; }; @@ -308,10 +317,10 @@ test('When finding a hasMany relationship the inverse belongsTo relationship is env.adapter.findMany = function(store, type, ids, snapshots) { assert.equal(snapshots[0].belongsTo('person').id, '1'); - return [ - { id: 5, description: "fifth" }, - { id: 2, description: "second" } - ]; + return { data: [ + { id: 5, type: 'occupation', attributes: { description: "fifth" } }, + { id: 2, type: 'occupation', attributes: { description: "second" } } + ]}; }; env.adapter.coalesceFindRequests = true; @@ -369,7 +378,7 @@ test('When finding a belongsTo relationship the inverse belongsTo relationship i env.adapter.findRecord = function(store, type, id, snapshot) { assert.equal(snapshot.belongsTo('person').id, '1'); - return { id: 5, description: 'fifth' }; + return { data: { id: 5, type: 'occupation', attributes: { description: 'fifth' } } }; }; run(() => { diff --git a/tests/unit/model/relationships/has-many-test.js b/tests/unit/model/relationships/has-many-test.js index 3fc39968926..b9f3d391d5a 100644 --- a/tests/unit/model/relationships/has-many-test.js +++ b/tests/unit/model/relationships/has-many-test.js @@ -564,7 +564,7 @@ test('hasMany lazily loads async relationships', function(assert) { env.adapter.findRecord = function(store, type, id, snapshot) { if (type === Tag && id === '12') { - return { id: 12, name: 'oohlala' }; + return { data: { id: 12, type: 'tag', attributes: { name: 'oohlala' } } }; } else { assert.ok(false, 'findRecord() should not be called with these values'); } @@ -809,17 +809,28 @@ test('hasMany relationships work when the data hash has not been loaded', functi assert.equal(type, Tag, 'type should be Tag'); assert.deepEqual(ids, ['5', '2'], 'ids should be 5 and 2'); - return [ - { id: 5, name: 'friendly' }, - { id: 2, name: 'smarmy' } - ]; + return { data: [ + { id: 5, type: 'tag', attributes: { name: 'friendly' } }, + { id: 2, type: 'tag', attributes: { name: 'smarmy' } } + ]}; }; env.adapter.findRecord = function(store, type, id, snapshot) { assert.equal(type, Person, 'type should be Person'); assert.equal(id, 1, 'id should be 1'); - return { id: 1, name: 'Tom Dale', tags: [5, 2] }; + return { + data: { + id: 1, + type: 'person', + attributes: { name: 'Tom Dale' }, + relationships: { + tags: { + data: [{ id: 5, type: 'tag'}, { id: 2, type: 'tag'}] + } + } + } + }; }; return run(() => { @@ -1211,8 +1222,10 @@ testInDebug('checks if passed array only contains instances of DS.Model', functi env.adapter.findRecord = function() { return { - type: 'person', - id: 1 + data: { + type: 'person', + id: 1 + } }; }; diff --git a/tests/unit/store/adapter-interop-test.js b/tests/unit/store/adapter-interop-test.js index 0ad27eacc61..bd03ce621d8 100644 --- a/tests/unit/store/adapter-interop-test.js +++ b/tests/unit/store/adapter-interop-test.js @@ -60,7 +60,10 @@ test('Calling Store#find invokes its adapter#find', function(assert) { assert.equal(snapshot.id, '1', "Adapter#find was called with the record created from Store#find"); return Ember.RSVP.resolve({ - id: 1 + data: { + id: 1, + type: 'test' + } }); } }); @@ -85,7 +88,7 @@ test('Calling Store#findRecord multiple times coalesces the calls into a adapter findMany(store, type, ids, snapshots) { assert.ok(true, 'Adapter#findMany was called'); assert.deepEqual(ids, ['1','2'], 'Correct ids were passed in to findMany'); - return Ember.RSVP.resolve([{ id: 1 }, { id: 2 }]); + return Ember.RSVP.resolve({ data: [{ id: 1, type: 'test' }, { id: 2, type: 'test' }] }); }, coalesceFindRequests: true }); @@ -109,7 +112,7 @@ test('Returning a promise from `findRecord` asynchronously loads data', function const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { - return resolve({ id: 1, name: "Scumbag Dale" }); + return resolve({ data: { id: 1, type: 'test', attributes: { name: "Scumbag Dale" } } }); } }); @@ -135,7 +138,7 @@ test('IDs provided as numbers are coerced to strings', function(assert) { const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { assert.equal(typeof id, 'string', 'id has been normalized to a string'); - return resolve({ id, name: 'Scumbag Sylvain' }); + return resolve({ data: { id, type: 'test', attributes: { name: 'Scumbag Sylvain' } } }); } }); @@ -229,7 +232,7 @@ test('loadMany takes an optional Object and passes it on to the Adapter', functi query(store, type, query) { assert.equal(type, store.modelFor('person'), 'The type was Person'); assert.equal(query, passedQuery, 'The query was passed in'); - return Ember.RSVP.resolve([]); + return Ember.RSVP.resolve({ data: [] }); } }); @@ -410,7 +413,7 @@ test("initial values of attributes can be passed in as the third argument to fin const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { assert.equal(snapshot.attr('name'), 'Test', 'Preloaded attribtue set'); - return { id: '1', name: 'Test' }; + return { data: { id: '1', type: 'test', attributes: { name: 'Test' } } }; } }); @@ -432,7 +435,7 @@ test('initial values of belongsTo can be passed in as the third argument to find const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { assert.equal(snapshot.belongsTo('friend').attr('name'), 'Tom', 'Preloaded belongsTo set'); - return { id }; + return { data: { id, type: 'person' } }; } }); @@ -470,7 +473,7 @@ test('initial values of belongsTo can be passed in as the third argument to find const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { - return { id }; + return { data: { id, type: 'person' } }; } }); @@ -502,7 +505,7 @@ test('initial values of hasMany can be passed in as the third argument to find a const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { assert.equal(snapshot.hasMany('friends')[0].attr('name'), 'Tom', 'Preloaded hasMany set'); - return { id, type }; + return { data: { id, type: 'person' } }; } }); @@ -541,7 +544,7 @@ test('initial values of hasMany can be passed in as the third argument to find a const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { assert.equal(snapshot.hasMany('friends')[0].id, '2', 'Preloaded hasMany set'); - return { id }; + return { data: { id, type: 'person' } }; } }); @@ -571,8 +574,13 @@ test('records should have their ids updated when the adapter returns the id data const Adapter = TestAdapter.extend({ createRecord(store, type, snapshot) { return { - name: snapshot.attr('name'), - id: idCounter++ + data: { + id: idCounter++, + type: 'person', + attributes: { + name: snapshot.attr('name') + } + } }; } }); @@ -632,19 +640,19 @@ test('store._scheduleFetchMany should not resolve until all the records are reso const adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { - let record = { id: id }; + let record = { id, type: type.modelName }; return new Ember.RSVP.Promise(resolve => { - run.later(() => resolve(record), 5); + run.later(() => resolve({ data: record }), 5); }); }, findMany(store, type, ids, snapshots) { - let records = ids.map(id => ( { id }) ); + let records = ids.map(id => ( { id, type: type.modelName }) ); return new Ember.RSVP.Promise(resolve => { run.later(() => { - resolve(records); + resolve({data: records }); }, 15); }); } @@ -688,15 +696,15 @@ test('the store calls adapter.findMany according to groupings returned by adapte findRecord(store, type, id, snapshot) { assert.equal(id, '10', 'The first group is passed to find'); - return { id }; + return { data: { id, type: 'test' } }; }, findMany(store, type, ids, snapshots) { - let records = ids.map(id => ({ id })); + let records = ids.map(id => ({ id, type: 'test' })); assert.deepEqual(ids, ['20', '21'], 'The second group is passed to findMany'); - return records; + return { data: records }; } }); @@ -734,15 +742,15 @@ test('the promise returned by `_scheduleFetch`, when it resolves, does not depen }, findRecord(store, type, id, snapshot) { - let record = { id }; + let record = { id, type: 'test' }; return new Ember.RSVP.Promise(function(resolve, reject) { if (id === 'igor') { - resolve(record); + resolve({ data: record }); } else { run.later(function () { davidResolved = true; - resolve(record); + resolve({ data: record }); }, 5); } }); @@ -786,15 +794,15 @@ test('the promise returned by `_scheduleFetch`, when it rejects, does not depend }, findRecord(store, type, id, snapshot) { - let record = { id }; + let record = { id, type: 'test' }; return new Ember.RSVP.Promise((resolve, reject) => { if (id === 'igor') { - reject(record); + reject({ data: record }); } else { run.later(() => { davidResolved = true; - resolve(record); + resolve({ data: record }); }, 5); } }); @@ -830,8 +838,8 @@ testInDebug('store._fetchRecord reject records that were not found, even when th const Adapter = TestAdapter.extend({ findMany(store, type, ids, snapshots) { - let records = ids.map((id) => ({ id })); - return [records[0]]; + let records = ids.map((id) => ({ id, type: 'test' })); + return { data: [records[0]] }; } }); @@ -859,9 +867,9 @@ testInDebug('store._fetchRecord warns when records are missing', function(assert const Adapter = TestAdapter.extend({ findMany(store, type, ids, snapshots) { - let records = ids.map(id => ({ id })).filter(({ id }) => id === 'david'); + let records = ids.map(id => ({ id, type: 'test' })).filter(({ id }) => id === 'david'); - return [records[0]]; + return {data: [records[0]] }; } }); @@ -902,7 +910,7 @@ test('store should not call shouldReloadRecord when the record is not in the sto }, findRecord() { assert.ok(true, 'find is always called when the record is not in the store'); - return { id: 1 }; + return { data: { id: 1, type: 'person' } }; } }); @@ -965,7 +973,7 @@ test('store should reload record when shouldReloadRecord returns true', function }, findRecord() { assert.ok(true, 'find should not be called when shouldReloadRecord returns false'); - return { id: 1, name: 'Tom' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Tom' } } }; } }); @@ -1004,7 +1012,7 @@ test('store should not call shouldBackgroundReloadRecord when the store is alrea }, findRecord() { assert.ok(true, 'find should be called'); - return { id: 1, name: 'Tom' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Tom' } } }; } }); @@ -1041,7 +1049,7 @@ test('store should not reload a record when `shouldBackgroundReloadRecord` is fa }, findRecord() { assert.ok(false, 'find should not be called'); - return { id: 1, name: 'Tom' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Tom' } } }; } }); @@ -1079,7 +1087,7 @@ test('store should reload the record in the background when `shouldBackgroundRel }, findRecord() { assert.ok(true, 'find should not be called'); - return { id: 1, name: 'Tom' }; + return { data: { id: 1, type: 'person', attributes: { name: 'Tom' } } }; } }); @@ -1148,7 +1156,7 @@ test('store should reload all records when shouldReloadAll returns true', functi }, findAll() { assert.ok(true, 'findAll should be called when shouldReloadAll returns true'); - return [{ id: 1, name: 'Tom' }]; + return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }]}; } }); @@ -1180,7 +1188,7 @@ test('store should not call shouldBackgroundReloadAll when the store is already }, findAll() { assert.ok(true, 'find should be called'); - return [{ id: 1, name: 'Tom' }]; + return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }]}; } }); @@ -1214,7 +1222,7 @@ test('store should not reload all records when `shouldBackgroundReloadAll` is fa }, findAll() { assert.ok(false, 'findAll should not be called'); - return [{ id: 1, name: 'Tom' }]; + return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }] }; } }); @@ -1249,7 +1257,7 @@ test('store should reload all records in the background when `shouldBackgroundRe }, findAll() { assert.ok(true, 'find should not be called'); - return [{ id: 1, name: 'Tom' }]; + return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }] }; } }); diff --git a/tests/unit/store/finders-test.js b/tests/unit/store/finders-test.js index 54df12b39c3..b6d724d305d 100644 --- a/tests/unit/store/finders-test.js +++ b/tests/unit/store/finders-test.js @@ -53,7 +53,7 @@ test('findRecord does not load a serializer until the adapter promise resolves', assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve({ id: 1, name: 'John Churchill' }); + deferedFind.resolve({ data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } } }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -85,7 +85,7 @@ test('findMany does not load a serializer until the adapter promise resolves', f assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve([{ id: 1, name: 'John Churchill' }, { id: 2, name: 'Louis Joseph' }]); + deferedFind.resolve({ data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }, { id: 2, type: 'person', attributes: { name: 'Louis Joseph' } }] }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -137,7 +137,7 @@ test('findHasMany does not load a serializer until the adapter promise resolves' assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve([{ id: 1, name: 'Scooby' }, { id: 2, name: 'Scrappy' }]); + deferedFind.resolve({ data: [{ id: 1, type: 'dog', attributes: { name: 'Scooby' } }, { id: 2, type: 'dog', attributes: { name: 'Scrappy' } }] }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -189,7 +189,7 @@ test('findBelongsTo does not load a serializer until the adapter promise resolve assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve({ id: 1, name: 'Scooby' }); + deferedFind.resolve({ data: { id: 1, type: 'dog', attributes: { name: 'Scooby' } } }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -218,7 +218,7 @@ test('findAll does not load a serializer until the adapter promise resolves', fu assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve([{ id: 1, name: 'John Churchill' }]); + deferedFind.resolve({ data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }] }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -247,7 +247,7 @@ test('query does not load a serializer until the adapter promise resolves', func assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve([{ id: 1, name: 'John Churchill' }]); + deferedFind.resolve({ data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }] }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -276,7 +276,7 @@ test('queryRecord does not load a serializer until the adapter promise resolves' assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve({ id: 1, name: 'John Churchill' }); + deferedFind.resolve({ data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } } }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); diff --git a/tests/unit/store/push-test.js b/tests/unit/store/push-test.js index a3c51f88660..e884f3627c0 100644 --- a/tests/unit/store/push-test.js +++ b/tests/unit/store/push-test.js @@ -251,17 +251,31 @@ test('Calling push with a normalized hash containing IDs of related records retu env.adapter.findRecord = function(store, type, id) { if (id === '1') { return Ember.RSVP.resolve({ - id: 1, - number: '5551212', - person: 'wat' + data: { + id: 1, + type: 'phone-number', + attributes: { number: '5551212' }, + relationships: { + person: { + data: { id: 'wat', type: 'person' } + } + } + } }); } if (id === "2") { return Ember.RSVP.resolve({ - id: 2, - number: '5552121', - person: 'wat' + data: { + id: 2, + type: 'phone-number', + attributes: { number: '5552121' }, + relationships: { + person: { + data: { id: 'wat', type: 'person' } + } + } + } }); } }; @@ -269,9 +283,16 @@ test('Calling push with a normalized hash containing IDs of related records retu return run(() => { let person = store.push(store.normalize('person', { id: 'wat', - firstName: 'John', - lastName: 'Smith', - phoneNumbers: ["1", "2"] + type: 'person', + attributes: { + 'first-name': 'John', + 'last-name': 'Smith' + }, + relationships: { + 'phone-numbers': { + data: [{ id: 1, type: 'phone-number' }, { id: 2, type: 'phone-number' }] + } + } })); return person.get('phoneNumbers').then(phoneNumbers => { @@ -573,10 +594,13 @@ test('Calling push with a link containing an object', function(assert) { run(() => { store.push(store.normalize('person', { id: '1', - firstName: 'Tan', - links: { - phoneNumbers: { - href: '/api/people/1/phone-numbers' + type: 'person', + attributes: { + 'first-name': 'Tan' + }, + relationships: { + 'phone-numbers': { + links: { related: '/api/people/1/phone-numbers' } } } })); @@ -591,9 +615,16 @@ test('Calling push with a link containing the value null', function(assert) { run(() => { store.push(store.normalize('person', { id: '1', - firstName: 'Tan', - links: { - phoneNumbers: null + type: 'person', + attributes: { + 'first-name': 'Tan' + }, + relationships: { + 'phone-numbers': { + links: { + related: null + } + } } })); }); diff --git a/tests/unit/store/unload-test.js b/tests/unit/store/unload-test.js index 3e711eca777..94b22b5faed 100644 --- a/tests/unit/store/unload-test.js +++ b/tests/unit/store/unload-test.js @@ -27,7 +27,7 @@ module('unit/store/unload - Store unloading records', { adapter: DS.Adapter.extend({ findRecord(store, type, id, snapshot) { tryToFind = true; - return Ember.RSVP.resolve({ id: id, wasFetched: true }); + return Ember.RSVP.resolve({ data: { id, type: snapshot.modelName, attributes: { 'was-fetched': true } } }); } }), @@ -144,9 +144,14 @@ test('can commit store after unload record with relationships', function(assert) adapter: DS.Adapter.extend({ findRecord(store, type, id, snapshot) { return Ember.RSVP.resolve({ - id: 1, - description: 'cuisinart', - brand: 1 + data: { + id: 1, + type: snapshot.modelName, + attributes: { + description: 'cuisinart', + brand: 1 + } + } }); }, From da8598c82c52cd1a283946a83c514251714c4dff Mon Sep 17 00:00:00 2001 From: Lisa Backer Date: Mon, 5 Jun 2017 19:33:46 -0400 Subject: [PATCH 2/2] Update test per review feedback --- tests/integration/filter-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/filter-test.js b/tests/integration/filter-test.js index 07c36a637c6..9670af43167 100644 --- a/tests/integration/filter-test.js +++ b/tests/integration/filter-test.js @@ -558,7 +558,7 @@ test('it is possible to filter created records by dirtiness', function(assert) { data: { id: snapshot.id, type: model.modelName, - attributes: Ember.merge(Ember.merge({}, snapshot._attributes)) + attributes: snapshot._attributes } } },