diff --git a/packages/ember-data/lib/system/is-array-like.js b/packages/ember-data/lib/system/is-array-like.js new file mode 100644 index 00000000000..bb1ca7b2870 --- /dev/null +++ b/packages/ember-data/lib/system/is-array-like.js @@ -0,0 +1,20 @@ +/* + We're using this to detect arrays and "array-like" objects. + + This is a copy of the `isArray` method found in `ember-runtime/utils` as we're + currently unable to import non-exposed modules. + + This method was previously exposed as `Ember.isArray` but since + https://github.com/emberjs/ember.js/pull/11463 `Ember.isArray` is an alias of + `Array.isArray` hence removing the "array-like" part. + */ +export default function isArrayLike(obj) { + if (!obj || obj.setInterval) { return false; } + if (Array.isArray(obj)) { return true; } + if (Ember.Array.detect(obj)) { return true; } + + let type = Ember.typeOf(obj); + if ('array' === type) { return true; } + if ((obj.length !== undefined) && 'object' === type) { return true; } + return false; +} diff --git a/packages/ember-data/lib/system/relationships/has-many.js b/packages/ember-data/lib/system/relationships/has-many.js index 33b50315649..9321893d480 100644 --- a/packages/ember-data/lib/system/relationships/has-many.js +++ b/packages/ember-data/lib/system/relationships/has-many.js @@ -4,6 +4,7 @@ import Model from "ember-data/system/model"; import normalizeModelName from "ember-data/system/normalize-model-name"; +import isArrayLike from "ember-data/system/is-array-like"; /** `DS.hasMany` is used to define One-To-Many and Many-To-Many @@ -145,7 +146,7 @@ function hasMany(type, options) { set: function(key, records) { var relationship = this._internalModel._relationships.get(key); relationship.clear(); - Ember.assert("You must pass an array of records to set a hasMany relationship", Ember.isArray(records)); + Ember.assert("You must pass an array of records to set a hasMany relationship", isArrayLike(records)); relationship.addRecords(Ember.A(records).mapBy('_internalModel')); return relationship.getRecords(); } diff --git a/packages/ember-data/lib/system/store.js b/packages/ember-data/lib/system/store.js index afa41c6cef2..5c77608ba02 100644 --- a/packages/ember-data/lib/system/store.js +++ b/packages/ember-data/lib/system/store.js @@ -418,90 +418,36 @@ Store = Service.extend({ // ................ /** - This is the main entry point into finding records. The first parameter to - this method is the model's name as a string. - - --- - - To find a record by ID, pass the `id` as the second parameter: - - ```javascript - store.find('person', 1); - ``` - - The `find` method will always return a **promise** that will be resolved - with the record. If the record was already in the store, the promise will - be resolved immediately. Otherwise, the store will ask the adapter's `find` - method to find the necessary data. - - The `find` method will always resolve its promise with the same object for - a given type and `id`. - - --- - - You can optionally `preload` specific attributes and relationships that you know of - by passing them as the third argument to find. - - For example, if your Ember route looks like `/posts/1/comments/2` and your API route - for the comment also looks like `/posts/1/comments/2` if you want to fetch the comment - without fetching the post you can pass in the post to the `find` call: - - ```javascript - store.find('comment', 2, { preload: { post: 1 } }); - ``` - - If you have access to the post model you can also pass the model itself: - - ```javascript - store.find('post', 1).then(function (myPostModel) { - store.find('comment', 2, {post: myPostModel}); - }); - ``` - - This way, your adapter's `find` or `buildURL` method will be able to look up the - relationship on the record and construct the nested URL without having to first - fetch the post. - - --- - - To find all records for a type, call `findAll`: - - ```javascript - store.findAll('person'); - ``` - - This will ask the adapter's `findAll` method to find the records for the - given type, and return a promise that will be resolved once the server - returns the values. The promise will resolve into all records of this type - present in the store, even if the server only returns a subset of them. - @method find @param {String} modelName - @param {(Object|String|Integer|null)} id + @param {String|Integer} id @param {Object} options @return {Promise} promise + @private */ find: function(modelName, id, options) { - Ember.assert("You need to pass a type to the store's find method", arguments.length >= 1); - Ember.assert("You may not pass `" + id + "` as id to the store's find method", arguments.length === 1 || !Ember.isNone(id)); - Ember.assert('Passing classes to store methods has been removed. Please pass a dasherized string instead of '+ Ember.inspect(modelName), typeof modelName === 'string'); + // The default `model` hook in Ember.Route calls `find(modelName, id)`, + // that's why we have to keep this method around even though `findRecord` is + // the public way to get a record by modelName and id. if (arguments.length === 1) { Ember.assert('Using store.find(type) has been removed. Use store.findAll(type) to retrieve all records for a given type.'); } - // We are passed a query instead of an id. if (Ember.typeOf(id) === 'object') { Ember.assert('Calling store.find() with a query object is no longer supported. Use store.query() instead.'); } if (options) { - Ember.assert('Calling store.find(type, id, preload) with a preload object is no longer supported. Use store.findRecord(type, id, { preload: preload }) instead.'); + Ember.assert('Calling store.find(type, id, { preload: preload }) is no longer supported. Use store.findRecord(type, id, { preload: preload }) instead.'); } - return this.findRecord(modelName, coerceId(id), options); - }, + Ember.assert("You need to pass the model name and id to the store's find method", arguments.length === 2); + Ember.assert("You cannot pass `" + Ember.inspect(id) + "` as id to the store's find method", Ember.typeOf(id) === 'string' || Ember.typeOf(id) === 'number'); + Ember.assert('Passing classes to store methods has been removed. Please pass a dasherized string instead of '+ Ember.inspect(modelName), typeof modelName === 'string'); + return this.findRecord(modelName, id); + }, /** This method returns a record for a given type and id combination. @@ -1275,19 +1221,6 @@ Store = Service.extend({ return this.hasRecordForId(modelName, id); }, - /** - This method returns the metadata for a specific type. - - @method metadataFor - @param {String} modelName - @return {object} - @deprecated - */ - metadataFor: function(modelName) { - Ember.deprecate("`store.metadataFor()` has been deprecated. You can use `.get('meta')` on relationships and arrays returned from `store.query()`."); - return this._metadataFor(modelName); - }, - /** @method _metadataFor @param {String} modelName @@ -1300,20 +1233,6 @@ Store = Service.extend({ return this.typeMapFor(typeClass).metadata; }, - /** - This method sets the metadata for a specific type. - - @method setMetadataFor - @param {String} modelName - @param {Object} metadata metadata to set - @return {object} - @deprecated - */ - setMetadataFor: function(modelName, metadata) { - Ember.deprecate("`store.setMetadataFor()` has been deprecated. Please return meta from your serializer's `extractMeta` hook."); - this._setMetadataFor(modelName, metadata); - }, - /** @method _setMetadataFor @param {String} modelName @@ -1587,25 +1506,6 @@ Store = Service.extend({ } factory.modelName = factory.modelName || normalizeModelName(modelName); - // deprecate typeKey - if (!('typeKey' in factory)) { - Object.defineProperty(factory, 'typeKey', { - enumerable: true, - configurable: false, - get: function() { - Ember.deprecate('Usage of `typeKey` has been deprecated and will be removed in Ember Data 1.0. It has been replaced by `modelName` on the model class.'); - var typeKey = this.modelName; - if (typeKey) { - typeKey = Ember.String.camelize(this.modelName); - } - return typeKey; - }, - set: function() { - Ember.assert('Setting typeKey is not supported. In addition, typeKey has also been deprecated in favor of modelName. Setting modelName is also not supported.'); - } - }); - } - return factory; }, @@ -1679,24 +1579,12 @@ Store = Service.extend({ records, as well as to update existing records. @method push - @param {String} modelName @param {Object} data @return {DS.Model|Array} the record(s) that was created or updated. */ - push: function(modelNameArg, dataArg) { - var data, modelName; - - if (Ember.typeOf(modelNameArg) === 'object' && Ember.typeOf(dataArg) === 'undefined') { - data = modelNameArg; - } else { - Ember.deprecate('store.push(type, data) has been deprecated. Please provide a JSON-API document object as the first and only argument to store.push.'); - Ember.assert("Expected an object as `data` in a call to `push` for " + modelNameArg + " , but was " + Ember.typeOf(dataArg), Ember.typeOf(dataArg) === 'object'); - Ember.assert("You must include an `id` for " + modelNameArg + " in an object passed to `push`", dataArg.id != null && dataArg.id !== ''); - data = _normalizeSerializerPayload(this.modelFor(modelNameArg), dataArg); - modelName = modelNameArg; - Ember.assert('Passing classes to store methods has been removed. Please pass a dasherized string instead of '+ Ember.inspect(modelName), typeof modelName === 'string' || typeof data === 'undefined'); - } + push: function(data) { + Ember.assert("Expected an object as `data` in a call to `push` but was " + Ember.typeOf(data), Ember.typeOf(data) === 'object'); if (data.included) { data.included.forEach((recordData) => this._pushInternalModel(recordData)); @@ -1862,55 +1750,6 @@ Store = Service.extend({ return serializer.normalize(model, payload); }, - /** - @method update - @param {String} modelName - @param {Object} data - @return {DS.Model} the record that was updated. - @deprecated Use [push](#method_push) instead - */ - update: function(modelName, data) { - Ember.assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${Ember.inspect(modelName)}`, typeof modelName === 'string'); - Ember.deprecate('Using store.update() has been deprecated since store.push() now handles partial updates. You should use store.push() instead.'); - return this.push(modelName, data); - }, - - /** - If you have an Array of normalized data to push, - you can call `pushMany` with the Array, and it will - call `push` repeatedly for you. - - @method pushMany - @param {String} modelName - @param {Array} datas - @return {Array} - @deprecated Use [push](#method_push) instead - */ - pushMany: function(modelName, datas) { - Ember.assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${Ember.inspect(modelName)}`, typeof modelName === 'string'); - Ember.deprecate('Using store.pushMany() has been deprecated since store.push() now handles multiple items. You should use store.push() instead.'); - var length = datas.length; - var result = new Array(length); - - for (var i = 0; i < length; i++) { - result[i] = this.push(modelName, datas[i]); - } - - return result; - }, - - /** - @method metaForType - @param {String} modelName - @param {Object} metadata - @deprecated Use [setMetadataFor](#method_setMetadataFor) instead - */ - metaForType: function(modelName, metadata) { - Ember.assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${Ember.inspect(modelName)}`, typeof modelName === 'string'); - Ember.deprecate('Using store.metaForType() has been deprecated. Use store.setMetadataFor() to set metadata for a specific type.'); - this.setMetadataFor(modelName, metadata); - }, - /** Build a brand new record for a given type, ID, and initial data. @@ -1953,17 +1792,6 @@ Store = Service.extend({ // . DESTRUCTION . // ............... - /** - @method dematerializeRecord - @private - @param {DS.Model} record - @deprecated Use [unloadRecord](#method_unloadRecord) instead - */ - dematerializeRecord: function(record) { - Ember.deprecate('Using store.dematerializeRecord() has been deprecated since it was intended for private use only. You should use store.unloadRecord() instead.'); - this._dematerializeRecord(record); - }, - /** When a record is destroyed, this un-indexes it and removes it from any record arrays so it can be GCed. diff --git a/packages/ember-data/tests/integration/adapter/build-url-mixin-test.js b/packages/ember-data/tests/integration/adapter/build-url-mixin-test.js index 6795e7450ea..63851a77619 100644 --- a/packages/ember-data/tests/integration/adapter/build-url-mixin-test.js +++ b/packages/ember-data/tests/integration/adapter/build-url-mixin-test.js @@ -174,7 +174,12 @@ test('buildURL - buildURL takes a record from find', function() { var post; run(function() { - post = store.push('post', { id: 2 }); + post = store.push({ + data: { + type: 'post', + id: '2' + } + }); }); run(function() { @@ -200,7 +205,21 @@ test('buildURL - buildURL takes the records from findMany', function() { var post; run(function() { - post = store.push('post', { id: 2, comments: [1,2,3] }); + post = store.push({ + data: { + type: 'post', + id: '2', + relationships: { + comments: { + data: [ + { id: '1', type: 'comment' }, + { id: '2', type: 'comment' }, + { id: '3', type: 'comment' } + ] + } + } + } + }); post.get('comments').then(async(function(post) { equal(passedUrl, "/posts/2/comments/"); })); @@ -216,7 +235,12 @@ test('buildURL - buildURL takes a record from create', function() { ajaxResponse({ comments: [{ id: 1 }] }); run(function() { - var post = store.push('post', { id: 2 }); + var post = store.push({ + data: { + type: 'post', + id: '2' + } + }); var comment = store.createRecord('comment'); comment.set('post', post); comment.save().then(async(function(post) { @@ -260,8 +284,18 @@ test('buildURL - buildURL takes a record from update', function() { var post, comment; run(function() { - post = store.push('post', { id: 2 }); - comment = store.push('comment', { id: 1 }); + post = store.push({ + data: { + type: 'post', + id: '2' + } + }); + comment = store.push({ + data: { + type: 'comment', + id: '1' + } + }); comment.set('post', post); }); run(function() { @@ -282,8 +316,18 @@ test('buildURL - buildURL takes a record from delete', function() { var post, comment; run(function() { - post = store.push('post', { id: 2 }); - comment = store.push('comment', { id: 1 }); + post = store.push({ + data: { + type: 'post', + id: '2' + } + }); + comment = store.push({ + data: { + type: 'comment', + id: '1' + } + }); comment.set('post', post); comment.deleteRecord(); diff --git a/packages/ember-data/tests/integration/adapter/find-all-test.js b/packages/ember-data/tests/integration/adapter/find-all-test.js index 958b11860f1..2357c776b9a 100644 --- a/packages/ember-data/tests/integration/adapter/find-all-test.js +++ b/packages/ember-data/tests/integration/adapter/find-all-test.js @@ -98,7 +98,15 @@ test("When all records for a type are requested, records that are already loaded run(function() { // Load a record from the server - store.push('person', { id: 1, name: "Jeremy Ashkenas" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Jeremy Ashkenas' + } + } + }); // Create a new, unsaved record in the store store.createRecord('person', { name: "Alex MacCaw" }); }); diff --git a/packages/ember-data/tests/integration/adapter/find-test.js b/packages/ember-data/tests/integration/adapter/find-test.js index ab5b937e889..dd22aa9b330 100644 --- a/packages/ember-data/tests/integration/adapter/find-test.js +++ b/packages/ember-data/tests/integration/adapter/find-test.js @@ -21,20 +21,14 @@ module("integration/adapter/find - Finding Records", { } }); -test("It raises an assertion when no type is passed", function() { - expectAssertion(function() { - store.find(); - }, "You need to pass a type to the store's find method"); -}); - test("It raises an assertion when `undefined` is passed as id (#1705)", function() { expectAssertion(function() { store.find('person', undefined); - }, "You may not pass `undefined` as id to the store's find method"); + }, "You cannot pass `undefined` as id to the store's find method"); expectAssertion(function() { store.find('person', null); - }, "You may not pass `null` as id to the store's find method"); + }, "You cannot pass `null` as id to the store's find method"); }); test("store.findAll should trigger a deprecation warning about store.shouldReloadAll", function() { diff --git a/packages/ember-data/tests/integration/adapter/record-persistence-test.js b/packages/ember-data/tests/integration/adapter/record-persistence-test.js index d9a18ce30cf..1d73cb06dd4 100644 --- a/packages/ember-data/tests/integration/adapter/record-persistence-test.js +++ b/packages/ember-data/tests/integration/adapter/record-persistence-test.js @@ -45,7 +45,15 @@ test("When a store is committed, the adapter's `commit` method should be called }; run(function() { - env.store.push('person', { id: 1, name: "Braaaahm Dale" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale' + } + } + }); }); var tom; @@ -101,7 +109,15 @@ test("when a store is committed, the adapter's `commit` method should be called var tom; run(function() { - env.store.push('person', { id: 1, name: "Tom Dale" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tom Dale" + } + } + }); }); env.store.find('person', 1).then(async(function(person) { tom = person; @@ -122,8 +138,15 @@ test("An adapter can notify the store that records were updated by calling `didS }; run(function() { - env.store.push('person', { id: 1 }); - env.store.push('person', { id: 2 }); + env.store.push({ + data: [{ + type: 'person', + id: '1' + }, { + type: 'person', + id: '2' + }] + }); }); all([env.store.find('person', 1), env.store.find('person', 2)]) @@ -157,8 +180,21 @@ test("An adapter can notify the store that records were updated and provide new }; run(function() { - env.store.push('person', { id: 1, name: "Braaaahm Dale" }); - env.store.push('person', { id: 2, name: "Gentile Katz" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Gentile Katz' + } + }] + }); }); hash({ tom: env.store.find('person', 1), yehuda: env.store.find('person', 2) }).then(async(function(people) { @@ -180,8 +216,15 @@ test("An adapter can notify the store that a record was updated by calling `didS }; run(function() { - store.push('person', { id: 1 }); - store.push('person', { id: 2 }); + store.push({ + data: [{ + type: 'person', + id: '1' + }, { + type: 'person', + id: '2' + }] + }); }); hash({ tom: store.find('person', 1), yehuda: store.find('person', 2) }).then(async(function(people) { @@ -208,8 +251,21 @@ test("An adapter can notify the store that a record was updated and provide new }; run(function() { - env.store.push('person', { id: 1, name: "Braaaahm Dale" }); - env.store.push('person', { id: 2, name: "Gentile Katz" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Gentile Katz' + } + }] + }); }); hash({ tom: store.find('person', 1), yehuda: store.find('person', 2) }).then(async(function(people) { @@ -232,8 +288,21 @@ test("An adapter can notify the store that records were deleted by calling `didS }; run(function() { - env.store.push('person', { id: 1, name: "Braaaahm Dale" }); - env.store.push('person', { id: 2, name: "Gentile Katz" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Gentile Katz' + } + }] + }); }); hash({ tom: store.find('person', 1), yehuda: store.find('person', 2) }).then(async(function(people) { diff --git a/packages/ember-data/tests/integration/adapter/rest-adapter-test.js b/packages/ember-data/tests/integration/adapter/rest-adapter-test.js index 30b46b6df77..01064e2ca33 100644 --- a/packages/ember-data/tests/integration/adapter/rest-adapter-test.js +++ b/packages/ember-data/tests/integration/adapter/rest-adapter-test.js @@ -244,7 +244,20 @@ test("create - findMany doesn't overwrite owner", function() { Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); run(function() { - store.push('post', { id: 1, name: "Rails is omakase", comments: [] }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + data: [] + } + } + } + }); }); var post = store.peekRecord('post', 1); @@ -409,8 +422,36 @@ test("create - a record on the many side of a hasMany relationship should update Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); run(function() { - store.push('post', { id: 1, name: "Rails is omakase", comments: [1] }); - store.push('comment', { id: 1, name: "Dat Parlay Letter", post: 1 }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' } + ] + } + } + } + }); + store.push({ + data: { + type: 'comment', + id: '1', + attributes: { + name: "Dat Parlay Letter" + }, + relationships: { + post: { + data: { type: 'post', id: '1' } + } + } + } + }); }); var post = store.peekRecord('post', 1); @@ -524,7 +565,15 @@ test("create - relationships are not duplicated", function() { test("update - an empty payload is a basic success", function() { run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -548,7 +597,15 @@ test("update - passes the requestType to buildURL", function() { }; run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -563,7 +620,15 @@ test("update - passes the requestType to buildURL", function() { test("update - a payload with updates applies the updates", function() { run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -583,7 +648,15 @@ test("update - a payload with updates applies the updates", function() { test("update - a payload with updates applies the updates (with legacy singular name)", function() { run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -626,7 +699,15 @@ test("update - a payload with sideloaded updates pushes the updates", function() test("update - a payload with sideloaded updates pushes the updates", function() { run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -660,7 +741,13 @@ test("update - a serializer's primary key and attributes are consulted when buil })); run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + name: "Rails is omakase" + } + }); }); ajaxResponse(); @@ -677,9 +764,35 @@ test("update - hasMany relationships faithfully reflect simultaneous adds and re Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); run(function() { - store.push('post', { id: 1, name: "Not everyone uses Rails", comments: [1] }); - store.push('comment', { id: 1, name: "Rails is omakase" }); - store.push('comment', { id: 2, name: "Yes. Yes it is." }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Not everyone uses Rails" + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' } + ] + } + } + }, + included: [{ + type: 'comment', + id: '1', + attributes: { + name: "Rails is omakase" + } + }, { + type: 'comment', + id: '2', + attributes: { + name: "Yes. Yes it is." + } + }] + }); }); ajaxResponse({ @@ -705,7 +818,15 @@ test("update - hasMany relationships faithfully reflect simultaneous adds and re test("delete - an empty payload is a basic success", function() { run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -729,7 +850,15 @@ test("delete - passes the requestType to buildURL", function() { }; run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -744,7 +873,15 @@ test("delete - passes the requestType to buildURL", function() { test("delete - a payload with sideloaded updates pushes the updates", function() { run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -767,7 +904,15 @@ test("delete - a payload with sideloaded updates pushes the updates", function() test("delete - a payload with sidloaded updates pushes the updates when the original record is omitted", function() { run(function() { - store.push('post', { id: 1, name: "Rails is omakase" }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -916,40 +1061,6 @@ test("findAll - data is normalized through custom serializers", function() { })); }); -test("findAll - since token is passed to the adapter", function() { - ajaxResponse({ - meta: { since: 'later' }, - posts: [ - { id: 1, name: "Rails is omakase" }, - { id: 2, name: "The Parley Letter" } - ] - }); - - store.setMetadataFor('post', { since: 'now' }); - - store.findAll('post').then(async(function(posts) { - equal(passedUrl, '/posts'); - equal(passedVerb, 'GET'); - equal(store.typeMapFor(Post).metadata.since, 'later'); - deepEqual(passedHash.data, { since: 'now' }); - })); -}); - -test("metadata is accessible", function() { - ajaxResponse({ - meta: { offset: 5 }, - posts: [{ id: 1, name: "Rails is very expensive sushi" }] - }); - - store.findAll('post').then(async(function(posts) { - equal( - store.metadataFor('post').offset, - 5, - "Metadata can be accessed with metadataFor." - ); - })); -}); - test("findQuery - if `sortQueryParams` option is not provided, query params are sorted alphabetically", function() { adapter.ajax = function(url, verb, hash) { passedUrl = url; @@ -1160,7 +1271,24 @@ test("findMany - findMany uses a correct URL to access the records", function() adapter.coalesceFindRequests = true; run(function() { - store.push('post', { id: 1, name: "Rails is omakase", comments: [1, 2, 3] }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); }); var post = store.peekRecord('post', 1); @@ -1186,7 +1314,24 @@ test("findMany - passes buildURL the requestType", function() { adapter.coalesceFindRequests = true; run(function() { - store.push('post', { id: 1, name: "Rails is omakase", comments: [1, 2, 3] }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); }); var post = store.peekRecord('post', 1); @@ -1206,7 +1351,24 @@ test("findMany - findMany does not coalesce by default", function() { Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); run(function() { - store.push('post', { id: 1, name: "Rails is omakase", comments: [1, 2, 3] }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); }); var post = store.peekRecord('post', 1); @@ -1229,7 +1391,24 @@ test("findMany - returning an array populates the array", function() { adapter.coalesceFindRequests = true; run(function() { - store.push('post', { id: 1, name: "Rails is omakase", comments: [1, 2, 3] }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -1264,7 +1443,24 @@ test("findMany - returning sideloaded data loads the data", function() { adapter.coalesceFindRequests = true; run(function() { - store.push('post', { id: 1, name: "Rails is omakase", comments: [1, 2, 3] }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -1312,7 +1508,24 @@ test("findMany - a custom serializer is used if present", function() { Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); run(function() { - store.push('post', { id: 1, name: "Rails is omakase", comments: [1, 2, 3] }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); }); store.find('post', 1).then(async(function(post) { @@ -1341,14 +1554,22 @@ test("findHasMany - returning an array populates the array", function() { Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); run(function() { - store.push( - 'post', - { - id: 1, - name: "Rails is omakase", - links: { comments: '/posts/1/comments' } + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + links: { + related: '/posts/1/comments' + } + } + } } - ); + }); }); run(store, 'find', 'post', '1').then(async(function(post) { @@ -1386,14 +1607,22 @@ test("findHasMany - passes buildURL the requestType", function() { Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); run(function() { - store.push( - 'post', - { - id: 1, - name: "Rails is omakase", - links: { comments: '/posts/1/comments' } + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + links: { + related: '/posts/1/comments' + } + } + } } - ); + }); }); run(store, 'find', 'post', '1').then(async(function(post) { @@ -1418,14 +1647,22 @@ test("findMany - returning sideloaded data loads the data", function() { adapter.coalesceFindRequests = true; run(function() { - store.push( - 'post', - { - id: 1, - name: "Rails is omakase", - links: { comments: '/posts/1/comments' } + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + links: { + related: '/posts/1/comments' + } + } + } } - ); + }); }); store.find('post', 1).then(async(function(post) { @@ -1465,14 +1702,22 @@ test("findMany - a custom serializer is used if present", function() { Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); run(function() { - store.push( - 'post', - { - id: 1, - name: "Rails is omakase", - links: { comments: '/posts/1/comments' } + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + name: "Rails is omakase" + }, + relationships: { + comments: { + links: { + related: '/posts/1/comments' + } + } + } } - ); + }); }); store.find('post', 1).then(async(function(post) { @@ -1505,9 +1750,21 @@ test('findBelongsTo - passes buildURL the requestType', function() { Comment.reopen({ post: DS.belongsTo('post', { async: true }) }); run(function() { - store.push('comment', { - id: 1, name: "FIRST", - links: { post: '/posts/1' } + store.push({ + data: { + type: 'comment', + id: '1', + attributes: { + name: "FIRST" + }, + relationships: { + post: { + links: { + related: '/posts/1' + } + } + } + } }); }); @@ -1530,7 +1787,23 @@ test('coalesceFindRequests warns if the expected records are not returned in the warns(function() { run(function() { - post = store.push('post', { id: 2, comments: [1,2,3] }); + store.push({ + data: { + type: 'post', + id: '2', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); + + post = store.peekRecord('post', 2); post.get('comments'); }); }, /expected to find records with the following ids in the adapter response but they were missing: \[2,3\]/); @@ -1561,7 +1834,22 @@ test('groupRecordsForFindMany groups records based on their url', function() { var post; run(function() { - post = store.push('post', { id: 2, comments: [1,2,3] }); + store.push({ + data: { + type: 'post', + id: '2', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); + post = store.peekRecord('post', 2); }); run(function() { @@ -1594,7 +1882,22 @@ test('groupRecordsForFindMany groups records correctly when singular URLs are en var post; run(function() { - post = store.push('post', { id: 2, comments: [1,2,3] }); + store.push({ + data: { + type: 'post', + id: '2', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); + post = store.peekRecord('post', 2); }); run(function() { @@ -1684,7 +1987,21 @@ test('groupRecordsForFindMany splits up calls for large ids', function() { var b2000 = repeatChar('b', 2000); var post; run(function() { - post = store.push('post', { id: 1, comments: [a2000, b2000] }); + store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: a2000 }, + { type: 'comment', id: b2000 } + ] + } + } + } + }); + post = store.peekRecord('post', 1); }); adapter.coalesceFindRequests = true; @@ -1722,7 +2039,21 @@ test('groupRecordsForFindMany groups calls for small ids', function() { var post; run(function() { - post = store.push('post', { id: 1, comments: [a100, b100] }); + store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: a100 }, + { type: 'comment', id: b100 } + ] + } + } + } + }); + post = store.peekRecord('post', 1); }); adapter.coalesceFindRequests = true; diff --git a/packages/ember-data/tests/integration/adapter/store-adapter-test.js b/packages/ember-data/tests/integration/adapter/store-adapter-test.js index b8dd302eedb..2de35c23a9b 100644 --- a/packages/ember-data/tests/integration/adapter/store-adapter-test.js +++ b/packages/ember-data/tests/integration/adapter/store-adapter-test.js @@ -134,8 +134,21 @@ test("by default, updateRecords calls updateRecord once per record", function() }; run(function() { - store.push('person', { id: 1, name: "Braaaahm Dale" }); - store.push('person', { id: 2, name: "Brohuda Katz" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Brohuda Katz' + } + }] + }); }); var promise = run(function() { @@ -184,8 +197,21 @@ test("calling store.didSaveRecord can provide an optional hash", function() { }; run(function() { - store.push('person', { id: 1, name: "Braaaahm Dale" }); - store.push('person', { id: 2, name: "Brohuda Katz" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Brohuda Katz' + } + }] + }); }); var promise = run(function() { @@ -236,8 +262,21 @@ test("by default, deleteRecord calls deleteRecord once per record", function() { }; run(function() { - store.push('person', { id: 1, name: "Tom Dale" }); - store.push('person', { id: 2, name: "Yehuda Katz" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Yehuda Katz' + } + }] + }); }); var promise = run(function() { @@ -281,8 +320,21 @@ test("by default, destroyRecord calls deleteRecord once per record without requi }; run(function() { - store.push('person', { id: 1, name: "Tom Dale" }); - store.push('person', { id: 2, name: "Yehuda Katz" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Yehuda Katz' + } + }] + }); }); var promise = run(function() { @@ -320,7 +372,15 @@ test("if an existing model is edited then deleted, deleteRecord is called on the // Load data for a record into the store. run(function() { - store.push('person', { id: 'deleted-record', name: "Tom Dale" }); + env.store.push({ + data: { + type: 'person', + id: 'deleted-record', + attributes: { + name: 'Tom Dale' + } + } + }); }); // Retrieve that loaded record and edit it so it becomes dirty @@ -350,7 +410,15 @@ test("if a deleted record errors, it enters the error state", function() { }; run(function() { - store.push('person', { id: 'deleted-record', name: "Tom Dale" }); + env.store.push({ + data: { + type: 'person', + id: 'deleted-record', + attributes: { + name: 'Tom Dale' + } + } + }); }); var tom; @@ -531,7 +599,16 @@ test("if an updated record is marked as invalid by the server, it enters an erro }; var yehuda = run(function() { - return store.push('person', { id: 1, name: "Brohuda Brokatz" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Brohuda Brokatz' + } + } + }); + return store.peekRecord('person', 1); }); Ember.run(function() { @@ -575,7 +652,16 @@ test("records can have errors on arbitrary properties after update", function() }; var yehuda = run(function() { - return store.push('person', { id: 1, name: "Brohuda Brokatz" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Brohuda Brokatz' + } + } + }); + return store.peekRecord('person', 1); }); run(function() { @@ -627,7 +713,16 @@ test("if an updated record is marked as invalid by the server, you can attempt t }; var yehuda = run(function() { - return store.push('person', { id: 1, name: "Brohuda Brokatz" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Brohuda Brokatz' + } + } + }); + return store.peekRecord('person', 1); }); Ember.run(function() { @@ -672,7 +767,16 @@ test("if a updated record is marked as erred by the server, it enters an error s }; var person = run(function() { - return store.push('person', { id: 1, name: "John Doe" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'John Doe' + } + } + }); + return store.peekRecord('person', 1); }); run(store, 'findRecord', 'person', 1).then(async(function(record) { @@ -727,7 +831,15 @@ test("relationships returned via `commit` do not trigger additional findManys", }); run(function() { - store.push('dog', { id: 1, name: "Scruffy" }); + env.store.push({ + data: { + type: 'dog', + id: '1', + attributes: { + name: 'Scruffy' + } + } + }); }); adapter.findRecord = function(store, type, id, snapshot) { @@ -736,8 +848,31 @@ test("relationships returned via `commit` do not trigger additional findManys", adapter.updateRecord = function(store, type, snapshot) { return new Ember.RSVP.Promise(function(resolve, reject) { - store.push('person', { id: 1, name: "Tom Dale", dogs: [1, 2] }); - store.push('dog', { id: 2, name: "Scruffles" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + dogs: { + data: [ + { type: 'dog', id: '1' }, + { type: 'dog', id: '2' } + ] + } + } + }, + included: [{ + type: 'dog', + id: '2', + attributes: { + name: 'Scruffles' + } + }] + }); + resolve({ id: 1, name: "Scruffy" }); }); }; @@ -772,7 +907,22 @@ test("relationships don't get reset if the links is the same", function() { }; run(function() { - store.push('person', { id: 1, name: "Tom Dale", links: { dogs: "/dogs" } }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + dogs: { + links: { + related: '/dogs' + } + } + } + } + }); }); var tom, dogs; @@ -783,7 +933,22 @@ test("relationships don't get reset if the links is the same", function() { return dogs; })).then(async(function(dogs) { equal(dogs.get('length'), 1, "The dogs are loaded"); - store.push('person', { id: 1, name: "Tom Dale", links: { dogs: "/dogs" } }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + dogs: { + links: { + related: '/dogs' + } + } + } + } + }); ok(tom.get('dogs') instanceof DS.PromiseArray, 'dogs is a promise'); return tom.get('dogs'); })).then(async(function(dogs) { @@ -844,7 +1009,16 @@ test("updateRecord receives a snapshot", function() { var person; run(function() { - person = store.push('person', { id: 1, name: "Tom Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + } + } + }); + person = store.peekRecord('person', 1); }); run(function() { @@ -864,7 +1038,16 @@ test("deleteRecord receives a snapshot", function() { var person; run(function() { - person = store.push('person', { id: 1, name: "Tom Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + } + } + }); + person = store.peekRecord('person', 1); }); run(function() { @@ -903,7 +1086,21 @@ test("findMany receives an array of snapshots", function() { var person; run(function() { - person = store.push('person', { id: 1, dogs: [2, 3] }); + store.push({ + data: { + type: 'person', + id: '1', + relationships: { + dogs: { + data: [ + { type: 'dog', id: '2' }, + { type: 'dog', id: '3' } + ] + } + } + } + }); + person = store.peekRecord('person', 1); }); run(function() { @@ -926,7 +1123,20 @@ test("findHasMany receives a snapshot", function() { var person; run(function() { - person = store.push('person', { id: 1, links: { dogs: 'dogs' } }); + store.push({ + data: { + type: 'person', + id: '1', + relationships: { + dogs: { + links: { + related: 'dogs' + } + } + } + } + }); + person = store.peekRecord('person', 1); }); run(function() { @@ -949,7 +1159,20 @@ test("findBelongsTo receives a snapshot", function() { var person; run(function() { - person = store.push('person', { id: 1, links: { dog: 'dog' } }); + store.push({ + data: { + type: 'person', + id: '1', + relationships: { + dog: { + links: { + related: 'dog' + } + } + } + } + }); + person = store.peekRecord('person', 1); }); run(function() { @@ -966,7 +1189,16 @@ test("record.save should pass adapterOptions to the updateRecord method", functi }); run(function() { - var person = store.push('person', { id: 1, name: 'Tom' }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom' + } + } + }); + var person = store.peekRecord('person', 1); person.save({ adapterOptions: { subscribe: true } }); }); }); @@ -994,7 +1226,16 @@ test("record.save should pass adapterOptions to the deleteRecord method", functi }); run(function() { - var person = store.push('person', { id: 1, name: 'Tom' }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom' + } + } + }); + var person = store.peekRecord('person', 1); person.destroyRecord({ adapterOptions: { subscribe: true } }); }); }); diff --git a/packages/ember-data/tests/integration/backwards-compat/deprecate-type-key-test.js b/packages/ember-data/tests/integration/backwards-compat/deprecate-type-key-test.js deleted file mode 100644 index 9341f9a5b00..00000000000 --- a/packages/ember-data/tests/integration/backwards-compat/deprecate-type-key-test.js +++ /dev/null @@ -1,26 +0,0 @@ -var Post, env; -module('integration/backwards-compat/deprecate-type-key', { - setup: function() { - env = setupStore({ - post: DS.Model.extend() - }); - Post = env.store.modelFor('post'); - }, - - teardown: function() { - } -}); - -if (Ember.platform.hasPropertyAccessors) { - test('typeKey is deprecated', function() { - expectDeprecation(function() { - return Post.typeKey; - }); - }); - - test('setting typeKey is not allowed', function() { - throws(function() { - Post.typeKey = 'hello'; - }); - }); -} diff --git a/packages/ember-data/tests/integration/debug-adapter-test.js b/packages/ember-data/tests/integration/debug-adapter-test.js index cab62ac8fd1..19801b3f6fa 100644 --- a/packages/ember-data/tests/integration/debug-adapter-test.js +++ b/packages/ember-data/tests/integration/debug-adapter-test.js @@ -54,7 +54,15 @@ test("Watching Model Types", function() { debugAdapter.watchModelTypes(added, updated); run(function() { - store.push('post', { id: 1, title: 'Post Title' }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Post Title' + } + } + }); }); }); @@ -62,7 +70,15 @@ test("Watching Records", function() { var post, record, addedRecords, updatedRecords, removedIndex, removedCount; Ember.run(function() { - store.push('post', { id: '1', title: 'Clean Post' }); + store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Clean Post' + } + } + }); }); var recordsAdded = function(wrappedRecords) { diff --git a/packages/ember-data/tests/integration/inverse-test.js b/packages/ember-data/tests/integration/inverse-test.js index 2de77e8b38d..9a08dd476b4 100644 --- a/packages/ember-data/tests/integration/inverse-test.js +++ b/packages/ember-data/tests/integration/inverse-test.js @@ -50,9 +50,6 @@ module('integration/inverse_test - inverseFor', { }); test("Finds the inverse when there is only one possible available", function () { - //Maybe store is evaluated lazily, so we need this :( - run(store, 'push', 'user', { id: 1 }); - deepEqual(Job.inverseFor('user', store), { type: User, name: 'job', @@ -69,13 +66,6 @@ test("Finds the inverse when only one side has defined it manually", function () previousJob: belongsTo('job', { async: false }) }); - //Maybe store is evaluated lazily, so we need this :( - var user, job; - run(function() { - user = store.push('user', { id: 1 }); - job = store.push('user', { id: 1 }); - }); - deepEqual(Job.inverseFor('owner', store), { type: User, //the model's type name: 'previousJob', //the models relationship key @@ -97,11 +87,6 @@ test("Returns null if inverse relationship it is manually set with a different r User.reopen({ job: belongsTo('job', { async: false }) }); - //Maybe store is evaluated lazily, so we need this :( - var user; - run(function() { - user = store.push('user', { id: 1 }); - }); equal(User.inverseFor('job', store), null, 'There is no inverse'); }); @@ -116,11 +101,7 @@ test("Errors out if you define 2 inverses to the same model", function () { job: belongsTo('job', { async: false }) }); - //Maybe store is evaluated lazily, so we need this :( expectAssertion(function() { - run(function() { - store.push('user', { id: 1 }); - }); User.inverseFor('job', store); }, "You defined the 'job' relationship on user, but you defined the inverse relationships of type job multiple times. Look at http://emberjs.com/guides/models/defining-models/#toc_explicit-inverses for how to explicitly specify inverses"); }); @@ -128,10 +109,6 @@ test("Errors out if you define 2 inverses to the same model", function () { test("Caches findInverseFor return value", function () { expect(1); - //Maybe store is evaluated lazily, so we need this :( - run(function() { - store.push('user', { id: 1 }); - }); var inverseForUser = Job.inverseFor('user', store); Job.findInverseFor = function() { @@ -147,7 +124,13 @@ test("Errors out if you do not define an inverse for a reflexive relationship", warns(function() { var reflexiveModel; run(function() { - reflexiveModel = store.push('reflexive-model', { id: 1 }); + store.push({ + data: { + type: 'reflexive-model', + id: '1' + } + }); + reflexiveModel = store.peekRecord('reflexive-model', 1); reflexiveModel.get('reflexiveProp'); }); }, /Detected a reflexive relationship by the name of 'reflexiveProp'/); diff --git a/packages/ember-data/tests/integration/peek-all-test.js b/packages/ember-data/tests/integration/peek-all-test.js index b19cebb993b..996e61d1bc8 100644 --- a/packages/ember-data/tests/integration/peek-all-test.js +++ b/packages/ember-data/tests/integration/peek-all-test.js @@ -5,8 +5,31 @@ var Person, store, array, moreArray; module("integration/peek-all - DS.Store#peekAll()", { setup: function() { - array = [{ id: 1, name: "Scumbag Dale" }, { id: 2, name: "Scumbag Katz" }]; - moreArray = [{ id: 3, name: "Scumbag Bryn" }]; + array = { + data: [{ + type: 'person', + id: '1', + attributes: { + name: "Scumbag Dale" + } + }, { + type: 'person', + id: '2', + attributes: { + name: "Scumbag Katz" + } + }] + }; + moreArray = { + data: [{ + type: 'person', + id: '3', + attributes: { + name: "Scumbag Bryn" + } + }] + }; + Person = DS.Model.extend({ name: DS.attr('string') }); store = createStore({ person: Person }); @@ -20,14 +43,14 @@ module("integration/peek-all - DS.Store#peekAll()", { test("store.peekAll('person') should return all records and should update with new ones", function() { run(function() { - store.pushMany('person', array); + store.push(array); }); var all = store.peekAll('person'); equal(get(all, 'length'), 2); run(function() { - store.pushMany('person', moreArray); + store.push(moreArray); }); equal(get(all, 'length'), 3); @@ -40,7 +63,15 @@ test("Calling store.peekAll() multiple times should update immediately inside th equal(get(store.peekAll('person'), 'length'), 0, 'should initially be empty'); store.createRecord('person', { name: "Tomster" }); equal(get(store.peekAll('person'), 'length'), 1, 'should contain one person'); - store.push('person', { id: 1, name: "Tomster's friend" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tomster's friend" + } + } + }); equal(get(store.peekAll('person'), 'length'), 2, 'should contain two people'); }); }); diff --git a/packages/ember-data/tests/integration/record-array-manager-test.js b/packages/ember-data/tests/integration/record-array-manager-test.js index 2ecfe42fce9..d7674f4775f 100644 --- a/packages/ember-data/tests/integration/record-array-manager-test.js +++ b/packages/ember-data/tests/integration/record-array-manager-test.js @@ -54,20 +54,41 @@ test("destroying the store correctly cleans everything up", function() { var person; run(function() { - store.push('car', { - id: 1, - make: 'BMC', - model: 'Mini Cooper', - person: 1 + store.push({ + data: { + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini Cooper' + }, + relationships: { + person: { + data: { type: 'person', id: '1' } + } + } + } }); }); run(function() { - person = store.push('person', { - id: 1, - name: 'Tom Dale', - cars: [1] + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + cars: { + data: [ + { type: 'car', id: '1' } + ] + } + } + } }); + person = store.peekRecord('person', 1); }); var filterd = manager.createFilteredRecordArray(Person, function() { return true; }); @@ -114,12 +135,22 @@ test("Should not filter a store.peekAll() array when a record property is change store.peekAll('car'); run(function() { - car = store.push('car', { - id: 1, - make: 'BMC', - model: 'Mini Cooper', - person: 1 + store.push({ + data: { + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini Cooper' + }, + relationships: { + person: { + data: { type: 'person', id: '1' } + } + } + } }); + car = store.peekRecord('car', 1); }); equal(populateLiveRecordArray.called.length, 1); diff --git a/packages/ember-data/tests/integration/records/delete-record-test.js b/packages/ember-data/tests/integration/records/delete-record-test.js index 41773a35836..7a7930ac8b7 100644 --- a/packages/ember-data/tests/integration/records/delete-record-test.js +++ b/packages/ember-data/tests/integration/records/delete-record-test.js @@ -31,8 +31,23 @@ test("records should not be removed from record arrays just after deleting, but var all; run(function() { - adam = env.store.push('person', { id: 1, name: "Adam Sunderland" }); - dave = env.store.push('person', { id: 2, name: "Dave Sunderland" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Adam Sunderland' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Dave Sunderland' + } + }] + }); + adam = env.store.peekRecord('person', 1); + dave = env.store.peekRecord('person', 2); all = env.store.peekAll('person'); }); @@ -57,8 +72,23 @@ test("records can be deleted during record array enumeration", function () { }; run(function() { - adam = env.store.push('person', { id: 1, name: "Adam Sunderland" }); - dave = env.store.push('person', { id: 2, name: "Dave Sunderland" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Adam Sunderland' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Dave Sunderland' + } + }] + }); + adam = env.store.peekRecord('person', 1); + dave = env.store.peekRecord('person', 2); }); var all = env.store.peekAll('person'); @@ -78,8 +108,23 @@ test("records can be deleted during record array enumeration", function () { test("when deleted records are rolled back, they are still in their previous record arrays", function () { var jaime, cersei; run(function() { - jaime = env.store.push('person', { id: 1, name: "Jaime Lannister" }); - cersei = env.store.push('person', { id: 2, name: "Cersei Lannister" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Jaime Lannister' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Cersei Lannister' + } + }] + }); + jaime = env.store.peekRecord('person', 1); + cersei = env.store.peekRecord('person', 2); }); var all = env.store.peekAll('person'); var filtered; diff --git a/packages/ember-data/tests/integration/records/property-changes-test.js b/packages/ember-data/tests/integration/records/property-changes-test.js index 228f1ae3fdf..f3789725be0 100644 --- a/packages/ember-data/tests/integration/records/property-changes-test.js +++ b/packages/ember-data/tests/integration/records/property-changes-test.js @@ -28,11 +28,17 @@ test('Calling push with partial records trigger observers for just those attribu var person; run(function() { - person = store.push('person', { - id: 'wat', - firstName: 'Yehuda', - lastName: 'Katz' + store.push({ + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz' + } + } }); + person = store.peekRecord('person', 'wat'); }); person.addObserver('firstName', function() { @@ -44,10 +50,15 @@ test('Calling push with partial records trigger observers for just those attribu }); run(function() { - store.push('person', { - id: 'wat', - firstName: 'Yehuda', - lastName: 'Katz!' + store.push({ + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz!' + } + } }); }); }); @@ -57,12 +68,17 @@ test('Calling push does not trigger observers for locally changed attributes wit var person; run(function() { - person = store.push('person', { - id: 'wat', - firstName: 'Yehuda', - lastName: 'Katz' + store.push({ + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz' + } + } }); - + person = store.peekRecord('person', 'wat'); person.set('lastName', 'Katz!'); }); @@ -75,10 +91,15 @@ test('Calling push does not trigger observers for locally changed attributes wit }); run(function() { - store.push('person', { - id: 'wat', - firstName: 'Yehuda', - lastName: 'Katz!' + store.push({ + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz!' + } + } }); }); }); @@ -92,12 +113,17 @@ test('Saving a record trigger observers for locally changed attributes with the }; run(function() { - person = store.push('person', { - id: 'wat', - firstName: 'Yehuda', - lastName: 'Katz' + store.push({ + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz' + } + } }); - + person = store.peekRecord('person', 'wat'); person.set('lastName', 'Katz!'); }); @@ -119,12 +145,17 @@ test('store.push should not override a modified attribute', function() { var person; run(function() { - person = store.push('person', { - id: 'wat', - firstName: 'Yehuda', - lastName: 'Katz' + store.push({ + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz' + } + } }); - + person = store.peekRecord('person', 'wat'); person.set('lastName', 'Katz!'); }); @@ -137,10 +168,15 @@ test('store.push should not override a modified attribute', function() { }); run(function() { - person = store.push('person', { - id: 'wat', - firstName: 'Tom', - lastName: 'Dale' + store.push({ + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Tom', + lastName: 'Dale' + } + } }); }); }); diff --git a/packages/ember-data/tests/integration/records/reload-test.js b/packages/ember-data/tests/integration/records/reload-test.js index a4600eed35a..48cc21dd6c7 100644 --- a/packages/ember-data/tests/integration/records/reload-test.js +++ b/packages/ember-data/tests/integration/records/reload-test.js @@ -54,7 +54,16 @@ test("When a single record is requested, the adapter's find method should be cal test("When a record is reloaded and fails, it can try again", function() { var tom; run(function() { - tom = env.store.push('person', { id: 1, name: "Tom Dale" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + } + } + }); + tom = env.store.peekRecord('person', 1); }); var count = 0; @@ -83,7 +92,15 @@ test("When a record is reloaded and fails, it can try again", function() { test("When a record is loaded a second time, isLoaded stays true", function() { run(function() { - env.store.push('person', { id: 1, name: "Tom Dale" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + } + } + }); }); run(function() { @@ -92,7 +109,16 @@ test("When a record is loaded a second time, isLoaded stays true", function() { person.addObserver('isLoaded', isLoadedDidChange); // Reload the record - env.store.push('person', { id: 1, name: "Tom Dale" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + } + } + }); + equal(get(person, 'isLoaded'), true, "The person is still loaded after load"); person.removeObserver('isLoaded', isLoadedDidChange); diff --git a/packages/ember-data/tests/integration/records/unload-test.js b/packages/ember-data/tests/integration/records/unload-test.js index b0df2e60b45..b72c3df5b65 100644 --- a/packages/ember-data/tests/integration/records/unload-test.js +++ b/packages/ember-data/tests/integration/records/unload-test.js @@ -44,7 +44,16 @@ module("integration/unload - Unloading Records", { test("can unload a single record", function () { var adam; run(function() { - adam = env.store.push('person', { id: 1, name: "Adam Sunderland" }); + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Adam Sunderland' + } + } + }); + adam = env.store.peekRecord('person', 1); }); Ember.run(function() { @@ -59,15 +68,40 @@ test("can unload all records for a given type", function () { var adam, bob, dudu; run(function() { - adam = env.store.push('person', { id: 1, name: "Adam Sunderland" }); - bob = env.store.push('person', { id: 2, name: "Bob Bobson" }); - - dudu = env.store.push('car', { - id: 1, - make: "VW", - model: "Beetle", - person: 1 + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Adam Sunderland' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Bob Bobson' + } + }] + }); + adam = env.store.peekRecord('person', 1); + bob = env.store.peekRecord('person', 2); + + env.store.push({ + data: { + type: 'car', + id: '1', + attributes: { + make: "VW", + model: "Beetle" + }, + relationships: { + person: { + data: { type: 'person', id: '1' } + } + } + } }); + dudu = bob = env.store.peekRecord('car', 1); }); Ember.run(function() { @@ -83,15 +117,40 @@ test("can unload all records", function () { var adam, bob, dudu; run(function() { - adam = env.store.push('person', { id: 1, name: "Adam Sunderland" }); - bob = env.store.push('person', { id: 2, name: "Bob Bobson" }); - - dudu = env.store.push('car', { - id: 1, - make: "VW", - model: "Beetle", - person: 1 + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Adam Sunderland' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Bob Bobson' + } + }] + }); + adam = env.store.peekRecord('person', 1); + bob = env.store.peekRecord('person', 2); + + env.store.push({ + data: { + type: 'car', + id: '1', + attributes: { + make: "VW", + model: "Beetle" + }, + relationships: { + person: { + data: { type: 'person', id: '1' } + } + } + } }); + dudu = bob = env.store.peekRecord('car', 1); }); Ember.run(function() { @@ -102,29 +161,26 @@ test("can unload all records", function () { equal(env.store.peekAll('car').get('length'), 0); }); -test("Unloading all records for a given type clears saved meta data.", function () { - - function metadataKeys(type) { - return Object.keys(env.store.metadataFor(type)); - } - - run(function() { - env.store.setMetadataFor('person', { count: 10 }); - }); - - Ember.run(function() { - env.store.unloadAll('person'); - }); - - deepEqual(metadataKeys('person'), [], 'Metadata for person is empty'); - -}); - test("removes findAllCache after unloading all records", function () { var adam, bob; run(function() { - adam = env.store.push('person', { id: 1, name: "Adam Sunderland" }); - bob = env.store.push('person', { id: 2, name: "Bob Bobson" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Adam Sunderland' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Bob Bobson' + } + }] + }); + adam = env.store.peekRecord('person', 1); + bob = env.store.peekRecord('person', 2); }); Ember.run(function() { @@ -138,8 +194,23 @@ test("removes findAllCache after unloading all records", function () { test("unloading all records also updates record array from peekAll()", function() { var adam, bob; run(function() { - adam = env.store.push('person', { id: 1, name: "Adam Sunderland" }); - bob = env.store.push('person', { id: 2, name: "Bob Bobson" }); + env.store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Adam Sunderland' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Bob Bobson' + } + }] + }); + adam = env.store.peekRecord('person', 1); + bob = env.store.peekRecord('person', 2); }); var all = env.store.peekAll('person'); @@ -156,20 +227,42 @@ test("unloading all records also updates record array from peekAll()", function( test("unloading a record also clears its relationship", function() { var adam, bob; run(function() { - adam = env.store.push('person', { - id: 1, - name: "Adam Sunderland", - cars: [1] + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Adam Sunderland' + }, + relationships: { + cars: { + data: [ + { type: 'car', id: '1' } + ] + } + } + } }); + adam = env.store.peekRecord('person', 1); }); run(function() { - bob = env.store.push('car', { - id: 1, - make: "Lotus", - model: "Exige", - person: 1 + env.store.push({ + data: { + type: 'car', + id: '1', + attributes: { + make: "Lotus", + model: "Exige" + }, + relationships: { + person: { + data: { type: 'person', id: '1' } + } + } + } }); + bob = env.store.peekRecord('car', 1); }); run(function() { @@ -188,17 +281,33 @@ test("unloading a record also clears its relationship", function() { test("unloading a record also clears the implicit inverse relationships", function() { var adam, bob; run(function() { - adam = env.store.push('person', { - id: 1, - name: "Adam Sunderland" + env.store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Adam Sunderland' + } + } }); + adam = env.store.peekRecord('person', 1); }); run(function() { - bob = env.store.push('group', { - id: 1, - people: [1] + env.store.push({ + data: { + type: 'group', + id: '1', + relationships: { + people: { + data: [ + { type: 'person', id: '1' } + ] + } + } + } }); + bob = env.store.peekRecord('group', 1); }); run(function() { diff --git a/packages/ember-data/tests/integration/relationships/has-many-test.js b/packages/ember-data/tests/integration/relationships/has-many-test.js index dcc22763f76..37ddc6e69f1 100644 --- a/packages/ember-data/tests/integration/relationships/has-many-test.js +++ b/packages/ember-data/tests/integration/relationships/has-many-test.js @@ -97,8 +97,23 @@ test("When a hasMany relationship is accessed, the adapter's findMany method sho }; run(function() { - env.store.push('post', { id: 1, comments: [1] }); - env.store.push('comment', { id: 1 }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' } + ] + } + } + }, + included: [{ + type: 'comment', + id: '1' + }] + }); env.store.findRecord('post', 1).then(function(post) { return post.get('comments'); }); @@ -119,7 +134,21 @@ test("adapter.findMany only gets unique IDs even if duplicate IDs are present in }; run(function() { - env.store.push('book', { id: 1, chapters: [2, 3, 3] }); + env.store.push({ + data: { + type: 'book', + id: '1', + relationships: { + chapters: { + data: [ + { type: 'chapter', id: '2' }, + { type: 'chapter', id: '3' }, + { type: 'chapter', id: '3' } + ] + } + } + } + }); env.store.findRecord('book', 1).then(function(book) { return book.get('chapters'); }); @@ -182,7 +211,20 @@ test("Accessing a hasMany backed by a link multiple times triggers only one requ var post; run(function() { - post = env.store.push('post', { id: 1, links: { comments: '/posts/1/comments' } }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + links: { + related: '/posts/1/comments' + } + } + } + } + }); + post = env.store.peekRecord('post', 1); }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { @@ -206,7 +248,17 @@ test("Accessing a hasMany backed by a link multiple times triggers only one requ run(function() { promise1 = post.get('comments'); //Invalidate the post.comments CP - env.store.push('comment', { id: 1, message: 1 }); + env.store.push({ + data: { + type: 'comment', + id: '1', + relationships: { + message: { + data: { type: 'post', id: '1' } + } + } + } + }); promise2 = post.get('comments'); }); Ember.RSVP.all([promise1, promise2]).then(function() { @@ -233,12 +285,35 @@ test("A hasMany backed by a link remains a promise after a record has been added }; var post; run(function() { - post = env.store.push('post', { id: 1, links: { comments: '/posts/1/comments' } }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + links: { + related: '/posts/1/comments' + } + } + } + } + }); + post = env.store.peekRecord('post', 1); }); run(function() { post.get('comments').then(function() { - env.store.push('comment', { id: 3, message: 1 }); + env.store.push({ + data: { + type: 'comment', + id: '3', + relationships: { + message: { + data: { type: 'post', id: '1' } + } + } + } + }); post.get('comments').then(function() { ok(true, 'Promise was called'); }); @@ -389,7 +464,21 @@ test("A sync hasMany relationship can be reloaded if it was fetched via ids", fu }; run(function() { - env.store.pushMany('comment', [{ id: 1, body: "First" }, { id: 2, body: "Second" }]); + env.store.push({ + data: [{ + type: 'comment', + id: '1', + attributes: { + body: 'First' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'Second' + } + }] + }); env.store.findRecord('post', '1').then(function(post) { var comments = post.get('comments'); @@ -496,7 +585,20 @@ test("PromiseArray proxies createRecord to its ManyArray once the hasMany is loa var post; run(function() { - post = env.store.push('post', { id: 1, links: { comments: 'someLink' } }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + links: { + related: 'someLink' + } + } + } + } + }); + post = env.store.peekRecord('post', 1); }); run(function() { @@ -527,7 +629,20 @@ test("PromiseArray proxies evented methods to its ManyArray", function() { var post, comments; run(function() { - post = env.store.push('post', { id: 1, links: { comments: 'someLink' } }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + links: { + related: 'someLink' + } + } + } + } + }); + post = env.store.peekRecord('post', 1); comments = post.get('comments'); }); @@ -588,7 +703,20 @@ test("An updated `links` value should invalidate a relationship cache", function var post; run(function() { - post = env.store.push('post', { id: 1, links: { comments: '/first' } }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + links: { + related: '/first' + } + } + } + } + }); + post = env.store.peekRecord('post', 1); }); run(function() { @@ -596,7 +724,19 @@ test("An updated `links` value should invalidate a relationship cache", function equal(comments.get('isLoaded'), true, "comments are loaded"); equal(comments.get('length'), 2, "comments have 2 length"); equal(comments.objectAt(0).get('body'), 'First', "comment 1 successfully loaded"); - env.store.push('post', { id: 1, links: { comments: '/second' } }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + links: { + related: '/second' + } + } + } + } + }); post.get('comments').then(function(newComments) { equal(comments, newComments, "hasMany array was kept the same"); equal(newComments.get('length'), 3, "comments updated successfully"); @@ -614,9 +754,27 @@ test("When a polymorphic hasMany relationship is accessed, the adapter's findMan }; run(function() { - env.store.push('user', { id: 1, messages: [{ id: 1, type: 'post' }, { id: 3, type: 'comment' }] }); - env.store.push('post', { id: 1 }); - env.store.push('comment', { id: 3 }); + env.store.push({ + data: { + type: 'user', + id: '1', + relationships: { + messages: { + data: [ + { type: 'post', id: '1' }, + { type: 'comment', id: '3' } + ] + } + } + }, + included: [{ + type: 'post', + id: '1' + }, { + type: 'comment', + id: '3' + }] + }); }); run(function() { @@ -641,7 +799,20 @@ test("When a polymorphic hasMany relationship is accessed, the store can call mu }; run(function() { - env.store.push('user', { id: 1, messages: [{ id: 1, type: 'post' }, { id: 3, type: 'comment' }] }); + env.store.push({ + data: { + type: 'user', + id: '1', + relationships: { + messages: { + data: [ + { type: 'post', id: '1' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); }); run(function() { @@ -678,8 +849,23 @@ test("polymorphic hasMany type-checks check the superclass when MODEL_FACTORY_IN test("Type can be inferred from the key of a hasMany relationship", function() { expect(1); run(function() { - env.store.push('user', { id: 1, contacts: [1] }); - env.store.push('contact', { id: 1 }); + env.store.push({ + data: { + type: 'user', + id: '1', + relationships: { + contacts: { + data: [ + { type: 'contact', id: '1' } + ] + } + } + }, + included: [{ + type: 'contact', + id: '1' + }] + }); }); run(function() { env.store.findRecord('user', 1).then(function(user) { @@ -697,8 +883,23 @@ test("Type can be inferred from the key of an async hasMany relationship", funct expect(1); run(function() { - env.store.push('user', { id: 1, contacts: [1] }); - env.store.push('contact', { id: 1 }); + env.store.push({ + data: { + type: 'user', + id: '1', + relationships: { + contacts: { + data: [ + { type: 'contact', id: '1' } + ] + } + } + }, + included: [{ + type: 'contact', + id: '1' + }] + }); }); run(function() { env.store.findRecord('user', 1).then(function(user) { @@ -716,9 +917,27 @@ test("Polymorphic relationships work with a hasMany whose type is inferred", fun expect(1); run(function() { - env.store.push('user', { id: 1, contacts: [{ id: 1, type: 'email' }, { id: 2, type: 'phone' }] }); - env.store.push('email', { id: 1 }); - env.store.push('phone', { id: 2 }); + env.store.push({ + data: { + type: 'user', + id: '1', + relationships: { + contacts: { + data: [ + { type: 'email', id: '1' }, + { type: 'phone', id: '2' } + ] + } + } + }, + included: [{ + type: 'email', + id: '1' + }, { + type: 'phone', + id: '2' + }] + }); }); run(function() { env.store.findRecord('user', 1).then(function(user) { @@ -754,7 +973,17 @@ test("Polymorphic relationships with a hasMany is set up correctly on both sides test("A record can't be created from a polymorphic hasMany relationship", function() { run(function() { - env.store.push('user', { id: 1, messages: [] }); + env.store.push({ + data: { + type: 'user', + id: '1', + relationships: { + messages: { + data: [] + } + } + } + }); }); run(function() { @@ -771,8 +1000,20 @@ test("A record can't be created from a polymorphic hasMany relationship", functi test("Only records of the same type can be added to a monomorphic hasMany relationship", function() { expect(1); run(function() { - env.store.push('post', { id: 1, comments: [] }); - env.store.push('post', { id: 2 }); + env.store.push({ + data: [{ + type: 'post', + id: '1', + relationships: { + comments: { + data: [] + } + } + }, { + type: 'post', + id: '2' + }] + }); }); run(function() { @@ -790,10 +1031,37 @@ test("Only records of the same type can be added to a monomorphic hasMany relati test("Only records of the same base type can be added to a polymorphic hasMany relationship", function() { expect(2); run(function() { - env.store.push('user', { id: 1, messages: [] }); - env.store.push('user', { id: 2, messages: [] }); - env.store.push('post', { id: 1, comments: [] }); - env.store.push('comment', { id: 3 }); + env.store.push({ + data: [{ + type: 'user', + id: '1', + relationships: { + messages: { + data: [] + } + } + }, { + type: 'user', + id: '2', + relationships: { + messages: { + data: [] + } + } + }], + included: [{ + type: 'post', + id: '1', + relationships: { + comments: { + data: [] + } + } + }, { + type: 'comment', + id: '3' + }] + }); }); var asyncRecords; @@ -824,8 +1092,23 @@ test("A record can be removed from a polymorphic association", function() { expect(4); run(function() { - env.store.push('user', { id: 1 , messages: [{ id: 3, type: 'comment' }] }); - env.store.push('comment', { id: 3 }); + env.store.push({ + data: { + type: 'user', + id: '1', + relationships: { + messages: { + data: [ + { type: 'comment', id: '3' } + ] + } + } + }, + included: [{ + type: 'comment', + id: '3' + }] + }); }); var asyncRecords; @@ -898,7 +1181,22 @@ test("we can set records SYNC HM relationship", function() { return env.store.createRecord('post'); }); run(function() { - post.set('comments', env.store.pushMany('comment', [{ id: 1, body: "First" }, { id: 2, body: "Second" }])); + env.store.push({ + data: [{ + type: 'comment', + id: '1', + attributes: { + body: 'First' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'Second' + } + }] + }); + post.set('comments', env.store.peekAll('comment')); }); equal(get(post, 'comments.length'), 2, "we can set HM relationship"); }); @@ -914,7 +1212,22 @@ test("We can set records ASYNC HM relationship", function() { return env.store.createRecord('post'); }); run(function() { - post.set('comments', env.store.pushMany('comment', [{ id: 1, body: "First" }, { id: 2, body: "Second" }])); + env.store.push({ + data: [{ + type: 'comment', + id: '1', + attributes: { + body: 'First' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'Second' + } + }] + }); + post.set('comments', env.store.peekAll('comment')); }); post.get('comments').then(async(function(comments) { @@ -958,8 +1271,32 @@ test("dual non-async HM <-> BT", function() { var post, firstComment; run(function() { - post = env.store.push('post', { id: 1, comments: [1] }); - firstComment = env.store.push('comment', { id: 1, post: 1 }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' } + ] + } + } + } + }); + env.store.push({ + data: { + type: 'comment', + id: '1', + relationships: { + comments: { + post: { type: 'post', id: '1' } + } + } + } + }); + post = env.store.peekRecord('post', 1); + firstComment = env.store.peekRecord('comment', 1); env.store.createRecord('comment', { post: post @@ -992,14 +1329,42 @@ test("When an unloaded record is added to the hasMany, it gets fetched once the var post; run(function() { - post = env.store.push('post', { id: 1, comments: [1, 2] }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' } + ] + } + } + } + }); + post = env.store.peekRecord('post', 1); }); run(function() { post.get('comments').then(async(function(fetchedComments) { equal(fetchedComments.get('length'), 2, 'comments fetched successfully'); equal(fetchedComments.objectAt(0).get('body'), 'first', 'first comment loaded successfully'); - env.store.push('post', { id: 1, comments: [1, 2, 3] }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); post.get('comments').then(async(function(newlyFetchedComments) { equal(newlyFetchedComments.get('length'), 3, 'all three comments fetched successfully'); equal(newlyFetchedComments.objectAt(2).get('body'), 'third', 'third comment loaded successfully'); @@ -1011,7 +1376,21 @@ test("When an unloaded record is added to the hasMany, it gets fetched once the test("A sync hasMany errors out if there are unlaoded records in it", function() { var post; run(function() { - post = env.store.push('post', { id: 1, comments: [1, 2] }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' } + ] + } + } + } + }); + post = env.store.peekRecord('post', 1); }); expectAssertion(function() { @@ -1023,39 +1402,137 @@ test("If reordered hasMany data has been pushed to the store, the many array ref var comment1, comment2, comment3, comment4; var post; run(function() { - comment1 = env.store.push('comment', { id: 1 }); - comment2 = env.store.push('comment', { id: 2 }); - comment3 = env.store.push('comment', { id: 3 }); - comment4 = env.store.push('comment', { id: 4 }); + env.store.push({ + data: [{ + type: 'comment', + id: '1' + }, { + type: 'comment', + id: '2' + }, { + type: 'comment', + id: '3' + }, { + type: 'comment', + id: '4' + }] + }); + + comment1 = env.store.peekRecord('comment', 1); + comment2 = env.store.peekRecord('comment', 2); + comment3 = env.store.peekRecord('comment', 3); + comment4 = env.store.peekRecord('comment', 4); }); run(function() { - post = env.store.push('post', { id: 1, comments: [1, 2] }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' } + ] + } + } + } + }); + post = env.store.peekRecord('post', 1); }); deepEqual(post.get('comments').toArray(), [comment1, comment2], 'Initial ordering is correct'); run(function() { - env.store.push('post', { id: 1, comments: [2, 1] }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '2' }, + { type: 'comment', id: '1' } + ] + } + } + } + }); }); deepEqual(post.get('comments').toArray(), [comment2, comment1], 'Updated ordering is correct'); run(function() { - env.store.push('post', { id: 1, comments: [2] }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '2' } + ] + } + } + } + }); }); deepEqual(post.get('comments').toArray(), [comment2], 'Updated ordering is correct'); run(function() { - env.store.push('post', { id: 1, comments: [1,2,3,4] }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' }, + { type: 'comment', id: '4' } + ] + } + } + } + }); }); deepEqual(post.get('comments').toArray(), [comment1, comment2, comment3, comment4], 'Updated ordering is correct'); run(function() { - env.store.push('post', { id: 1, comments: [4,3] }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '4' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); }); deepEqual(post.get('comments').toArray(), [comment4, comment3], 'Updated ordering is correct'); run(function() { - env.store.push('post', { id: 1, comments: [4,2,3,1] }); + env.store.push({ + data: { + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '4' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' }, + { type: 'comment', id: '1' } + ] + } + } + } + }); }); deepEqual(post.get('comments').toArray(), [comment4, comment2, comment3, comment1], 'Updated ordering is correct'); }); @@ -1063,8 +1540,31 @@ test("If reordered hasMany data has been pushed to the store, the many array ref test("Rollbacking attributes for deleted record restores implicit relationship correctly when the hasMany side has been deleted - async", function () { var book, chapter; run(function() { - book = env.store.push('book', { id: 1, title: "Stanley's Amazing Adventures", chapters: [2] }); - chapter = env.store.push('chapter', { id: 2, title: 'Sailing the Seven Seas' }); + env.store.push({ + data: { + type: 'book', + id: '1', + attributes: { + title: "Stanley's Amazing Adventures" + }, + relationships: { + chapters: { + data: [ + { type: 'chapter', id: '2' } + ] + } + } + }, + included: [{ + type: 'chapter', + id: '2', + attributes: { + title: 'Sailing the Seven Seas' + } + }] + }); + book = env.store.peekRecord('book', 1); + chapter = env.store.peekRecord('chapter', 2); }); run(function() { chapter.deleteRecord(); @@ -1080,8 +1580,31 @@ test("Rollbacking attributes for deleted record restores implicit relationship c test("Rollbacking attributes for deleted record restores implicit relationship correctly when the hasMany side has been deleted - sync", function () { var book, chapter; run(function() { - book = env.store.push('book', { id: 1, title: "Stanley's Amazing Adventures", chapters: [2] }); - chapter = env.store.push('chapter', { id: 2, title: 'Sailing the Seven Seas' }); + env.store.push({ + data: { + type: 'book', + id: '1', + attributes: { + title: "Stanley's Amazing Adventures" + }, + relationships: { + chapters: { + data: [ + { type: 'chapter', id: '2' } + ] + } + } + }, + included: [{ + type: 'chapter', + id: '2', + attributes: { + title: 'Sailing the Seven Seas' + } + }] + }); + book = env.store.peekRecord('book', 1); + chapter = env.store.peekRecord('chapter', 2); }); run(function() { chapter.deleteRecord(); @@ -1098,8 +1621,29 @@ test("Rollbacking attributes for deleted record restores implicit relationship c }); var chapter, page; run(function() { - chapter = env.store.push('chapter', { id: 2, title: 'Sailing the Seven Seas' }); - page = env.store.push('page', { id: 3, number: 1, chapter: 2 }); + env.store.push({ + data: { + type: 'chapter', + id: '2', + attributes: { + title: 'Sailing the Seven Seas' + } + }, + included: [{ + type: 'page', + id: '3', + attributes: { + number: 1 + }, + relationships: { + chapter: { + data: { type: 'chapter', id: '2' } + } + } + }] + }); + chapter = env.store.peekRecord('chapter', 2); + page = env.store.peekRecord('page', 3); }); run(function() { chapter.deleteRecord(); @@ -1115,8 +1659,29 @@ test("Rollbacking attributes for deleted record restores implicit relationship c test("Rollbacking attributes for deleted record restores implicit relationship correctly when the belongsTo side has been deleted - sync", function () { var chapter, page; run(function() { - chapter = env.store.push('chapter', { id: 2, title: 'Sailing the Seven Seas' }); - page = env.store.push('page', { id: 3, number: 1, chapter: 2 }); + env.store.push({ + data: { + type: 'chapter', + id: '2', + attributes: { + title: 'Sailing the Seven Seas' + } + }, + included: [{ + type: 'page', + id: '3', + attributes: { + number: 1 + }, + relationships: { + chapter: { + data: { type: 'chapter', id: '2' } + } + } + }] + }); + chapter = env.store.peekRecord('chapter', 2); + page = env.store.peekRecord('page', 3); }); run(function() { chapter.deleteRecord(); @@ -1133,9 +1698,39 @@ test("ManyArray notifies the array observers and flushes bindings when removing" var observe = false; run(function() { - page = env.store.push('page', { id: 1, number: 1 }); - page2 = env.store.push('page', { id: 2, number: 2 }); - chapter = env.store.push('chapter', { id: 1, title: 'Sailing the Seven Seas', pages: [1, 2] }); + env.store.push({ + data: [{ + type: 'page', + id: '1', + attributes: { + number: 1 + } + }, { + type: 'page', + id: '2', + attributes: { + number: 2 + } + }, { + type: 'chapter', + id: '1', + attributes: { + title: 'Sailing the Seven Seas' + }, + relationships: { + pages: { + data: [ + { type: 'page', id: '1' }, + { type: 'page', id: '2' } + ] + } + } + }] + }); + page = env.store.peekRecord('page', 1); + page2 = env.store.peekRecord('page', 2); + chapter = env.store.peekRecord('chapter', 1); + chapter.get('pages').addEnumerableObserver(this, { willChange: function(pages, removing, addCount) { if (observe) { @@ -1162,9 +1757,38 @@ test("ManyArray notifies the array observers and flushes bindings when adding", var observe = false; run(function() { - page = env.store.push('page', { id: 1, number: 1 }); - page2 = env.store.push('page', { id: 2, number: 2 }); - chapter = env.store.push('chapter', { id: 1, title: 'Sailing the Seven Seas', pages: [1] }); + env.store.push({ + data: [{ + type: 'page', + id: '1', + attributes: { + number: 1 + } + }, { + type: 'page', + id: '2', + attributes: { + number: 2 + } + }, { + type: 'chapter', + id: '1', + attributes: { + title: 'Sailing the Seven Seas' + }, + relationships: { + pages: { + data: [ + { type: 'page', id: '1' } + ] + } + } + }] + }); + page = env.store.peekRecord('page', 1); + page2 = env.store.peekRecord('page', 2); + chapter = env.store.peekRecord('chapter', 1); + chapter.get('pages').addEnumerableObserver(this, { willChange: function(pages, removing, addCount) { if (observe) { @@ -1209,12 +1833,48 @@ test("Relationship.clear removes all records correctly", function() { }); run(function() { - post = env.store.push('post', { id: 2, title: 'Sailing the Seven Seas', comments: [1, 2] }); - env.store.pushMany('comment', [ - { id: 1, post: 2 }, - { id: 2, post: 2 }, - { id: 3, post: 2 } - ]); + env.store.push({ + data: [{ + type: 'post', + id: '2', + attributes: { + title: 'Sailing the Seven Seas' + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' } + ] + } + } + }, { + type: 'comment', + id: '1', + relationships: { + post: { + data: { type: 'post', id: '2' } + } + } + }, { + type: 'comment', + id: '2', + relationships: { + post: { + data: { type: 'post', id: '2' } + } + } + }, { + type: 'comment', + id: '3', + relationships: { + post: { + data: { type: 'post', id: '2' } + } + } + }] + }); + post = env.store.peekRecord('post', 2); }); run(function() { @@ -1238,11 +1898,40 @@ test('unloading a record with associated records does not prevent the store from }); run(function() { - post = env.store.push('post', { id: 2, title: 'Sailing the Seven Seas', comments: [1,2] }); - env.store.pushMany('comment', [ - { id: 1, post: 2 }, - { id: 2, post: 2 } - ]); + env.store.push({ + data: [{ + type: 'post', + id: '2', + attributes: { + title: 'Sailing the Seven Seas' + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' } + ] + } + } + }, { + type: 'comment', + id: '1', + relationships: { + post: { + data: { type: 'post', id: '2' } + } + } + }, { + type: 'comment', + id: '2', + relationships: { + post: { + data: { type: 'post', id: '2' } + } + } + }] + }); + post = env.store.peekRecord('post', 2); // This line triggers the original bug that gets manifested // in teardown for apps, e.g. store.destroy that is caused by @@ -1268,20 +1957,11 @@ test("adding and removing records from hasMany relationship #2666", function() { var Post = DS.Model.extend({ comments: DS.hasMany('comment', { async: true }) }); - var POST_FIXTURES = [ - { id: 1, comments: [1, 2, 3] } - ]; var Comment = DS.Model.extend({ post: DS.belongsTo('post', { async: false }) }); - var COMMENT_FIXTURES = [ - { id: 1 }, - { id: 2 }, - { id: 3 } - ]; - env = setupStore({ post: Post, comment: Comment, @@ -1301,8 +1981,30 @@ test("adding and removing records from hasMany relationship #2666", function() { })); run(function() { - env.store.pushMany('post', POST_FIXTURES); - env.store.pushMany('comment', COMMENT_FIXTURES); + env.store.push({ + data: [{ + type: 'post', + id: '1', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + }, { + type: 'comment', + id: '1' + }, { + type: 'comment', + id: '2' + }, { + type: 'comment', + id: '3' + }] + }); }); run(function() { @@ -1432,7 +2134,13 @@ test("hasMany hasData sync created", function () { test("Model's hasMany relationship should not be created during model creation", function () { var user; run(function () { - user = env.store.push('user', { id: 1 }); + env.store.push({ + data: { + type: 'user', + id: '1' + } + }); + user = env.store.peekRecord('user', 1); ok(!user._internalModel._relationships.has('messages'), 'Newly created record should not have relationships'); }); }); @@ -1454,11 +2162,30 @@ test("metadata is accessible when pushed as a meta property for a relationship", }; run(function() { - book = env.store.push('book', { id: 1, title: 'Sailing the Seven Seas', meta: { chapters: 'the lefkada sea' }, links: { chapters: '/chapters' } }); + env.store.push({ + data: { + type: 'book', + id: '1', + attributes: { + title: 'Sailing the Seven Seas' + }, + relationships: { + chapters: { + meta: { + where: 'the lefkada sea' + }, + links: { + related: '/chapters' + } + } + } + } + }); + book = env.store.peekRecord('book', 1); }); run(function() { - equal(book._internalModel._relationships.get('chapters').meta, 'the lefkada sea', 'meta is there'); + equal(book._internalModel._relationships.get('chapters').meta.where, 'the lefkada sea', 'meta is there'); }); }); @@ -1481,7 +2208,23 @@ test("metadata is accessible when return from a fetchLink", function() { var book; run(function() { - book = env.store.push('book', { id: 1, title: 'Sailing the Seven Seas', links: { chapters: '/chapters' } }); + env.store.push({ + data: { + type: 'book', + id: '1', + attributes: { + title: 'Sailing the Seven Seas' + }, + relationships: { + chapters: { + links: { + related: '/chapters' + } + } + } + } + }); + book = env.store.peekRecord('book', 1); }); run(function() { @@ -1521,8 +2264,37 @@ test("metadata should be reset between requests", function() { var book1, book2; run(function() { - book1 = env.store.push('book', { id: 1, title: 'Sailing the Seven Seas', links: { chapters: 'chapters' } }); - book2 = env.store.push('book', { id: 2, title: 'Another book title', links: { chapters: 'chapters' } }); + env.store.push({ + data: [{ + type: 'book', + id: '1', + attributes: { + title: 'Sailing the Seven Seas' + }, + relationships: { + chapters: { + links: { + related: 'chapters' + } + } + } + }, { + type: 'book', + id: '2', + attributes: { + title: 'Another book title' + }, + relationships: { + chapters: { + links: { + related: 'chapters' + } + } + } + }] + }); + book1 = env.store.peekRecord('book', 1); + book2 = env.store.peekRecord('book', 2); }); run(function() { diff --git a/packages/ember-data/tests/integration/relationships/polymorphic-mixins-belongs-to-test.js b/packages/ember-data/tests/integration/relationships/polymorphic-mixins-belongs-to-test.js index d9b7fcb0657..0060b0a769e 100644 --- a/packages/ember-data/tests/integration/relationships/polymorphic-mixins-belongs-to-test.js +++ b/packages/ember-data/tests/integration/relationships/polymorphic-mixins-belongs-to-test.js @@ -52,8 +52,28 @@ module('integration/relationships/polymorphic_mixins_belongs_to_test - Polymorph test("Relationship is available from the belongsTo side even if only loaded from the inverse side - async", function () { var user, video; run(function() { - user = store.push('user', { id: 1, name: 'Stanley', bestMessage: 2, bestMessageType: 'video' }); - video = store.push('video', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + }, + relationships: { + bestMessage: { + data: { type: 'video', id: '2' } + } + } + }, { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + video = store.peekRecord('video', 2); }); run(function() { user.get('bestMessage').then(function(message) { @@ -71,8 +91,23 @@ test("Relationship is available from the belongsTo side even if only loaded from test("Setting the polymorphic belongsTo gets propagated to the inverse side - async", function () { var user, video; run(function() { - user = store.push('user', { id: 1, name: 'Stanley' }); - video = store.push('video', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + } + }, { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + video = store.peekRecord('video', 2); }); run(function() { @@ -89,8 +124,23 @@ test("Setting the polymorphic belongsTo gets propagated to the inverse side - as test("Setting the polymorphic belongsTo with an object that does not implement the mixin errors out", function () { var user, video; run(function() { - user = store.push('user', { id: 1, name: 'Stanley' }); - video = store.push('not-message', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + } + }, { + type: 'not-message', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + video = store.peekRecord('not-message', 2); }); run(function() { @@ -109,8 +159,23 @@ test("Setting the polymorphic belongsTo gets propagated to the inverse side - mo try { var user, video; run(function() { - user = store.push('user', { id: 1, name: 'Stanley' }); - video = store.push('video', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + } + }, { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + video = store.peekRecord('video', 2); }); run(function() { @@ -134,8 +199,23 @@ test("Setting the polymorphic belongsTo with an object that does not implement t try { var user, video; run(function() { - user = store.push('user', { id: 1, name: 'Stanley' }); - video = store.push('not-message', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + } + }, { + type: 'not-message', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + video = store.peekRecord('not-message', 2); }); run(function() { diff --git a/packages/ember-data/tests/integration/relationships/polymorphic-mixins-has-many-test.js b/packages/ember-data/tests/integration/relationships/polymorphic-mixins-has-many-test.js index b9a5602650a..e0470db7e7a 100644 --- a/packages/ember-data/tests/integration/relationships/polymorphic-mixins-has-many-test.js +++ b/packages/ember-data/tests/integration/relationships/polymorphic-mixins-has-many-test.js @@ -53,8 +53,30 @@ module('integration/relationships/polymorphic_mixins_has_many_test - Polymorphic test("Relationship is available from the belongsTo side even if only loaded from the hasMany side - async", function () { var user, video; run(function() { - user = store.push('user', { id: 1, name: 'Stanley', messages: [{ id: 2, type: 'video' }] }); - video = store.push('video', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + }, + relationships: { + messages: { + data: [ + { type: 'video', id: '2' } + ] + } + } + }, { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + video = store.peekRecord('video', 2); }); run(function() { user.get('messages').then(function(messages) { @@ -72,8 +94,28 @@ test("Relationship is available from the belongsTo side even if only loaded from test("Pushing to the hasMany reflects the change on the belongsTo side - async", function () { var user, video; run(function() { - user = store.push('user', { id: 1, name: 'Stanley', messages: [] }); - video = store.push('video', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + }, + relationships: { + messages: { + data: [] + } + } + }, { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + video = store.peekRecord('video', 2); }); run(function() { @@ -92,8 +134,28 @@ test("Pushing to the hasMany reflects the change on the belongsTo side - async", test("Pushing a an object that does not implement the mixin to the mixin accepting array errors out", function () { var user,notMessage; run(function() { - user = store.push('user', { id: 1, name: 'Stanley', messages: [] }); - notMessage = store.push('not-message', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + }, + relationships: { + messages: { + data: [] + } + } + }, { + type: 'not-message', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + notMessage = store.peekRecord('not-message', 2); }); run(function() { @@ -112,8 +174,28 @@ test("Pushing to the hasMany reflects the change on the belongsTo side - model i try { var user, video; run(function() { - user = store.push('user', { id: 1, name: 'Stanley', messages: [] }); - video = store.push('video', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + }, + relationships: { + messages: { + data: [] + } + } + }, { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + video = store.peekRecord('video', 2); }); run(function() { @@ -139,8 +221,28 @@ test("Pushing a an object that does not implement the mixin to the mixin accepti try { var user,notMessage; run(function() { - user = store.push('user', { id: 1, name: 'Stanley', messages: [] }); - notMessage = store.push('not-message', { id: 2, video: 'Here comes Youtube' }); + store.push({ + data: [{ + type: 'user', + id: '1', + attributes: { + name: 'Stanley' + }, + relationships: { + messages: { + data: [] + } + } + }, { + type: 'not-message', + id: '2', + attributes: { + video: 'Here comes Youtube' + } + }] + }); + user = store.peekRecord('user', 1); + notMessage = store.peekRecord('not-message', 2); }); run(function() { diff --git a/packages/ember-data/tests/integration/serializers/embedded-records-mixin-test.js b/packages/ember-data/tests/integration/serializers/embedded-records-mixin-test.js index a61055ba8bf..2213fe27c7d 100644 --- a/packages/ember-data/tests/integration/serializers/embedded-records-mixin-test.js +++ b/packages/ember-data/tests/integration/serializers/embedded-records-mixin-test.js @@ -898,7 +898,16 @@ test("serialize with embedded objects (hasMany relationship)", function() { test("serialize with embedded objects (unknown hasMany relationship)", function() { var league; run(function() { - league = env.store.push('home-planet', { name: "Villain League", id: "123" }); + env.store.push({ + data: { + type: 'home-planet', + id: '123', + attributes: { + name: "Villain League" + } + } + }); + league = env.store.peekRecord('home-planet', 123); }); env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { diff --git a/packages/ember-data/tests/integration/serializers/json-serializer-test.js b/packages/ember-data/tests/integration/serializers/json-serializer-test.js index 213a8327c93..ffca2537f2d 100644 --- a/packages/ember-data/tests/integration/serializers/json-serializer-test.js +++ b/packages/ember-data/tests/integration/serializers/json-serializer-test.js @@ -251,7 +251,16 @@ test('Serializer should respect the attrs hash when serializing records', functi var parentPost; run(function() { - parentPost = env.store.push('post', { id: 2, title: "Rails is omakase" }); + env.store.push({ + data: { + type: 'post', + id: '2', + attributes: { + title: "Rails is omakase" + } + } + }); + parentPost = env.store.peekRecord('post', 2); post = env.store.createRecord('post', { title: "Rails is omakase", parentPost: parentPost }); }); diff --git a/packages/ember-data/tests/integration/snapshot-test.js b/packages/ember-data/tests/integration/snapshot-test.js index cd2da929fec..355f4634f88 100644 --- a/packages/ember-data/tests/integration/snapshot-test.js +++ b/packages/ember-data/tests/integration/snapshot-test.js @@ -30,7 +30,16 @@ test("record._createSnapshot() returns a snapshot", function() { expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); ok(snapshot instanceof DS.Snapshot, 'snapshot is an instance of DS.Snapshot'); @@ -41,7 +50,16 @@ test("snapshot.id, snapshot.type and snapshot.modelName returns correctly", func expect(3); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); equal(snapshot.id, '1', 'id is correct'); @@ -54,7 +72,16 @@ test("snapshot.attr() does not change when record changes", function() { expect(2); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); equal(snapshot.attr('title'), 'Hello World', 'snapshot title is correct'); @@ -67,7 +94,16 @@ test("snapshot.attr() throws an error attribute not found", function() { expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); throws(function() { @@ -80,7 +116,16 @@ test("snapshot.attributes() returns a copy of all attributes for the current sna expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); var attributes = snapshot.attributes(); @@ -93,7 +138,16 @@ test("snapshot.changedAttributes() returns a copy of all changed attributes for expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); post.set('title', 'Hello World!'); var snapshot = post._createSnapshot(); @@ -107,7 +161,16 @@ test("snapshot.belongsTo() returns undefined if relationship is undefined", func expect(1); run(function() { - var comment = env.store.push('comment', { id: 1, body: 'This is comment' }); + env.store.push({ + data: { + type: 'comment', + id: '1', + attributes: { + body: 'This is comment' + } + } + }); + var comment = env.store.peekRecord('comment', 1); var snapshot = comment._createSnapshot(); var relationship = snapshot.belongsTo('post'); @@ -119,8 +182,27 @@ test("snapshot.belongsTo() returns null if relationship is unset", function() { expect(1); run(function() { - env.store.push('post', { id: 1, title: 'Hello World' }); - var comment = env.store.push('comment', { id: 2, body: 'This is comment', post: null }); + env.store.push({ + data: [{ + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment' + }, + relationships: { + post: { + data: null + } + } + }] + }); + var comment = env.store.peekRecord('comment', 2); var snapshot = comment._createSnapshot(); var relationship = snapshot.belongsTo('post'); @@ -132,8 +214,27 @@ test("snapshot.belongsTo() returns a snapshot if relationship is set", function( expect(3); run(function() { - env.store.push('post', { id: 1, title: 'Hello World' }); - var comment = env.store.push('comment', { id: 2, body: 'This is comment', post: 1 }); + env.store.push({ + data: [{ + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment' + }, + relationships: { + post: { + data: { type: 'post', id: '1' } + } + } + }] + }); + var comment = env.store.peekRecord('comment', 2); var snapshot = comment._createSnapshot(); var relationship = snapshot.belongsTo('post'); @@ -147,8 +248,28 @@ test("snapshot.belongsTo() returns null if relationship is deleted", function() expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); - var comment = env.store.push('comment', { id: 2, body: 'This is comment', post: 1 }); + env.store.push({ + data: [{ + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment' + }, + relationships: { + post: { + data: { type: 'post', id: '1' } + } + } + }] + }); + var post = env.store.peekRecord('post', 1); + var comment = env.store.peekRecord('comment', 2); post.deleteRecord(); @@ -163,7 +284,23 @@ test("snapshot.belongsTo() returns undefined if relationship is a link", functio expect(1); run(function() { - var comment = env.store.push('comment', { id: 2, body: 'This is comment', links: { post: 'post' } }); + env.store.push({ + data: { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment' + }, + relationships: { + post: { + links: { + related: 'post' + } + } + } + } + }); + var comment = env.store.peekRecord('comment', 2); var snapshot = comment._createSnapshot(); var relationship = snapshot.belongsTo('post'); @@ -175,7 +312,16 @@ test("snapshot.belongsTo() throws error if relation doesn't exist", function() { expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); throws(function() { @@ -192,7 +338,23 @@ test("snapshot.belongsTo() returns a snapshot if relationship link has been fetc }; run(function() { - var comment = env.store.push('comment', { id: 2, body: 'This is comment', links: { post: 'post' } }); + env.store.push({ + data: { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment' + }, + relationships: { + post: { + links: { + related: 'post' + } + } + } + } + }); + var comment = env.store.peekRecord('comment', 2); comment.get('post').then(function(post) { var snapshot = comment._createSnapshot(); @@ -208,8 +370,23 @@ test("snapshot.belongsTo() and snapshot.hasMany() returns correctly when adding expect(4); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); - var comment = env.store.push('comment', { id: 2, body: 'blabla' }); + env.store.push({ + data: [{ + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment' + } + }] + }); + var post = env.store.peekRecord('post', 1); + var comment = env.store.peekRecord('comment', 2); post.get('comments').then(function(comments) { comments.addObject(comment); @@ -233,8 +410,23 @@ test("snapshot.belongsTo() and snapshot.hasMany() returns correctly when setting expect(4); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); - var comment = env.store.push('comment', { id: 2, body: 'blabla' }); + env.store.push({ + data: [{ + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment' + } + }] + }); + var post = env.store.peekRecord('post', 1); + var comment = env.store.peekRecord('comment', 2); comment.set('post', post); @@ -256,8 +448,27 @@ test("snapshot.belongsTo() returns ID if option.id is set", function() { expect(1); run(function() { - env.store.push('post', { id: 1, title: 'Hello World' }); - var comment = env.store.push('comment', { id: 2, body: 'This is comment', post: 1 }); + env.store.push({ + data: [{ + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment' + }, + relationships: { + post: { + data: { type: 'post', id: '1' } + } + } + }] + }); + var comment = env.store.peekRecord('comment', 2); var snapshot = comment._createSnapshot(); var relationship = snapshot.belongsTo('post', { id: true }); @@ -269,8 +480,28 @@ test("snapshot.belongsTo() returns null if option.id is set but relationship was expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); - var comment = env.store.push('comment', { id: 2, body: 'This is comment', post: 1 }); + env.store.push({ + data: [{ + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment' + }, + relationships: { + post: { + data: { type: 'post', id: '1' } + } + } + }] + }); + var post = env.store.peekRecord('post', 1); + var comment = env.store.peekRecord('comment', 2); post.deleteRecord(); @@ -285,7 +516,16 @@ test("snapshot.hasMany() returns undefined if relationship is undefined", functi expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); var relationship = snapshot.hasMany('comments'); @@ -293,11 +533,25 @@ test("snapshot.hasMany() returns undefined if relationship is undefined", functi }); }); -test("snapshot.hasMany() returns empty array if relationship is unset", function() { +test("snapshot.hasMany() returns empty array if relationship is empty", function() { expect(2); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World', comments: null }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + }, + relationships: { + comments: { + data: [] + } + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); var relationship = snapshot.hasMany('comments'); @@ -310,9 +564,36 @@ test("snapshot.hasMany() returns array of snapshots if relationship is set", fun expect(5); run(function() { - env.store.push('comment', { id: 1, body: 'This is the first comment' }); - env.store.push('comment', { id: 2, body: 'This is the second comment' }); - var post = env.store.push('post', { id: 3, title: 'Hello World', comments: [1, 2] }); + env.store.push({ + data: [{ + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is the second comment' + } + }, { + type: 'post', + id: '3', + attributes: { + title: 'Hello World' + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' } + ] + } + } + }] + }); + var post = env.store.peekRecord('post', 3); var snapshot = post._createSnapshot(); var relationship = snapshot.hasMany('comments'); @@ -332,9 +613,38 @@ test("snapshot.hasMany() returns empty array if relationship records are deleted expect(2); run(function() { - var comment1 = env.store.push('comment', { id: 1, body: 'This is the first comment' }); - var comment2 = env.store.push('comment', { id: 2, body: 'This is the second comment' }); - var post = env.store.push('post', { id: 3, title: 'Hello World', comments: [1, 2] }); + env.store.push({ + data: [{ + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is the second comment' + } + }, { + type: 'post', + id: '3', + attributes: { + title: 'Hello World' + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' } + ] + } + } + }] + }); + var comment1 = env.store.peekRecord('comment', 1); + var comment2 = env.store.peekRecord('comment', 2); + var post = env.store.peekRecord('post', 3); comment1.deleteRecord(); comment2.deleteRecord(); @@ -351,7 +661,24 @@ test("snapshot.hasMany() returns array of IDs if option.ids is set", function() expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World', comments: [2, 3] }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); var relationship = snapshot.hasMany('comments', { ids: true }); @@ -363,9 +690,38 @@ test("snapshot.hasMany() returns empty array of IDs if option.ids is set but rel expect(2); run(function() { - var comment1 = env.store.push('comment', { id: 1, body: 'This is the first comment' }); - var comment2 = env.store.push('comment', { id: 2, body: 'This is the second comment' }); - var post = env.store.push('post', { id: 3, title: 'Hello World', comments: [1, 1] }); + env.store.push({ + data: [{ + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is the second comment' + } + }, { + type: 'post', + id: '3', + attributes: { + title: 'Hello World' + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' } + ] + } + } + }] + }); + var comment1 = env.store.peekRecord('comment', 1); + var comment2 = env.store.peekRecord('comment', 2); + var post = env.store.peekRecord('post', 3); comment1.deleteRecord(); comment2.deleteRecord(); @@ -382,7 +738,23 @@ test("snapshot.hasMany() returns undefined if relationship is a link", function( expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World', links: { comments: 'comments' } }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + }, + relationships: { + comments: { + links: { + related: 'comments' + } + } + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); var relationship = snapshot.hasMany('comments'); @@ -398,7 +770,23 @@ test("snapshot.hasMany() returns array of snapshots if relationship link has bee }; run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World', links: { comments: 'comments' } }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + }, + relationships: { + comments: { + links: { + related: 'comments' + } + } + } + } + }); + var post = env.store.peekRecord('post', 1); post.get('comments').then(function(comments) { var snapshot = post._createSnapshot(); @@ -414,7 +802,16 @@ test("snapshot.hasMany() throws error if relation doesn't exist", function() { expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); throws(function() { @@ -427,10 +824,44 @@ test("snapshot.hasMany() respects the order of items in the relationship", funct expect(3); run(function() { - env.store.push('comment', { id: 1, body: 'This is the first comment' }); - env.store.push('comment', { id: 2, body: 'This is the second comment' }); - var comment3 = env.store.push('comment', { id: 3, body: 'This is the third comment' }); - var post = env.store.push('post', { id: 4, title: 'Hello World', comments: [1, 2, 3] }); + env.store.push({ + data: [{ + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment' + } + }, { + type: 'comment', + id: '2', + attributes: { + body: 'This is the second comment' + } + }, { + type: 'comment', + id: '3', + attributes: { + body: 'This is the third comment' + } + }, { + type: 'post', + id: '4', + attributes: { + title: 'Hello World' + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + }] + }); + var comment3 = env.store.peekRecord('comment', 3); + var post = env.store.peekRecord('post', 4); post.get('comments').removeObject(comment3); post.get('comments').insertAt(0, comment3); @@ -448,7 +879,16 @@ test("snapshot.eachAttribute() proxies to record", function() { expect(1); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); var attributes = []; @@ -471,8 +911,23 @@ test("snapshot.eachRelationship() proxies to record", function() { }; run(function() { - var comment = env.store.push('comment', { id: 1, body: 'This is the first comment' }); - var post = env.store.push('post', { id: 2, title: 'Hello World' }); + env.store.push({ + data: [{ + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment' + } + }, { + type: 'post', + id: '2', + attributes: { + title: 'Hello World' + } + }] + }); + var comment = env.store.peekRecord('comment', 1); + var post = env.store.peekRecord('post', 2); var snapshot; snapshot = comment._createSnapshot(); @@ -491,7 +946,21 @@ test("snapshot.belongsTo() does not trigger a call to store.scheduleFetch", func }; run(function() { - var comment = env.store.push('comment', { id: 2, body: 'This is comment', post: 1 }); + env.store.push({ + data: { + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment' + }, + relationships: { + post: { + data: { type: 'post', id: '2' } + } + } + } + }); + var comment = env.store.peekRecord('comment', 1); var snapshot = comment._createSnapshot(); snapshot.belongsTo('post'); @@ -506,7 +975,24 @@ test("snapshot.hasMany() does not trigger a call to store.scheduleFetch", functi }; run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World', comments: [2, 3] }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + }, + relationships: { + comments: { + data: [ + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' } + ] + } + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); snapshot.hasMany('comments'); @@ -517,7 +1003,16 @@ test("snapshot.serialize() serializes itself", function() { expect(2); run(function() { - var post = env.store.push('post', { id: 1, title: 'Hello World' }); + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World' + } + } + }); + var post = env.store.peekRecord('post', 1); var snapshot = post._createSnapshot(); post.set('title', 'New Title'); diff --git a/packages/ember-data/tests/integration/store-test.js b/packages/ember-data/tests/integration/store-test.js index f5fb1526bc2..e8beb8c1a42 100644 --- a/packages/ember-data/tests/integration/store-test.js +++ b/packages/ember-data/tests/integration/store-test.js @@ -113,18 +113,36 @@ asyncTest("find calls do not resolve when the store is destroyed", function() { test("destroying the store correctly cleans everything up", function() { var car, person; run(function() { - car = store.push('car', { - id: 1, - make: 'BMC', - model: 'Mini', - person: 1 - }); - - person = store.push('person', { - id: 1, - name: 'Tom Dale', - cars: [1] + store.push({ + data: [{ + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini' + }, + relationships: { + person: { + data: { type: 'person', id: '1' } + } + } + }, { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + cars: { + data: [ + { type: 'car', id: '1' } + ] + } + } + }] }); + car = store.peekRecord('car', 1); + person = store.peekRecord('person', 1); }); var personWillDestroy = tap(person, 'willDestroy'); @@ -225,13 +243,19 @@ test("Using store#findRecord on existing record reloads it", function() { var car; run(function() { - car = store.push('car', { - id: 1, - make: 'BMC', - model: 'Mini' + store.push({ + data: { + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini' + } + } }); - + car = store.peekRecord('car', 1); }); + ajaxResponse({ cars: [{ id: 1, @@ -285,10 +309,15 @@ test("Using store#findAll with existing records performs a query, updating exist expect(3); run(function() { - store.push('car', { - id: 1, - make: 'BMC', - model: 'Mini' + store.push({ + data: { + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini' + } + } }); }); @@ -321,8 +350,23 @@ test("store#findAll should return all known records even if they are not in the expect(4); run(function() { - store.push('car', { id: 1, make: 'BMC', model: 'Mini' }); - store.push('car', { id: 2, make: 'BMCW', model: 'Isetta' }); + store.push({ + data: [{ + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini' + } + }, { + type: 'car', + id: '2', + attributes: { + make: 'BMCW', + model: 'Isetta' + } + }] + }); }); ajaxResponse({ @@ -360,10 +404,21 @@ test("Using store#fetch on an empty record calls find", function() { }); run(function() { - store.push('person', { - id: 1, - name: 'Tom Dale', - cars: [20] + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + cars: { + data: [ + { type: 'car', id: '20' } + ] + } + } + } }); }); @@ -407,10 +462,16 @@ test("Using store#deleteRecord should mark the model for removal", function() { var person; run(function() { - person = store.push('person', { - id: 1, - name: 'Tom Dale' + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + } + } }); + person = store.peekRecord('person', 1); }); ok(store.hasRecordForId('person', 1), 'expected the record to be in the store'); diff --git a/packages/ember-data/tests/unit/adapter-populated-record-array-test.js b/packages/ember-data/tests/unit/adapter-populated-record-array-test.js index 6b881395c33..3b5cc2b2d3a 100644 --- a/packages/ember-data/tests/unit/adapter-populated-record-array-test.js +++ b/packages/ember-data/tests/unit/adapter-populated-record-array-test.js @@ -1,4 +1,4 @@ -var Person, array, store; +var Person, store; var run = Ember.run; var adapter = DS.Adapter.extend({ @@ -17,10 +17,6 @@ module("unit/adapter_populated_record_array - DS.AdapterPopulatedRecordArray", { adapter: adapter, person: Person }); - array = [{ id: '1', name: "Scumbag Dale" }, - { id: '2', name: "Scumbag Katz" }, - { id: '3', name: "Scumbag Bryn" }]; - } }); @@ -29,7 +25,28 @@ test("when a record is deleted in an adapter populated record array, it should b .createAdapterPopulatedRecordArray(store.modelFor('person'), null); run(function() { - recordArray.load(array); + var records = store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Scumbag Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Scumbag Katz' + } + }, { + type: 'person', + id: '3', + attributes: { + name: 'Scumbag Bryn' + } + }] + }); + recordArray.loadRecords(records); }); equal(recordArray.get('length'), 3, "expected recordArray to contain exactly 3 records"); diff --git a/packages/ember-data/tests/unit/many-array-test.js b/packages/ember-data/tests/unit/many-array-test.js index e6fc7f5eba3..045ee88baee 100644 --- a/packages/ember-data/tests/unit/many-array-test.js +++ b/packages/ember-data/tests/unit/many-array-test.js @@ -49,10 +49,37 @@ test("manyArray.save() calls save() on all records", function() { } }); - store.push('tag', { id: 1, name: 'Ember.js' }); - store.push('tag', { id: 2, name: 'Tomster' }); + store.push({ + data: [{ + type: 'tag', + id: '1', + attributes: { + name: 'Ember.js' + } + }, { + type: 'tag', + id: '2', + attributes: { + name: 'Tomster' + } + }, { + type: 'post', + id: '3', + attributes: { + title: 'A framework for creating ambitious web applications' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '1' }, + { type: 'tag', id: '2' } + ] + } + } + }] + }); + var post = store.peekRecord('post', 3); - var post = store.push('post', { id: 3, title: 'A framework for creating ambitious web applications', tags: [1, 2] }); post.get('tags').save().then(function() { ok(true, 'manyArray.save() promise resolved'); }); @@ -81,10 +108,55 @@ test("manyArray trigger arrayContentChange functions with the correct values", f } }); run(function() { - store.push('tag', { id: 1, name: 'Ember.js' }); - store.push('tag', { id: 2, name: 'Ember Data' }); - var post = store.push('post', { id: 2, title: 'A framework for creating ambitious web applications', tags: [1] }); - post = store.push('post', { id: 2, title: 'A framework for creating ambitious web applications', tags: [1, 2] }); + store.push({ + data: [{ + type: 'tag', + id: '1', + attributes: { + name: 'Ember.js' + } + }, { + type: 'tag', + id: '2', + attributes: { + name: 'Tomster' + } + }, { + type: 'post', + id: '3', + attributes: { + title: 'A framework for creating ambitious web applications' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '1' } + ] + } + } + }] + }); + var post = store.peekRecord('post', 3); + + store.push({ + data: { + type: 'post', + id: '3', + attributes: { + title: 'A framework for creating ambitious web applications' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '1' }, + { type: 'tag', id: '2' } + ] + } + } + } + }); + + post = store.peekRecord('post', 3); }); DS.ManyArray.reopen({ arrayContentWillChange: originalArrayContentWillChange, diff --git a/packages/ember-data/tests/unit/model-test.js b/packages/ember-data/tests/unit/model-test.js index 2a43eb650c4..2a5c7ac8e7b 100644 --- a/packages/ember-data/tests/unit/model-test.js +++ b/packages/ember-data/tests/unit/model-test.js @@ -2,7 +2,7 @@ var get = Ember.get; var set = Ember.set; var run = Ember.run; -var Person, store, array, env; +var Person, store, env; module("unit/model - DS.Model", { setup: function() { @@ -40,7 +40,17 @@ test("setting a property on a record that has not changed does not cause it to b expect(2); run(function() { - store.push('person', { id: 1, name: "Peter", isDrugAddict: true }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Peter', + isDrugAddict: true + } + } + }); + store.findRecord('person', 1).then(function(person) { equal(person.get('hasDirtyAttributes'), false, "precond - person record should not be dirty"); @@ -56,7 +66,16 @@ test("resetting a property on a record cause it to become clean again", function expect(3); run(function() { - store.push('person', { id: 1, name: "Peter", isDrugAddict: true }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Peter', + isDrugAddict: true + } + } + }); store.findRecord('person', 1).then(function(person) { equal(person.get('hasDirtyAttributes'), false, "precond - person record should not be dirty"); person.set('isDrugAddict', false); @@ -71,7 +90,16 @@ test("a record becomes clean again only if all changed properties are reset", fu expect(5); run(function() { - store.push('person', { id: 1, name: "Peter", isDrugAddict: true }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Peter', + isDrugAddict: true + } + } + }); store.findRecord('person', 1).then(function(person) { equal(person.get('hasDirtyAttributes'), false, "precond - person record should not be dirty"); person.set('isDrugAddict', false); @@ -90,7 +118,12 @@ test("a record reports its unique id via the `id` property", function() { expect(1); run(function() { - store.push('person', { id: 1 }); + store.push({ + data: { + type: 'person', + id: '1' + } + }); store.findRecord('person', 1).then(function(record) { equal(get(record, 'id'), 1, "reports id as id by default"); }); @@ -101,7 +134,12 @@ test("a record's id is included in its toString representation", function() { expect(1); run(function() { - store.push('person', { id: 1 }); + store.push({ + data: { + type: 'person', + id: '1' + } + }); store.findRecord('person', 1).then(function(record) { equal(record.toString(), '<(subclass of DS.Model):'+Ember.guidFor(record)+':1>', "reports id in toString"); }); @@ -120,7 +158,15 @@ test("trying to set an `id` attribute should raise", function() { expectAssertion(function() { run(function() { - store.push('person', { id: 1, name: "Scumdale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Scumdale' + } + } + }); store.findRecord('person', 1); }); }, /You may not set `id`/); @@ -135,7 +181,13 @@ test("a collision of a record's id with object function's name", function() { Object.prototype.watch = function() {}; } run(function() { - store.push('person', { id: 'watch' }); + store.push({ + data: { + type: 'person', + id: 'watch' + } + }); + store.findRecord('person', 'watch').then(function(record) { equal(get(record, 'id'), 'watch', "record is successfully created and could be found by its id"); }); @@ -176,7 +228,12 @@ test("it should cache attributes", function() { var date = new Date(dateString); run(function() { - store.push('post', { id: 1 }); + store.push({ + data: { + type: 'post', + id: '1' + } + }); store.findRecord('post', 1).then(function(record) { run(function() { record.set('updatedAt', date); @@ -207,7 +264,17 @@ test("changedAttributes() return correct values", function() { run(function() { - mascot = store.push('mascot', { id: 1, likes: 'JavaScript', isMascot: true }); + store.push({ + data: { + type: 'mascot', + id: '1', + attributes: { + likes: 'JavaScript', + isMascot: true + } + } + }); + mascot = store.peekRecord('mascot', 1); }); equal(Object.keys(mascot.changedAttributes()).length, 0, 'there are no initial changes'); @@ -291,11 +358,16 @@ test("Calling attr(), belongsTo() or hasMany() throws a warning", function() { test("supports pushedData in root.deleted.uncommitted", function() { var record; - var hash = { id: 1 }; + var hash = { + data: { + type: 'person', + id: '1' + } + }; run(function() { - record = store.push('person', hash); + record = store.push(hash); record.deleteRecord(); - store.push('person', hash); + store.push(hash); equal(get(record, 'currentState.stateName'), 'root.deleted.uncommitted', 'record accepts pushedData is in root.deleted.uncommitted state'); }); @@ -303,9 +375,14 @@ test("supports pushedData in root.deleted.uncommitted", function() { test("currentState is accessible when the record is created", function() { var record; - var hash = { id: 1 }; + var hash = { + data: { + type: 'person', + id: '1' + } + }; run(function() { - record = store.push('person', hash); + record = store.push(hash); equal(get(record, 'currentState.stateName'), 'root.loaded.saved', 'records pushed into the store start in the loaded state'); }); @@ -314,14 +391,33 @@ test("currentState is accessible when the record is created", function() { module("unit/model - DS.Model updating", { setup: function() { - array = [{ id: 1, name: "Scumbag Dale" }, { id: 2, name: "Scumbag Katz" }, { id: 3, name: "Scumbag Bryn" }]; Person = DS.Model.extend({ name: DS.attr('string') }); env = setupStore({ person: Person }); store = env.store; run(function() { - store.pushMany('person', array); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Scumbag Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Scumbag Katz' + } + }, { + type: 'person', + id: '3', + attributes: { + name: 'Scumbag Bryn' + } + }] + }); }); }, teardown: function() { @@ -329,7 +425,6 @@ module("unit/model - DS.Model updating", { store.destroy(); Person = null; store = null; - array = null; }); } }); @@ -485,11 +580,6 @@ test("setting a property back to its original value removes the property from th module("unit/model - with a simple Person model", { setup: function() { - array = [ - { id: 1, name: "Scumbag Dale" }, - { id: 2, name: "Scumbag Katz" }, - { id: 3, name: "Scumbag Bryn" } - ]; Person = DS.Model.extend({ name: DS.attr('string') }); @@ -497,7 +587,27 @@ module("unit/model - with a simple Person model", { person: Person }); run(function() { - store.pushMany('person', array); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Scumbag Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Scumbag Katz' + } + }, { + type: 'person', + id: '3', + attributes: { + name: 'Scumbag Bryn' + } + }] + }); }); }, teardown: function() { @@ -505,7 +615,6 @@ module("unit/model - with a simple Person model", { store.destroy(); Person = null; store = null; - array = null; }); } }); @@ -639,7 +748,12 @@ var convertsWhenSet = function(type, provided, expected) { var testStore = createStore({ model: Model }); run(function() { - testStore.push('model', { id: 2 }); + testStore.push({ + data: { + type: 'model', + id: '2' + } + }); testStore.findRecord('model', 2).then(function(record) { set(record, 'name', provided); deepEqual(record.serialize().name, expected, type + " saves " + provided + " as " + expected); @@ -703,7 +817,12 @@ test("a DS.Model can describe Date attributes", function() { }); run(function() { - store.push('person', { id: 1 }); + store.push({ + data: { + type: 'person', + id: '1' + } + }); store.findRecord('person', 1).then(function(record) { run(function() { record.set('updatedAt', date); @@ -827,7 +946,15 @@ test("Pushing a record into the store should transition it to the loaded state", run(function() { var person = store.createRecord('person', { id: 1, name: 'TomHuda' }); equal(person.get('isNew'), true, 'createRecord should put records into the new state'); - store.push('person', { id: 1, name: 'TomHuda' }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'TomHuda' + } + } + }); equal(person.get('isNew'), false, 'push should put records into the loaded state'); }); }); @@ -859,8 +986,11 @@ test('toJSON looks up the JSONSerializer using the store instead of using JSONSe // present on the serializer due to using .create // instead of `store.serializerFor`. run(() => { - person = store.push('person', { - id: 1 + person = store.push({ + data: { + type: 'person', + id: '1' + } }); }); var errorThrown = false; diff --git a/packages/ember-data/tests/unit/model/lifecycle-callbacks-test.js b/packages/ember-data/tests/unit/model/lifecycle-callbacks-test.js index 431b7d94126..ecb2cde0526 100644 --- a/packages/ember-data/tests/unit/model/lifecycle-callbacks-test.js +++ b/packages/ember-data/tests/unit/model/lifecycle-callbacks-test.js @@ -303,7 +303,15 @@ test("an ID of 0 is allowed", function() { }); run(function() { - store.push('person', { id: 0, name: "Tom Dale" }); + store.push({ + data: { + type: 'person', + id: '0', + attributes: { + name: "Tom Dale" + } + } + }); }); equal(store.peekAll('person').objectAt(0).get('name'), "Tom Dale", "found record with id 0"); diff --git a/packages/ember-data/tests/unit/model/merge-test.js b/packages/ember-data/tests/unit/model/merge-test.js index e5b9b4d35f4..917f04d0585 100644 --- a/packages/ember-data/tests/unit/model/merge-test.js +++ b/packages/ember-data/tests/unit/model/merge-test.js @@ -58,7 +58,15 @@ test("Make sure snapshot is created at save time not at flush time", function() var person; run(function() { - person = store.push('person', { id: 1, name: "Tom" }); + person = store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tom" + } + } + }); person.set('name', "Thomas Dale"); }); @@ -97,7 +105,15 @@ test("When a record is in flight, pushes are applied underneath the in flight ch var person; run(function() { - person = store.push('person', { id: 1, name: "Tom" }); + person = store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tom" + } + } + }); person.set('name', "Thomas Dale"); }); @@ -108,7 +124,16 @@ test("When a record is in flight, pushes are applied underneath the in flight ch person.set('name', "Tomasz Dale"); - store.push('person', { id: 1, name: "Tommy Dale", city: "PDX" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tommy Dale", + city: "PDX" + } + } + }); equal(person.get('name'), "Tomasz Dale", "the local changes applied on top"); equal(person.get('city'), "PDX", "the pushed change is available"); @@ -129,7 +154,16 @@ test("When a record is dirty, pushes are overridden by local changes", function( var person; run(function() { - person = store.push('person', { id: 1, name: "Tom Dale", city: "San Francisco" }); + person = store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tom Dale", + city: "San Francisco" + } + } + }); person.set('name', "Tomasz Dale"); }); @@ -138,7 +172,16 @@ test("When a record is dirty, pushes are overridden by local changes", function( equal(person.get('city'), "San Francisco", "the original data applies"); run(function() { - store.push('person', { id: 1, name: "Thomas Dale", city: "Portland" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Thomas Dale", + city: "Portland" + } + } + }); }); equal(person.get('hasDirtyAttributes'), true, "the local changes are reapplied"); @@ -154,7 +197,16 @@ test("When a record is invalid, pushes are overridden by local changes", functio var person; run(function() { - person = store.push('person', { id: 1, name: "Brendan McLoughlin", city: "Boston" }); + person = store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Brendan McLoughlin", + city: "Boston" + } + } + }); person.set('name', "Brondan McLoughlin"); person.send('becameInvalid'); }); @@ -165,7 +217,16 @@ test("When a record is invalid, pushes are overridden by local changes", functio equal(person.get('city'), "Boston", "the original data applies"); run(function() { - store.push('person', { id: 1, name: "bmac", city: "Prague" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "bmac", + city: "Prague" + } + } + }); }); equal(person.get('hasDirtyAttributes'), true, "the local changes are reapplied"); @@ -190,7 +251,15 @@ test("A record with no changes can still be saved", function() { var person; run(function() { - person = store.push('person', { id: 1, name: "Tom Dale" }); + person = store.push({ + data: { + type: 'person', + id: '1', + attributeS: { + name: "Tom Dale" + } + } + }); }); run(function() { @@ -216,7 +285,15 @@ test("A dirty record can be reloaded", function() { var person; run(function() { - person = store.push('person', { id: 1, name: "Tom Dale" }); + person = store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tom Dale" + } + } + }); person.set('name', "Tomasz Dale"); }); diff --git a/packages/ember-data/tests/unit/model/relationships/belongs-to-test.js b/packages/ember-data/tests/unit/model/relationships/belongs-to-test.js index f01b3158fec..7f1e07689c4 100644 --- a/packages/ember-data/tests/unit/model/relationships/belongs-to-test.js +++ b/packages/ember-data/tests/unit/model/relationships/belongs-to-test.js @@ -22,8 +22,38 @@ test("belongsTo lazily loads relationships as needed", function() { var store = env.store; run(function() { - store.pushMany('tag', [{ id: 5, name: "friendly" }, { id: 2, name: "smarmy" }, { id: 12, name: "oohlala" }]); - store.push('person', { id: 1, name: "Tom Dale", tag: 5 }); + store.push({ + data: [{ + type: 'tag', + id: '5', + attributes: { + name: 'friendly' + } + }, { + type: 'tag', + id: '2', + attributes: { + name: 'smarmy' + } + }, { + type: 'tag', + id: '12', + attributes: { + name: 'oohlala' + } + }, { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tag: { + data: { type: 'tag', id: '5' } + } + } + }] + }); }); run(function() { @@ -96,8 +126,26 @@ test("async belongsTo relationships work when the data hash has already been loa var store = env.store; run(function() { - store.push('tag', { id: 2, name: "friendly" }); - store.push('person', { id: 1, name: "Tom Dale", tag: 2 }); + store.push({ + data: [{ + type: 'tag', + id: '2', + attributes: { + name: 'friendly' + } + }, { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tag: { + data: { type: 'tag', id: '2' } + } + } + }] + }); }); run(function() { @@ -166,7 +214,23 @@ test("When finding a hasMany relationship the inverse belongsTo relationship is env.adapter.coalesceFindRequests = true; run(function() { - store.push('person', { id: 1, name: "Tom Dale", occupations: [5, 2] }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + occupations: { + data: [ + { type: 'occupation', id: '5' }, + { type: 'occupation', id: '2' } + ] + } + } + } + }); }); run(function() { @@ -210,7 +274,20 @@ test("When finding a belongsTo relationship the inverse belongsTo relationship i }; run(function() { - store.push('person', { id: 1, name: "Tom Dale", occupation: 5 }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + occupation: { + data: { type: 'occupation', id: '5' } + } + } + } + }); }); run(function() { @@ -237,8 +314,38 @@ test("belongsTo supports relationships to models with id 0", function() { var store = env.store; run(function() { - store.pushMany('tag', [{ id: 0, name: "friendly" }, { id: 2, name: "smarmy" }, { id: 12, name: "oohlala" }]); - store.push('person', { id: 1, name: "Tom Dale", tag: 0 }); + store.push({ + data: [{ + type: 'tag', + id: '0', + attributes: { + name: 'friendly' + } + }, { + type: 'tag', + id: '2', + attributes: { + name: 'smarmy' + } + }, { + type: 'tag', + id: '12', + attributes: { + name: 'oohlala' + } + }, { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tag: { + data: { type: 'tag', id: '0' } + } + } + }] + }); }); run(function() { @@ -270,8 +377,32 @@ test("belongsTo gives a warning when provided with a serialize option", function var store = env.store; run(function() { - store.pushMany('hobby', [{ id: 1, name: "fishing" }, { id: 1, name: "coding" }]); - store.push('person', { id: 1, name: "Tom Dale", hobby: 1 }); + store.push({ + data: [{ + type: 'hobby', + id: '1', + attributes: { + name: 'fishing' + } + }, { + type: 'hobby', + id: '2', + attributes: { + name: 'coding' + } + }, { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + hobby: { + data: { type: 'hobby', id: '1' } + } + } + }] + }); }); warns(function() { @@ -299,8 +430,32 @@ test("belongsTo gives a warning when provided with an embedded option", function var store = env.store; run(function() { - store.pushMany('hobby', [{ id: 1, name: "fishing" }, { id: 1, name: "coding" }]); - store.push('person', { id: 1, name: "Tom Dale", hobby: 1 }); + store.push({ + data: [{ + type: 'hobby', + id: '1', + attributes: { + name: 'fishing' + } + }, { + type: 'hobby', + id: '2', + attributes: { + name: 'coding' + } + }, { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + hobby: { + data: { type: 'hobby', id: '1' } + } + } + }] + }); }); warns(function() { diff --git a/packages/ember-data/tests/unit/model/relationships/has-many-test.js b/packages/ember-data/tests/unit/model/relationships/has-many-test.js index b33f4da0648..917c6c3dc6b 100644 --- a/packages/ember-data/tests/unit/model/relationships/has-many-test.js +++ b/packages/ember-data/tests/unit/model/relationships/has-many-test.js @@ -42,10 +42,65 @@ test("hasMany handles pre-loaded relationships", function() { var store = env.store; run(function() { - store.pushMany('tag', [{ id: 5, name: "friendly" }, { id: 2, name: "smarmy" }]); - store.pushMany('pet', [{ id: 4, name: "fluffy" }, { id: 7, name: "snowy" }, { id: 12, name: "cerberus" }]); - store.push('person', { id: 1, name: "Tom Dale", tags: [5] }); - store.push('person', { id: 2, name: "Yehuda Katz", tags: [12] }); + store.push({ + data: [{ + type: 'tag', + id: '5', + attributes: { + name: 'friendly' + } + }, { + type: 'tag', + id: '2', + attributes: { + name: 'smarmy' + } + }, { + type: 'pet', + id: '4', + attributes: { + name: 'fluffy' + } + }, { + type: 'pet', + id: '7', + attributes: { + name: 'snowy' + } + }, { + type: 'pet', + id: '12', + attributes: { + name: 'cerberus' + } + }, { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '5' } + ] + } + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Yehuda Katz' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '12' } + ] + } + } + }] + }); }); run(function() { @@ -57,7 +112,23 @@ test("hasMany handles pre-loaded relationships", function() { equal(get(tags.objectAt(0), 'name'), "friendly", "the first tag should be a Tag"); run(function() { - store.push('person', { id: 1, name: "Tom Dale", tags: [5, 2] }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '5' }, + { type: 'tag', id: '2' } + ] + } + } + } + }); }); equal(tags, get(person, 'tags'), "a relationship returns the same object every time"); @@ -67,7 +138,15 @@ test("hasMany handles pre-loaded relationships", function() { asyncEqual(get(person, 'tags').objectAt(0), store.findRecord('tag', 5), "relationship objects are the same as objects retrieved directly"); run(function() { - store.push('person', { id: 3, name: "KSelden" }); + store.push({ + data: { + type: 'person', + id: '3', + attributes: { + name: 'KSelden' + } + } + }); }); return store.findRecord('person', 3); @@ -75,7 +154,22 @@ test("hasMany handles pre-loaded relationships", function() { equal(get(get(kselden, 'tags'), 'length'), 0, "a relationship that has not been supplied returns an empty array"); run(function() { - store.push('person', { id: 4, name: "Cyvid Hamluck", pets: [4] }); + store.push({ + data: { + type: 'person', + id: '4', + attributes: { + name: 'Cyvid Hamluck' + }, + relationships: { + pets: { + data: [ + { type: 'pet', id: '4' } + ] + } + } + } + }); }); return store.findRecord('person', 4); }).then(function(cyvid) { @@ -86,7 +180,23 @@ test("hasMany handles pre-loaded relationships", function() { equal(get(pets.objectAt(0), 'name'), "fluffy", "the first pet should be correct"); run(function() { - store.push('person', { id: 4, name: "Cyvid Hamluck", pets: [4, 12] }); + store.push({ + data: { + type: 'person', + id: '4', + attributes: { + name: 'Cyvid Hamluck' + }, + relationships: { + pets: { + data: [ + { type: 'pet', id: '4' }, + { type: 'pet', id: '12' } + ] + } + } + } + }); }); equal(pets, get(cyvid, 'pets'), "a relationship returns the same object every time"); @@ -129,10 +239,65 @@ test("hasMany lazily loads async relationships", function() { var store = env.store; run(function() { - store.pushMany('tag', [{ id: 5, name: "friendly" }, { id: 2, name: "smarmy" }]); - store.pushMany('pet', [{ id: 4, name: "fluffy" }, { id: 7, name: "snowy" }, { id: 12, name: "cerberus" }]); - store.push('person', { id: 1, name: "Tom Dale", tags: [5] }); - store.push('person', { id: 2, name: "Yehuda Katz", tags: [12] }); + store.push({ + data: [{ + type: 'tag', + id: '5', + attributes: { + name: 'friendly' + } + }, { + type: 'tag', + id: '2', + attributes: { + name: 'smarmy' + } + }, { + type: 'pet', + id: '4', + attributes: { + name: 'fluffy' + } + }, { + type: 'pet', + id: '7', + attributes: { + name: 'snowy' + } + }, { + type: 'pet', + id: '12', + attributes: { + name: 'cerberus' + } + }, { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '5' } + ] + } + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Yehuda Katz' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '12' } + ] + } + } + }] + }); }); var wycats; @@ -248,8 +413,41 @@ test("relationships work when declared with a string path", function() { }); run(function() { - env.store.pushMany('tag', [{ id: 5, name: "friendly" }, { id: 2, name: "smarmy" }, { id: 12, name: "oohlala" }]); - env.store.push('person', { id: 1, name: "Tom Dale", tags: [5, 2] }); + env.store.push({ + data: [{ + type: 'tag', + id: '5', + attributes: { + name: 'friendly' + } + }, { + type: 'tag', + id: '2', + attributes: { + name: 'smarmy' + } + }, { + type: 'tag', + id: '12', + attributes: { + name: 'oohlala' + } + }, { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '5' }, + { type: 'tag', id: '2' } + ] + } + } + }] + }); }); run(function() { @@ -331,8 +529,28 @@ test("it is possible to add a new item to a relationship", function() { var store = env.store; run(function() { - store.push('person', { id: 1, name: "Tom Dale", tags: [1] }); - store.push('tag', { id: 1, name: "ember" }); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '1' } + ] + } + } + }, { + type: 'tag', + id: '1', + attributes: { + name: 'ember' + } + }] + }); }); run(function() { @@ -366,10 +584,47 @@ test("possible to replace items in a relationship using setObjects w/ Ember Enum var store = env.store; run(function() { - store.push('person', { id: 1, name: "Tom Dale", tags: [1] }); - store.push('person', { id: 2, name: "Sylvain Mina", tags: [2] }); - store.push('tag', { id: 1, name: "ember" }); - store.push('tag', { id: 2, name: "ember-data" }); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '1' } + ] + } + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Sylvain Mina' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '2' } + ] + } + } + }, { + type: 'tag', + id: '1', + attributes: { + name: 'ember' + } + }, { + type: 'tag', + id: '2', + attributes: { + name: 'ember-data' + } + }] + }); }); var tom, sylvain; @@ -403,8 +658,28 @@ test("it is possible to remove an item from a relationship", function() { var store = env.store; run(function() { - store.push('person', { id: 1, name: "Tom Dale", tags: [1] }); - store.push('tag', { id: 1, name: "ember" }); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale' + }, + relationships: { + tags: { + data: [ + { type: 'tag', id: '1' } + ] + } + } + }, { + type: 'tag', + id: '1', + attributes: { + name: 'ember' + } + }] + }); }); run(function() { diff --git a/packages/ember-data/tests/unit/model/relationships/record-array-test.js b/packages/ember-data/tests/unit/model/relationships/record-array-test.js index 3af9030e9c7..f4ad4bc0593 100644 --- a/packages/ember-data/tests/unit/model/relationships/record-array-test.js +++ b/packages/ember-data/tests/unit/model/relationships/record-array-test.js @@ -14,7 +14,28 @@ test("updating the content of a RecordArray updates its content", function() { var records, tags, internalModel; run(function() { - records = store.pushMany('tag', [{ id: 5, name: "friendly" }, { id: 2, name: "smarmy" }, { id: 12, name: "oohlala" }]); + store.push({ + data: [{ + type: 'tag', + id: '5', + attributes: { + name: 'friendly' + } + }, { + type: 'tag', + id: '2', + attributes: { + name: 'smarmy' + } + }, { + type: 'tag', + id: '12', + attributes: { + name: 'oohlala' + } + }] + }); + records = store.peekAll('tag'); internalModel = Ember.A(records).mapBy('_internalModel'); tags = DS.RecordArray.create({ content: Ember.A(internalModel.slice(0, 2)), store: store, type: Tag }); }); @@ -47,7 +68,15 @@ test("can create child record from a hasMany relationship", function() { var store = env.store; run(function() { - store.push('person', { id: 1, name: "Tom Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tom Dale" + } + } + }); }); run(function() { diff --git a/packages/ember-data/tests/unit/model/rollback-attributes-test.js b/packages/ember-data/tests/unit/model/rollback-attributes-test.js index 66c90ffd94e..bd019c6656d 100644 --- a/packages/ember-data/tests/unit/model/rollback-attributes-test.js +++ b/packages/ember-data/tests/unit/model/rollback-attributes-test.js @@ -16,7 +16,17 @@ module("unit/model/rollbackAttributes - model.rollbackAttributes()", { test("changes to attributes can be rolled back", function() { var person; run(function() { - person = store.push('person', { id: 1, firstName: "Tom", lastName: "Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + firstName: "Tom", + lastName: "Dale" + } + } + }); + person = store.peekRecord('person', 1); person.set('firstName', "Thomas"); }); @@ -33,7 +43,16 @@ test("changes to attributes can be rolled back", function() { test("changes to unassigned attributes can be rolled back", function() { var person; run(function() { - person = store.push('person', { id: 1, lastName: "Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + lastName: "Dale" + } + } + }); + person = store.peekRecord('person', 1); person.set('firstName', "Thomas"); }); @@ -57,7 +76,17 @@ test("changes to attributes made after a record is in-flight only rolls back the var person; run(function() { - person = store.push('person', { id: 1, firstName: "Tom", lastName: "Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + firstName: "Tom", + lastName: "Dale" + } + } + }); + person = store.peekRecord('person', 1); person.set('firstName', "Thomas"); }); @@ -89,7 +118,17 @@ test("a record's changes can be made if it fails to save", function() { var person; run(function() { - person = store.push('person', { id: 1, firstName: "Tom", lastName: "Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + firstName: "Tom", + lastName: "Dale" + } + } + }); + person = store.peekRecord('person', 1); person.set('firstName', "Thomas"); }); @@ -117,7 +156,17 @@ test("a deleted record's attributes can be rollbacked if it fails to save, recor var person, people; run(function() { - person = store.push('person', { id: 1, firstName: "Tom", lastName: "Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + firstName: "Tom", + lastName: "Dale" + } + } + }); + person = store.peekRecord('person', 1); people = store.peekAll('person'); }); @@ -209,7 +258,13 @@ test("deleted record's attributes can be rollbacked", function() { var person, people; run(function() { - person = store.push('person', { id: 1 }); + store.push({ + data: { + type: 'person', + id: '1' + } + }); + person = store.peekRecord('person', 1); people = store.peekAll('person'); person.deleteRecord(); }); @@ -259,7 +314,16 @@ test("invalid record's attributes can be rollbacked", function() { env = setupStore({ dog: Dog, adapter: adapter }); var dog; run(function() { - dog = env.store.push('dog', { id: 1, name: "Pluto" }); + env.store.push({ + data: { + type: 'dog', + id: '1', + attributes: { + name: "Pluto" + } + } + }); + dog = env.store.peekRecord('dog', 1); dog.set('name', "is a dwarf planet"); }); @@ -321,7 +385,17 @@ test("invalid record's attributes rolled back to correct state after set", funct env = setupStore({ dog: Dog, adapter: adapter }); var dog; run(function() { - dog = env.store.push('dog', { id: 1, name: "Pluto", breed: "Disney" }); + env.store.push({ + data: { + type: 'dog', + id: '1', + attributes: { + name: "Pluto", + breed: "Disney" + } + } + }); + dog = env.store.peekRecord('dog', 1); dog.set('name', "is a dwarf planet"); dog.set('breed', 'planet'); }); @@ -382,7 +456,16 @@ test("when destroying a record setup the record state to invalid, the record's a env = setupStore({ dog: Dog, adapter: adapter }); var dog; run(function() { - dog = env.store.push('dog', { id: 1, name: "Pluto" }); + env.store.push({ + data: { + type: 'dog', + id: '1', + attributes: { + name: "Pluto" + } + } + }); + dog = env.store.peekRecord('dog', 1); }); run(function() { diff --git a/packages/ember-data/tests/unit/record-array-test.js b/packages/ember-data/tests/unit/record-array-test.js index e2a0ea7a413..8f9b8343029 100644 --- a/packages/ember-data/tests/unit/record-array-test.js +++ b/packages/ember-data/tests/unit/record-array-test.js @@ -20,7 +20,27 @@ test("a record array is backed by records", function() { person: Person }); run(function() { - store.pushMany('person', array); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Scumbag Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Scumbag Katz' + } + }, { + type: 'person', + id: '3', + attributes: { + name: 'Scumbag Bryn' + } + }] + }); }); run(function() { @@ -39,12 +59,28 @@ test("acts as a live query", function() { }); var recordArray = store.peekAll('person'); run(function() { - store.push('person', { id: 1, name: 'wycats' }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'wycats' + } + } + }); }); equal(get(recordArray, 'lastObject.name'), 'wycats'); run(function() { - store.push('person', { id: 2, name: 'brohuda' }); + store.push({ + data: { + type: 'person', + id: '2', + attributes: { + name: 'brohuda' + } + } + }); }); equal(get(recordArray, 'lastObject.name'), 'brohuda'); }); @@ -62,7 +98,15 @@ test("stops updating when destroyed", function() { var recordArray = store.peekAll('person'); run(function() { - store.push('person', { id: 1, name: 'wycats' }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'wycats' + } + } + }); }); run(function() { @@ -71,7 +115,15 @@ test("stops updating when destroyed", function() { run(function() { equal(recordArray.get('length'), emptyLength, "Has no more records"); - store.push('person', { id: 2, name: 'brohuda' }); + store.push({ + data: { + type: 'person', + id: '2', + attributes: { + name: 'brohuda' + } + } + }); }); equal(recordArray.get('length'), emptyLength, "Has not been updated"); @@ -100,8 +152,30 @@ test("a loaded record is removed from a record array when it is deleted", functi var store = env.store; run(function() { - store.pushMany('person', array); - store.push('tag', { id: 1 }); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Scumbag Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Scumbag Katz' + } + }, { + type: 'person', + id: '3', + attributes: { + name: 'Scumbag Bryn' + } + }, { + type: 'tag', + id: '1' + }] + }); }); run(function() { @@ -151,8 +225,27 @@ test("a loaded record is not removed from a record array when it is deleted even var scumbag, tag; run(function() { - scumbag = store.push('person', { id: 1, name: 'Scumbag Tom' }); - tag = store.push('tag', { id: 1, people: [1] }); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Scumbag Tom' + } + }, { + type: 'tag', + id: '1', + relationships: { + people: { + data: [ + { type: 'person', id: '1' } + ] + } + } + }] + }); + scumbag = store.peekRecord('person', 1); + tag = store.peekRecord('tag', 1); scumbag.deleteRecord(); }); @@ -181,9 +274,36 @@ test("a loaded record is not removed from both the record array and from the bel var scumbag, tag, tool; run(function() { - scumbag = store.push('person', { id: 1, name: 'Scumbag Tom' }); - tag = store.push('tag', { id: 1, people: [1] }); - tool = store.push('tool', { id: 1, person: 1 }); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Scumbag Tom' + } + }, { + type: 'tag', + id: '1', + relationships: { + people: { + data: [ + { type: 'person', id: '1' } + ] + } + } + }, { + type: 'tool', + id: '1', + relationships: { + person: { + data: { type: 'person', id: '1' } + } + } + }] + }); + scumbag = store.peekRecord('person', 1); + tag = store.peekRecord('tag', 1); + tool = store.peekRecord('tool', 1); }); equal(tag.get('people.length'), 1, "record is in the record array"); @@ -236,7 +356,27 @@ test("a record array returns undefined when asking for a member outside of its c }); run(function() { - store.pushMany('person', array); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Scumbag Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Scumbag Katz' + } + }, { + type: 'person', + id: '3', + attributes: { + name: 'Scumbag Bryn' + } + }] + }); }); var recordArray = store.peekAll('person'); @@ -250,7 +390,27 @@ test("a record array should be able to be enumerated in any order", function() { person: Person }); run(function() { - store.pushMany('person', array); + store.push({ + data: [{ + type: 'person', + id: '1', + attributes: { + name: 'Scumbag Dale' + } + }, { + type: 'person', + id: '2', + attributes: { + name: 'Scumbag Katz' + } + }, { + type: 'person', + id: '3', + attributes: { + name: 'Scumbag Bryn' + } + }] + }); }); var recordArray = store.peekAll('person'); diff --git a/packages/ember-data/tests/unit/store/adapter-interop-test.js b/packages/ember-data/tests/unit/store/adapter-interop-test.js index 9c25bb42a1c..4129a29c3d5 100644 --- a/packages/ember-data/tests/unit/store/adapter-interop-test.js +++ b/packages/ember-data/tests/unit/store/adapter-interop-test.js @@ -126,7 +126,15 @@ test("IDs provided as numbers are coerced to strings", function() { currentStore.findRecord('test', 1).then(async(function(object) { equal(typeof object.get('id'), 'string', "id was coerced to a string"); run(function() { - currentStore.push('test', { id: 2, name: "Scumbag Sam Saffron" }); + currentStore.push({ + data: { + type: 'test', + id: '2', + attributes: { + name: "Scumbag Sam Saffron" + } + } + }); }); return currentStore.findRecord('test', 2); })).then(async(function(object) { @@ -136,9 +144,6 @@ test("IDs provided as numbers are coerced to strings", function() { }); }); - -var array = [{ id: "1", name: "Scumbag Dale" }, { id: "2", name: "Scumbag Katz" }, { id: "3", name: "Scumbag Bryn" }]; - test("can load data for the same record if it is not dirty", function() { expect(3); @@ -151,13 +156,29 @@ test("can load data for the same record if it is not dirty", function() { }); run(function() { - store.push('person', { id: 1, name: "Tom Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tom Dale" + } + } + }); store.findRecord('person', 1).then(async(function(tom) { equal(get(tom, 'hasDirtyAttributes'), false, "precond - record is not dirty"); equal(get(tom, 'name'), "Tom Dale", "returns the correct name"); - store.push('person', { id: 1, name: "Captain Underpants" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Captain Underpants" + } + } + }); equal(get(tom, 'name'), "Captain Underpants", "updated record with new date"); })); }); @@ -175,23 +196,6 @@ test("DS.Store loads individual records without explicit IDs with a custom prima }); */ -test("pushMany extracts ids from an Array of hashes if no ids are specified", function() { - expect(1); - - var Person = DS.Model.extend({ name: DS.attr('string') }); - - var store = createStore({ - person: Person - }); - - run(function() { - store.pushMany('person', array); - store.findRecord('person', 1).then(async(function(person) { - equal(get(person, 'name'), "Scumbag Dale", "correctly extracted id for loaded data"); - })); - }); -}); - test("loadMany takes an optional Object and passes it on to the Adapter", function() { expect(2); @@ -265,7 +269,15 @@ test("peekAll(type) returns a record array of all records of a specific type", f }); run(function() { - store.push('person', { id: 1, name: "Tom Dale" }); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: "Tom Dale" + } + } + }); }); var results = store.peekAll('person'); @@ -273,7 +285,15 @@ test("peekAll(type) returns a record array of all records of a specific type", f equal(get(results.objectAt(0), 'name'), "Tom Dale", "record has the correct information"); run(function() { - store.push('person', { id: 2, name: "Yehuda Katz" }); + store.push({ + data: { + type: 'person', + id: '2', + attributes: { + name: "Yehuda Katz" + } + } + }); }); equal(get(results, 'length'), 2, "record array should have the new object"); equal(get(results.objectAt(1), 'name'), "Yehuda Katz", "record has the correct information"); @@ -418,7 +438,16 @@ test("initial values of belongsTo can be passed in as the third argument to find var tom; run(function() { - tom = store.push('person', { id: 2, name: 'Tom' }); + store.push({ + data: { + type: 'person', + id: '2', + attributes: { + name: 'Tom' + } + } + }); + tom = store.peekRecord('person', 2); store.findRecord('person', 1, { preload: { friend: tom } }); }); }); @@ -476,7 +505,16 @@ test("initial values of hasMany can be passed in as the third argument to find a var tom; run(function() { - tom = store.push('person', { id: 2, name: 'Tom' }); + store.push({ + data: { + type: 'person', + id: '2', + attributes: { + name: 'Tom' + } + } + }); + tom = store.peekRecord('person', 2); store.findRecord('person', 1, { preload: { friends: [tom] } }); }); }); @@ -866,7 +904,12 @@ test("store should not reload record when shouldReloadRecord returns false", fun }); run(function() { - store.push('person', { id: 1 }); + store.push({ + data: { + type: 'person', + id: '1' + } + }); store.findRecord('person', 1); }); }); @@ -895,7 +938,12 @@ test("store should reload record when shouldReloadRecord returns true", function }); run(function() { - store.push('person', { id: 1 }); + store.push({ + data: { + type: 'person', + id: '1' + } + }); store.findRecord('person', 1).then(function(record) { equal(record.get('name'), 'Tom'); }); @@ -928,7 +976,12 @@ test("store should not call shouldBackgroundReloadRecord when the store is alrea }); run(function() { - store.push('person', { id: 1 }); + store.push({ + data: { + type: 'person', + id: '1' + } + }); store.findRecord('person', 1).then(function(record) { equal(record.get('name'), 'Tom'); }); @@ -959,7 +1012,12 @@ test("store should not reload a record when `shouldBackgroundReloadRecord` is fa }); run(function() { - store.push('person', { id: 1 }); + store.push({ + data: { + type: 'person', + id: '1' + } + }); store.findRecord('person', 1).then(function(record) { equal(record.get('name'), undefined); }); @@ -991,7 +1049,12 @@ test("store should reload the record in the background when `shouldBackgroundRel }); run(function() { - store.push('person', { id: 1 }); + store.push({ + data: { + type: 'person', + id: '1' + } + }); store.findRecord('person', 1).then(function(record) { equal(record.get('name'), undefined); }); diff --git a/packages/ember-data/tests/unit/store/create-record-test.js b/packages/ember-data/tests/unit/store/create-record-test.js index 8ad6f32b7dc..c43e62a693c 100644 --- a/packages/ember-data/tests/unit/store/create-record-test.js +++ b/packages/ember-data/tests/unit/store/create-record-test.js @@ -33,7 +33,22 @@ test("doesn't modify passed in properties hash", function() { test("allow passing relationships as well as attributes", function() { var records, storage; run(function() { - records = store.pushMany('record', [{ id: 1, title: "it's a beautiful day" }, { id: 2, title: "it's a beautiful day" }]); + store.push({ + data: [{ + type: 'record', + id: '1', + attributes: { + title: "it's a beautiful day" + } + }, { + type: 'record', + id: '2', + attributes: { + title: "it's a beautiful day" + } + }] + }); + records = store.peekAll('record'); storage = store.createRecord('storage', { name: 'Great store', records: records }); }); diff --git a/packages/ember-data/tests/unit/store/has_record_for_id_test.js b/packages/ember-data/tests/unit/store/has_record_for_id_test.js index a865c3ee3d5..8289a2bda9d 100644 --- a/packages/ember-data/tests/unit/store/has_record_for_id_test.js +++ b/packages/ember-data/tests/unit/store/has_record_for_id_test.js @@ -41,11 +41,22 @@ module("unit/store/hasRecordForId - Store hasRecordForId", { test("hasRecordForId should return false for records in the empty state ", function() { run(function() { - store.push('person', { - id: 1, - firstName: "Yehuda", - lastName: "Katz", - phoneNumbers: [1] + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + firstName: "Yehuda", + lastName: "Katz" + }, + relationships: { + phoneNumbers: { + data: [ + { type: 'phone-number', id: '1' } + ] + } + } + } }); equal(false, store.hasRecordForId('phone-number', 1), 'hasRecordForId only returns true for loaded records'); @@ -55,11 +66,22 @@ test("hasRecordForId should return false for records in the empty state ", funct test("hasRecordForId should return true for records in the loaded state ", function() { run(function() { - store.push('person', { - id: 1, - firstName: "Yehuda", - lastName: "Katz", - phoneNumbers: [1] + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + firstName: "Yehuda", + lastName: "Katz" + }, + relationships: { + phoneNumbers: { + data: [ + { type: 'phone-number', id: '1' } + ] + } + } + } }); equal(true, store.hasRecordForId('person', 1), 'hasRecordForId returns true for records loaded into the store'); diff --git a/packages/ember-data/tests/unit/store/metadata-for-test.js b/packages/ember-data/tests/unit/store/metadata-for-test.js deleted file mode 100644 index 45ebd5e6a65..00000000000 --- a/packages/ember-data/tests/unit/store/metadata-for-test.js +++ /dev/null @@ -1,53 +0,0 @@ -var store; - -var run = Ember.run; - -module("unit/store/metadata_for - DS.Store#metadataFor", { - setup: function() { - store = createStore({ - post: DS.Model.extend(), - comment: DS.Model.extend() - }); - }, - - teardown: function() { - run(function() { - store.destroy(); - }); - } -}); - -test("metaForType should be deprecated", function() { - expect(1); - - expectDeprecation(function() { - store.metaForType('post', { foo: 'bar' }); - }); -}); - -test("metadataFor and setMetadataFor should return and set correct metadata", function() { - expect(7); - - function metadataKeys(type) { - return Object.keys(store.metadataFor(type)); - } - - // Currently not using QUnit.deepEqual due to the way deepEqual - // comparing __proto__. In its check to see if an object has - // no proto, it checks strict equality on null instead of null or undefined. - - deepEqual(metadataKeys('post'), [], 'Metadata for post is initially empty'); - - store.setMetadataFor('post', { foo: 'bar' }); - - deepEqual(metadataKeys('post'), ['foo'], 'metadata for post contains foo:bar'); - equal(store.metadataFor('post').foo, 'bar'); - - store.setMetadataFor('post', { hello: 'world' }); - - deepEqual(metadataKeys('post'), ['foo', 'hello']); - equal(store.metadataFor('post').foo, 'bar', 'keeps original metadata'); - equal(store.metadataFor('post').hello, 'world', 'merges new metadata'); - - deepEqual(metadataKeys('comment'), [], 'metadata for comment is empty'); -}); diff --git a/packages/ember-data/tests/unit/store/peek-record-test.js b/packages/ember-data/tests/unit/store/peek-record-test.js index e9c256a6b58..b3e8754d6b1 100644 --- a/packages/ember-data/tests/unit/store/peek-record-test.js +++ b/packages/ember-data/tests/unit/store/peek-record-test.js @@ -22,7 +22,12 @@ module("unit/store/peekRecord - Store peekRecord", { test("peekRecord should return the record if it is in the store ", function() { run(function() { - var person = store.push('person', { id: 1 }); + var person = store.push({ + data: { + type: 'person', + id: '1' + } + }); equal(person, store.peekRecord('person', 1), 'peekRecord only return the corresponding record in the store'); }); }); diff --git a/packages/ember-data/tests/unit/store/push-test.js b/packages/ember-data/tests/unit/store/push-test.js index bd10b941a5b..9f38f2d7516 100644 --- a/packages/ember-data/tests/unit/store/push-test.js +++ b/packages/ember-data/tests/unit/store/push-test.js @@ -53,11 +53,13 @@ test("Calling push with a normalized hash returns a record", function() { run(function() { var person = store.push({ - type: 'person', - id: 'wat', - attributes: { - firstName: 'Yehuda', - lastName: 'Katz' + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz' + } } }); store.findRecord('person', 'wat').then(function(foundPerson) { @@ -79,11 +81,13 @@ test("Supplying a model class for `push` is the same as supplying a string", fun run(function() { store.push({ - type: 'programmer', - id: 'wat', - attributes: { - firstName: 'Yehuda', - lastName: 'Katz' + data: { + type: 'programmer', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz' + } } }); @@ -108,42 +112,41 @@ test("Calling push triggers `didLoad` even if the record hasn't been requested f run(function() { store.push({ - type: 'person', - id: 'wat', - attributes: { - firstName: 'Yehuda', - lastName: 'Katz' + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz' + } } }); }); }); -test("Calling update should be deprecated", function() { - expectDeprecation(function() { - run(function() { - store.update('person', { id: '1', firstName: 'Yehuda', lastName: 'Katz' }); - }); - }); -}); - test("Calling push with partial records updates just those attributes", function() { expect(2); run(function() { - var person = store.push({ - type: 'person', - id: 'wat', - attributes: { - firstName: 'Yehuda', - lastName: 'Katz' + store.push({ + data: { + type: 'person', + id: 'wat', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz' + } } }); + var person = store.peekRecord('person', 'wat'); store.push({ - type: 'person', - id: 'wat', - attributes: { - lastName: "Katz!" + data: { + type: 'person', + id: 'wat', + attributes: { + lastName: "Katz!" + } } }); @@ -184,33 +187,6 @@ test("Calling push on normalize allows partial updates with raw JSON", function equal(person.get('lastName'), "Jackson", "existing fields are untouched"); }); -test("Calling push with a normalized hash containing related records returns a record", function() { - var number1, number2, person; - run(function() { - number1 = store.push('phone-number', { - id: 1, - number: '5551212', - person: 'wat' - }); - - number2 = store.push('phone-number', { - id: 2, - number: '5552121', - person: 'wat' - }); - - person = store.push('person', { - id: 'wat', - firstName: 'John', - lastName: 'Smith', - phoneNumbers: [number1, number2] - }); - }); - - - deepEqual(person.get('phoneNumbers').toArray(), [number1, number2], "phoneNumbers array is correct"); -}); - test("Calling push with a normalized hash containing IDs of related records returns a record", function() { expect(1); @@ -539,7 +515,17 @@ test('calling push with hasMany relationship the value must be an array', functi invalidValues.forEach(function(invalidValue) { throws(function() { run(function() { - store.push('person', { id: 1, phoneNumbers: invalidValue }); + store.push({ + data: { + type: 'person', + id: '1', + relationships: { + phoneNumbers: { + data: invalidValue + } + } + } + }); }); }, /must be an array/); }); @@ -557,33 +543,30 @@ test('calling push with missing or invalid `id` throws assertion error', functio invalidValues.forEach(function(invalidValue) { throws(function() { run(function() { - store.push('person', invalidValue); + store.push({ + data: invalidValue + }); }); - }, /You must include an `id`/); + }, /You must include an 'id'/); }); }); test('calling push with belongsTo relationship the value must not be an array', function() { throws(function() { run(function() { - store.push('phone-number', { id: 1, person: [1] }); - }); - }, /must not be an array/); -}); - -test('calling push with an embedded relationship throws a useful error', function() { - throws(function() { - run(function() { - store.push('person', { - id: 1, - firstName: 'Ada', - lastName: 'Lovelace', - phoneNumbers: [ - { number: '5551212', person: 1 } - ] + store.push({ + data: { + type: 'phone-number', + id: '1', + relationships: { + person: { + data: [1] + } + } + } }); }); - }, /If this is an embedded relationship/); + }, /must not be an array/); }); test("Enabling Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS should warn on unknown keys", function() { @@ -592,11 +575,16 @@ test("Enabling Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS should warn on unknown keys", f try { Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS = true; warns(function() { - store.push('person', { - id: '1', - firstName: 'Tomster', - emailAddress: 'tomster@emberjs.com', - isMascot: true + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + firstName: 'Tomster', + emailAddress: 'tomster@emberjs.com', + isMascot: true + } + } }); }); } finally { @@ -608,41 +596,21 @@ test("Enabling Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS should warn on unknown keys", f test("Calling push with unknown keys should not warn by default", function() { noWarns(function() { run(function() { - store.push('person', { - id: '1', - firstName: 'Tomster', - emailAddress: 'tomster@emberjs.com', - isMascot: true + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + firstName: 'Tomster', + emailAddress: 'tomster@emberjs.com', + isMascot: true + } + } }); }); }, /The payload for 'person' contains these unknown keys: \[emailAddress,isMascot\]. Make sure they've been defined in your model./); }); -test("Calling pushMany is deprecated", function() { - var person1, person2; - expectDeprecation(function() { - run(function() { - person1 = { id: 1, firstName: 'John', lastName: 'Smith' }; - person2 = { id: 2, firstName: 'Suzie', lastName: 'Q' }; - - store.pushMany('person', [person1, person2]); - }); - }, 'Using store.pushMany() has been deprecated since store.push() now handles multiple items. You should use store.push() instead.'); -}); - - -test("Calling push(type, data) is deprecated", function() { - var person1; - expectDeprecation(function() { - run(function() { - person1 = { id: 1, firstName: 'John', lastName: 'Smith' }; - - store.push('person', person1); - }); - }, /store.push\(type, data\) has been deprecated/); -}); - - module("unit/store/push - DS.Store#push with JSON-API", { setup: function() { var Person = DS.Model.extend({ diff --git a/packages/ember-data/tests/unit/store/unload-test.js b/packages/ember-data/tests/unit/store/unload-test.js index 122ef2197ca..17749433328 100644 --- a/packages/ember-data/tests/unit/store/unload-test.js +++ b/packages/ember-data/tests/unit/store/unload-test.js @@ -29,9 +29,14 @@ test("unload a dirty record", function() { expect(2); run(function() { - store.push('record', { - id: 1, - title: 'toto' + store.push({ + data: { + type: 'record', + id: '1', + attributes: { + title: 'toto' + } + } }); store.findRecord('record', 1).then(function(record) { @@ -56,7 +61,15 @@ test("unload a record", function() { expect(5); run(function() { - store.push('record', { id: 1, title: 'toto' }); + store.push({ + data: { + type: 'record', + id: '1', + attributes: { + title: 'toto' + } + } + }); store.findRecord('record', 1).then(function(record) { equal(get(record, 'id'), 1, "found record with id 1"); equal(get(record, 'hasDirtyAttributes'), false, "record is not dirty"); @@ -113,8 +126,27 @@ test("can commit store after unload record with relationships", function() { var asyncRecords; run(function() { - store.push('brand', { id: 1, name: 'EmberJS' }); - store.push('product', { id: 1, description: 'toto', brand: 1 }); + store.push({ + data: [{ + type: 'brand', + id: '1', + attributes: { + name: 'EmberJS' + } + }, { + type: 'product', + id: '1', + attributes: { + description: 'toto' + }, + relationships: { + brand: { + data: { type: 'brand', id: '1' } + } + } + }] + }); + asyncRecords = Ember.RSVP.hash({ brand: store.findRecord('brand', 1), product: store.findRecord('product', 1) diff --git a/packages/ember-data/tests/unit/utils-test.js b/packages/ember-data/tests/unit/utils-test.js index 083f13e51e4..8e9546ba64b 100644 --- a/packages/ember-data/tests/unit/utils-test.js +++ b/packages/ember-data/tests/unit/utils-test.js @@ -38,9 +38,27 @@ test("assertPolymorphicType works for subclasses", function() { var user, post, person; Ember.run(function() { - user = env.store.push('user', { id: 1, messages: [] }); - post = env.store.push('post', { id: 1 }); - person = env.store.push('person', { id: 1 }); + env.store.push({ + data: [{ + type: 'user', + id: '1', + relationships: { + messages: { + data: [] + } + } + }, { + type: 'post', + id: '1' + }, { + type: 'person', + id: '1' + }] + }); + + user = env.store.peekRecord('user', 1); + post = env.store.peekRecord('post', 1); + person = env.store.peekRecord('person', 1); }); // TODO un-comment once we test the assertPolymorphicType directly @@ -74,9 +92,21 @@ test("assertPolymorphicType works for mixins", function() { var post, video, person; Ember.run(function() { - post = env.store.push('post', { id: 1 }); - video = env.store.push('video', { id: 1 }); - person = env.store.push('person', { id: 1 }); + env.store.push({ + data: [{ + type: 'post', + id: '1' + }, { + type: 'video', + id: '1' + }, { + type: 'person', + id: '1' + }] + }); + post = env.store.peekRecord('post', 1); + video = env.store.peekRecord('video', 1); + person = env.store.peekRecord('person', 1); }); // TODO un-comment once we test the assertPolymorphicType directly