diff --git a/addon/-private/system/model/internal-model.js b/addon/-private/system/model/internal-model.js index 6cfab4699b6..236dd1617af 100644 --- a/addon/-private/system/model/internal-model.js +++ b/addon/-private/system/model/internal-model.js @@ -106,6 +106,7 @@ export default function InternalModel(type, id, store, _, data) { this.recordReference = new RecordReference(store, this); this.references = {}; this.isReloading = false; + this._isDestroyed = false; this.isError = false; this.error = null; this.__ember_meta__ = null; @@ -272,7 +273,12 @@ InternalModel.prototype = { } }, + get isDestroyed() { + return this._isDestroyed; + }, + destroy() { + this._isDestroyed = true; if (this.record) { return this.record.destroy(); } diff --git a/addon/-private/system/model/states.js b/addon/-private/system/model/states.js index 934d6e4fa6d..23fddd3ae71 100644 --- a/addon/-private/system/model/states.js +++ b/addon/-private/system/model/states.js @@ -4,7 +4,7 @@ import Ember from 'ember'; import { assert } from "ember-data/-private/debug"; -var get = Ember.get; +const { get } = Ember; /* This file encapsulates the various states that a record can transition through during its lifecycle. @@ -224,7 +224,7 @@ function didSetProperty(internalModel, context) { // but the adapter has not yet acknowledged success. // `invalid`: the record has invalid information and cannot be // sent to the adapter yet. -var DirtyState = { +const DirtyState = { initialState: 'uncommitted', // FLAGS @@ -237,11 +237,11 @@ var DirtyState = { // have not yet begun to be saved, and are not invalid. uncommitted: { // EVENTS - didSetProperty: didSetProperty, + didSetProperty, //TODO(Igor) reloading now triggers a //loadingData event, though it seems fine? - loadingData: Ember.K, + loadingData() { }, propertyWasReset(internalModel, name) { if (!internalModel.hasChangedAttributes()) { internalModel.send('rolledBack'); } @@ -257,7 +257,7 @@ var DirtyState = { heimdall.stop(token); }, - becomeDirty: Ember.K, + becomeDirty() { }, willCommit(internalModel) { internalModel.transitionTo('inFlight'); @@ -289,20 +289,18 @@ var DirtyState = { isSaving: true, // EVENTS - didSetProperty: didSetProperty, - becomeDirty: Ember.K, - pushedData: Ember.K, + didSetProperty, + becomeDirty() { }, + pushedData() { }, unloadRecord: assertAgainstUnloadRecord, // TODO: More robust semantics around save-while-in-flight - willCommit: Ember.K, + willCommit() { }, didCommit(internalModel) { - var dirtyType = get(this, 'dirtyType'); - internalModel.transitionTo('saved'); - internalModel.send('invokeLifecycleCallbacks', dirtyType); + internalModel.send('invokeLifecycleCallbacks', this.dirtyType); }, becameInvalid(internalModel) { @@ -337,9 +335,9 @@ var DirtyState = { } }, - becameInvalid: Ember.K, - becomeDirty: Ember.K, - pushedData: Ember.K, + becameInvalid() { }, + becomeDirty() { }, + pushedData() { }, willCommit(internalModel) { internalModel.clearErrorMessages(); @@ -367,10 +365,10 @@ var DirtyState = { // necessary. function deepClone(object) { - var clone = {}; - var value; + const clone = {}; + let value; - for (var prop in object) { + for (let prop in object) { value = object[prop]; if (value && typeof value === 'object') { clone[prop] = deepClone(value); @@ -383,7 +381,7 @@ function deepClone(object) { } function mixin(original, hash) { - for (var prop in hash) { + for (let prop in hash) { original[prop] = hash[prop]; } @@ -395,7 +393,7 @@ function dirtyState(options) { return mixin(newState, options); } -var createdState = dirtyState({ +const createdState = dirtyState({ dirtyType: 'created', // FLAGS isNew: true @@ -404,11 +402,12 @@ var createdState = dirtyState({ createdState.invalid.rolledBack = function(internalModel) { internalModel.transitionTo('deleted.saved'); }; + createdState.uncommitted.rolledBack = function(internalModel) { internalModel.transitionTo('deleted.saved'); }; -var updatedState = dirtyState({ +const updatedState = dirtyState({ dirtyType: 'updated' }); @@ -443,7 +442,7 @@ updatedState.uncommitted.deleteRecord = function(internalModel) { internalModel.transitionTo('deleted.uncommitted'); }; -var RootState = { +const RootState = { // FLAGS isEmpty: false, isLoading: false, @@ -460,7 +459,7 @@ var RootState = { // doesn't change your state. For example, if you're in the // in-flight state, rolling back the record doesn't move // you out of the in-flight state. - rolledBack: Ember.K, + rolledBack() { }, unloadRecord(internalModel) { // clear relationships before moving to deleted state // otherwise it fails @@ -468,8 +467,7 @@ var RootState = { internalModel.transitionTo('deleted.saved'); }, - - propertyWasReset: Ember.K, + propertyWasReset() { }, // SUBSTATES @@ -542,7 +540,7 @@ var RootState = { //TODO(Igor) Reloading now triggers a loadingData event, //but it should be ok? - loadingData: Ember.K, + loadingData() { }, // SUBSTATES @@ -556,9 +554,9 @@ var RootState = { }, // EVENTS - didSetProperty: didSetProperty, + didSetProperty, - pushedData: Ember.K, + pushedData() { }, becomeDirty(internalModel) { internalModel.transitionTo('updated.uncommitted'); @@ -589,8 +587,7 @@ var RootState = { // loaded.saved.notFound would be triggered by a failed // `reload()` on an unchanged record - notFound: Ember.K - + notFound() { } }, // A record is in this state after it has been locally @@ -637,9 +634,9 @@ var RootState = { internalModel.triggerLater('ready'); }, - pushedData: Ember.K, - becomeDirty: Ember.K, - deleteRecord: Ember.K, + pushedData() { }, + becomeDirty() { }, + deleteRecord() { }, rolledBack(internalModel) { internalModel.transitionTo('loaded.saved'); @@ -660,7 +657,7 @@ var RootState = { unloadRecord: assertAgainstUnloadRecord, // TODO: More robust semantics around save-while-in-flight - willCommit: Ember.K, + willCommit() { }, didCommit(internalModel) { internalModel.transitionTo('saved'); @@ -696,9 +693,8 @@ var RootState = { internalModel.triggerLater('didCommit', internalModel); }, - willCommit: Ember.K, - - didCommit: Ember.K + willCommit() { }, + didCommit() { } }, invalid: { @@ -714,10 +710,10 @@ var RootState = { } }, - becameInvalid: Ember.K, - becomeDirty: Ember.K, - deleteRecord: Ember.K, - willCommit: Ember.K, + becameInvalid() { }, + becomeDirty() { }, + deleteRecord() { }, + willCommit() { }, rolledBack(internalModel) { @@ -750,16 +746,14 @@ function wireState(object, parent, name) { object.parentState = parent; object.stateName = name; - for (var prop in object) { + for (let prop in object) { if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') { continue; } if (typeof object[prop] === 'object') { - object[prop] = wireState(object[prop], object, name + "." + prop); + object[prop] = wireState(object[prop], object, name + '.' + prop); } } return object; } -RootState = wireState(RootState, null, "root"); - -export default RootState; +export default wireState(RootState, null, 'root'); diff --git a/addon/-private/system/record-array-manager.js b/addon/-private/system/record-array-manager.js index 4c40c396de9..1b44f1279d3 100644 --- a/addon/-private/system/record-array-manager.js +++ b/addon/-private/system/record-array-manager.js @@ -8,9 +8,8 @@ import { FilteredRecordArray, AdapterPopulatedRecordArray } from "ember-data/-private/system/record-arrays"; -var MapWithDefault = Ember.MapWithDefault; +const { get, MapWithDefault } = Ember; import OrderedSet from "ember-data/-private/system/ordered-set"; -var get = Ember.get; const { _addRecordToRecordArray, @@ -68,9 +67,7 @@ export default Ember.Object.extend({ }); this.liveRecordArrays = MapWithDefault.create({ - defaultValue: (typeClass) => { - return this.createRecordArray(typeClass); - } + defaultValue: typeClass => this.createRecordArray(typeClass) }); this.changedRecords = []; @@ -102,9 +99,10 @@ export default Ember.Object.extend({ */ updateRecordArrays() { heimdall.increment(updateRecordArrays); - this.changedRecords.forEach((internalModel) => { - if (get(internalModel, 'record.isDestroyed') || get(internalModel, 'record.isDestroying') || - (get(internalModel, 'currentState.stateName') === 'root.deleted.saved')) { + this.changedRecords.forEach(internalModel => { + + if (internalModel.isDestroyed || + internalModel.currentState.stateName === 'root.deleted.saved') { this._recordWasDeleted(internalModel); } else { this._recordWasChanged(internalModel); @@ -116,11 +114,11 @@ export default Ember.Object.extend({ _recordWasDeleted(record) { heimdall.increment(_recordWasDeleted); - var recordArrays = record._recordArrays; + let recordArrays = record._recordArrays; if (!recordArrays) { return; } - recordArrays.forEach((array) => array.removeInternalModel(record)); + recordArrays.forEach(array => array.removeInternalModel(record)); record._recordArrays = null; }, @@ -128,10 +126,10 @@ export default Ember.Object.extend({ _recordWasChanged(record) { heimdall.increment(_recordWasChanged); - var typeClass = record.type; - var recordArrays = this.filteredRecordArrays.get(typeClass); - var filter; - recordArrays.forEach((array) => { + let typeClass = record.type; + let recordArrays = this.filteredRecordArrays.get(typeClass); + let filter; + recordArrays.forEach(array => { filter = get(array, 'filterFunction'); this.updateFilterRecordArray(array, filter, typeClass, record); }); @@ -140,17 +138,17 @@ export default Ember.Object.extend({ //Need to update live arrays on loading recordWasLoaded(record) { heimdall.increment(recordWasLoaded); - var typeClass = record.type; - var recordArrays = this.filteredRecordArrays.get(typeClass); - var filter; + let typeClass = record.type; + let recordArrays = this.filteredRecordArrays.get(typeClass); + let filter; - recordArrays.forEach((array) => { + recordArrays.forEach(array => { filter = get(array, 'filterFunction'); this.updateFilterRecordArray(array, filter, typeClass, record); }); if (this.liveRecordArrays.has(typeClass)) { - var liveRecordArray = this.liveRecordArrays.get(typeClass); + let liveRecordArray = this.liveRecordArrays.get(typeClass); this._addRecordToRecordArray(liveRecordArray, record); } }, @@ -165,8 +163,8 @@ export default Ember.Object.extend({ */ updateFilterRecordArray(array, filter, typeClass, record) { heimdall.increment(updateFilterRecordArray); - var shouldBeInArray = filter(record.getRecord()); - var recordArrays = this.recordArraysForRecord(record); + let shouldBeInArray = filter(record.getRecord()); + let recordArrays = this.recordArraysForRecord(record); if (shouldBeInArray) { this._addRecordToRecordArray(array, record); } else { @@ -177,7 +175,7 @@ export default Ember.Object.extend({ _addRecordToRecordArray(array, record) { heimdall.increment(_addRecordToRecordArray); - var recordArrays = this.recordArraysForRecord(record); + let recordArrays = this.recordArraysForRecord(record); if (!recordArrays.has(array)) { array.addInternalModel(record); recordArrays.add(array); @@ -186,11 +184,11 @@ export default Ember.Object.extend({ populateLiveRecordArray(array, modelName) { heimdall.increment(populateLiveRecordArray); - var typeMap = this.store.typeMapFor(modelName); - var records = typeMap.records; - var record; + let typeMap = this.store.typeMapFor(modelName); + let records = typeMap.records; + let record; - for (var i = 0; i < records.length; i++) { + for (let i = 0; i < records.length; i++) { record = records[i]; if (!record.isDeleted() && !record.isEmpty()) { @@ -213,11 +211,11 @@ export default Ember.Object.extend({ */ updateFilter(array, modelName, filter) { heimdall.increment(updateFilter); - var typeMap = this.store.typeMapFor(modelName); - var records = typeMap.records; - var record; + let typeMap = this.store.typeMapFor(modelName); + let records = typeMap.records; + let record; - for (var i = 0; i < records.length; i++) { + for (let i = 0; i < records.length; i++) { record = records[i]; if (!record.isDeleted() && !record.isEmpty()) { @@ -248,15 +246,13 @@ export default Ember.Object.extend({ */ createRecordArray(typeClass) { heimdall.increment(createRecordArray); - var array = RecordArray.create({ + return RecordArray.create({ type: typeClass, content: Ember.A(), store: this.store, isLoaded: true, manager: this }); - - return array; }, /** @@ -270,7 +266,7 @@ export default Ember.Object.extend({ */ createFilteredRecordArray(typeClass, filter, query) { heimdall.increment(createFilteredRecordArray); - var array = FilteredRecordArray.create({ + let array = FilteredRecordArray.create({ query: query, type: typeClass, content: Ember.A(), @@ -294,7 +290,7 @@ export default Ember.Object.extend({ */ createAdapterPopulatedRecordArray(typeClass, query) { heimdall.increment(createAdapterPopulatedRecordArray); - var array = AdapterPopulatedRecordArray.create({ + let array = AdapterPopulatedRecordArray.create({ type: typeClass, query: query, content: Ember.A(), @@ -320,7 +316,7 @@ export default Ember.Object.extend({ */ registerFilteredRecordArray(array, typeClass, filter) { heimdall.increment(registerFilteredRecordArray); - var recordArrays = this.filteredRecordArrays.get(typeClass); + let recordArrays = this.filteredRecordArrays.get(typeClass); recordArrays.push(array); this.updateFilter(array, typeClass, filter); @@ -335,32 +331,32 @@ export default Ember.Object.extend({ */ unregisterRecordArray(array) { heimdall.increment(unregisterRecordArray); - var typeClass = array.type; + + let typeClass = array.type; // unregister filtered record array - const recordArrays = this.filteredRecordArrays.get(typeClass); - const removedFromFiltered = remove(recordArrays, array); + let recordArrays = this.filteredRecordArrays.get(typeClass); + let removedFromFiltered = remove(recordArrays, array); // remove from adapter populated record array - const removedFromAdapterPopulated = remove(this._adapterPopulatedRecordArrays, array); + let removedFromAdapterPopulated = remove(this._adapterPopulatedRecordArrays, array); if (!removedFromFiltered && !removedFromAdapterPopulated) { // unregister live record array if (this.liveRecordArrays.has(typeClass)) { - var liveRecordArrayForType = this.liveRecordArrayFor(typeClass); + let liveRecordArrayForType = this.liveRecordArrayFor(typeClass); if (array === liveRecordArrayForType) { this.liveRecordArrays.delete(typeClass); } } - } }, willDestroy() { this._super(...arguments); - this.filteredRecordArrays.forEach((value) => flatten(value).forEach(destroy)); + this.filteredRecordArrays.forEach(value => flatten(value).forEach(destroy)); this.liveRecordArrays.forEach(destroy); this._adapterPopulatedRecordArrays.forEach(destroy); } @@ -372,10 +368,10 @@ function destroy(entry) { function flatten(list) { heimdall.increment(array_flatten); - var length = list.length; - var result = Ember.A(); + let length = list.length; + let result = []; - for (var i = 0; i < length; i++) { + for (let i = 0; i < length; i++) { result = result.concat(list[i]); } @@ -384,7 +380,7 @@ function flatten(list) { function remove(array, item) { heimdall.increment(array_remove); - const index = array.indexOf(item); + let index = array.indexOf(item); if (index !== -1) { array.splice(index, 1); diff --git a/tests/integration/filter-test.js b/tests/integration/filter-test.js index 3f359de96d6..7d650812499 100644 --- a/tests/integration/filter-test.js +++ b/tests/integration/filter-test.js @@ -1,164 +1,164 @@ import setupStore from 'dummy/tests/helpers/store'; import Ember from 'ember'; -import {module, test} from 'qunit'; +import { module, test } from 'qunit'; import DS from 'ember-data'; import customAdapter from 'dummy/tests/helpers/custom-adapter'; -var get = Ember.get; -var set = Ember.set; -var run = Ember.run; +const { + get, + set, + run +} = Ember; -var Person, store, env, array, recordArray; +let store, env, data, recordArray; -module("integration/filter - DS.Model updating", { +const Person = DS.Model.extend({ + name: DS.attr('string'), + bestFriend: DS.belongsTo('person', { inverse: null, async: false }), + upperName: Ember.computed('name', function() { + return this.get('name').toUpperCase(); + }).readOnly() +}); + +module('integration/filter - DS.Model updating', { beforeEach() { - array = [{ - id: '1', - type: 'person', - attributes: { - name: 'Scumbag Dale' - }, - relationships: { - bestFriend: { - data: { - id: '2', - type: 'person' + data = [ + { + id: '1', + type: 'person', + attributes: { + name: 'Scumbag Dale' + }, + relationships: { + bestFriend: { + data: { + id: '2', + type: 'person' + } } } + }, + { + id: '2', + type: 'person', + attributes: { + name: 'Scumbag Katz' + } + }, + { + id: '3', + type: 'person', + attributes: { + name: 'Scumbag Bryn' + } } - }, { - id: '2', - type: 'person', - attributes: { - name: 'Scumbag Katz' - } - }, { - id: '3', - type: 'person', - attributes: { - name: 'Scumbag Bryn' - } - }]; - Person = DS.Model.extend({ name: DS.attr('string'), bestFriend: DS.belongsTo('person', { inverse: null, async: false }) }); + ]; env = setupStore({ person: Person }); store = env.store; }, + afterEach() { + edited = null; + data = null; + run(store, 'destroy'); - Person = null; - array = null; } }); function tapFn(fn, callback) { - var old_fn = fn; + const old_fn = fn; - var new_fn = function() { - var result = old_fn.apply(this, arguments); + function new_fn() { + let result = old_fn.apply(this, arguments); if (callback) { callback.apply(fn, arguments); } new_fn.summary.called.push(arguments); return result; - }; + } new_fn.summary = { called: [] }; return new_fn; } -test("when a DS.Model updates its attributes, its changes affect its filtered Array membership", function(assert) { - run(function() { - store.push({ data: array }); - }); - var people; +test('when a DS.Model updates its attributes, its changes affect its filtered Array membership', function(assert) { + run(() => store.push({ data })); - run(function() { - people = store.filter('person', function(hash) { - if (hash.get('name').match(/Katz$/)) { return true; } + let people = run(() => { + return store.filter('person', hash => { + if (hash.get('name').match(/Katz$/)) { + return true; + } }); }); - run(function() { - assert.equal(get(people, 'length'), 1, "precond - one item is in the RecordArray"); - }); + assert.equal(get(people, 'length'), 1, 'precond - one item is in the RecordArray'); - var person = people.objectAt(0); + const person = people.objectAt(0); - assert.equal(get(person, 'name'), "Scumbag Katz", "precond - the item is correct"); + assert.equal(get(person, 'name'), 'Scumbag Katz', 'precond - the item is correct'); - run(function() { - set(person, 'name', "Yehuda Katz"); - }); + run(() => set(person, 'name', 'Yehuda Katz')); - assert.equal(get(people, 'length'), 1, "there is still one item"); - assert.equal(get(person, 'name'), "Yehuda Katz", "it has the updated item"); + assert.equal(get(people, 'length'), 1, 'there is still one item'); + assert.equal(get(person, 'name'), 'Yehuda Katz', "it has the updated item"); - run(function() { - set(person, 'name', "Yehuda Katz-Foo"); - }); + run(() => set(person, 'name', 'Yehuda Katz-Foo')); assert.equal(get(people, 'query'), null, 'expected no query object set'); - assert.equal(get(people, 'length'), 0, "there are now no items"); + assert.equal(get(people, 'length'), 0, 'there are now no items'); }); -test("when a DS.Model updates its relationships, its changes affect its filtered Array membership", function(assert) { - run(function() { - store.push({ data: array }); - }); - var people; +test('when a DS.Model updates its relationships, its changes affect its filtered Array membership', function(assert) { + run(() => store.push({ data })); - run(function() { - people = store.filter('person', function(person) { - if (person.get('bestFriend') && person.get('bestFriend.name').match(/Katz$/)) { return true; } + let people = run(() => { + return store.filter('person', person => { + if (person.get('bestFriend') && person.get('bestFriend.name').match(/Katz$/)) { + return true; + } }); }); - run(function() { - assert.equal(get(people, 'length'), 1, "precond - one item is in the RecordArray"); - }); + run(() => assert.equal(get(people, 'length'), 1, 'precond - one item is in the RecordArray')); - var person = people.objectAt(0); + let person = people.objectAt(0); - assert.equal(get(person, 'name'), "Scumbag Dale", "precond - the item is correct"); + assert.equal(get(person, 'name'), 'Scumbag Dale', 'precond - the item is correct'); - run(function() { - set(person, 'bestFriend', null); - }); + run(() => set(person, 'bestFriend', null)); - assert.equal(get(people, 'length'), 0, "there are now 0 items"); + assert.equal(get(people, 'length'), 0, 'there are now 0 items'); - var erik = store.peekRecord('person', 3); - var yehuda = store.peekRecord('person', 2); - run(function() { - erik.set('bestFriend', yehuda); - }); + let erik = store.peekRecord('person', 3); + let yehuda = store.peekRecord('person', 2); + + run(() => erik.set('bestFriend', yehuda)); person = people.objectAt(0); - assert.equal(get(people, 'length'), 1, "there is now 1 item"); - assert.equal(get(person, 'name'), "Scumbag Bryn", "precond - the item is correct"); + assert.equal(get(people, 'length'), 1, 'there is now 1 item'); + assert.equal(get(person, 'name'), 'Scumbag Bryn', 'precond - the item is correct'); }); +test('a record array can have a filter on it', function(assert) { + run(() => store.push({ data })); -test("a record array can have a filter on it", function(assert) { - run(function() { - store.push({ data: array }); - }); - var recordArray; - - run(function() { - recordArray = store.filter('person', function(hash) { - if (hash.get('name').match(/Scumbag [KD]/)) { return true; } + let recordArray = run(() => { + return store.filter('person', hash => { + if (hash.get('name').match(/Scumbag [KD]/)) { + return true; + } }); }); - assert.equal(get(recordArray, 'length'), 2, "The Record Array should have the filtered objects on it"); + assert.equal(get(recordArray, 'length'), 2, 'The Record Array should have the filtered objects on it'); - run(function () { + run(() => { store.push({ data: [{ id: '4', @@ -170,9 +170,9 @@ test("a record array can have a filter on it", function(assert) { }); }); - assert.equal(get(recordArray, 'length'), 3, "The Record Array should be updated as new items are added to the store"); + assert.equal(get(recordArray, 'length'), 3, 'The Record Array should be updated as new items are added to the store'); - run(function () { + run(() => { store.push({ data: [{ id: '1', @@ -184,74 +184,74 @@ test("a record array can have a filter on it", function(assert) { }); }); - assert.equal(get(recordArray, 'length'), 2, "The Record Array should be updated as existing members are updated"); + assert.equal(get(recordArray, 'length'), 2, 'The Record Array should be updated as existing members are updated'); }); -test("a filtered record array includes created elements", function(assert) { - run(function() { - store.push({ data: array }); - }); - var recordArray; +test('a filtered record array includes created elements', function(assert) { + run(() => store.push({ data })); - run(function() { - recordArray = store.filter('person', function(hash) { - if (hash.get('name').match(/Scumbag [KD]/)) { return true; } + let recordArray = run(() => { + return store.filter('person', hash => { + if (hash.get('name').match(/Scumbag [KD]/)) { + return true; + } }); }); - assert.equal(get(recordArray, 'length'), 2, "precond - The Record Array should have the filtered objects on it"); + assert.equal(get(recordArray, 'length'), 2, 'precond - The Record Array should have the filtered objects on it'); - run(function() { - store.createRecord('person', { name: "Scumbag Koz" }); + run(() => { + store.createRecord('person', { name: 'Scumbag Koz' }); }); - assert.equal(get(recordArray, 'length'), 3, "The record array has the new object on it"); + assert.equal(get(recordArray, 'length'), 3, 'The record array has the new object on it'); }); -test("a Record Array can update its filter", function(assert) { +test('a Record Array can update its filter', function(assert) { customAdapter(env, DS.Adapter.extend({ - deleteRecord(store, type, snapshot) { - return Ember.RSVP.resolve(); - }, - shouldBackgroundReloadRecord: () => false + deleteRecord(store, type, snapshot) { }, + shouldBackgroundReloadRecord() { return false; } })); - run(function() { - store.push({ data: array }); - }); + run(() => store.push({ data })); - var dickens = run(function() { - var record = store.createRecord('person', { id: 4, name: "Scumbag Dickens" }); + let dickens = run(() => { + let record = store.createRecord('person', { id: 4, name: 'Scumbag Dickens' }); record.deleteRecord(); return record; }); - var asyncDale, asyncKatz, asyncBryn; - run(function() { - asyncDale = store.findRecord('person', 1); - asyncKatz = store.findRecord('person', 2); - asyncBryn = store.findRecord('person', 3); + let asyncData = run(() => { + return { + dale: store.findRecord('person', 1), + katz: store.findRecord('person', 2), + bryn: store.findRecord('person', 3) + }; }); - store.filter('person', function(hash) { - if (hash.get('name').match(/Scumbag [KD]/)) { return true; } - }).then(assert.wait(function(recordArray) { + return store.filter('person', hash => { + if (hash.get('name').match(/Scumbag [KD]/)) { + return true; + } + }).then(recordArray => { - Ember.RSVP.hash({ dale: asyncDale, katz: asyncKatz, bryn: asyncBryn }).then(assert.wait(function(records) { + return Ember.RSVP.hash(asyncData).then(records => { assert.contains(recordArray, records.dale); assert.contains(recordArray, records.katz); assert.without(recordArray, records.bryn); assert.without(recordArray, dickens); - Ember.run(function() { - recordArray.set('filterFunction', function(hash) { - if (hash.get('name').match(/Katz/)) { return true; } + run(() => { + recordArray.set('filterFunction', hash => { + if (hash.get('name').match(/Katz/)) { + return true; + } }); }); - assert.equal(get(recordArray, 'length'), 1, "The Record Array should have one object on it"); + assert.equal(get(recordArray, 'length'), 1, 'The Record Array should have one object on it'); - Ember.run(function () { + run(() => { store.push({ data: [{ id: '5', @@ -263,9 +263,9 @@ test("a Record Array can update its filter", function(assert) { }); }); - assert.equal(get(recordArray, 'length'), 2, "The Record Array now has the new object matching the filter"); + assert.equal(get(recordArray, 'length'), 2, 'The Record Array now has the new object matching the filter'); - Ember.run(function () { + run(() => { store.push({ data: [{ id: '6', @@ -277,47 +277,45 @@ test("a Record Array can update its filter", function(assert) { }); }); - assert.equal(get(recordArray, 'length'), 2, "The Record Array doesn't have objects matching the old filter"); - })); - })); + assert.equal(get(recordArray, 'length'), 2, 'The Record Array doesn\'t have objects matching the old filter'); + }); + }); }); -test("a Record Array can update its filter and notify array observers", function(assert) { +test('a Record Array can update its filter and notify array observers', function(assert) { customAdapter(env, DS.Adapter.extend({ - deleteRecord(store, type, snapshot) { - return Ember.RSVP.resolve(); - }, - shouldBackgroundReloadRecord: () => false + deleteRecord(store, type, snapshot) { }, + shouldBackgroundReloadRecord() { return false; } })); - run(function() { - store.push({ data: array }); - }); - var dickens; + run(() => store.push({ data })); - run(function() { - dickens = store.createRecord('person', { id: 4, name: "Scumbag Dickens" }); + let dickens = run(() => { + dickens = store.createRecord('person', { id: 4, name: 'Scumbag Dickens' }); dickens.deleteRecord(); + return dickens; }); - var asyncDale, asyncKatz, asyncBryn; - - run(function() { - asyncDale = store.findRecord('person', 1); - asyncKatz = store.findRecord('person', 2); - asyncBryn = store.findRecord('person', 3); + let asyncData = run(() => { + return [ + store.findRecord('person', 1), + store.findRecord('person', 2), + store.findRecord('person', 3) + ]; }); - store.filter('person', function(hash) { - if (hash.get('name').match(/Scumbag [KD]/)) { return true; } - }).then(assert.wait(function(recordArray) { + store.filter('person', hash => { + if (hash.get('name').match(/Scumbag [KD]/)) { + return true; + } + }).then(assert.wait(recordArray => { - var didChangeIdx; - var didChangeRemoved = 0; - var didChangeAdded = 0; + let didChangeIdx; + let didChangeRemoved = 0; + let didChangeAdded = 0; - var arrayObserver = { - arrayWillChange: Ember.K, + let arrayObserver = { + arrayWillChange() { }, arrayDidChange(array, idx, removed, added) { didChangeIdx = idx; @@ -328,17 +326,19 @@ test("a Record Array can update its filter and notify array observers", function recordArray.addArrayObserver(arrayObserver); - Ember.run(function() { - recordArray.set('filterFunction', function(hash) { - if (hash.get('name').match(/Katz/)) { return true; } + run(() => { + recordArray.set('filterFunction', hash => { + if (hash.get('name').match(/Katz/)) { + return true; + } }); }); - Ember.RSVP.all([asyncDale, asyncKatz, asyncBryn]).then(assert.wait(function() { - assert.equal(didChangeRemoved, 1, "removed one item from array"); + return Ember.RSVP.all(asyncData).then(() => { + assert.equal(didChangeRemoved, 1, 'removed one item from array'); didChangeRemoved = 0; - Ember.run(function () { + run(() => { store.push({ data: [{ id: '5', @@ -350,12 +350,12 @@ test("a Record Array can update its filter and notify array observers", function }); }); - assert.equal(didChangeAdded, 1, "one item was added"); + assert.equal(didChangeAdded, 1, 'one item was added'); didChangeAdded = 0; - assert.equal(recordArray.objectAt(didChangeIdx).get('name'), "Other Katz"); + assert.equal(recordArray.objectAt(didChangeIdx).get('name'), 'Other Katz'); - Ember.run(function () { + run(() => { store.push({ data: [{ id: '6', @@ -367,42 +367,35 @@ test("a Record Array can update its filter and notify array observers", function }); }); - assert.equal(didChangeAdded, 0, "did not get called when an object that doesn't match is added"); + assert.equal(didChangeAdded, 0, 'did not get called when an object that doesn\'t match is added'); - Ember.run(function() { - recordArray.set('filterFunction', function(hash) { - if (hash.get('name').match(/Scumbag [KD]/)) { return true; } + run(() => { + recordArray.set('filterFunction', hash => { + if (hash.get('name').match(/Scumbag [KD]/)) { + return true; + } }); }); - assert.equal(didChangeAdded, 2, "one item is added when going back"); - assert.equal(recordArray.objectAt(didChangeIdx).get('name'), "Scumbag Demon"); - assert.equal(recordArray.objectAt(didChangeIdx-1).get('name'), "Scumbag Dale"); - })); + assert.equal(didChangeAdded, 2, 'one item is added when going back'); + assert.equal(recordArray.objectAt(didChangeIdx).get('name'), 'Scumbag Demon'); + assert.equal(recordArray.objectAt(didChangeIdx-1).get('name'), 'Scumbag Dale'); + }); })); }); -test("it is possible to filter by computed properties", function(assert) { +test('it is possible to filter by computed properties', function(assert) { customAdapter(env, DS.Adapter.extend({ shouldBackgroundReloadRecord: () => false })); - Person.reopen({ - name: DS.attr('string'), - upperName: Ember.computed(function() { - return this.get('name').toUpperCase(); - }).property('name') - }); - var filter; - run(function() { - filter = store.filter('person', function(person) { - return person.get('upperName') === "TOM DALE"; - }); + let filter = run(() => { + return store.filter('person', person => person.get('upperName') === 'TOM DALE'); }); - assert.equal(filter.get('length'), 0, "precond - the filter starts empty"); + assert.equal(filter.get('length'), 0, 'precond - the filter starts empty'); - run(function () { + run(() => { store.push({ data: [{ id: '1', @@ -414,29 +407,23 @@ test("it is possible to filter by computed properties", function(assert) { }); }); - assert.equal(filter.get('length'), 1, "the filter now has a record in it"); + assert.equal(filter.get('length'), 1, 'the filter now has a record in it'); - store.findRecord('person', 1).then(assert.wait(function(person) { - Ember.run(function() { - person.set('name', "Yehuda Katz"); + return store.findRecord('person', 1).then(person => { + run(() => { + person.set('name', 'Yehuda Katz'); }); - assert.equal(filter.get('length'), 0, "the filter is empty again"); - })); + assert.equal(filter.get('length'), 0, 'the filter is empty again'); + }); }); -test("a filter created after a record is already loaded works", function(assert) { +test('a filter created after a record is already loaded works', function(assert) { customAdapter(env, DS.Adapter.extend({ - shouldBackgroundReloadRecord: () => false + shouldBackgroundReloadRecord() { return false; } })); - Person.reopen({ - name: DS.attr('string'), - upperName: Ember.computed(function() { - return this.get('name').toUpperCase(); - }).property('name') - }); - run(function () { + run(() => { store.push({ data: [{ id: '1', @@ -447,89 +434,83 @@ test("a filter created after a record is already loaded works", function(assert) }] }); }); - var filter; - run(function() { - filter = store.filter('person', function(person) { - return person.get('upperName') === "TOM DALE"; - }); + let filter = run(() => { + return store.filter('person', person => person.get('upperName') === 'TOM DALE'); }); - assert.equal(filter.get('length'), 1, "the filter now has a record in it"); + assert.equal(filter.get('length'), 1, 'the filter now has a record in it'); assert.asyncEqual(filter.objectAt(0), store.findRecord('person', 1)); }); -test("filter with query persists query on the resulting filteredRecordArray", function(assert) { +test('filter with query persists query on the resulting filteredRecordArray', function(assert) { customAdapter(env, DS.Adapter.extend({ query(store, type, id) { - return Ember.RSVP.resolve([{ - id: id, - name: "Tom Dale" - }]); + return [ + { + id: id, + name: 'Tom Dale' + } + ]; } })); - var filter; - - run(function() { - filter = store.filter('person', { foo: 1 }, function(person) { - return true; - }); + let filter = run(() => { + return store.filter('person', { foo: 1 }, person => true); }); - Ember.run(function() { - filter.then(function(array) { + return run(() => { + return filter.then(array => { assert.deepEqual(get(array, 'query'), { foo: 1 }, 'has expected query'); }); }); }); - -test("it is possible to filter by state flags", function(assert) { - var filter; - +test('it is possible to filter by state flags', function(assert) { customAdapter(env, DS.Adapter.extend({ findRecord(store, type, id, snapshot) { - return Ember.RSVP.resolve({ id: id, name: "Tom Dale" }); + return { + id, + name: 'Tom Dale' + }; } })); - run(function() { - filter = store.filter('person', function(person) { - return person.get('isLoaded'); - }); + let filter = run(() => { + return store.filter('person', person => person.get('isLoaded')); }); - assert.equal(filter.get('length'), 0, "precond - there are no records yet"); + assert.equal(filter.get('length'), 0, 'precond - there are no records yet'); - Ember.run(function() { - var asyncPerson = store.findRecord('person', 1); + let person = run(() => { + let person = store.findRecord('person', 1); - // Ember.run will block `find` from being synchronously + // run will block `find` from being synchronously // resolved in test mode - assert.equal(filter.get('length'), 0, "the unloaded record isn't in the filter"); + assert.equal(filter.get('length'), 0, 'the unloaded record isn\'t in the filter'); + return person; + }); - asyncPerson.then(assert.wait(function(person) { - assert.equal(filter.get('length'), 1, "the now-loaded record is in the filter"); - assert.asyncEqual(filter.objectAt(0), store.findRecord('person', 1)); - })); + return person.then(person => { + assert.equal(filter.get('length'), 1, 'the now-loaded record is in the filter'); + assert.asyncEqual(filter.objectAt(0), store.findRecord('person', 1)); }); }); -test("it is possible to filter loaded records by dirtiness", function(assert) { +test('it is possible to filter loaded records by dirtiness', function(assert) { customAdapter(env, DS.Adapter.extend({ - updateRecord() { - return Ember.RSVP.resolve(); + updateRecord(type, model, snapshot) { + return { id: snapshot.id }; }, - shouldBackgroundReloadRecord: () => false + shouldBackgroundReloadRecord() { + return false; + } })); - var filter = store.filter('person', function(person) { - return !person.get('hasDirtyAttributes'); - }); + let filter = store.filter('person', person => !person.get('hasDirtyAttributes')); - run(function () { + run(() => { store.push({ data: [{ id: '1', @@ -541,225 +522,240 @@ test("it is possible to filter loaded records by dirtiness", function(assert) { }); }); - store.findRecord('person', 1).then(assert.wait(function(person) { - assert.equal(filter.get('length'), 1, "the clean record is in the filter"); + return store.findRecord('person', 1).then(person => { + assert.equal(filter.get('length'), 1, 'the clean record is in the filter'); // Force synchronous update of the filter, even though // we're already inside a run loop - Ember.run(function() { - person.set('name', "Yehuda Katz"); - }); + run(() => person.set('name', 'Yehuda Katz')); - assert.equal(filter.get('length'), 0, "the now-dirty record is not in the filter"); + assert.equal(filter.get('length'), 0, 'the now-dirty record is not in the filter'); return person.save(); - })).then(assert.wait(function(person) { - assert.equal(filter.get('length'), 1, "the clean record is back in the filter"); - })); + }).then(person => { + assert.equal(filter.get('length'), 1, 'the clean record is back in the filter'); + }); }); -test("it is possible to filter created records by dirtiness", function(assert) { - run(function() { +test('it is possible to filter created records by dirtiness', function(assert) { + run(() => { customAdapter(env, DS.Adapter.extend({ - createRecord() { - return Ember.RSVP.resolve(); + createRecord(type, model, snapshot) { + return Ember.merge(Ember.merge({}, snapshot._attributes), { id: snapshot.id} ) }, - shouldBackgroundReloadRecord: () => false + shouldBackgroundReloadRecord() { return false; } })); }); - var filter; - - run(function() { - filter = store.filter('person', function(person) { - return !person.get('hasDirtyAttributes'); - }); + let filter = run(() => { + return store.filter('person', person => !person.get('hasDirtyAttributes')); }); - var person; - - run(function() { - person = store.createRecord('person', { + let person = run(() => { + return store.createRecord('person', { id: 1, - name: "Tom Dale" + name: 'Tom Dale' }); }); - assert.equal(filter.get('length'), 0, "the dirty record is not in the filter"); + assert.equal(filter.get('length'), 0, 'the dirty record is not in the filter'); - run(function() { - person.save().then(function(person) { - assert.equal(filter.get('length'), 1, "the clean record is in the filter"); + return run(() => { + return person.save().then(person => { + assert.equal(filter.get('length'), 1, 'the clean record is in the filter'); }); }); }); -test("it is possible to filter created records by isReloading", function(assert) { +test('it is possible to filter created records by isReloading', function(assert) { customAdapter(env, DS.Adapter.extend({ findRecord(store, type, id, snapshot) { - return Ember.RSVP.resolve({ + return { id: 1, - name: "Tom Dalle" - }); + name: 'Tom Dalle' + }; } })); - var filter = store.filter('person', function(person) { + let filter = store.filter('person', person => { return !person.get('isReloading'); }); - var person = store.createRecord('person', { + let person = store.createRecord('person', { id: 1, - name: "Tom Dale" + name: 'Tom Dale' }); - person.reload().then(assert.wait(function(person) { - assert.equal(filter.get('length'), 1, "the filter correctly returned a reloaded object"); + return person.reload().then(assert.wait(person => { + assert.equal(filter.get('length'), 1, 'the filter correctly returned a reloaded object'); })); }); - // SERVER SIDE TESTS -var edited; +let edited; -var clientEdits = function(ids) { +function clientEdits(ids) { edited = []; - ids.forEach((id) => { - // wrap in an Ember.run to guarantee coalescence of the + ids.forEach(id => { + // wrap in an run to guarantee coalescence of the // iterated `set` calls and promise resolution. - Ember.run(function() { - store.findRecord('person', id).then(function(person) { + run(() => { + store.findRecord('person', id).then(person => { edited.push(person); person.set('name', 'Client-side ' + id ); }); }); }); -}; - -var clientCreates = function(names) { - edited = []; +} - // wrap in an Ember.run to guarantee coalescence of the +function clientCreates(names) { + // wrap in an run to guarantee coalescence of the // iterated `set` calls. - Ember.run(function() { - names.forEach(function(name) { - edited.push(store.createRecord('person', { name: 'Client-side ' + name })); - }); + edited = run(() => { + return names.map(name => store.createRecord('person', { name: 'Client-side ' + name })); }); -}; +} -var serverResponds = function() { - edited.forEach(function(person) { run(person, 'save'); }); -}; +function serverResponds() { + edited.forEach(person => run(person, 'save')); +} -var setup = function(assert, serverCallbacks) { - run(function() { - customAdapter(env, DS.Adapter.extend(serverCallbacks)); +function setup(assert, serverCallbacks) { + customAdapter(env, DS.Adapter.extend(serverCallbacks)); - store.push({ data: array }); + run(() => { + store.push({ data }); - recordArray = store.filter('person', function(hash) { - if (hash.get('name').match(/Scumbag/)) { return true; } + recordArray = store.filter('person', hash => { + if (hash.get('name').match(/Scumbag/)) { + return true; + } }); }); - assert.equal(get(recordArray, 'length'), 3, "The filter function should work"); -}; + assert.equal(get(recordArray, 'length'), 3, 'The filter function should work'); +} -test("a Record Array can update its filter after server-side updates one record", function(assert) { +test('a Record Array can update its filter after server-side updates one record', function(assert) { setup(assert, { updateRecord(store, type, snapshot) { - return Ember.RSVP.resolve({ id: 1, name: "Scumbag Server-side Dale" }); + return { + id: 1, + name: 'Scumbag Server-side Dale' + }; }, - shouldBackgroundReloadRecord: () => false + shouldBackgroundReloadRecord() { return false; } }); clientEdits([1]); - assert.equal(get(recordArray, 'length'), 2, "The record array updates when the client changes records"); + assert.equal(get(recordArray, 'length'), 2, 'The record array updates when the client changes records'); serverResponds(); - assert.equal(get(recordArray, 'length'), 3, "The record array updates when the server changes one record"); + assert.equal(get(recordArray, 'length'), 3, 'The record array updates when the server changes one record'); }); -test("a Record Array can update its filter after server-side updates multiple records", function(assert) { +test('a Record Array can update its filter after server-side updates multiple records', function(assert) { setup(assert, { updateRecord(store, type, snapshot) { switch (snapshot.id) { - case "1": - return Ember.RSVP.resolve({ id: 1, name: "Scumbag Server-side Dale" }); - case "2": - return Ember.RSVP.resolve({ id: 2, name: "Scumbag Server-side Katz" }); + case '1': + return { + id: 1, + name: 'Scumbag Server-side Dale' + }; + case '2': + return { + id: 2, + name: 'Scumbag Server-side Katz' + }; } }, - shouldBackgroundReloadRecord: () => false + shouldBackgroundReloadRecord() { return false; } }); - clientEdits([1,2]); - assert.equal(get(recordArray, 'length'), 1, "The record array updates when the client changes records"); + clientEdits([1, 2]); + assert.equal(get(recordArray, 'length'), 1, 'The record array updates when the client changes records'); serverResponds(); - assert.equal(get(recordArray, 'length'), 3, "The record array updates when the server changes multiple records"); + assert.equal(get(recordArray, 'length'), 3, 'The record array updates when the server changes multiple records'); }); -test("a Record Array can update its filter after server-side creates one record", function(assert) { +test('a Record Array can update its filter after server-side creates one record', function(assert) { setup(assert, { createRecord(store, type, snapshot) { - return Ember.RSVP.resolve({ id: 4, name: "Scumbag Server-side Tim" }); + return { + id: 4, + name: 'Scumbag Server-side Tim' + }; } }); - clientCreates(["Tim"]); - assert.equal(get(recordArray, 'length'), 3, "The record array does not include non-matching records"); + clientCreates(['Tim']); + assert.equal(get(recordArray, 'length'), 3, 'The record array does not include non-matching records'); serverResponds(); - assert.equal(get(recordArray, 'length'), 4, "The record array updates when the server creates a record"); + assert.equal(get(recordArray, 'length'), 4, 'The record array updates when the server creates a record'); }); -test("a Record Array can update its filter after server-side creates multiple records", function(assert) { +test('a Record Array can update its filter after server-side creates multiple records', function(assert) { setup(assert, { createRecord(store, type, snapshot) { switch (snapshot.attr('name')) { - case "Client-side Mike": - return Ember.RSVP.resolve({ id: 4, name: "Scumbag Server-side Mike" }); - case "Client-side David": - return Ember.RSVP.resolve({ id: 5, name: "Scumbag Server-side David" }); + case 'Client-side Mike': + return { + id: 4, + name: 'Scumbag Server-side Mike' + }; + case 'Client-side David': + return { + id: 5, + name: 'Scumbag Server-side David' + }; } } }); - clientCreates(["Mike", "David"]); - assert.equal(get(recordArray, 'length'), 3, "The record array does not include non-matching records"); + clientCreates(['Mike', 'David']); + assert.equal(get(recordArray, 'length'), 3, 'The record array does not include non-matching records'); serverResponds(); - assert.equal(get(recordArray, 'length'), 5, "The record array updates when the server creates multiple records"); + assert.equal(get(recordArray, 'length'), 5, 'The record array updates when the server creates multiple records'); }); -test("a Record Array can update its filter after server-side creates multiple records", function(assert) { +test('a Record Array can update its filter after server-side creates multiple records', function(assert) { setup(assert, { createRecord(store, type, snapshot) { switch (snapshot.attr('name')) { - case "Client-side Mike": - return Ember.RSVP.resolve({ id: 4, name: "Scumbag Server-side Mike" }); - case "Client-side David": - return Ember.RSVP.resolve({ id: 5, name: "Scumbag Server-side David" }); + case 'Client-side Mike': + return { + id: 4, + name: 'Scumbag Server-side Mike' + }; + case 'Client-side David': + return { + id: 5, + name: 'Scumbag Server-side David' + }; } } }); - clientCreates(["Mike", "David"]); - assert.equal(get(recordArray, 'length'), 3, "The record array does not include non-matching records"); + clientCreates(['Mike', 'David']); + assert.equal(get(recordArray, 'length'), 3, 'The record array does not include non-matching records'); serverResponds(); - assert.equal(get(recordArray, 'length'), 5, "The record array updates when the server creates multiple records"); + assert.equal(get(recordArray, 'length'), 5, 'The record array updates when the server creates multiple records'); }); -test("destroying filteredRecordArray unregisters models from being filtered", function(assert) { - var filterFn = tapFn(function() { return true; }); +test('destroying filteredRecordArray unregisters models from being filtered', function(assert) { + const filterFn = tapFn(() => true); + customAdapter(env, DS.Adapter.extend({ - shouldBackgroundReloadRecord: () => false + shouldBackgroundReloadRecord() { return false; } })); - run(function () { + + run(() => { store.push({ data: [{ id: '1', @@ -771,19 +767,12 @@ test("destroying filteredRecordArray unregisters models from being filtered", fu }); }); - var recordArray; - - run(function() { - recordArray = store.filter('person', filterFn); - }); + const recordArray = run(() => store.filter('person', filterFn)); assert.equal(filterFn.summary.called.length, 1); - Ember.run(function() { - recordArray.then(function(array) { - array.destroy(); - }); - }); + run(() => recordArray.then(array => array.destroy())); + clientEdits([1]); assert.equal(filterFn.summary.called.length, 1, 'expected the filter function not being called anymore');