diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000000..0d169ddba78 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,6 @@ +tmp +dist +node-tests/fixtures/ +blueprints/*/mocha-files/ +blueprints/*/qunit-files/ +blueprints/*/files/ diff --git a/.eslintrc.js b/.eslintrc.js index 3cb5fd6ea66..eec3bbc74e7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,19 +1,14 @@ -/* global module */ module.exports = { root: true, parserOptions: { - ecmaVersion: 6, + ecmaVersion: 2017, sourceType: 'module', }, - extends: 'eslint:recommended', - env: { - 'browser': true, - }, - globals: { - 'heimdall': true, - 'Map': false, - }, + extends: ['eslint:recommended', 'prettier'], + plugins: ['prettier'], rules: { + 'prettier/prettier': 'error', + 'no-unused-vars': ['error', { 'args': 'none', }], @@ -29,35 +24,83 @@ module.exports = { 'no-irregular-whitespace': 'error', 'no-undef': 'error', 'no-eq-null': 'error', + }, + overrides: [ + // node files + { + files: [ + 'ember-cli-build.js', + 'index.js', + 'testem.js', + 'lib/**/*.js', + 'blueprints/*/index.js', + 'blueprints/*.js', + 'config/**/*.js', + 'tests/dummy/config/**/*.js', + 'node-tests/**', + 'bin/**', + ], + excludedFiles: [ + 'addon/**', + 'addon-test-support/**', + 'app/**', + 'tests/dummy/app/**' + ], + parserOptions: { + sourceType: 'script', + ecmaVersion: 2015 + }, + env: { + browser: false, + node: true, + es6: true, + }, + plugins: ['node'], + rules: Object.assign({}, require('eslint-plugin-node').configs.recommended.rules, { + // add your custom rules and overrides for node files here + }) + }, - // from JSCS - 'array-bracket-spacing': ['error', 'never'], - 'comma-style': ['error', 'last'], - 'brace-style': ['error', '1tbs', { - 'allowSingleLine': true, - }], - 'no-spaced-func': 'error', - 'no-empty': 'error', - 'curly': ['error', 'all'], - 'eol-last': 'error', - 'no-trailing-spaces': 'error', - 'comma-dangle': ['error', 'never'], - 'space-before-blocks': ['error', 'always'], - 'indent': ['error', 2, { - 'SwitchCase': 1, - }], - 'keyword-spacing': ['error', { - 'overrides': { - 'else': { - 'before': true, - }, - 'while': { - 'before': true, - }, - 'catch': { - 'before': true, - }, + // browser files + { + files: [ + 'addon/**', + 'app/**', + 'tests/**', + ], + excludedFiles: [ + 'tests/dummy/config/**' + ], + env: { + browser: true, + node: false, }, - }], - }, + globals: { + heimdall: true, + Map: false, + } + }, + + // browser tests + { + files: [ + 'tests/**' + ], + + rules: { + 'no-console': 0 + } + }, + + // node tests + { + files: [ + 'node-tests/**' + ], + + env: { + mocha: true, + } + } + ], }; diff --git a/.npmignore b/.npmignore index a77a4b041d4..4a0e13d6067 100644 --- a/.npmignore +++ b/.npmignore @@ -25,3 +25,5 @@ testem.js *.gemspec **/*.rb node-tests/ +lib/yuidoc.js +lib/version-replace.js diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000000..978b4d511ea --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,7 @@ +'use strict'; + +module.exports = { + singleQuote: true, + trailingComma: 'es5', + printWidth: 100, +}; diff --git a/.travis.yml b/.travis.yml index 1f6d6bdacb8..7503f1bb1c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,7 @@ jobs: env: NAME=test # used only to make Travis UI show description script: - ./bin/lint-features + - yarn lint:js - yarn test - stage: additional tests diff --git a/addon/-debug/index.js b/addon/-debug/index.js index 7d8fc71c211..240e5031959 100644 --- a/addon/-debug/index.js +++ b/addon/-debug/index.js @@ -40,7 +40,12 @@ if (DEBUG) { return modelClass.detect(addedModelClass); }; - assertPolymorphicType = function assertPolymorphicType(parentInternalModel, relationshipMeta, addedInternalModel, store) { + assertPolymorphicType = function assertPolymorphicType( + parentInternalModel, + relationshipMeta, + addedInternalModel, + store + ) { let addedModelName = addedInternalModel.modelName; let parentModelName = parentInternalModel.modelName; let key = relationshipMeta.key; @@ -53,4 +58,4 @@ if (DEBUG) { }; } -export { assertPolymorphicType } +export { assertPolymorphicType }; diff --git a/addon/-private/adapters/build-url-mixin.js b/addon/-private/adapters/build-url-mixin.js index 2472a83d31a..d1552ae675f 100644 --- a/addon/-private/adapters/build-url-mixin.js +++ b/addon/-private/adapters/build-url-mixin.js @@ -94,11 +94,17 @@ export default Mixin.create({ if (modelName) { path = this.pathForType(modelName); - if (path) { url.push(path); } + if (path) { + url.push(path); + } } - if (id) { url.push(encodeURIComponent(id)); } - if (prefix) { url.unshift(prefix); } + if (id) { + url.push(encodeURIComponent(id)); + } + if (prefix) { + url.unshift(prefix); + } url = url.join('/'); if (!host && url && url.charAt(0) !== '/') { @@ -392,10 +398,10 @@ export default Mixin.create({ // Do nothing, the full host is already included. return path; - // Absolute path + // Absolute path } else if (path.charAt(0) === '/') { return `${host}${path}`; - // Relative path + // Relative path } else { return `${parentURL}/${path}`; } @@ -403,8 +409,12 @@ export default Mixin.create({ // No path provided let url = []; - if (host) { url.push(host); } - if (namespace) { url.push(namespace); } + if (host) { + url.push(host); + } + if (namespace) { + url.push(namespace); + } return url.join('/'); }, @@ -439,5 +449,5 @@ export default Mixin.create({ pathForType(modelName) { let camelized = camelize(modelName); return pluralize(camelized); - } + }, }); diff --git a/addon/-private/adapters/errors.js b/addon/-private/adapters/errors.js index ec8919818cf..8cfd7b978dd 100644 --- a/addon/-private/adapters/errors.js +++ b/addon/-private/adapters/errors.js @@ -81,8 +81,8 @@ export function AdapterError(errors, message = 'Adapter operation failed') { this.errors = errors || [ { title: 'Adapter Error', - detail: message - } + detail: message, + }, ]; } @@ -165,8 +165,10 @@ AdapterError.extend = extendFn(AdapterError); @class InvalidError @namespace DS */ -export const InvalidError = extend(AdapterError, - 'The adapter rejected the commit because it was invalid'); +export const InvalidError = extend( + AdapterError, + 'The adapter rejected the commit because it was invalid' +); /** A `DS.TimeoutError` is used by an adapter to signal that a request @@ -200,8 +202,7 @@ export const InvalidError = extend(AdapterError, @class TimeoutError @namespace DS */ -export const TimeoutError = extend(AdapterError, - 'The adapter operation timed out'); +export const TimeoutError = extend(AdapterError, 'The adapter operation timed out'); /** A `DS.AbortError` is used by an adapter to signal that a request to @@ -212,8 +213,7 @@ export const TimeoutError = extend(AdapterError, @class AbortError @namespace DS */ -export const AbortError = extend(AdapterError, - 'The adapter operation was aborted'); +export const AbortError = extend(AdapterError, 'The adapter operation was aborted'); /** A `DS.UnauthorizedError` equates to a HTTP `401 Unauthorized` response @@ -320,7 +320,10 @@ export const ConflictError = extend(AdapterError, 'The adapter operation failed @class ServerError @namespace DS */ -export const ServerError = extend(AdapterError, 'The adapter operation failed due to a server error'); +export const ServerError = extend( + AdapterError, + 'The adapter operation failed due to a server error' +); /** Convert an hash of errors into an array with errors in JSON-API format. @@ -372,7 +375,7 @@ export function errorsHashToArray(errors) { let out = []; if (isPresent(errors)) { - Object.keys(errors).forEach((key) => { + Object.keys(errors).forEach(key => { let messages = makeArray(errors[key]); for (let i = 0; i < messages.length; i++) { let title = 'Invalid Attribute'; @@ -385,8 +388,8 @@ export function errorsHashToArray(errors) { title: title, detail: messages[i], source: { - pointer: pointer - } + pointer: pointer, + }, }); } }); @@ -439,7 +442,7 @@ export function errorsArrayToHash(errors) { let out = {}; if (isPresent(errors)) { - errors.forEach((error) => { + errors.forEach(error => { if (error.source && error.source.pointer) { let key = error.source.pointer.match(SOURCE_POINTER_REGEXP); diff --git a/addon/-private/attr.js b/addon/-private/attr.js index ddbb80e3724..47d2947c6e6 100644 --- a/addon/-private/attr.js +++ b/addon/-private/attr.js @@ -10,16 +10,16 @@ function getDefaultValue(record, options, key) { return options.defaultValue.apply(null, arguments); } else { let defaultValue = options.defaultValue; - assert(`Non primitive defaultValues are not supported because they are shared between all instances. If you would like to use a complex object as a default value please provide a function that returns the complex object.`, - typeof defaultValue !== 'object' || defaultValue === null); + assert( + `Non primitive defaultValues are not supported because they are shared between all instances. If you would like to use a complex object as a default value please provide a function that returns the complex object.`, + typeof defaultValue !== 'object' || defaultValue === null + ); return defaultValue; } } function hasValue(record, key) { - return key in record._attributes || - key in record._inFlightAttributes || - key in record._data; + return key in record._attributes || key in record._inFlightAttributes || key in record._data; } /** @@ -118,7 +118,7 @@ export default function attr(type, options) { let meta = { type: type, isAttribute: true, - options: options + options: options, }; return computed({ @@ -132,6 +132,6 @@ export default function attr(type, options) { }, set(key, value) { return this._internalModel.setDirtyAttribute(key, value); - } + }, }).meta(meta); } diff --git a/addon/-private/core.js b/addon/-private/core.js index b16369a0ff4..70816f3c203 100644 --- a/addon/-private/core.js +++ b/addon/-private/core.js @@ -19,7 +19,7 @@ import VERSION from 'ember-data/version'; */ const DS = Ember.Namespace.create({ VERSION: VERSION, - name: "DS" + name: 'DS', }); if (Ember.libraries) { diff --git a/addon/-private/index.js b/addon/-private/index.js index 6cfb8a5da96..a1addb6ec09 100644 --- a/addon/-private/index.js +++ b/addon/-private/index.js @@ -1,7 +1,7 @@ // public export { default as Model } from './system/model/model'; export { default as Errors } from './system/model/errors'; -export { default as Store } from './system/store'; +export { default as Store } from './system/store'; export { default as DS } from './core'; export { default as belongsTo } from './system/relationships/belongs-to'; export { default as hasMany } from './system/relationships/has-many'; @@ -19,7 +19,7 @@ export { TimeoutError, AbortError, errorsHashToArray, - errorsArrayToHash + errorsArrayToHash, } from './adapters/errors'; // maybe public ? @@ -33,16 +33,9 @@ export { default as isEnabled } from './features'; export { default as RootState } from './system/model/states'; export { default as InternalModel } from './system/model/internal-model'; -export { - PromiseArray, - PromiseObject, - PromiseManyArray -} from './system/promise-proxies'; +export { PromiseArray, PromiseObject, PromiseManyArray } from './system/promise-proxies'; -export { - RecordArray, - AdapterPopulatedRecordArray -} from './system/record-arrays'; +export { RecordArray, AdapterPopulatedRecordArray } from './system/record-arrays'; export { default as ManyArray } from './system/many-array'; export { default as RecordArrayManager } from './system/record-array-manager'; @@ -56,6 +49,8 @@ export { default as DebugAdapter } from './system/debug/debug-adapter'; // Used by tests export { default as diffArray } from './system/diff-array'; -export { default as RelationshipPayloadsManager } from './system/relationships/relationship-payloads-manager'; +export { + default as RelationshipPayloadsManager, +} from './system/relationships/relationship-payloads-manager'; export { default as RelationshipPayloads } from './system/relationships/relationship-payloads'; export { default as SnapshotRecordArray } from './system/snapshot-record-array'; diff --git a/addon/-private/system/backburner.js b/addon/-private/system/backburner.js index 266c37c3b4b..7ac43f9b390 100644 --- a/addon/-private/system/backburner.js +++ b/addon/-private/system/backburner.js @@ -1,7 +1,11 @@ import Ember from 'ember'; import { DEBUG } from '@glimmer/env'; -const backburner = new Ember._Backburner(['normalizeRelationships', 'syncRelationships', 'finished']); +const backburner = new Ember._Backburner([ + 'normalizeRelationships', + 'syncRelationships', + 'finished', +]); if (DEBUG) { Ember.Test.registerWaiter(() => { diff --git a/addon/-private/system/coerce-id.js b/addon/-private/system/coerce-id.js index 8f8c305a98d..18173352148 100644 --- a/addon/-private/system/coerce-id.js +++ b/addon/-private/system/coerce-id.js @@ -5,7 +5,11 @@ // ID into the URL, and if we later try to deserialize that URL and find the // corresponding record, we will not know if it is a string or a number. export default function coerceId(id) { - if (id === null || id === undefined || id === '') { return null; } - if (typeof id === 'string') { return id; } + if (id === null || id === undefined || id === '') { + return null; + } + if (typeof id === 'string') { + return id; + } return '' + id; } diff --git a/addon/-private/system/debug/debug-adapter.js b/addon/-private/system/debug/debug-adapter.js index eca07a7d7df..2904a93427f 100644 --- a/addon/-private/system/debug/debug-adapter.js +++ b/addon/-private/system/debug/debug-adapter.js @@ -23,7 +23,7 @@ export default DataAdapter.extend({ return [ { name: 'isNew', desc: 'New' }, { name: 'isModified', desc: 'Modified' }, - { name: 'isClean', desc: 'Clean' } + { name: 'isClean', desc: 'Clean' }, ]; }, @@ -32,14 +32,18 @@ export default DataAdapter.extend({ }, columnsForType(typeClass) { - let columns = [{ - name: 'id', - desc: 'Id' - }]; + let columns = [ + { + name: 'id', + desc: 'Id', + }, + ]; let count = 0; let self = this; get(typeClass, 'attributes').forEach((meta, name) => { - if (count++ > self.attributeLimit) { return false; } + if (count++ > self.attributeLimit) { + return false; + } let desc = capitalize(underscore(name).replace('_', ' ')); columns.push({ name: name, desc: desc }); }); @@ -57,7 +61,10 @@ export default DataAdapter.extend({ } } } - assert("Cannot find model name. Please upgrade to Ember.js >= 1.13 for Ember Inspector support", !!modelName); + assert( + 'Cannot find model name. Please upgrade to Ember.js >= 1.13 for Ember Inspector support', + !!modelName + ); return this.get('store').peekAll(modelName); }, @@ -65,7 +72,7 @@ export default DataAdapter.extend({ let count = 0; let columnValues = { id: get(record, 'id') }; - record.eachAttribute((key) => { + record.eachAttribute(key => { if (count++ > this.attributeLimit) { return false; } @@ -77,8 +84,8 @@ export default DataAdapter.extend({ getRecordKeywords(record) { let keywords = []; let keys = A(['id']); - record.eachAttribute((key) => keys.push(key)); - keys.forEach((key) => keywords.push(get(record, key))); + record.eachAttribute(key => keys.push(key)); + keys.forEach(key => keywords.push(get(record, key))); return keywords; }, @@ -86,7 +93,7 @@ export default DataAdapter.extend({ return { isNew: record.get('isNew'), isModified: record.get('hasDirtyAttributes') && !record.get('isNew'), - isClean: !record.get('hasDirtyAttributes') + isClean: !record.get('hasDirtyAttributes'), }; }, @@ -104,7 +111,7 @@ export default DataAdapter.extend({ let releaseMethods = A(); let keysToObserve = A(['id', 'isNew', 'hasDirtyAttributes']); - record.eachAttribute((key) => keysToObserve.push(key)); + record.eachAttribute(key => keysToObserve.push(key)); let adapter = this; keysToObserve.forEach(function(key) { @@ -118,9 +125,9 @@ export default DataAdapter.extend({ }); let release = function() { - releaseMethods.forEach((fn) => fn()); + releaseMethods.forEach(fn => fn()); }; return release; - } + }, }); diff --git a/addon/-private/system/diff-array.js b/addon/-private/system/diff-array.js index ae28e8e35b3..e935a525b6b 100644 --- a/addon/-private/system/diff-array.js +++ b/addon/-private/system/diff-array.js @@ -18,7 +18,7 @@ export default function diffArray(oldArray, newArray) { let firstChangeIndex = null; // null signifies no changes // find the first change - for (let i=0; i internalModel.isNew() && toSet.indexOf(internalModel) === -1 + internalModel => internalModel.isNew() && toSet.indexOf(internalModel) === -1 ); toSet = toSet.concat(newInternalModels); // diff to find changes let diff = diffArray(this.currentState, toSet); - if (diff.firstChangeIndex !== null) { // it's null if no change found + if (diff.firstChangeIndex !== null) { + // it's null if no change found // we found a change this.arrayContentWillChange(diff.firstChangeIndex, diff.removedCount, diff.addedCount); this.set('length', toSet.length); @@ -191,7 +194,7 @@ export default EmberObject.extend(MutableArray, Evented, { //TODO(Igor) optimize _removeInternalModels(internalModels) { - for (let i=0; i < internalModels.length; i++) { + for (let i = 0; i < internalModels.length; i++) { let index = this.currentState.indexOf(internalModels[i]); this.internalReplace(index, 1); } @@ -208,7 +211,7 @@ export default EmberObject.extend(MutableArray, Evented, { replace(idx, amt, objects) { let internalModels; if (amt > 0) { - internalModels = this.currentState.slice(idx, idx+amt); + internalModels = this.currentState.slice(idx, idx + amt); this.get('relationship').removeInternalModels(internalModels); } if (objects) { @@ -265,8 +268,11 @@ export default EmberObject.extend(MutableArray, Evented, { save() { let manyArray = this; let promiseLabel = 'DS: ManyArray#save ' + get(this, 'type'); - let promise = all(this.invoke("save"), promiseLabel). - then(() => manyArray, null, 'DS: ManyArray#save return ManyArray'); + let promise = all(this.invoke('save'), promiseLabel).then( + () => manyArray, + null, + 'DS: ManyArray#save return ManyArray' + ); return PromiseArray.create({ promise }); }, @@ -283,10 +289,13 @@ export default EmberObject.extend(MutableArray, Evented, { const store = get(this, 'store'); const type = get(this, 'type'); - assert(`You cannot add '${type.modelName}' records to this polymorphic relationship.`, !get(this, 'isPolymorphic')); + assert( + `You cannot add '${type.modelName}' records to this polymorphic relationship.`, + !get(this, 'isPolymorphic') + ); let record = store.createRecord(type.modelName, hash); this.pushObject(record); return record; - } + }, }); diff --git a/addon/-private/system/map.js b/addon/-private/system/map.js index 6018913a453..c7c0be9846b 100644 --- a/addon/-private/system/map.js +++ b/addon/-private/system/map.js @@ -64,7 +64,7 @@ export default class MapWithDeprecations { copy() { deprecate( 'Calling `.copy()` on a map generated by ember-data is deprecated, please migrate to using native Map functionality only.', - false, + false, { id: 'ember-data.map.copy', until: '3.5.0' } ); @@ -72,7 +72,7 @@ export default class MapWithDeprecations { // constructor args with its `Map` let newMap = new MapWithDeprecations(); this._map.forEach(function(value, key) { - newMap.set(key, value) + newMap.set(key, value); }); return newMap; @@ -81,7 +81,7 @@ export default class MapWithDeprecations { isEmpty() { deprecate( 'Calling `.isEmpty()` on a map generated by ember-data is deprecated, please migrate to using native Map functionality only.', - false, + false, { id: 'ember-data.map.isEmpty', until: '3.5.0' } ); @@ -89,14 +89,34 @@ export default class MapWithDeprecations { } // proxy all normal Map methods to the underlying Map - get size() { return this._map.size; } - clear() { return this._map.clear(...arguments) } - delete() { return this._map.delete(...arguments) } - entries() { return this._map.entries(...arguments) } - forEach() { return this._map.forEach(...arguments) } - get() { return this._map.get(...arguments) } - has() { return this._map.has(...arguments) } - keys() { return this._map.keys(...arguments) } - set() { return this._map.set(...arguments) } - values() { return this._map.values(...arguments) } + get size() { + return this._map.size; + } + clear() { + return this._map.clear(...arguments); + } + delete() { + return this._map.delete(...arguments); + } + entries() { + return this._map.entries(...arguments); + } + forEach() { + return this._map.forEach(...arguments); + } + get() { + return this._map.get(...arguments); + } + has() { + return this._map.has(...arguments); + } + keys() { + return this._map.keys(...arguments); + } + set() { + return this._map.set(...arguments); + } + values() { + return this._map.values(...arguments); + } } diff --git a/addon/-private/system/model/errors.js b/addon/-private/system/model/errors.js index b955dc1ef61..005fb9ec7ca 100644 --- a/addon/-private/system/model/errors.js +++ b/addon/-private/system/model/errors.js @@ -86,7 +86,6 @@ import { warn } from '@ember/debug'; @uses Ember.Evented */ export default ArrayProxy.extend(Evented, { - /** Register with target handler @@ -107,7 +106,7 @@ export default ArrayProxy.extend(Evented, { return new MapWithDefault({ defaultValue() { return A(); - } + }, }); }), @@ -165,7 +164,9 @@ export default ArrayProxy.extend(Evented, { */ unknownProperty(attribute) { let errors = this.errorsFor(attribute); - if (errors.length === 0) { return undefined; } + if (errors.length === 0) { + return undefined; + } return errors; }, @@ -203,7 +204,7 @@ export default ArrayProxy.extend(Evented, { */ add(attribute, messages) { warn(`Interacting with a record errors object will no longer change the record state.`, false, { - id: 'ds.errors.add' + id: 'ds.errors.add', }); let wasEmpty = get(this, 'isEmpty'); @@ -215,7 +216,6 @@ export default ArrayProxy.extend(Evented, { } }, - /** Adds error messages to a given attribute without sending event. @@ -225,7 +225,9 @@ export default ArrayProxy.extend(Evented, { _add(attribute, messages) { messages = this._findOrCreateMessages(attribute, messages); this.addObjects(messages); - get(this, 'errorsByAttributeName').get(attribute).addObjects(messages); + get(this, 'errorsByAttributeName') + .get(attribute) + .addObjects(messages); this.notifyPropertyChange(attribute); }, @@ -247,7 +249,7 @@ export default ArrayProxy.extend(Evented, { } else { _messages[i] = { attribute: attribute, - message: message + message: message, }; } } @@ -292,10 +294,12 @@ export default ArrayProxy.extend(Evented, { */ remove(attribute) { warn(`Interacting with a record errors object will no longer change the record state.`, false, { - id: 'ds.errors.remove' + id: 'ds.errors.remove', }); - if (get(this, 'isEmpty')) { return; } + if (get(this, 'isEmpty')) { + return; + } this._remove(attribute); @@ -311,7 +315,9 @@ export default ArrayProxy.extend(Evented, { @private */ _remove(attribute) { - if (get(this, 'isEmpty')) { return; } + if (get(this, 'isEmpty')) { + return; + } let content = this.rejectBy('attribute', attribute); set(this, 'content', content); @@ -345,16 +351,17 @@ export default ArrayProxy.extend(Evented, { */ clear() { warn(`Interacting with a record errors object will no longer change the record state.`, false, { - id: 'ds.errors.clear' + id: 'ds.errors.clear', }); - if (get(this, 'isEmpty')) { return; } + if (get(this, 'isEmpty')) { + return; + } this._clear(); this.trigger('becameValid'); }, - /** Removes all error messages. to the record. @@ -363,7 +370,9 @@ export default ArrayProxy.extend(Evented, { @private */ _clear() { - if (get(this, 'isEmpty')) { return; } + if (get(this, 'isEmpty')) { + return; + } let errorsByAttributeName = get(this, 'errorsByAttributeName'); let attributes = A(); @@ -380,7 +389,6 @@ export default ArrayProxy.extend(Evented, { ArrayProxy.prototype.clear.call(this); }, - /** Checks if there is error messages for the given attribute. @@ -405,5 +413,5 @@ export default ArrayProxy.extend(Evented, { */ has(attribute) { return this.errorsFor(attribute).length > 0; - } + }, }); diff --git a/addon/-private/system/model/internal-model.js b/addon/-private/system/model/internal-model.js index 61fda841a20..e94bb3623d3 100644 --- a/addon/-private/system/model/internal-model.js +++ b/addon/-private/system/model/internal-model.js @@ -9,19 +9,15 @@ import RSVP, { Promise } from 'rsvp'; import Ember from 'ember'; import { DEBUG } from '@glimmer/env'; import { assert, inspect } from '@ember/debug'; -import RootState from "./states"; -import Relationships from "../relationships/state/create"; -import Snapshot from "../snapshot"; -import OrderedSet from "../ordered-set"; -import isArrayLike from "../is-array-like"; +import RootState from './states'; +import Relationships from '../relationships/state/create'; +import Snapshot from '../snapshot'; +import OrderedSet from '../ordered-set'; +import isArrayLike from '../is-array-like'; import { getOwner } from '../../utils'; -import { - RecordReference, - BelongsToReference, - HasManyReference -} from "../references"; +import { RecordReference, BelongsToReference, HasManyReference } from '../references'; /* The TransitionChainMap caches the `state.enters`, `state.setups`, and final state reached @@ -39,19 +35,15 @@ const _extractPivotNameCache = Object.create(null); const _splitOnDotCache = Object.create(null); function splitOnDot(name) { - return _splitOnDotCache[name] || ( - _splitOnDotCache[name] = name.split('.') - ); + return _splitOnDotCache[name] || (_splitOnDotCache[name] = name.split('.')); } function extractPivotName(name) { - return _extractPivotNameCache[name] || ( - _extractPivotNameCache[name] = splitOnDot(name)[0] - ); + return _extractPivotNameCache[name] || (_extractPivotNameCache[name] = splitOnDot(name)[0]); } function areAllModelsUnloaded(internalModels) { - for (let i=0; i record.hasOwnProperty('_internalModel') === true); - })()); + assert( + `All elements of a hasMany relationship must be instances of DS.Model, you passed ${inspect( + records + )}`, + (function() { + return A(records).every(record => record.hasOwnProperty('_internalModel') === true); + })() + ); let relationship = this._relationships.get(key); relationship.clear(); @@ -700,7 +730,7 @@ export default class InternalModel { name: key, oldValue: oldValue, originalValue: originalValue, - value: value + value: value, }); } @@ -879,7 +909,6 @@ export default class InternalModel { this._attributes = null; } - if (get(this, 'isError')) { this._inFlightAttributes = null; this.didCleanError(); @@ -915,7 +944,9 @@ export default class InternalModel { let transitionMapId = `${state.stateName}->${name}`; do { - if (state.exit) { state.exit(this); } + if (state.exit) { + state.exit(this); + } state = state.parentState; } while (!state[pivotName]); @@ -938,8 +969,12 @@ export default class InternalModel { for (i = 0, l = path.length; i < l; i++) { state = state[path[i]]; - if (state.enter) { enters.push(state); } - if (state.setup) { setups.push(state); } + if (state.enter) { + enters.push(state); + } + if (state.setup) { + setups.push(state); + } } TransitionChainMap[transitionMapId] = { setups, enters, state }; @@ -962,12 +997,12 @@ export default class InternalModel { } _unhandledEvent(state, name, context) { - let errorMessage = "Attempted to handle event `" + name + "` "; - errorMessage += "on " + String(this) + " while in state "; - errorMessage += state.stateName + ". "; + let errorMessage = 'Attempted to handle event `' + name + '` '; + errorMessage += 'on ' + String(this) + ' while in state '; + errorMessage += state.stateName + '. '; if (context !== undefined) { - errorMessage += "Called with " + inspect(context) + "."; + errorMessage += 'Called with ' + inspect(context) + '.'; } throw new EmberError(errorMessage); @@ -992,7 +1027,7 @@ export default class InternalModel { let triggers = this._deferredTriggers; let record = this._record; let trigger = record.trigger; - for (let i = 0, l= triggers.length; i { + Object.keys(implicitRelationships).forEach(key => { let rel = implicitRelationships[key]; rel.removeCompletelyFromInverse(); @@ -1035,7 +1070,7 @@ export default class InternalModel { let implicitRelationships = this._implicitRelationships; this.__implicitRelationships = null; - Object.keys(implicitRelationships).forEach((key) => { + Object.keys(implicitRelationships).forEach(key => { let rel = implicitRelationships[key]; destroyRelationship(rel); }); @@ -1058,7 +1093,7 @@ export default class InternalModel { */ preloadData(preload) { //TODO(Igor) consider the polymorphic case - Object.keys(preload).forEach((key) => { + Object.keys(preload).forEach(key => { let preloadValue = get(preload, key); let relationshipMeta = this.modelClass.metaForProperty(key); if (relationshipMeta.isRelationship) { @@ -1080,7 +1115,10 @@ export default class InternalModel { } _preloadHasMany(key, preloadValue, modelClass) { - assert("You need to pass in an array to set a hasMany property on a record", Array.isArray(preloadValue)); + assert( + 'You need to pass in an array to set a hasMany property on a record', + Array.isArray(preloadValue) + ); let recordsToSet = new Array(preloadValue.length); for (let i = 0; i < preloadValue.length; i++) { @@ -1122,7 +1160,10 @@ export default class InternalModel { } setId(id) { - assert('A record\'s id cannot be changed once it is in the loaded state', this.id === null || this.id === id || this.isNew()); + assert( + "A record's id cannot be changed once it is in the loaded state", + this.id === null || this.id === id || this.isNew() + ); let didChange = id !== this.id; this.id = id; @@ -1138,7 +1179,7 @@ export default class InternalModel { if (this.hasRecord) { this._record.setProperties({ isError: true, - adapterError: error + adapterError: error, }); } } @@ -1150,7 +1191,7 @@ export default class InternalModel { if (this.hasRecord) { this._record.setProperties({ isError: false, - adapterError: null + adapterError: null, }); } } @@ -1164,7 +1205,11 @@ export default class InternalModel { */ adapterDidCommit(data) { if (data) { - this.store._internalModelDidReceiveRelationshipData(this.modelName, this.id, data.relationships); + this.store._internalModelDidReceiveRelationshipData( + this.modelName, + this.id, + data.relationships + ); data = data.attributes; } @@ -1182,7 +1227,9 @@ export default class InternalModel { this.send('didCommit'); this.updateRecordArrays(); - if (!data) { return; } + if (!data) { + return; + } this._record._notifyProperties(changedKeys); } @@ -1239,7 +1286,7 @@ export default class InternalModel { let keys = Object.keys(this._inFlightAttributes); if (keys.length > 0) { let attrs = this._attributes; - for (let i=0; i < keys.length; i++) { + for (let i = 0; i < keys.length; i++) { if (attrs[keys[i]] === undefined) { attrs[keys[i]] = this._inFlightAttributes[keys[i]]; } @@ -1299,7 +1346,7 @@ export default class InternalModel { let hasAttrs = this.hasChangedAttributes(); let attrs; if (hasAttrs) { - attrs= this._attributes; + attrs = this._attributes; } original = Object.create(null); @@ -1338,15 +1385,21 @@ export default class InternalModel { if (DEBUG) { let modelName = this.modelName; - assert(`There is no ${kind} relationship named '${name}' on a model of modelClass '${modelName}'`, relationship); + assert( + `There is no ${kind} relationship named '${name}' on a model of modelClass '${modelName}'`, + relationship + ); let actualRelationshipKind = relationship.relationshipMeta.kind; - assert(`You tried to get the '${name}' relationship on a '${modelName}' via record.${kind}('${name}'), but the relationship is of kind '${actualRelationshipKind}'. Use record.${actualRelationshipKind}('${name}') instead.`, actualRelationshipKind === kind); + assert( + `You tried to get the '${name}' relationship on a '${modelName}' via record.${kind}('${name}'), but the relationship is of kind '${actualRelationshipKind}'. Use record.${actualRelationshipKind}('${name}') instead.`, + actualRelationshipKind === kind + ); } - if (kind === "belongsTo") { + if (kind === 'belongsTo') { reference = new BelongsToReference(this.store, this, relationship); - } else if (kind === "hasMany") { + } else if (kind === 'hasMany') { reference = new HasManyReference(this.store, this, relationship); } diff --git a/addon/-private/system/model/model.js b/addon/-private/system/model/model.js index 7c221af8461..2c1c45e0f1a 100644 --- a/addon/-private/system/model/model.js +++ b/addon/-private/system/model/model.js @@ -2,20 +2,17 @@ import ComputedProperty from '@ember/object/computed'; import { isNone } from '@ember/utils'; import EmberError from '@ember/error'; import Evented from '@ember/object/evented'; -import EmberObject, { - computed, - get -} from '@ember/object'; +import EmberObject, { computed, get } from '@ember/object'; import Map from '../map'; import { DEBUG } from '@glimmer/env'; import { assert, warn } from '@ember/debug'; -import { PromiseObject } from "../promise-proxies"; -import Errors from "../model/errors"; +import { PromiseObject } from '../promise-proxies'; +import Errors from '../model/errors'; import RootState from '../model/states'; import { relationshipsByNameDescriptor, relatedTypesDescriptor, - relationshipsDescriptor + relationshipsDescriptor, } from '../relationships/ext'; import Ember from 'ember'; @@ -29,7 +26,9 @@ function findPossibleInverses(type, inverseType, name, relationshipsSoFar) { let possibleRelationships = relationshipsSoFar || []; let relationshipMap = get(inverseType, 'relationships'); - if (!relationshipMap) { return possibleRelationships; } + if (!relationshipMap) { + return possibleRelationships; + } let relationships = relationshipMap.get(type.modelName).filter(relationship => { let optionsForRelationship = inverseType.metaForProperty(relationship.name).options; @@ -53,9 +52,9 @@ function findPossibleInverses(type, inverseType, name, relationshipsSoFar) { return possibleRelationships; } -function intersection (array1, array2) { +function intersection(array1, array2) { let result = []; - array1.forEach((element) => { + array1.forEach(element => { if (array2.indexOf(element) >= 0) { result.push(element); } @@ -64,9 +63,7 @@ function intersection (array1, array2) { return result; } -const RESERVED_MODEL_PROPS = [ - 'currentState', 'data', 'store' -]; +const RESERVED_MODEL_PROPS = ['currentState', 'data', 'store']; const retrieveFromCurrentState = computed('currentState', function(key) { return get(this._internalModel.currentState, key); @@ -401,13 +398,15 @@ const Model = EmberObject.extend(Evented, { errors: computed(function() { let errors = Errors.create(); - errors._registerHandlers(this._internalModel, + errors._registerHandlers( + this._internalModel, function() { this.send('becameInvalid'); }, function() { this.send('becameValid'); - }); + } + ); return errors; }).readOnly(), @@ -537,7 +536,6 @@ const Model = EmberObject.extend(Evented, { return this._internalModel.transitionTo(name); }, - /** Marks the record as deleted but does not save it. You must call `save` afterwards if you want to persist it. You might use this @@ -625,7 +623,9 @@ const Model = EmberObject.extend(Evented, { @method unloadRecord */ unloadRecord() { - if (this.isDestroyed) { return; } + if (this.isDestroyed) { + return; + } this._internalModel.unloadRecord(); }, @@ -790,7 +790,7 @@ const Model = EmberObject.extend(Evented, { */ save(options) { return PromiseObject.create({ - promise: this._internalModel.save(options).then(() => this) + promise: this._internalModel.save(options).then(() => this), }); }, @@ -827,16 +827,15 @@ const Model = EmberObject.extend(Evented, { if (typeof options === 'object' && options !== null && options.adapterOptions) { wrappedAdapterOptions = { - adapterOptions: options.adapterOptions + adapterOptions: options.adapterOptions, }; } return PromiseObject.create({ - promise: this._internalModel.reload(wrappedAdapterOptions).then(() => this) + promise: this._internalModel.reload(wrappedAdapterOptions).then(() => this), }); }, - /** Override the default event firing from Ember.Evented to also call methods with the given name. @@ -855,14 +854,17 @@ const Model = EmberObject.extend(Evented, { for (let i = 1; i < length; i++) { args[i - 1] = arguments[i]; } - fn.apply(this, args) + fn.apply(this, args); } this._super(...arguments); }, attr() { - assert("The `attr` method is not available on DS.Model, a DS.Snapshot was probably expected. Are you passing a DS.Model instead of a DS.Snapshot to your serializer?", false); + assert( + 'The `attr` method is not available on DS.Model, a DS.Snapshot was probably expected. Are you passing a DS.Model instead of a DS.Snapshot to your serializer?', + false + ); }, /** @@ -1009,7 +1011,7 @@ const Model = EmberObject.extend(Evented, { */ _debugInfo() { let attributes = ['id']; - let relationships = { }; + let relationships = {}; let expensiveProperties = []; this.eachAttribute((name, meta) => attributes.push(name)); @@ -1018,8 +1020,8 @@ const Model = EmberObject.extend(Evented, { { name: 'Attributes', properties: attributes, - expand: true - } + expand: true, + }, ]; this.eachRelationship((name, relationship) => { @@ -1030,7 +1032,7 @@ const Model = EmberObject.extend(Evented, { groups.push({ name: relationship.name, properties, - expand: true + expand: true, }); } properties.push(name); @@ -1039,7 +1041,15 @@ const Model = EmberObject.extend(Evented, { groups.push({ name: 'Flags', - properties: ['isLoaded', 'hasDirtyAttributes', 'isSaving', 'isDeleted', 'isError', 'isNew', 'isValid'] + properties: [ + 'isLoaded', + 'hasDirtyAttributes', + 'isSaving', + 'isDeleted', + 'isError', + 'isNew', + 'isValid', + ], }); return { @@ -1048,8 +1058,8 @@ const Model = EmberObject.extend(Evented, { includeOtherProperties: true, groups: groups, // don't pre-calculate unless cached - expensiveProperties: expensiveProperties - } + expensiveProperties: expensiveProperties, + }, }; }, @@ -1131,7 +1141,7 @@ const Model = EmberObject.extend(Evented, { eachAttribute(callback, binding) { this.constructor.eachAttribute(callback, binding); - } + }, }); /** @@ -1143,7 +1153,7 @@ Object.defineProperty(Model.prototype, 'data', { configurable: false, get() { return this._internalModel._data; - } + }, }); Object.defineProperty(Model.prototype, 'id', { @@ -1157,7 +1167,7 @@ Object.defineProperty(Model.prototype, 'id', { // (addListener via validatePropertyInjections) invokes toString before the // object is real. return this._internalModel && this._internalModel.id; - } + }, }); if (DEBUG) { @@ -1166,9 +1176,11 @@ if (DEBUG) { this._super(...arguments); if (!this._internalModel) { - throw new EmberError('You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'); + throw new EmberError( + 'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.' + ); } - } + }, }); } @@ -1309,15 +1321,14 @@ Model.reopenClass({ // through `relationshipsByName` (relationship.options && relationship.options.inverse === null) ) { - return inverseMap[name] = null; + return (inverseMap[name] = null); } - return inverseMap[name] = this._findInverseFor(name, store); + return (inverseMap[name] = this._findInverseFor(name, store)); }, //Calculate the inverse, ignoring the cache _findInverseFor(name, store) { - let inverseType = this.typeForRelationship(name, store); if (!inverseType) { return null; @@ -1326,7 +1337,9 @@ Model.reopenClass({ let propertyMeta = this.metaForProperty(name); //If inverse is manually specified to be null, like `comments: DS.hasMany('message', { inverse: null })` let options = propertyMeta.options; - if (options.inverse === null) { return null; } + if (options.inverse === null) { + return null; + } let inverseName, inverseKind, inverse, inverseOptions; @@ -1335,8 +1348,14 @@ Model.reopenClass({ inverseName = options.inverse; inverse = get(inverseType, 'relationshipsByName').get(inverseName); - assert("We found no inverse relationships by the name of '" + inverseName + "' on the '" + inverseType.modelName + - "' model. This is most likely due to a missing attribute on your model definition.", !isNone(inverse)); + assert( + "We found no inverse relationships by the name of '" + + inverseName + + "' on the '" + + inverseType.modelName + + "' model. This is most likely due to a missing attribute on your model definition.", + !isNone(inverse) + ); // TODO probably just return the whole inverse here inverseKind = inverse.kind; @@ -1344,44 +1363,73 @@ Model.reopenClass({ } else { //No inverse was specified manually, we need to use a heuristic to guess one if (propertyMeta.parentType && propertyMeta.type === propertyMeta.parentType.modelName) { - warn(`Detected a reflexive relationship by the name of '${name}' without an inverse option. Look at https://guides.emberjs.com/current/models/relationships/#toc_reflexive-relations for how to explicitly specify inverses.`, false, { - id: 'ds.model.reflexive-relationship-without-inverse' - }); + warn( + `Detected a reflexive relationship by the name of '${name}' without an inverse option. Look at https://guides.emberjs.com/current/models/relationships/#toc_reflexive-relations for how to explicitly specify inverses.`, + false, + { + id: 'ds.model.reflexive-relationship-without-inverse', + } + ); } let possibleRelationships = findPossibleInverses(this, inverseType, name); - if (possibleRelationships.length === 0) { return null; } + if (possibleRelationships.length === 0) { + return null; + } - let filteredRelationships = possibleRelationships.filter((possibleRelationship) => { + let filteredRelationships = possibleRelationships.filter(possibleRelationship => { let optionsForRelationship = inverseType.metaForProperty(possibleRelationship.name).options; return name === optionsForRelationship.inverse; }); - assert("You defined the '" + name + "' relationship on " + this + ", but you defined the inverse relationships of type " + - inverseType.toString() + " multiple times. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses", - filteredRelationships.length < 2); - - if (filteredRelationships.length === 1 ) { + assert( + "You defined the '" + + name + + "' relationship on " + + this + + ', but you defined the inverse relationships of type ' + + inverseType.toString() + + ' multiple times. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses', + filteredRelationships.length < 2 + ); + + if (filteredRelationships.length === 1) { possibleRelationships = filteredRelationships; } - assert("You defined the '" + name + "' relationship on " + this + ", but multiple possible inverse relationships of type " + - this + " were found on " + inverseType + ". Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses", - possibleRelationships.length === 1); + assert( + "You defined the '" + + name + + "' relationship on " + + this + + ', but multiple possible inverse relationships of type ' + + this + + ' were found on ' + + inverseType + + '. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses', + possibleRelationships.length === 1 + ); inverseName = possibleRelationships[0].name; inverseKind = possibleRelationships[0].kind; inverseOptions = possibleRelationships[0].options; } - assert(`The ${inverseType.modelName}:${inverseName} relationship declares 'inverse: null', but it was resolved as the inverse for ${this.modelName}:${name}.`, !inverseOptions || inverseOptions.inverse !== null); + assert( + `The ${ + inverseType.modelName + }:${inverseName} relationship declares 'inverse: null', but it was resolved as the inverse for ${ + this.modelName + }:${name}.`, + !inverseOptions || inverseOptions.inverse !== null + ); return { type: inverseType, name: inverseName, kind: inverseKind, - options: inverseOptions + options: inverseOptions, }; }, @@ -1465,7 +1513,7 @@ Model.reopenClass({ relationshipNames: computed(function() { let names = { hasMany: [], - belongsTo: [] + belongsTo: [], }; this.eachComputedProperty((name, meta) => { @@ -1705,7 +1753,11 @@ Model.reopenClass({ this.eachComputedProperty((name, meta) => { if (meta.isAttribute) { - assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.toString(), name !== 'id'); + assert( + "You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + + this.toString(), + name !== 'id' + ); meta.name = name; map.set(name, meta); @@ -1872,7 +1924,7 @@ Model.reopenClass({ */ toString() { return `model:${get(this, 'modelName')}`; - } + }, }); if (DEBUG) { @@ -1881,8 +1933,18 @@ if (DEBUG) { // rely on the data property. willMergeMixin(props) { let constructor = this.constructor; - assert('`' + intersection(Object.keys(props), RESERVED_MODEL_PROPS)[0] + '` is a reserved property name on DS.Model objects. Please choose a different property name for ' + constructor.toString(), !intersection(Object.keys(props), RESERVED_MODEL_PROPS)[0]); - assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + constructor.toString(), Object.keys(props).indexOf('id') === -1); + assert( + '`' + + intersection(Object.keys(props), RESERVED_MODEL_PROPS)[0] + + '` is a reserved property name on DS.Model objects. Please choose a different property name for ' + + constructor.toString(), + !intersection(Object.keys(props), RESERVED_MODEL_PROPS)[0] + ); + assert( + "You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + + constructor.toString(), + Object.keys(props).indexOf('id') === -1 + ); }, /** @@ -1914,7 +1976,6 @@ if (DEBUG) { didDefineProperty(proto, key, value) { // Check if the value being set is a computed property. if (value instanceof ComputedProperty) { - // If it is, get the metadata for the relationship. This is // populated by the `DS.belongsTo` helper when it is creating // the computed property. @@ -1926,7 +1987,7 @@ if (DEBUG) { */ meta.parentType = proto.constructor; } - } + }, }); } diff --git a/addon/-private/system/model/states.js b/addon/-private/system/model/states.js index 84085f14fe4..ad7562b5659 100644 --- a/addon/-private/system/model/states.js +++ b/addon/-private/system/model/states.js @@ -239,10 +239,12 @@ const DirtyState = { //TODO(Igor) reloading now triggers a //loadingData event, though it seems fine? - loadingData() { }, + loadingData() {}, propertyWasReset(internalModel, name) { - if (!internalModel.hasChangedAttributes()) { internalModel.send('rolledBack'); } + if (!internalModel.hasChangedAttributes()) { + internalModel.send('rolledBack'); + } }, pushedData(internalModel) { @@ -277,7 +279,7 @@ const DirtyState = { rollback(internalModel) { internalModel.rollbackAttributes(); internalModel.triggerLater('ready'); - } + }, }, // Once a record has been handed off to the adapter to be @@ -289,13 +291,13 @@ const DirtyState = { // EVENTS didSetProperty, - becomeDirty() { }, - pushedData() { }, + becomeDirty() {}, + pushedData() {}, unloadRecord: assertAgainstUnloadRecord, // TODO: More robust semantics around save-while-in-flight - willCommit() { }, + willCommit() {}, didCommit(internalModel) { internalModel.transitionTo('saved'); @@ -314,7 +316,7 @@ const DirtyState = { becameError(internalModel) { internalModel.transitionTo('uncommitted'); internalModel.triggerLater('becameError', internalModel); - } + }, }, // A record is in the `invalid` if the adapter has indicated @@ -338,9 +340,9 @@ const DirtyState = { } }, - becameInvalid() { }, - becomeDirty() { }, - pushedData() { }, + becameInvalid() {}, + becomeDirty() {}, + pushedData() {}, willCommit(internalModel) { internalModel.clearErrorMessages(); @@ -359,8 +361,8 @@ const DirtyState = { invokeLifecycleCallbacks(internalModel) { internalModel.triggerLater('becameInvalid', internalModel); - } - } + }, + }, }; // The created and updated states are created outside the state @@ -399,7 +401,7 @@ function dirtyState(options) { const createdState = dirtyState({ dirtyType: 'created', // FLAGS - isNew: true + isNew: true, }); createdState.invalid.rolledBack = function(internalModel) { @@ -413,7 +415,7 @@ createdState.uncommitted.rolledBack = function(internalModel) { }; const updatedState = dirtyState({ - dirtyType: 'updated' + dirtyType: 'updated', }); function createdStateDeleteRecord(internalModel) { @@ -438,7 +440,7 @@ createdState.uncommitted.pushedData = function(internalModel) { createdState.uncommitted.propertyWasReset = function() {}; function assertAgainstUnloadRecord(internalModel) { - assert("You can only unload a record which is not inFlight. `" + internalModel + "`", false); + assert('You can only unload a record which is not inFlight. `' + internalModel + '`', false); } updatedState.invalid.becameValid = function(internalModel) { @@ -477,11 +479,10 @@ const 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() { }, - unloadRecord(internalModel) { - }, + rolledBack() {}, + unloadRecord(internalModel) {}, - propertyWasReset() { }, + propertyWasReset() {}, // SUBSTATES @@ -508,7 +509,7 @@ const RootState = { internalModel.transitionTo('loaded.saved'); internalModel.triggerLater('didLoad'); internalModel.triggerLater('ready'); - } + }, }, // A record enters this state when the store asks @@ -540,7 +541,7 @@ const RootState = { notFound(internalModel) { internalModel.transitionTo('empty'); - } + }, }, // A record enters this state when its data is populated. @@ -554,7 +555,7 @@ const RootState = { //TODO(Igor) Reloading now triggers a loadingData event, //but it should be ok? - loadingData() { }, + loadingData() {}, // SUBSTATES @@ -570,7 +571,7 @@ const RootState = { // EVENTS didSetProperty, - pushedData() { }, + pushedData() {}, becomeDirty(internalModel) { internalModel.transitionTo('updated.uncommitted'); @@ -588,14 +589,13 @@ const RootState = { internalModel.transitionTo('deleted.uncommitted'); }, - unloadRecord(internalModel) { - }, + unloadRecord(internalModel) {}, didCommit() {}, // loaded.saved.notFound would be triggered by a failed // `reload()` on an unchanged record - notFound() { } + notFound() {}, }, // A record is in this state after it has been locally @@ -606,7 +606,7 @@ const RootState = { // A record is in this state if it has already been // saved to the server, but there are new local changes // that have not yet been saved. - updated: updatedState + updated: updatedState, }, // A record is in this state if it was deleted from the store. @@ -630,7 +630,6 @@ const RootState = { // state. It will exit this state when the record // starts to commit. uncommitted: { - // EVENTS willCommit(internalModel) { @@ -642,15 +641,15 @@ const RootState = { internalModel.triggerLater('ready'); }, - pushedData() { }, - becomeDirty() { }, - deleteRecord() { }, + pushedData() {}, + becomeDirty() {}, + deleteRecord() {}, rolledBack(internalModel) { internalModel.transitionTo('loaded.saved'); internalModel.triggerLater('ready'); internalModel.triggerLater('rolledBack'); - } + }, }, // After a record starts committing, but @@ -666,7 +665,7 @@ const RootState = { unloadRecord: assertAgainstUnloadRecord, // TODO: More robust semantics around save-while-in-flight - willCommit() { }, + willCommit() {}, didCommit(internalModel) { internalModel.transitionTo('saved'); @@ -681,7 +680,7 @@ const RootState = { becameInvalid(internalModel) { internalModel.transitionTo('invalid'); internalModel.triggerLater('becameInvalid', internalModel); - } + }, }, // Once the adapter indicates that the deletion has @@ -700,9 +699,9 @@ const RootState = { internalModel.triggerLater('didCommit', internalModel); }, - willCommit() { }, - didCommit() { }, - pushedData() {} + willCommit() {}, + didCommit() {}, + pushedData() {}, }, invalid: { @@ -718,10 +717,10 @@ const RootState = { } }, - becameInvalid() { }, - becomeDirty() { }, - deleteRecord() { }, - willCommit() { }, + becameInvalid() {}, + becomeDirty() {}, + deleteRecord() {}, + willCommit() {}, rolledBack(internalModel) { internalModel.clearErrorMessages(); @@ -731,9 +730,8 @@ const RootState = { becameValid(internalModel) { internalModel.transitionTo('uncommitted'); - } - - } + }, + }, }, invokeLifecycleCallbacks(internalModel, dirtyType) { @@ -744,7 +742,7 @@ const RootState = { } internalModel.triggerLater('didCommit', internalModel); - } + }, }; function wireState(object, parent, name) { @@ -754,7 +752,9 @@ function wireState(object, parent, name) { object.stateName = name; for (let prop in object) { - if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') { continue; } + if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') { + continue; + } if (typeof object[prop] === 'object') { object[prop] = wireState(object[prop], object, name + '.' + prop); } diff --git a/addon/-private/system/normalize-link.js b/addon/-private/system/normalize-link.js index 59d9d6536e8..33e7a31ad97 100644 --- a/addon/-private/system/normalize-link.js +++ b/addon/-private/system/normalize-link.js @@ -12,8 +12,10 @@ */ export default function _normalizeLink(link) { switch (typeof link) { - case 'object': return link; - case 'string': return { href: link }; + case 'object': + return link; + case 'string': + return { href: link }; } return null; } diff --git a/addon/-private/system/promise-proxies.js b/addon/-private/system/promise-proxies.js index a740d003c6b..4a419ac7a01 100644 --- a/addon/-private/system/promise-proxies.js +++ b/addon/-private/system/promise-proxies.js @@ -36,7 +36,7 @@ import { assert } from '@ember/debug'; @uses Ember.PromiseProxyMixin */ export const PromiseArray = ArrayProxy.extend(PromiseProxyMixin, { - meta: reads('content.meta') + meta: reads('content.meta'), }); /** @@ -72,36 +72,40 @@ export let PromiseObject = ObjectProxy.extend(PromiseProxyMixin); export function promiseObject(promise, label) { return PromiseObject.create({ - promise: Promise.resolve(promise, label) + promise: Promise.resolve(promise, label), }); } export function promiseArray(promise, label) { return PromiseArray.create({ - promise: Promise.resolve(promise, label) + promise: Promise.resolve(promise, label), }); } export const PromiseBelongsTo = PromiseObject.extend({ - // we don't proxy meta because we would need to proxy it to the relationship state container // however, meta on relationships does not trigger change notifications. // if you need relationship meta, you should do `record.belongsTo(relationshipName).meta()` meta: computed(function() { assert( 'You attempted to access meta on the promise for the async belongsTo relationship ' + - `${this.get('_belongsToState').internalModel.modelName}:${this.get('_belongsToState').key}'.` + - '\nUse `record.belongsTo(relationshipName).meta()` instead.', + `${this.get('_belongsToState').internalModel.modelName}:${ + this.get('_belongsToState').key + }'.` + + '\nUse `record.belongsTo(relationshipName).meta()` instead.', false ); }), reload() { - assert('You are trying to reload an async belongsTo before it has been created', this.get('content') !== undefined); + assert( + 'You are trying to reload an async belongsTo before it has been created', + this.get('content') !== undefined + ); this.get('_belongsToState').reload(); return this; - } + }, }); /** @@ -130,7 +134,10 @@ export function proxyToContent(method) { export const PromiseManyArray = PromiseArray.extend({ reload() { - assert('You are trying to reload an async manyArray before it has been created', get(this, 'content')); + assert( + 'You are trying to reload an async manyArray before it has been created', + get(this, 'content') + ); this.set('promise', this.get('content').reload()); return this; }, @@ -145,11 +152,11 @@ export const PromiseManyArray = PromiseArray.extend({ off: proxyToContent('off'), - has: proxyToContent('has') + has: proxyToContent('has'), }); export function promiseManyArray(promise, label) { return PromiseManyArray.create({ - promise: Promise.resolve(promise, label) + promise: Promise.resolve(promise, label), }); } diff --git a/addon/-private/system/record-array-manager.js b/addon/-private/system/record-array-manager.js index a3608c16a54..e8e3ae6c5b8 100644 --- a/addon/-private/system/record-array-manager.js +++ b/addon/-private/system/record-array-manager.js @@ -7,10 +7,7 @@ import { set, get } from '@ember/object'; import { run as emberRun } from '@ember/runloop'; import { assert } from '@ember/debug'; import cloneNull from './clone-null'; -import { - RecordArray, - AdapterPopulatedRecordArray -} from './record-arrays'; +import { RecordArray, AdapterPopulatedRecordArray } from './record-arrays'; const { _flush, @@ -20,8 +17,9 @@ const { createRecordArray, liveRecordArrayFor, recordDidChange, - unregisterRecordArray -} = heimdall.registerMonitor('recordArrayManager', + unregisterRecordArray, +} = heimdall.registerMonitor( + 'recordArrayManager', '_flush', 'array_remove', 'create', @@ -72,7 +70,7 @@ export default class RecordArrayManager { internalModel._pendingRecordArrayManagerFlush = true; let pending = this._pending; - let models = pending[modelName] = pending[modelName] || []; + let models = (pending[modelName] = pending[modelName] || []); if (models.push(internalModel) !== 1) { return; } @@ -123,7 +121,10 @@ export default class RecordArrayManager { } _syncLiveRecordArray(array, modelName) { - assert(`recordArrayManger.syncLiveRecordArray expects modelName not modelClass as the second param`, typeof modelName === 'string'); + assert( + `recordArrayManger.syncLiveRecordArray expects modelName not modelClass as the second param`, + typeof modelName === 'string' + ); let pending = this._pending[modelName]; let hasPendingChanges = Array.isArray(pending); let hasNoPotentialDeletions = !hasPendingChanges || pending.length === 0; @@ -177,7 +178,10 @@ export default class RecordArrayManager { @return {DS.RecordArray} */ liveRecordArrayFor(modelName) { - assert(`recordArrayManger.liveRecordArrayFor expects modelName not modelClass as the param`, typeof modelName === 'string'); + assert( + `recordArrayManger.liveRecordArrayFor expects modelName not modelClass as the param`, + typeof modelName === 'string' + ); heimdall.increment(liveRecordArrayFor); @@ -218,7 +222,10 @@ export default class RecordArrayManager { @return {DS.RecordArray} */ createRecordArray(modelName, content) { - assert(`recordArrayManger.createRecordArray expects modelName not modelClass as the param`, typeof modelName === 'string'); + assert( + `recordArrayManger.createRecordArray expects modelName not modelClass as the param`, + typeof modelName === 'string' + ); heimdall.increment(createRecordArray); let array = RecordArray.create({ @@ -226,7 +233,7 @@ export default class RecordArrayManager { content: A(content || []), store: this.store, isLoaded: true, - manager: this + manager: this, }); if (Array.isArray(content)) { @@ -236,7 +243,6 @@ export default class RecordArrayManager { return array; } - /** Create a `DS.AdapterPopulatedRecordArray` for a modelName with given query. @@ -247,7 +253,10 @@ export default class RecordArrayManager { */ createAdapterPopulatedRecordArray(modelName, query, internalModels, payload) { heimdall.increment(createAdapterPopulatedRecordArray); - assert(`recordArrayManger.createAdapterPopulatedRecordArray expects modelName not modelClass as the first param, received ${modelName}`, typeof modelName === 'string'); + assert( + `recordArrayManger.createAdapterPopulatedRecordArray expects modelName not modelClass as the first param, received ${modelName}`, + typeof modelName === 'string' + ); let array; if (Array.isArray(internalModels)) { @@ -260,7 +269,7 @@ export default class RecordArrayManager { isLoaded: true, isUpdating: false, meta: cloneNull(payload.meta), - links: cloneNull(payload.links) + links: cloneNull(payload.links), }); associateWithRecordArray(internalModels, array); @@ -270,7 +279,7 @@ export default class RecordArrayManager { query: query, content: A(), store: this.store, - manager: this + manager: this, }); } @@ -295,7 +304,6 @@ export default class RecordArrayManager { let removedFromAdapterPopulated = remove(this._adapterPopulatedRecordArrays, array); if (!removedFromAdapterPopulated) { - let liveRecordArrayForType = this._liveRecordArrays[modelName]; // unregister live record array if (liveRecordArrayForType) { @@ -311,7 +319,9 @@ export default class RecordArrayManager { } willDestroy() { - Object.keys(this._liveRecordArrays).forEach(modelName => this._liveRecordArrays[modelName].destroy()); + Object.keys(this._liveRecordArrays).forEach(modelName => + this._liveRecordArrays[modelName].destroy() + ); this._adapterPopulatedRecordArrays.forEach(destroy); this.isDestroyed = true; } @@ -356,12 +366,16 @@ function updateLiveRecordArray(array, internalModels) { if (isDeleted) { modelsToRemove.push(internalModel); - recordArrays.delete(array) + recordArrays.delete(array); } } - if (modelsToAdd.length > 0) { array._pushInternalModels(modelsToAdd); } - if (modelsToRemove.length > 0) { array._removeInternalModels(modelsToRemove); } + if (modelsToAdd.length > 0) { + array._pushInternalModels(modelsToAdd); + } + if (modelsToRemove.length > 0) { + array._removeInternalModels(modelsToRemove); + } // return whether we performed an update. // Necessary until 3.5 allows us to finish off ember-data-filter support. diff --git a/addon/-private/system/record-arrays.js b/addon/-private/system/record-arrays.js index d65107ed72a..5439899ad81 100644 --- a/addon/-private/system/record-arrays.js +++ b/addon/-private/system/record-arrays.js @@ -2,10 +2,7 @@ @module ember-data */ -import RecordArray from "./record-arrays/record-array"; -import AdapterPopulatedRecordArray from "./record-arrays/adapter-populated-record-array"; +import RecordArray from './record-arrays/record-array'; +import AdapterPopulatedRecordArray from './record-arrays/adapter-populated-record-array'; -export { - RecordArray, - AdapterPopulatedRecordArray -}; +export { RecordArray, AdapterPopulatedRecordArray }; diff --git a/addon/-private/system/record-arrays/adapter-populated-record-array.js b/addon/-private/system/record-arrays/adapter-populated-record-array.js index 7ccf8e89085..d3cc1e68a91 100644 --- a/addon/-private/system/record-arrays/adapter-populated-record-array.js +++ b/addon/-private/system/record-arrays/adapter-populated-record-array.js @@ -1,8 +1,8 @@ import { once } from '@ember/runloop'; import { A } from '@ember/array'; import { get } from '@ember/object'; -import RecordArray from "./record-array"; -import cloneNull from "../clone-null"; +import RecordArray from './record-array'; +import cloneNull from '../clone-null'; /** Represents an ordered list of records whose order and membership is @@ -80,7 +80,7 @@ export default RecordArray.extend({ isLoaded: true, isUpdating: false, meta: cloneNull(payload.meta), - links: cloneNull(payload.links) + links: cloneNull(payload.links), }); this.manager._associateWithRecordArray(internalModels, this); @@ -88,5 +88,5 @@ export default RecordArray.extend({ // TODO: should triggering didLoad event be the last action of the runLoop? once(this, 'trigger', 'didLoad'); heimdall.stop(token); - } + }, }); diff --git a/addon/-private/system/record-arrays/record-array.js b/addon/-private/system/record-arrays/record-array.js index 71d2ffdef1c..78afefda737 100644 --- a/addon/-private/system/record-arrays/record-array.js +++ b/addon/-private/system/record-arrays/record-array.js @@ -7,8 +7,8 @@ import Evented from '@ember/object/evented'; import ArrayProxy from '@ember/array/proxy'; import { set, get, computed } from '@ember/object'; import { Promise } from 'rsvp'; -import { PromiseArray } from "../promise-proxies"; -import SnapshotRecordArray from "../snapshot-record-array"; +import { PromiseArray } from '../promise-proxies'; +import SnapshotRecordArray from '../snapshot-record-array'; /** A record array is an array that contains records of a certain modelName. The record @@ -53,7 +53,7 @@ export default ArrayProxy.extend(Evented, { @type Boolean */ this.isLoaded = this.isLoaded || false; - /** + /** The flag to signal a `RecordArray` is currently loading data. Example @@ -70,7 +70,7 @@ export default ArrayProxy.extend(Evented, { */ this.isUpdating = false; - /** + /** The store that created this record array. @property store @@ -82,7 +82,11 @@ export default ArrayProxy.extend(Evented, { }, replace() { - throw new Error(`The result of a server query (for all ${this.modelName} types) is immutable. To modify contents, use toArray()`); + throw new Error( + `The result of a server query (for all ${ + this.modelName + } types) is immutable. To modify contents, use toArray()` + ); }, /** @@ -131,13 +135,17 @@ export default ArrayProxy.extend(Evented, { @method update */ update() { - if (get(this, 'isUpdating')) { return this._updatingPromise; } + if (get(this, 'isUpdating')) { + return this._updatingPromise; + } this.set('isUpdating', true); let updatingPromise = this._update().finally(() => { this._updatingPromise = null; - if (this.get('isDestroying') || this.get('isDestroyed')) { return } + if (this.get('isDestroying') || this.get('isDestroyed')) { + return; + } this.set('isUpdating', false); }); @@ -197,8 +205,11 @@ export default ArrayProxy.extend(Evented, { */ save() { let promiseLabel = `DS: RecordArray#save ${this.modelName}`; - let promise = Promise.all(this.invoke('save'), promiseLabel) - .then(() => this, null, 'DS: RecordArray#save return RecordArray'); + let promise = Promise.all(this.invoke('save'), promiseLabel).then( + () => this, + null, + 'DS: RecordArray#save return RecordArray' + ); return PromiseArray.create({ promise }); }, @@ -251,5 +262,5 @@ export default ArrayProxy.extend(Evented, { */ _takeSnapshot() { return get(this, 'content').map(internalModel => internalModel.createSnapshot()); - } + }, }); diff --git a/addon/-private/system/references/belongs-to.js b/addon/-private/system/references/belongs-to.js index 44094076f65..24c9ad6cddf 100644 --- a/addon/-private/system/references/belongs-to.js +++ b/addon/-private/system/references/belongs-to.js @@ -14,7 +14,6 @@ import { assertPolymorphicType } from 'ember-data/-debug'; @extends DS.Reference */ export default class BelongsToReference extends Reference { - constructor(store, parentInternalModel, belongsToRelationship) { super(store, parentInternalModel); this.belongsToRelationship = belongsToRelationship; @@ -60,10 +59,10 @@ export default class BelongsToReference extends Reference { */ remoteType() { if (this.belongsToRelationship.link) { - return "link"; + return 'link'; } - return "id"; + return 'id'; } /** @@ -235,7 +234,7 @@ export default class BelongsToReference extends Reference { @return {Promise} A promise that resolves with the new value in this belongs-to relationship. */ push(objectOrPromise) { - return resolve(objectOrPromise).then((data) => { + return resolve(objectOrPromise).then(data => { let record; if (data instanceof Model) { @@ -244,7 +243,12 @@ export default class BelongsToReference extends Reference { record = this.store.push(data); } - assertPolymorphicType(this.internalModel, this.belongsToRelationship.relationshipMeta, record._internalModel, this.store); + assertPolymorphicType( + this.internalModel, + this.belongsToRelationship.relationshipMeta, + record._internalModel, + this.store + ); this.belongsToRelationship.setCanonicalInternalModel(record._internalModel); @@ -346,12 +350,12 @@ export default class BelongsToReference extends Reference { @return {Promise} a promise that resolves with the record in this belongs-to relationship. */ load() { - if (this.remoteType() === "id") { + if (this.remoteType() === 'id') { return this.belongsToRelationship.getRecord(); } - if (this.remoteType() === "link") { - return this.belongsToRelationship.findLink().then((internalModel) => { + if (this.remoteType() === 'link') { + return this.belongsToRelationship.findLink().then(internalModel => { return this.value(); }); } @@ -393,9 +397,8 @@ export default class BelongsToReference extends Reference { @return {Promise} a promise that resolves with the record in this belongs-to relationship after the reload has completed. */ reload() { - return this.belongsToRelationship.reload().then((internalModel) => { + return this.belongsToRelationship.reload().then(internalModel => { return this.value(); }); } - } diff --git a/addon/-private/system/references/has-many.js b/addon/-private/system/references/has-many.js index ddd775d89de..60b7acb75fd 100644 --- a/addon/-private/system/references/has-many.js +++ b/addon/-private/system/references/has-many.js @@ -61,10 +61,10 @@ export default class HasManyReference extends Reference { */ remoteType() { if (this.hasManyRelationship.link) { - return "link"; + return 'link'; } - return "ids"; + return 'ids'; } /** @@ -232,20 +232,25 @@ export default class HasManyReference extends Reference { @return {DS.ManyArray} */ push(objectOrPromise) { - return resolve(objectOrPromise).then((payload) => { + return resolve(objectOrPromise).then(payload => { let array = payload; - if (typeof payload === "object" && payload.data) { + if (typeof payload === 'object' && payload.data) { array = payload.data; } let internalModels; - internalModels = array.map((obj) => { + internalModels = array.map(obj => { let record = this.store.push(obj); if (DEBUG) { let relationshipMeta = this.hasManyRelationship.relationshipMeta; - assertPolymorphicType(this.internalModel, relationshipMeta, record._internalModel, this.store); + assertPolymorphicType( + this.internalModel, + relationshipMeta, + record._internalModel, + this.store + ); } return record._internalModel; @@ -398,5 +403,4 @@ export default class HasManyReference extends Reference { reload() { return this.hasManyRelationship.reload(); } - } diff --git a/addon/-private/system/references/record.js b/addon/-private/system/references/record.js index 086945b3a22..56bb3338192 100644 --- a/addon/-private/system/references/record.js +++ b/addon/-private/system/references/record.js @@ -87,7 +87,7 @@ export default class RecordReference extends Reference { @return Promise a promise for the value (record or relationship) */ push(objectOrPromise) { - return resolve(objectOrPromise).then((data) => { + return resolve(objectOrPromise).then(data => { return this.store.push(data); }); } @@ -159,5 +159,4 @@ export default class RecordReference extends Reference { return this.load(); } - } diff --git a/addon/-private/system/references/reference.js b/addon/-private/system/references/reference.js index 5f3fbdae646..bdf669d3ae4 100644 --- a/addon/-private/system/references/reference.js +++ b/addon/-private/system/references/reference.js @@ -4,7 +4,7 @@ var Reference = function(store, internalModel) { }; Reference.prototype = { - constructor: Reference + constructor: Reference, }; export default Reference; diff --git a/addon/-private/system/relationships/belongs-to.js b/addon/-private/system/relationships/belongs-to.js index 8256a5737ee..3fe47ee9cc7 100644 --- a/addon/-private/system/relationships/belongs-to.js +++ b/addon/-private/system/relationships/belongs-to.js @@ -1,6 +1,6 @@ import { computed } from '@ember/object'; import { assert, warn, inspect } from '@ember/debug'; -import normalizeModelName from "../normalize-model-name"; +import normalizeModelName from '../normalize-model-name'; /** `DS.belongsTo` is used to define One-To-One and One-To-Many @@ -88,7 +88,12 @@ export default function belongsTo(modelName, options) { userEnteredModelName = normalizeModelName(userEnteredModelName); } - assert("The first argument to DS.belongsTo must be a string representing a model type key, not an instance of " + inspect(userEnteredModelName) + ". E.g., to define a relation to the Person model, use DS.belongsTo('person')", typeof userEnteredModelName === 'string' || typeof userEnteredModelName === 'undefined'); + assert( + 'The first argument to DS.belongsTo must be a string representing a model type key, not an instance of ' + + inspect(userEnteredModelName) + + ". E.g., to define a relation to the Person model, use DS.belongsTo('person')", + typeof userEnteredModelName === 'string' || typeof userEnteredModelName === 'undefined' + ); opts = opts || {}; @@ -98,21 +103,33 @@ export default function belongsTo(modelName, options) { options: opts, kind: 'belongsTo', name: 'Belongs To', - key: null + key: null, }; return computed({ get(key) { if (opts.hasOwnProperty('serialize')) { - warn(`You provided a serialize option on the "${key}" property in the "${this._internalModel.modelName}" class, this belongs in the serializer. See DS.Serializer and it's implementations https://emberjs.com/api/data/classes/DS.Serializer.html`, false, { - id: 'ds.model.serialize-option-in-belongs-to' - }); + warn( + `You provided a serialize option on the "${key}" property in the "${ + this._internalModel.modelName + }" class, this belongs in the serializer. See DS.Serializer and it's implementations https://emberjs.com/api/data/classes/DS.Serializer.html`, + false, + { + id: 'ds.model.serialize-option-in-belongs-to', + } + ); } if (opts.hasOwnProperty('embedded')) { - warn(`You provided an embedded option on the "${key}" property in the "${this._internalModel.modelName}" class, this belongs in the serializer. See DS.EmbeddedRecordsMixin https://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html`, false, { - id: 'ds.model.embedded-option-in-belongs-to' - }); + warn( + `You provided an embedded option on the "${key}" property in the "${ + this._internalModel.modelName + }" class, this belongs in the serializer. See DS.EmbeddedRecordsMixin https://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html`, + false, + { + id: 'ds.model.embedded-option-in-belongs-to', + } + ); } return this._internalModel._relationships.get(key).getRecord(); @@ -121,6 +138,6 @@ export default function belongsTo(modelName, options) { this._internalModel.setDirtyBelongsTo(key, value); return this._internalModel._relationships.get(key).getRecord(); - } + }, }).meta(meta); } diff --git a/addon/-private/system/relationships/ext.js b/addon/-private/system/relationships/ext.js index d848397cf1d..d35608b5583 100644 --- a/addon/-private/system/relationships/ext.js +++ b/addon/-private/system/relationships/ext.js @@ -1,16 +1,15 @@ import { A } from '@ember/array'; -import { computed , get } from '@ember/object'; +import { computed, get } from '@ember/object'; import MapWithDefault from '../map-with-default'; import Map from '../map'; import { assert } from '@ember/debug'; -import { - typeForRelationshipMeta, - relationshipFromMeta -} from "../relationship-meta"; +import { typeForRelationshipMeta, relationshipFromMeta } from '../relationship-meta'; export const relationshipsDescriptor = computed(function() { let map = new MapWithDefault({ - defaultValue() { return []; } + defaultValue() { + return []; + }, }); let relationshipsByName = get(this, 'relationshipsByName'); @@ -36,10 +35,18 @@ export const relatedTypesDescriptor = computed(function() { meta.key = name; modelName = typeForRelationshipMeta(meta); - assert(`You specified a hasMany (${meta.type}) on ${meta.parentType} but ${meta.type} was not found.`, modelName); + assert( + `You specified a hasMany (${meta.type}) on ${meta.parentType} but ${ + meta.type + } was not found.`, + modelName + ); if (!types.includes(modelName)) { - assert(`Trying to sideload ${name} on ${this.toString()} but the type doesn't exist.`, !!modelName); + assert( + `Trying to sideload ${name} on ${this.toString()} but the type doesn't exist.`, + !!modelName + ); types.push(modelName); } } diff --git a/addon/-private/system/relationships/has-many.js b/addon/-private/system/relationships/has-many.js index 6a575466a41..56546c69e89 100644 --- a/addon/-private/system/relationships/has-many.js +++ b/addon/-private/system/relationships/has-many.js @@ -3,7 +3,7 @@ */ import { computed } from '@ember/object'; import { assert, inspect } from '@ember/debug'; -import normalizeModelName from "../normalize-model-name"; +import normalizeModelName from '../normalize-model-name'; /** `DS.hasMany` is used to define One-To-Many and Many-To-Many @@ -117,7 +117,12 @@ export default function hasMany(type, options) { type = undefined; } - assert(`The first argument to DS.hasMany must be a string representing a model type key, not an instance of ${inspect(type)}. E.g., to define a relation to the Comment model, use DS.hasMany('comment')`, typeof type === 'string' || typeof type === 'undefined'); + assert( + `The first argument to DS.hasMany must be a string representing a model type key, not an instance of ${inspect( + type + )}. E.g., to define a relation to the Comment model, use DS.hasMany('comment')`, + typeof type === 'string' || typeof type === 'undefined' + ); options = options || {}; @@ -135,7 +140,7 @@ export default function hasMany(type, options) { isRelationship: true, kind: 'hasMany', name: 'Has Many', - key: null + key: null, }; return computed({ @@ -146,6 +151,6 @@ export default function hasMany(type, options) { this._internalModel.setDirtyHasMany(key, records); return this._internalModel._relationships.get(key).getRecords(); - } + }, }).meta(meta); } diff --git a/addon/-private/system/relationships/relationship-payloads-manager.js b/addon/-private/system/relationships/relationship-payloads-manager.js index bc67a6aefde..64282e729cf 100644 --- a/addon/-private/system/relationships/relationship-payloads-manager.js +++ b/addon/-private/system/relationships/relationship-payloads-manager.js @@ -112,7 +112,9 @@ export default class RelationshipPayloadsManager { @method */ push(modelName, id, relationshipsData) { - if (!relationshipsData) { return; } + if (!relationshipsData) { + return; + } Object.keys(relationshipsData).forEach(key => { let relationshipPayloads = this._getRelationshipPayloads(modelName, key, true); @@ -208,7 +210,8 @@ export default class RelationshipPayloadsManager { inverseMeta = modelClass.inverseFor(relationshipName, store); } - let selfIsPolymorphic = relationshipMeta.options !== undefined && relationshipMeta.options.polymorphic === true; + let selfIsPolymorphic = + relationshipMeta.options !== undefined && relationshipMeta.options.polymorphic === true; let inverseBaseModelName = relationshipMeta.type; // CASE: We have no inverse @@ -228,7 +231,7 @@ export default class RelationshipPayloadsManager { rhs_isPolymorphic: false, hasInverse: false, isSelfReferential: false, // modelName === inverseBaseModelName, - isReflexive: false + isReflexive: false, }; inverseCache.set(modelName, relationshipName, info); @@ -239,7 +242,9 @@ export default class RelationshipPayloadsManager { // CASE: We do have an inverse let inverseRelationshipName = inverseMeta.name; - let inverseRelationshipMeta = get(inverseMeta.type, 'relationshipsByName').get(inverseRelationshipName); + let inverseRelationshipMeta = get(inverseMeta.type, 'relationshipsByName').get( + inverseRelationshipName + ); let baseModelName = inverseRelationshipMeta.type; let isSelfReferential = baseModelName === inverseBaseModelName; @@ -254,11 +259,15 @@ export default class RelationshipPayloadsManager { // CASE: We may have already discovered the inverse for the baseModelName // CASE: We have already discovered the inverse - cached = inverseCache.get(baseModelName, relationshipName) || + cached = + inverseCache.get(baseModelName, relationshipName) || inverseCache.get(inverseBaseModelName, inverseRelationshipName); if (cached) { // TODO this assert can be removed if the above assert is enabled - assert(`The ${inverseBaseModelName}:${inverseRelationshipName} relationship declares 'inverse: null', but it was resolved as the inverse for ${baseModelName}:${relationshipName}.`, cached.hasInverse !== false); + assert( + `The ${inverseBaseModelName}:${inverseRelationshipName} relationship declares 'inverse: null', but it was resolved as the inverse for ${baseModelName}:${relationshipName}.`, + cached.hasInverse !== false + ); let isLHS = cached.lhs_baseModelName === baseModelName; let modelNames = isLHS ? cached.lhs_modelNames : cached.rhs_modelNames; @@ -281,10 +290,12 @@ export default class RelationshipPayloadsManager { rhs_baseModelName: inverseBaseModelName, rhs_relationshipName: inverseRelationshipName, rhs_relationshipMeta: inverseRelationshipMeta, - rhs_isPolymorphic: inverseRelationshipMeta.options !== undefined && inverseRelationshipMeta.options.polymorphic === true, + rhs_isPolymorphic: + inverseRelationshipMeta.options !== undefined && + inverseRelationshipMeta.options.polymorphic === true, hasInverse: true, isSelfReferential, - isReflexive: isSelfReferential && relationshipName === inverseRelationshipName + isReflexive: isSelfReferential && relationshipName === inverseRelationshipName, }; // Create entries for the baseModelName as well as modelName to speed up @@ -324,7 +335,7 @@ export default class RelationshipPayloadsManager { // This works out better than creating a single common key, because to // compute that key we would need to do work to look up the inverse // - let cache = this._cache[lhsKey] = new RelationshipPayloads(relInfo); + let cache = (this._cache[lhsKey] = new RelationshipPayloads(relInfo)); if (relInfo.hasInverse === true) { this._cache[rhsKey] = cache; diff --git a/addon/-private/system/relationships/relationship-payloads.js b/addon/-private/system/relationships/relationship-payloads.js index e82d5b7bcc5..07b051dd14f 100644 --- a/addon/-private/system/relationships/relationship-payloads.js +++ b/addon/-private/system/relationships/relationship-payloads.js @@ -140,7 +140,12 @@ export default class RelationshipPayloads { if (this._isLHS(modelName, relationshipName)) { return this.lhs_payloads.get(modelName, id); } else { - assert(`${modelName}:${relationshipName} is not either side of this relationship, ${this._relInfo.lhs_key}<->${this._relInfo.rhs_key}`, this._isRHS(modelName, relationshipName)); + assert( + `${modelName}:${relationshipName} is not either side of this relationship, ${ + this._relInfo.lhs_key + }<->${this._relInfo.rhs_key}`, + this._isRHS(modelName, relationshipName) + ); return this.rhs_payloads.get(modelName, id); } } @@ -169,7 +174,14 @@ export default class RelationshipPayloads { if (this._isLHS(modelName, relationshipName)) { delete this.lhs_payloads.delete(modelName, id); } else { - assert(`${modelName}:${relationshipName} is not either side of this relationship, ${this._relInfo.lhs_baseModelName}:${this._relInfo.lhs_relationshipName}<->${this._relInfo.rhs_baseModelName}:${this._relInfo.rhs_relationshipName}`, this._isRHS(modelName, relationshipName)); + assert( + `${modelName}:${relationshipName} is not either side of this relationship, ${ + this._relInfo.lhs_baseModelName + }:${this._relInfo.lhs_relationshipName}<->${this._relInfo.rhs_baseModelName}:${ + this._relInfo.rhs_relationshipName + }`, + this._isRHS(modelName, relationshipName) + ); delete this.rhs_payloads.delete(modelName, id); } } @@ -186,9 +198,11 @@ export default class RelationshipPayloads { let isRelationship = relationshipName === relInfo.lhs_relationshipName; if (isRelationship === true) { - return isSelfReferential === true || // itself + return ( + isSelfReferential === true || // itself modelName === relInfo.lhs_baseModelName || // base or non-polymorphic - relInfo.lhs_modelNames.indexOf(modelName) !== -1; // polymorphic + relInfo.lhs_modelNames.indexOf(modelName) !== -1 + ); // polymorphic } return false; @@ -206,19 +220,23 @@ export default class RelationshipPayloads { let isRelationship = relationshipName === relInfo.rhs_relationshipName; if (isRelationship === true) { - return isSelfReferential === true || // itself + return ( + isSelfReferential === true || // itself modelName === relInfo.rhs_baseModelName || // base or non-polymorphic - relInfo.rhs_modelNames.indexOf(modelName) !== -1; // polymorphic + relInfo.rhs_modelNames.indexOf(modelName) !== -1 + ); // polymorphic } return false; } _flushPending() { - if (this._pendingPayloads.length === 0) { return; } + if (this._pendingPayloads.length === 0) { + return; + } let payloadsToBeProcessed = this._pendingPayloads.splice(0, this._pendingPayloads.length); - for (let i=0; i${this._relInfo.rhs_key}`, this._isRHS(modelName, relationshipName)); + assert( + `${modelName}:${relationshipName} is not either side of this relationship, ${ + this._relInfo.lhs_key + }<->${this._relInfo.rhs_key}`, + this._isRHS(modelName, relationshipName) + ); previousPayload = this.rhs_payloads.get(modelName, id); payloadMap = this.rhs_payloads; inversePayloadMap = this.lhs_payloads; @@ -307,17 +330,18 @@ export default class RelationshipPayloads { payloadMap.set(modelName, id, relationshipData); if (!isMatchingIdentifier) { - this._populateInverse(relationshipData, inverseRelationshipData, inversePayloadMap, inverseIsMany); + this._populateInverse( + relationshipData, + inverseRelationshipData, + inversePayloadMap, + inverseIsMany + ); } } } _isMatchingIdentifier(a, b) { - return a && b && - a.type === b.type && - a.id === b.id && - !Array.isArray(a) && - !Array.isArray(b); + return a && b && a.type === b.type && a.id === b.id && !Array.isArray(a) && !Array.isArray(b); } /** @@ -338,7 +362,7 @@ export default class RelationshipPayloads { } if (Array.isArray(relationshipData.data)) { - for (let i=0; i x.id !== id); + inversePayload.data = data.filter(x => x.id !== id); } else if (Array.isArray(partialData)) { - inversePayload._partialData = partialData.filter((x) => x.id !== id); + inversePayload._partialData = partialData.filter(x => x.id !== id); } else { // this merges forward links and meta inversePayload.data = null; diff --git a/addon/-private/system/relationships/state/belongs-to.js b/addon/-private/system/relationships/state/belongs-to.js index 2f859682ec9..ba907947725 100644 --- a/addon/-private/system/relationships/state/belongs-to.js +++ b/addon/-private/system/relationships/state/belongs-to.js @@ -1,10 +1,8 @@ import { Promise as EmberPromise } from 'rsvp'; import { assert } from '@ember/debug'; import { assertPolymorphicType } from 'ember-data/-debug'; -import { - PromiseBelongsTo -} from "../../promise-proxies"; -import Relationship from "./relationship"; +import { PromiseBelongsTo } from '../../promise-proxies'; +import Relationship from './relationship'; export default class BelongsToRelationship extends Relationship { constructor(store, internalModel, inverseKey, relationshipMeta) { @@ -36,7 +34,9 @@ export default class BelongsToRelationship extends Relationship { } setInitialCanonicalInternalModel(internalModel) { - if (!internalModel) { return; } + if (!internalModel) { + return; + } // When we initialize a belongsTo relationship, we want to avoid work like // notifying our internalModel that we've "changed" and excessive thrash on @@ -48,7 +48,9 @@ export default class BelongsToRelationship extends Relationship { } addCanonicalInternalModel(internalModel) { - if (this.canonicalMembers.has(internalModel)) { return;} + if (this.canonicalMembers.has(internalModel)) { + return; + } if (this.canonicalState) { this.removeCanonicalInternalModel(this.canonicalState); @@ -76,7 +78,6 @@ export default class BelongsToRelationship extends Relationship { } } - removeCompletelyFromInverse() { super.removeCompletelyFromInverse(); @@ -98,7 +99,9 @@ export default class BelongsToRelationship extends Relationship { } addInternalModel(internalModel) { - if (this.members.has(internalModel)) { return; } + if (this.members.has(internalModel)) { + return; + } assertPolymorphicType(this.internalModel, this.relationshipMeta, internalModel, this.store); @@ -113,12 +116,17 @@ export default class BelongsToRelationship extends Relationship { setRecordPromise(newPromise) { let content = newPromise.get && newPromise.get('content'); - assert("You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.", content !== undefined); + assert( + 'You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.', + content !== undefined + ); this.setInternalModel(content ? content._internalModel : content); } removeInternalModelFromOwn(internalModel) { - if (!this.members.has(internalModel)) { return;} + if (!this.members.has(internalModel)) { + return; + } this.inverseInternalModel = null; super.removeInternalModelFromOwn(internalModel); this.notifyBelongsToChanged(); @@ -135,7 +143,9 @@ export default class BelongsToRelationship extends Relationship { } removeCanonicalInternalModelFromOwn(internalModel) { - if (!this.canonicalMembers.has(internalModel)) { return;} + if (!this.canonicalMembers.has(internalModel)) { + return; + } this.canonicalState = null; super.removeCanonicalInternalModelFromOwn(internalModel); } @@ -154,12 +164,14 @@ export default class BelongsToRelationship extends Relationship { } fetchLink() { - return this.store.findBelongsTo(this.internalModel, this.link, this.relationshipMeta).then((internalModel) => { - if (internalModel) { - this.addInternalModel(internalModel); - } - return internalModel; - }); + return this.store + .findBelongsTo(this.internalModel, this.link, this.relationshipMeta) + .then(internalModel => { + if (internalModel) { + this.addInternalModel(internalModel); + } + return internalModel; + }); } getRecord() { @@ -173,7 +185,7 @@ export default class BelongsToRelationship extends Relationship { promise = this.findRecord(); } - let record = this.inverseInternalModel ? this.inverseInternalModel.getRecord() : null + let record = this.inverseInternalModel ? this.inverseInternalModel.getRecord() : null; return this._updateLoadingPromise(promise, record); } else { @@ -181,7 +193,16 @@ export default class BelongsToRelationship extends Relationship { return null; } let toReturn = this.inverseInternalModel.getRecord(); - assert("You looked up the '" + this.key + "' relationship on a '" + this.internalModel.modelName + "' with id " + this.internalModel.id + " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)", toReturn === null || !toReturn.get('isEmpty')); + assert( + "You looked up the '" + + this.key + + "' relationship on a '" + + this.internalModel.modelName + + "' with id " + + this.internalModel.id + + ' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)', + toReturn === null || !toReturn.get('isEmpty') + ); return toReturn; } } @@ -189,14 +210,14 @@ export default class BelongsToRelationship extends Relationship { _updateLoadingPromise(promise, content) { if (this._loadingPromise) { if (content !== undefined) { - this._loadingPromise.set('content', content) + this._loadingPromise.set('content', content); } - this._loadingPromise.set('promise', promise) + this._loadingPromise.set('promise', promise); } else { this._loadingPromise = PromiseBelongsTo.create({ _belongsToState: this, promise, - content + content, }); } @@ -229,7 +250,7 @@ export default class BelongsToRelationship extends Relationship { localStateIsEmpty() { let internalModel = this.inverseInternalModel; - return !internalModel || internalModel.isEmpty(); + return !internalModel || internalModel.isEmpty(); } updateData(data, initial) { diff --git a/addon/-private/system/relationships/state/create.js b/addon/-private/system/relationships/state/create.js index 1039683f91e..ed82b773f7c 100644 --- a/addon/-private/system/relationships/state/create.js +++ b/addon/-private/system/relationships/state/create.js @@ -1,6 +1,6 @@ import { get } from '@ember/object'; -import ManyRelationship from "./has-many"; -import BelongsToRelationship from "./belongs-to"; +import ManyRelationship from './has-many'; +import BelongsToRelationship from './belongs-to'; import { DEBUG } from '@glimmer/env'; function shouldFindInverse(relationshipMeta) { @@ -60,11 +60,21 @@ export default class Relationships { let relationshipsByName = get(internalModel.type, 'relationshipsByName'); let rel = relationshipsByName.get(key); - if (!rel) { return undefined; } - - let relationshipPayload = internalModel.store._relationshipsPayloads.get(internalModel.modelName, internalModel.id, key); + if (!rel) { + return undefined; + } - relationship = relationships[key] = createRelationshipFor(internalModel, rel, internalModel.store); + let relationshipPayload = internalModel.store._relationshipsPayloads.get( + internalModel.modelName, + internalModel.id, + key + ); + + relationship = relationships[key] = createRelationshipFor( + internalModel, + rel, + internalModel.store + ); if (relationshipPayload) { relationship.push(relationshipPayload, true); diff --git a/addon/-private/system/relationships/state/has-many.js b/addon/-private/system/relationships/state/has-many.js index cc4523051cf..54253422634 100755 --- a/addon/-private/system/relationships/state/has-many.js +++ b/addon/-private/system/relationships/state/has-many.js @@ -24,13 +24,13 @@ export default class ManyRelationship extends Relationship { _updateLoadingPromise(promise, content) { if (this._loadingPromise) { if (content) { - this._loadingPromise.set('content', content) + this._loadingPromise.set('content', content); } - this._loadingPromise.set('promise', promise) + this._loadingPromise.set('promise', promise); } else { this._loadingPromise = PromiseManyArray.create({ promise, - content + content, }); } @@ -38,7 +38,12 @@ export default class ManyRelationship extends Relationship { } get manyArray() { - assert(`Error: relationship ${this.parentType}:${this.key} has both many array and retained many array`, this._manyArray === null || this._retainedManyArray === null); + assert( + `Error: relationship ${this.parentType}:${ + this.key + } has both many array and retained many array`, + this._manyArray === null || this._retainedManyArray === null + ); if (!this._manyArray && !this.isDestroying) { this._manyArray = ManyArray.create({ @@ -48,7 +53,7 @@ export default class ManyRelationship extends Relationship { type: this.store.modelFor(this.belongsToType), record: this.internalModel, meta: this.meta, - isPolymorphic: this.isPolymorphic + isPolymorphic: this.isPolymorphic, }); if (this._retainedManyArray !== null) { @@ -120,7 +125,7 @@ export default class ManyRelationship extends Relationship { // return; // } - let pending = this._pendingManyArrayUpdates = this._pendingManyArrayUpdates || []; + let pending = (this._pendingManyArrayUpdates = this._pendingManyArrayUpdates || []); pending.push(internalModel, idx); if (this._willUpdateManyArray === true) { @@ -271,7 +276,9 @@ export default class ManyRelationship extends Relationship { let internalModelSet = setForArray(internalModels); members.forEach(member => { - if (internalModelSet.has(member)) { return; } + if (internalModelSet.has(member)) { + return; + } internalModelsToRemove.push(member); }); @@ -290,7 +297,7 @@ export default class ManyRelationship extends Relationship { return; } - for (let i = 0; i< internalModels.length; i++) { + for (let i = 0; i < internalModels.length; i++) { let internalModel = internalModels[i]; if (this.canonicalMembers.has(internalModel)) { continue; @@ -305,16 +312,18 @@ export default class ManyRelationship extends Relationship { } fetchLink() { - return this.store.findHasMany(this.internalModel, this.link, this.relationshipMeta).then(records => { - if (records.hasOwnProperty('meta')) { - this.updateMeta(records.meta); - } - this.store._backburner.join(() => { - this.updateInternalModelsFromAdapter(records); - this.manyArray.set('isLoaded', true); + return this.store + .findHasMany(this.internalModel, this.link, this.relationshipMeta) + .then(records => { + if (records.hasOwnProperty('meta')) { + this.updateMeta(records.meta); + } + this.store._backburner.join(() => { + this.updateInternalModelsFromAdapter(records); + this.manyArray.set('isLoaded', true); + }); + return this.manyArray; }); - return this.manyArray; - }); } findRecords() { @@ -350,7 +359,14 @@ export default class ManyRelationship extends Relationship { return this._updateLoadingPromise(promise, manyArray); } else { - assert(`You looked up the '${this.key}' relationship on a '${this.internalModel.type.modelName}' with id ${this.internalModel.id} but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async ('DS.hasMany({ async: true })')`, manyArray.isEvery('isEmpty', false)); + assert( + `You looked up the '${this.key}' relationship on a '${ + this.internalModel.type.modelName + }' with id ${ + this.internalModel.id + } but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async ('DS.hasMany({ async: true })')`, + manyArray.isEvery('isEmpty', false) + ); manyArray.set('isLoaded', true); @@ -404,7 +420,7 @@ function setForArray(array) { var set = new OrderedSet(); if (array) { - for (var i=0, l=array.length; i { + this.forAllMembers(inverseInternalModel => { let relationship = inverseInternalModel._relationships.get(this.inverseKey); relationship.inverseDidDematerialize(this.internalModel); }); @@ -233,7 +236,7 @@ export default class Relationship { removeInternalModels(internalModels) { heimdall.increment(removeInternalModels); - internalModels.forEach((internalModel) => this.removeInternalModel(internalModel)); + internalModels.forEach(internalModel => this.removeInternalModel(internalModel)); } addInternalModels(internalModels, idx) { @@ -248,9 +251,9 @@ export default class Relationship { addCanonicalInternalModels(internalModels, idx) { heimdall.increment(addCanonicalInternalModels); - for (let i=0; i result); + return promise.then(result => result); } } @@ -525,7 +550,7 @@ export default class Relationship { this.computeChanges(internalModels); } - notifyRecordRelationshipAdded() { } + notifyRecordRelationshipAdded() {} setHasAnyRelationshipData(value) { this.hasAnyRelationshipData = value; @@ -592,15 +617,13 @@ export default class Relationship { */ if (hasRelationshipDataProperty) { - let relationshipIsEmpty = payload.data === null || - (Array.isArray(payload.data) && payload.data.length === 0); + let relationshipIsEmpty = + payload.data === null || (Array.isArray(payload.data) && payload.data.length === 0); this.setHasAnyRelationshipData(true); this.setRelationshipIsStale(false); this.setRelationshipIsEmpty(relationshipIsEmpty); - this.setHasRelatedResources( - relationshipIsEmpty || !this.localStateIsEmpty() - ); + this.setHasRelatedResources(relationshipIsEmpty || !this.localStateIsEmpty()); } else if (hasLink) { this.setRelationshipIsStale(true); } @@ -608,6 +631,5 @@ export default class Relationship { updateData() {} - destroy() { - } + destroy() {} } diff --git a/addon/-private/system/snapshot.js b/addon/-private/system/snapshot.js index 369e868a3f1..2ff17d9d7de 100644 --- a/addon/-private/system/snapshot.js +++ b/addon/-private/system/snapshot.js @@ -91,7 +91,7 @@ export default class Snapshot { let record = this.record; attributes = this.__attributes = Object.create(null); - record.eachAttribute((keyName) => attributes[keyName] = get(record, keyName)); + record.eachAttribute(keyName => (attributes[keyName] = get(record, keyName))); } return attributes; @@ -131,7 +131,9 @@ export default class Snapshot { if (keyName in this._attributes) { return this._attributes[keyName]; } - throw new EmberError("Model '" + inspect(this.record) + "' has no attribute named '" + keyName + "' defined."); + throw new EmberError( + "Model '" + inspect(this.record) + "' has no attribute named '" + keyName + "' defined." + ); } /** @@ -169,7 +171,7 @@ export default class Snapshot { let changedAttributes = Object.create(null); let changedAttributeKeys = Object.keys(this._changedAttributes); - for (let i=0, length = changedAttributeKeys.length; i < length; i++) { + for (let i = 0, length = changedAttributeKeys.length; i < length; i++) { let key = changedAttributeKeys[i]; changedAttributes[key] = this._changedAttributes[key].slice(); } @@ -227,13 +229,16 @@ export default class Snapshot { relationship = this._internalModel._relationships.get(keyName); if (!(relationship && relationship.relationshipMeta.kind === 'belongsTo')) { - throw new EmberError("Model '" + inspect(this.record) + "' has no belongsTo relationship named '" + keyName + "' defined."); + throw new EmberError( + "Model '" + + inspect(this.record) + + "' has no belongsTo relationship named '" + + keyName + + "' defined." + ); } - let { - hasAnyRelationshipData, - inverseInternalModel - } = relationship; + let { hasAnyRelationshipData, inverseInternalModel } = relationship; if (hasAnyRelationshipData) { if (inverseInternalModel && !inverseInternalModel.isDeleted()) { @@ -300,17 +305,20 @@ export default class Snapshot { relationship = this._internalModel._relationships.get(keyName); if (!(relationship && relationship.relationshipMeta.kind === 'hasMany')) { - throw new EmberError("Model '" + inspect(this.record) + "' has no hasMany relationship named '" + keyName + "' defined."); + throw new EmberError( + "Model '" + + inspect(this.record) + + "' has no hasMany relationship named '" + + keyName + + "' defined." + ); } - let { - hasAnyRelationshipData, - members - } = relationship; + let { hasAnyRelationshipData, members } = relationship; if (hasAnyRelationshipData) { results = []; - members.forEach((member) => { + members.forEach(member => { if (!member.isDeleted()) { if (ids) { results.push(member.id); diff --git a/addon/-private/system/store.js b/addon/-private/system/store.js index f146066966e..3ca251ae158 100644 --- a/addon/-private/system/store.js +++ b/addon/-private/system/store.js @@ -18,24 +18,21 @@ import { instrument } from 'ember-data/-debug'; import { assert, deprecate, warn, inspect } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; import Model from './model/model'; -import normalizeModelName from "./normalize-model-name"; +import normalizeModelName from './normalize-model-name'; import IdentityMap from './identity-map'; -import { - promiseArray, - promiseObject -} from "./promise-proxies"; +import { promiseArray, promiseObject } from './promise-proxies'; import { _bind, _guard, _objectIsAlive, guardDestroyedStore, - incrementRequestCount -} from "./store/common"; + incrementRequestCount, +} from './store/common'; -import { normalizeResponseHelper } from "./store/serializer-response"; -import { serializerForAdapter } from "./store/serializers"; +import { normalizeResponseHelper } from './store/serializer-response'; +import { serializerForAdapter } from './store/serializers'; import RelationshipPayloadsManager from './relationships/relationship-payloads-manager'; import { @@ -45,13 +42,13 @@ import { _findBelongsTo, _findAll, _query, - _queryRecord -} from "./store/finders"; + _queryRecord, +} from './store/finders'; import { getOwner } from '../utils'; -import coerceId from "./coerce-id"; -import RecordArrayManager from "./record-array-manager"; -import InternalModel from "./model/internal-model"; +import coerceId from './coerce-id'; +import RecordArrayManager from './record-array-manager'; +import InternalModel from './model/internal-model'; import edBackburner from './backburner'; const badIdFormatAssertion = '`id` passed to `findRecord()` has to be non-empty string or number'; @@ -97,8 +94,9 @@ const { peekAll, peekRecord, serializerFor, - _internalModelsFor -} = heimdall.registerMonitor('store', + _internalModelsFor, +} = heimdall.registerMonitor( + 'store', '_generateId', '_internalModelForId', '_load', @@ -188,7 +186,6 @@ const { @extends Ember.Service */ Store = Service.extend({ - /** @method init @private @@ -220,7 +217,11 @@ Store = Service.extend({ this._updatedInternalModels = []; // used to keep track of all the find requests that need to be coalesced - this._pendingFetch = new MapWithDefault({ defaultValue() { return []; } }); + this._pendingFetch = new MapWithDefault({ + defaultValue() { + return []; + }, + }); this._adapterCache = Object.create(null); this._serializerCache = Object.create(null); @@ -265,7 +266,10 @@ Store = Service.extend({ defaultAdapter: computed('adapter', function() { let adapter = get(this, 'adapter'); - assert('You tried to set `adapter` property to an instance of `DS.Adapter`, where it should be a name', typeof adapter === 'string'); + assert( + 'You tried to set `adapter` property to an instance of `DS.Adapter`, where it should be a name', + typeof adapter === 'string' + ); return this.adapterFor(adapter); }), @@ -303,8 +307,14 @@ Store = Service.extend({ @return {DS.Model} record */ createRecord(modelName, inputProperties) { - assert(`You need to pass a model name to the store's createRecord method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's createRecord method`, + isPresent(modelName) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); // This is wrapped in a `run.join` so that in test environments users do not need to manually wrap // calls to `createRecord`. The run loop usage here is because we batch the joining and updating @@ -415,12 +425,30 @@ Store = Service.extend({ // The default `model` hook in 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. - assert(`Using store.find(type) has been removed. Use store.findAll(modelName) to retrieve all records for a given type.`, arguments.length !== 1); - assert(`Calling store.find(modelName, id, { preload: preload }) is no longer supported. Use store.findRecord(modelName, id, { preload: preload }) instead.`, !options); - assert(`You need to pass the model name and id to the store's find method`, arguments.length === 2); - assert(`You cannot pass '${id}' as id to the store's find method`, typeof id === 'string' || typeof id === 'number'); - assert(`Calling store.find() with a query object is no longer supported. Use store.query() instead.`, typeof id !== 'object'); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Using store.find(type) has been removed. Use store.findAll(modelName) to retrieve all records for a given type.`, + arguments.length !== 1 + ); + assert( + `Calling store.find(modelName, id, { preload: preload }) is no longer supported. Use store.findRecord(modelName, id, { preload: preload }) instead.`, + !options + ); + assert( + `You need to pass the model name and id to the store's find method`, + arguments.length === 2 + ); + assert( + `You cannot pass '${id}' as id to the store's find method`, + typeof id === 'string' || typeof id === 'number' + ); + assert( + `Calling store.find() with a query object is no longer supported. Use store.query() instead.`, + typeof id !== 'object' + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); return this.findRecord(modelName, id); }, @@ -648,8 +676,14 @@ Store = Service.extend({ */ findRecord(modelName, id, options) { assert(`You need to pass a model name to the store's findRecord method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); - assert(badIdFormatAssertion, (typeof id === 'string' && id.length > 0) || (typeof id === 'number' && !isNaN(id))); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); + assert( + badIdFormatAssertion, + (typeof id === 'string' && id.length > 0) || (typeof id === 'number' && !isNaN(id)) + ); let normalizedModelName = normalizeModelName(modelName); @@ -662,7 +696,10 @@ Store = Service.extend({ let fetchedInternalModel = this._findRecord(internalModel, options); - return promiseRecord(fetchedInternalModel, `DS: Store#findRecord ${normalizedModelName} with id: ${id}`); + return promiseRecord( + fetchedInternalModel, + `DS: Store#findRecord ${normalizedModelName} with id: ${id}` + ); }, _findRecord(internalModel, options) { @@ -699,7 +736,10 @@ Store = Service.extend({ let fetchedInternalModel = this._findEmptyInternalModel(internalModel, options); - return promiseRecord(fetchedInternalModel, `DS: Store#findRecord ${internalModel.modelName} with id: ${internalModel.id}`); + return promiseRecord( + fetchedInternalModel, + `DS: Store#findRecord ${internalModel.modelName} with id: ${internalModel.id}` + ); }, _findEmptyInternalModel(internalModel, options) { @@ -727,7 +767,10 @@ Store = Service.extend({ */ findByIds(modelName, ids) { assert(`You need to pass a model name to the store's findByIds method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let promises = new Array(ids.length); @@ -737,7 +780,9 @@ Store = Service.extend({ promises[i] = this.findRecord(normalizedModelName, ids[i]); } - return promiseArray(RSVP.all(promises).then(A, null, `DS: Store#findByIds of ${normalizedModelName} complete`)); + return promiseArray( + RSVP.all(promises).then(A, null, `DS: Store#findByIds of ${normalizedModelName} complete`) + ); }, /** @@ -755,7 +800,10 @@ Store = Service.extend({ let adapter = this.adapterFor(modelName); assert(`You tried to find a record but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to find a record but your adapter (for ${modelName}) does not implement 'findRecord'`, typeof adapter.findRecord === 'function'); + assert( + `You tried to find a record but your adapter (for ${modelName}) does not implement 'findRecord'`, + typeof adapter.findRecord === 'function' + ); return _find(adapter, this, internalModel.type, internalModel.id, internalModel, options); }, @@ -780,7 +828,7 @@ Store = Service.extend({ let pendingFetchItem = { internalModel, resolver, - options + options, }; let promise = resolver.promise; @@ -835,7 +883,7 @@ Store = Service.extend({ let recordFetch = store._fetchRecord( recordResolverPair.internalModel, recordResolverPair.options - ); // TODO adapter options + ); // TODO adapter options recordResolverPair.resolver.resolve(recordFetch); } @@ -872,7 +920,7 @@ Store = Service.extend({ '" ]', false, { - id: 'ds.store.missing-records-from-adapter' + id: 'ds.store.missing-records-from-adapter', } ); rejectInternalModels(missingInternalModels); @@ -885,7 +933,12 @@ Store = Service.extend({ let pair = seeking[internalModel.id]; if (pair) { - pair.resolver.reject(error || new Error(`Expected: '${internalModel}' to be present in the adapter provided payload, but it was not found.`)); + pair.resolver.reject( + error || + new Error( + `Expected: '${internalModel}' to be present in the adapter provided payload, but it was not found.` + ) + ); } } } @@ -930,12 +983,15 @@ Store = Service.extend({ .catch(function(error) { rejectInternalModels(groupedInternalModels, error); }); - }(groupedInternalModels)); + })(groupedInternalModels); } else if (ids.length === 1) { var pair = seeking[groupedInternalModels[0].id]; _fetchRecord(pair); } else { - assert("You cannot return an empty array from adapter's method groupRecordsForFindMany", false); + assert( + "You cannot return an empty array from adapter's method groupRecordsForFindMany", + false + ); } } } else { @@ -1014,8 +1070,14 @@ Store = Service.extend({ peekRecord(modelName, id) { heimdall.increment(peekRecord); assert(`You need to pass a model name to the store's peekRecord method`, isPresent(modelName)); - assert(`You need to pass both a model name and id to the store's peekRecord method`, isPresent(modelName) && isPresent(id)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass both a model name and id to the store's peekRecord method`, + isPresent(modelName) && isPresent(id) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); if (this.hasRecordForId(normalizedModelName, id)) { @@ -1044,7 +1106,10 @@ Store = Service.extend({ assert(`You cannot reload a record without an ID`, id); assert(`You tried to reload a record but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to reload a record but your adapter does not implement 'findRecord'`, typeof adapter.findRecord === 'function' || typeof adapter.find === 'function'); + assert( + `You tried to reload a record but your adapter does not implement 'findRecord'`, + typeof adapter.findRecord === 'function' || typeof adapter.find === 'function' + ); return this._scheduleFetch(internalModel, options); }, @@ -1069,8 +1134,14 @@ Store = Service.extend({ @return {Boolean} */ hasRecordForId(modelName, id) { - assert(`You need to pass a model name to the store's hasRecordForId method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's hasRecordForId method`, + isPresent(modelName) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); @@ -1092,7 +1163,10 @@ Store = Service.extend({ */ recordForId(modelName, id) { assert(`You need to pass a model name to the store's recordForId method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); return this._internalModelForId(modelName, id).getRecord(); }, @@ -1147,7 +1221,6 @@ Store = Service.extend({ return Promise.all(finds); }, - /** If a relationship was originally populated by the adapter as a link (as opposed to a list of IDs), this method is called when the @@ -1169,8 +1242,16 @@ Store = Service.extend({ findHasMany(internalModel, link, relationship) { let adapter = this.adapterFor(internalModel.modelName); - assert(`You tried to load a hasMany relationship but you have no adapter (for ${internalModel.modelName})`, adapter); - assert(`You tried to load a hasMany relationship from a specified 'link' in the original payload but your adapter does not implement 'findHasMany'`, typeof adapter.findHasMany === 'function'); + assert( + `You tried to load a hasMany relationship but you have no adapter (for ${ + internalModel.modelName + })`, + adapter + ); + assert( + `You tried to load a hasMany relationship from a specified 'link' in the original payload but your adapter does not implement 'findHasMany'`, + typeof adapter.findHasMany === 'function' + ); return _findHasMany(adapter, this, internalModel, link, relationship); }, @@ -1186,8 +1267,16 @@ Store = Service.extend({ findBelongsTo(internalModel, link, relationship) { let adapter = this.adapterFor(internalModel.modelName); - assert(`You tried to load a belongsTo relationship but you have no adapter (for ${internalModel.modelName})`, adapter); - assert(`You tried to load a belongsTo relationship from a specified 'link' in the original payload but your adapter does not implement 'findBelongsTo'`, typeof adapter.findBelongsTo === 'function'); + assert( + `You tried to load a belongsTo relationship but you have no adapter (for ${ + internalModel.modelName + })`, + adapter + ); + assert( + `You tried to load a belongsTo relationship from a specified 'link' in the original payload but your adapter does not implement 'findBelongsTo'`, + typeof adapter.findBelongsTo === 'function' + ); return _findBelongsTo(adapter, this, internalModel, link, relationship); }, @@ -1248,12 +1337,15 @@ Store = Service.extend({ query(modelName, query, options) { assert(`You need to pass a model name to the store's query method`, isPresent(modelName)); assert(`You need to pass a query hash to the store's query method`, query); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let adapterOptionsWrapper = {}; if (options && options.adapterOptions) { - adapterOptionsWrapper.adapterOptions = options.adapterOptions + adapterOptionsWrapper.adapterOptions = options.adapterOptions; } let normalizedModelName = normalizeModelName(modelName); @@ -1264,7 +1356,10 @@ Store = Service.extend({ let token = heimdall.start('store._query'); assert(`You need to pass a model name to the store's query method`, isPresent(modelName)); assert(`You need to pass a query hash to the store's query method`, query); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let modelToken = heimdall.start('initial-modelFor-lookup'); heimdall.stop(modelToken); @@ -1274,11 +1369,16 @@ Store = Service.extend({ heimdall.stop(adapterToken); assert(`You tried to load a query but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to load a query but your adapter does not implement 'query'`, typeof adapter.query === 'function'); + assert( + `You tried to load a query but your adapter does not implement 'query'`, + typeof adapter.query === 'function' + ); let pA = promiseArray(_query(adapter, this, modelName, query, array, options)); instrument(() => { - pA.finally(() => { heimdall.stop(token); }); + pA.finally(() => { + heimdall.stop(token); + }); }); return pA; }, @@ -1383,28 +1483,39 @@ Store = Service.extend({ queryRecord(modelName, query, options) { assert(`You need to pass a model name to the store's queryRecord method`, isPresent(modelName)); assert(`You need to pass a query hash to the store's queryRecord method`, query); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let adapter = this.adapterFor(normalizedModelName); let adapterOptionsWrapper = {}; if (options && options.adapterOptions) { - adapterOptionsWrapper.adapterOptions = options.adapterOptions + adapterOptionsWrapper.adapterOptions = options.adapterOptions; } - assert(`You tried to make a query but you have no adapter (for ${normalizedModelName})`, adapter); - assert(`You tried to make a query but your adapter does not implement 'queryRecord'`, typeof adapter.queryRecord === 'function'); + assert( + `You tried to make a query but you have no adapter (for ${normalizedModelName})`, + adapter + ); + assert( + `You tried to make a query but your adapter does not implement 'queryRecord'`, + typeof adapter.queryRecord === 'function' + ); - return promiseObject(_queryRecord(adapter, this, modelName, query, adapterOptionsWrapper).then(internalModel => { - // the promise returned by store.queryRecord is expected to resolve with - // an instance of DS.Model - if (internalModel) { - return internalModel.getRecord(); - } + return promiseObject( + _queryRecord(adapter, this, modelName, query, adapterOptionsWrapper).then(internalModel => { + // the promise returned by store.queryRecord is expected to resolve with + // an instance of DS.Model + if (internalModel) { + return internalModel.getRecord(); + } - return null; - })); + return null; + }) + ); }, /** @@ -1597,14 +1708,19 @@ Store = Service.extend({ */ findAll(modelName, options) { assert(`You need to pass a model name to the store's findAll method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let token = heimdall.start('store.findAll'); let normalizedModelName = normalizeModelName(modelName); let fetch = this._fetchAll(normalizedModelName, this.peekAll(normalizedModelName), options); instrument(() => { - fetch.finally(() => { heimdall.stop(token); }); + fetch.finally(() => { + heimdall.stop(token); + }); }); return fetch; @@ -1622,7 +1738,10 @@ Store = Service.extend({ let sinceToken = this._internalModelsFor(modelName).metadata.since; assert(`You tried to load all records but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to load all records but your adapter does not implement 'findAll'`, typeof adapter.findAll === 'function'); + assert( + `You tried to load all records but your adapter does not implement 'findAll'`, + typeof adapter.findAll === 'function' + ); if (options.reload) { set(array, 'isUpdating', true); @@ -1685,7 +1804,10 @@ Store = Service.extend({ peekAll(modelName) { heimdall.increment(peekAll); assert(`You need to pass a model name to the store's peekAll method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); return this.recordArrayManager.liveRecordArrayFor(normalizedModelName); }, @@ -1705,7 +1827,10 @@ Store = Service.extend({ @param {String} modelName */ unloadAll(modelName) { - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, !modelName || typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + !modelName || typeof modelName === 'string' + ); if (arguments.length === 0) { this._identityMap.clear(); @@ -1716,7 +1841,10 @@ Store = Service.extend({ }, filter() { - assert('The filter API has been moved to a plugin. To enable store.filter using an environment flag, or to use an alternative, you can visit the ember-data-filter addon page. https://github.com/ember-data/ember-data-filter', false); + assert( + 'The filter API has been moved to a plugin. To enable store.filter using an environment flag, or to use an alternative, you can visit the ember-data-filter addon page. https://github.com/ember-data/ember-data-filter', + false + ); }, // .............. @@ -1741,7 +1869,7 @@ Store = Service.extend({ internalModel.adapterWillCommit(); this._pendingSave.push({ snapshot: snapshot, - resolver: resolver + resolver: resolver, }); emberRun.once(this, this.flushPendingSave); }, @@ -1778,7 +1906,6 @@ Store = Service.extend({ resolver.resolve(_commit(adapter, this, operation, snapshot)); } - }, /** @@ -1804,7 +1931,12 @@ Store = Service.extend({ this.updateId(internalModel, data); this._setupRelationshipsForModel(internalModel, data); } else { - assert(`Your ${internalModel.modelName} record was saved to the server, but the response does not have an id and no id has been set client side. Records must have ids. Please update the server response to provide an id in the response or generate the id on the client side either before saving the record or while normalizing the response.`, internalModel.id); + assert( + `Your ${ + internalModel.modelName + } record was saved to the server, but the response does not have an id and no id has been set client side. Records must have ids. Please update the server response to provide an id in the response or generate the id on the client side either before saving the record or while normalizing the response.`, + internalModel.id + ); } //We first make sure the primary data has been updated @@ -1856,22 +1988,33 @@ Store = Service.extend({ let id = coerceId(data.id); // ID absolutely can't be missing if the oldID is empty (missing Id in response for a new record) - assert(`'${modelName}' was saved to the server, but the response does not have an id and your record does not either.`, !(id === null && oldId === null)); + assert( + `'${modelName}' was saved to the server, but the response does not have an id and your record does not either.`, + !(id === null && oldId === null) + ); // ID absolutely can't be different than oldID if oldID is not null - assert(`'${modelName}:${oldId}' was saved to the server, but the response returned the new id '${id}'. The store cannot assign a new id to a record that already has an id.`, !(oldId !== null && id !== oldId)); + assert( + `'${modelName}:${oldId}' was saved to the server, but the response returned the new id '${id}'. The store cannot assign a new id to a record that already has an id.`, + !(oldId !== null && id !== oldId) + ); // ID can be null if oldID is not null (altered ID in response for a record) // however, this is more than likely a developer error. if (oldId !== null && id === null) { - warn(`Your ${modelName} record was saved to the server, but the response does not have an id.`, !(oldId !== null && id === null)); + warn( + `Your ${modelName} record was saved to the server, but the response does not have an id.`, + !(oldId !== null && id === null) + ); return; } let existingInternalModel = this._existingInternalModelForId(modelName, id); - assert(`'${modelName}' was saved to the server, but the response returned the new id '${id}', which has already been used with another record.'`, - isNone(existingInternalModel) || existingInternalModel === internalModel); + assert( + `'${modelName}' was saved to the server, but the response returned the new id '${id}', which has already been used with another record.'`, + isNone(existingInternalModel) || existingInternalModel === internalModel + ); this._internalModelsFor(internalModel.modelName).set(id, internalModel); @@ -1930,11 +2073,17 @@ Store = Service.extend({ false, { id: 'ember-data:_modelForMixin', - until: '3.5' + until: '3.5', } ); - assert(`You need to pass a model name to the store's _modelForMixin method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's _modelForMixin method`, + isPresent(modelName) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); return _modelForMixin(this, normalizedModelName); @@ -1954,7 +2103,10 @@ Store = Service.extend({ */ modelFor(modelName) { assert(`You need to pass a model name to the store's modelFor method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let maybeFactory = this._modelFactoryFor(modelName); @@ -1967,20 +2119,22 @@ Store = Service.extend({ @private */ _modelFor(modelName) { - deprecate( - '_modelFor is private and deprecated, you should use modelFor instead', - false, - { - id: 'ember-data:_modelFor', - until: '3.5' - } - ); + deprecate('_modelFor is private and deprecated, you should use modelFor instead', false, { + id: 'ember-data:_modelFor', + until: '3.5', + }); return this.modelFor(modelName); }, _modelFactoryFor(modelName) { - assert(`You need to pass a model name to the store's _modelFactoryFor method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's _modelFactoryFor method`, + isPresent(modelName) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let factory = getModelFactory(this, this._modelFactoryCache, normalizedModelName); @@ -1998,7 +2152,7 @@ Store = Service.extend({ modelFactoryFor(modelName) { deprecate('modelFactoryFor is private and deprecated', false, { id: 'ember-data:modelFactoryFor', - until: '3.5' + until: '3.5', }); return this._modelFactoryFor(modelName); }, @@ -2016,7 +2170,10 @@ Store = Service.extend({ */ _hasModelFor(modelName) { assert(`You need to pass a model name to the store's hasModelFor method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let factory = getModelFactory(this, this._modelFactoryCache, normalizedModelName); @@ -2228,7 +2385,12 @@ Store = Service.extend({ return null; } - assert(`Expected an object in the 'data' property in a call to 'push' for ${jsonApiDoc.type}, but was ${typeOf(jsonApiDoc.data)}`, typeOf(jsonApiDoc.data) === 'object'); + assert( + `Expected an object in the 'data' property in a call to 'push' for ${ + jsonApiDoc.type + }, but was ${typeOf(jsonApiDoc.data)}`, + typeOf(jsonApiDoc.data) === 'object' + ); return this._pushInternalModel(jsonApiDoc.data); }); @@ -2239,8 +2401,14 @@ Store = Service.extend({ _pushInternalModel(data) { heimdall.increment(_pushInternalModel); let modelName = data.type; - assert(`You must include an 'id' for ${modelName} in an object passed to 'push'`, data.id !== null && data.id !== undefined && data.id !== ''); - assert(`You tried to push data with a type '${modelName}' but no model could be found with that name.`, this._hasModelFor(modelName)); + assert( + `You must include an 'id' for ${modelName} in an object passed to 'push'`, + data.id !== null && data.id !== undefined && data.id !== '' + ); + assert( + `You tried to push data with a type '${modelName}' but no model could be found with that name.`, + this._hasModelFor(modelName) + ); if (DEBUG) { // If ENV.DS_WARN_ON_UNKNOWN_KEYS is set to true and the payload @@ -2250,18 +2418,22 @@ Store = Service.extend({ let modelClass = this.modelFor(modelName); // Check unknown attributes - let unknownAttributes = Object.keys(data.attributes || {}).filter((key) => { + let unknownAttributes = Object.keys(data.attributes || {}).filter(key => { return !get(modelClass, 'fields').has(key); }); let unknownAttributesMessage = `The payload for '${modelName}' contains these unknown attributes: ${unknownAttributes}. Make sure they've been defined in your model.`; - warn(unknownAttributesMessage, unknownAttributes.length === 0, { id: 'ds.store.unknown-keys-in-payload' }); + warn(unknownAttributesMessage, unknownAttributes.length === 0, { + id: 'ds.store.unknown-keys-in-payload', + }); // Check unknown relationships - let unknownRelationships = Object.keys(data.relationships || {}).filter((key) => { + let unknownRelationships = Object.keys(data.relationships || {}).filter(key => { return !get(modelClass, 'fields').has(key); }); let unknownRelationshipsMessage = `The payload for '${modelName}' contains these unknown relationships: ${unknownRelationships}. Make sure they've been defined in your model.`; - warn(unknownRelationshipsMessage, unknownRelationships.length === 0, { id: 'ds.store.unknown-keys-in-payload' }); + warn(unknownRelationshipsMessage, unknownRelationships.length === 0, { + id: 'ds.store.unknown-keys-in-payload', + }); } } @@ -2371,10 +2543,16 @@ Store = Service.extend({ if (!inputPayload) { payload = modelName; serializer = defaultSerializer(this); - assert(`You cannot use 'store#pushPayload' without a modelName unless your default serializer defines 'pushPayload'`, typeof serializer.pushPayload === 'function'); + assert( + `You cannot use 'store#pushPayload' without a modelName unless your default serializer defines 'pushPayload'`, + typeof serializer.pushPayload === 'function' + ); } else { payload = inputPayload; - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); serializer = this.serializerFor(normalizedModelName); } @@ -2403,7 +2581,12 @@ Store = Service.extend({ normalize(modelName, payload) { heimdall.increment(normalize); assert(`You need to pass a model name to the store's normalize method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${inspect(modelName)}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${inspect( + modelName + )}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let serializer = this.serializerFor(normalizedModelName); let model = this.modelFor(normalizedModelName); @@ -2424,11 +2607,17 @@ Store = Service.extend({ _buildInternalModel(modelName, id, data) { heimdall.increment(_buildInternalModel); - assert(`You can no longer pass a modelClass as the first argument to store._buildInternalModel. Pass modelName instead.`, typeof modelName === 'string'); + assert( + `You can no longer pass a modelClass as the first argument to store._buildInternalModel. Pass modelName instead.`, + typeof modelName === 'string' + ); let existingInternalModel = this._existingInternalModelForId(modelName, id); - assert(`The id ${id} has already been used with another record for modelClass '${modelName}'.`, !existingInternalModel); + assert( + `The id ${id} has already been used with another record for modelClass '${modelName}'.`, + !existingInternalModel + ); // lookupFactory should really return an object that creates // instances with the injections applied @@ -2503,12 +2692,17 @@ Store = Service.extend({ adapterFor(modelName) { heimdall.increment(adapterFor); assert(`You need to pass a model name to the store's adapterFor method`, isPresent(modelName)); - assert(`Passing classes to store.adapterFor has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store.adapterFor has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let { _adapterCache } = this; let adapter = _adapterCache[normalizedModelName]; - if (adapter) { return adapter; } + if (adapter) { + return adapter; + } let owner = getOwner(this); @@ -2575,13 +2769,21 @@ Store = Service.extend({ */ serializerFor(modelName) { heimdall.increment(serializerFor); - assert(`You need to pass a model name to the store's serializerFor method`, isPresent(modelName)); - assert(`Passing classes to store.serializerFor has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's serializerFor method`, + isPresent(modelName) + ); + assert( + `Passing classes to store.serializerFor has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let { _serializerCache } = this; let serializer = _serializerCache[normalizedModelName]; - if (serializer) { return serializer; } + if (serializer) { + return serializer; + } let owner = getOwner(this); @@ -2677,7 +2879,12 @@ Store = Service.extend({ if (isNone(resourceIdentifier)) { return; } - assertRelationshipData(this, relationship.internalModel, resourceIdentifier, relationship.relationshipMeta); + assertRelationshipData( + this, + relationship.internalModel, + resourceIdentifier, + relationship.relationshipMeta + ); return this._internalModelForId(resourceIdentifier.type, resourceIdentifier.id); }, @@ -2687,20 +2894,27 @@ Store = Service.extend({ return; } - assert(`A ${relationship.internalModel.modelName} record was pushed into the store with the value of ${relationship.key} being '${inspect(resourceIdentifiers)}', but ${relationship.key} is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer.`, Array.isArray(resourceIdentifiers)); + assert( + `A ${ + relationship.internalModel.modelName + } record was pushed into the store with the value of ${relationship.key} being '${inspect( + resourceIdentifiers + )}', but ${ + relationship.key + } is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer.`, + Array.isArray(resourceIdentifiers) + ); let _internalModels = new Array(resourceIdentifiers.length); for (let i = 0; i < resourceIdentifiers.length; i++) { _internalModels[i] = this._pushResourceIdentifier(relationship, resourceIdentifiers[i]); } return _internalModels; - } + }, }); // Delegation to the adapter and promise management - - function defaultSerializer(store) { return store.serializerFor('application'); } @@ -2710,21 +2924,30 @@ function _commit(adapter, store, operation, snapshot) { let modelName = snapshot.modelName; let modelClass = store.modelFor(modelName); assert(`You tried to update a record but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`, typeof adapter[operation] === 'function'); + assert( + `You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`, + typeof adapter[operation] === 'function' + ); - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot)); let serializer = serializerForAdapter(store, adapter, modelName); let label = `DS: Extract and notify about ${operation} completion of ${internalModel}`; - assert(`Your adapter's '${operation}' method must return a value, but it returned 'undefined'`, promise !==undefined); + assert( + `Your adapter's '${operation}' method must return a value, but it returned 'undefined'`, + promise !== undefined + ); promise = guardDestroyedStore(promise, store, label); promise = _guard(promise, _bind(_objectIsAlive, internalModel)); - return promise.then((adapterPayload) => { - /* + return promise.then( + adapterPayload => { + /* Note to future spelunkers hoping to optimize. We rely on this `run` to create a run loop if needed that `store._push` and `store.didSaveRecord` will both share. @@ -2733,30 +2956,40 @@ function _commit(adapter, store, operation, snapshot) { have an outer run loop available still from the first call to `store._push`; */ - store._backburner.join(() => { - let payload, data; - if (adapterPayload) { - payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation); - if (payload.included) { - store._push({ data: null, included: payload.included }); + store._backburner.join(() => { + let payload, data; + if (adapterPayload) { + payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + snapshot.id, + operation + ); + if (payload.included) { + store._push({ data: null, included: payload.included }); + } + data = payload.data; } - data = payload.data; - } - store.didSaveRecord(internalModel, { data }); - }); + store.didSaveRecord(internalModel, { data }); + }); - return internalModel; - }, function(error) { - if (error instanceof InvalidError) { - let errors = serializer.extractErrors(store, modelClass, error, snapshot.id); + return internalModel; + }, + function(error) { + if (error instanceof InvalidError) { + let errors = serializer.extractErrors(store, modelClass, error, snapshot.id); - store.recordWasInvalid(internalModel, errors); - } else { - store.recordWasError(internalModel, error); - } + store.recordWasInvalid(internalModel, errors); + } else { + store.recordWasError(internalModel, error); + } - throw error; - }, label); + throw error; + }, + label + ); } function isInverseRelationshipInitialized(store, internalModel, data, key, modelNameToInverseMap) { @@ -2769,7 +3002,10 @@ function isInverseRelationshipInitialized(store, internalModel, data, key, model let inverseMap = modelNameToInverseMap[internalModel.modelName]; if (!inverseMap) { - inverseMap = modelNameToInverseMap[internalModel.modelName] = get(internalModel.type, 'inverseMap'); + inverseMap = modelNameToInverseMap[internalModel.modelName] = get( + internalModel.type, + 'inverseMap' + ); } let inverseRelationshipMetadata = inverseMap[key]; if (inverseRelationshipMetadata === undefined) { @@ -2783,16 +3019,23 @@ function isInverseRelationshipInitialized(store, internalModel, data, key, model let { name: inverseRelationshipName } = inverseRelationshipMetadata; if (Array.isArray(relationshipData)) { - for (let i=0; i { let relationships = internalModel._relationships; - let relationshipRequiresNotification = relationships.has(relationshipName) || - isInverseRelationshipInitialized(store, internalModel, data, relationshipName, modelNameToInverseMap); + let relationshipRequiresNotification = + relationships.has(relationshipName) || + isInverseRelationshipInitialized( + store, + internalModel, + data, + relationshipName, + modelNameToInverseMap + ); if (relationshipRequiresNotification) { let relationshipData = data.relationships[relationshipName]; @@ -2910,17 +3159,35 @@ function setupRelationships(store, internalModel, data, modelNameToInverseMap) { if (relationshipData.links) { let isAsync = relationshipMeta.options && relationshipMeta.options.async !== false; - warn(`You pushed a record of type '${internalModel.modelName}' with a relationship '${relationshipName}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload.`, isAsync || relationshipData.data , { - id: 'ds.store.push-link-for-sync-relationship' - }); + warn( + `You pushed a record of type '${ + internalModel.modelName + }' with a relationship '${relationshipName}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload.`, + isAsync || relationshipData.data, + { + id: 'ds.store.push-link-for-sync-relationship', + } + ); } else if (relationshipData.data) { if (relationshipMeta.kind === 'belongsTo') { assertRelationshipData(store, internalModel, relationshipData.data, relationshipMeta); } else if (relationshipMeta.kind === 'hasMany') { - assert(`A ${internalModel.modelName} record was pushed into the store with the value of ${relationshipName} being '${inspect(relationshipData.data)}', but ${relationshipName} is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer.`, Array.isArray(relationshipData.data)); + assert( + `A ${ + internalModel.modelName + } record was pushed into the store with the value of ${relationshipName} being '${inspect( + relationshipData.data + )}', but ${relationshipName} is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer.`, + Array.isArray(relationshipData.data) + ); if (Array.isArray(relationshipData.data)) { for (let i = 0; i < relationshipData.data.length; i++) { - assertRelationshipData(store, internalModel, relationshipData.data[i], relationshipMeta); + assertRelationshipData( + store, + internalModel, + relationshipData.data[i], + relationshipMeta + ); } } } @@ -2930,23 +3197,38 @@ function setupRelationships(store, internalModel, data, modelNameToInverseMap) { } function assertRelationshipData(store, internalModel, data, meta) { - assert(`A ${internalModel.modelName} record was pushed into the store with the value of ${meta.key} being '${JSON.stringify(data)}', but ${meta.key} is a belongsTo relationship so the value must not be an array. You should probably check your data payload or serializer.`, !Array.isArray(data)); assert( - `Encountered a relationship identifier without a type for the ${meta.kind} relationship '${meta.key}' on ${internalModel}, expected a json-api identifier with type '${meta.type}' but found '${JSON.stringify(data)}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, + `A ${internalModel.modelName} record was pushed into the store with the value of ${ + meta.key + } being '${JSON.stringify(data)}', but ${ + meta.key + } is a belongsTo relationship so the value must not be an array. You should probably check your data payload or serializer.`, + !Array.isArray(data) + ); + assert( + `Encountered a relationship identifier without a type for the ${meta.kind} relationship '${ + meta.key + }' on ${internalModel}, expected a json-api identifier with type '${ + meta.type + }' but found '${JSON.stringify( + data + )}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, data === null || (typeof data.type === 'string' && data.type.length) ); assert( - `Encountered a relationship identifier without an id for the ${meta.kind} relationship '${meta.key}' on ${internalModel}, expected a json-api identifier but found '${JSON.stringify(data)}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, + `Encountered a relationship identifier without an id for the ${meta.kind} relationship '${ + meta.key + }' on ${internalModel}, expected a json-api identifier but found '${JSON.stringify( + data + )}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, data === null || coerceId(data.id) ); assert( - `Encountered a relationship identifier with type '${ - data.type - }' for the ${meta.kind} relationship '${meta.key}' on ${ - internalModel - }, Expected a json-api identifier with type '${ + `Encountered a relationship identifier with type '${data.type}' for the ${ + meta.kind + } relationship '${meta.key}' on ${internalModel}, Expected a json-api identifier with type '${ meta.type - }'. No model was found for '${data.type}'.`, + }'. No model was found for '${data.type}'.`, data === null || !data.type || store._hasModelFor(data.type) ); } diff --git a/addon/-private/system/store/common.js b/addon/-private/system/store/common.js index 007671f5114..c095fe701c8 100644 --- a/addon/-private/system/store/common.js +++ b/addon/-private/system/store/common.js @@ -3,11 +3,8 @@ import { DEBUG } from '@glimmer/env'; import Ember from 'ember'; import { Promise } from 'rsvp'; -const { - __bind, - __guard, - __objectIsAlive -} = heimdall.registerMonitor('system.store.common', +const { __bind, __guard, __objectIsAlive } = heimdall.registerMonitor( + 'system.store.common', '_bind', '_guard', '_objectIsAlive' @@ -34,7 +31,7 @@ export function _guard(promise, test) { export function _objectIsAlive(object) { heimdall.increment(__objectIsAlive); - return !(get(object, "isDestroyed") || get(object, "isDestroying")); + return !(get(object, 'isDestroyed') || get(object, 'isDestroying')); } let ASYNC_REQUEST_COUNT = 0; @@ -51,5 +48,10 @@ if (DEBUG) { export function guardDestroyedStore(promise, store, label) { promise = Promise.resolve(promise, label); - return _guard(promise, () => { if (DEBUG) { ASYNC_REQUEST_COUNT--; } return _objectIsAlive(store); }); + return _guard(promise, () => { + if (DEBUG) { + ASYNC_REQUEST_COUNT--; + } + return _objectIsAlive(store); + }); } diff --git a/addon/-private/system/store/finders.js b/addon/-private/system/store/finders.js index d9923eaf29a..1709a79cb39 100644 --- a/addon/-private/system/store/finders.js +++ b/addon/-private/system/store/finders.js @@ -8,11 +8,11 @@ import { _guard, _objectIsAlive, guardDestroyedStore, - incrementRequestCount -} from "./common"; + incrementRequestCount, +} from './common'; -import { normalizeResponseHelper } from "./serializer-response"; -import { serializerForAdapter } from "./serializers"; +import { normalizeResponseHelper } from './serializer-response'; +import { serializerForAdapter } from './serializers'; function payloadIsNotBlank(adapterPayload) { if (Array.isArray(adapterPayload)) { @@ -23,7 +23,9 @@ function payloadIsNotBlank(adapterPayload) { } export function _find(adapter, store, modelClass, id, internalModel, options) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let snapshot = internalModel.createSnapshot(options); let { modelName } = internalModel; let promise = Promise.resolve().then(() => adapter.findRecord(store, modelClass, id, snapshot)); @@ -31,29 +33,54 @@ export function _find(adapter, store, modelClass, id, internalModel, options) { promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - assert(`You made a 'findRecord' request for a '${modelName}' with id '${id}', but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload)); - let serializer = serializerForAdapter(store, adapter, modelName); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, id, 'findRecord'); - assert(`Ember Data expected the primary data returned from a 'findRecord' response to be an object but instead it found an array.`, !Array.isArray(payload.data)); - - warn(`You requested a record of type '${modelName}' with id '${id}' but the adapter returned a payload with primary data having an id of '${payload.data.id}'. Use 'store.findRecord()' when the requested id is the same as the one returned by the adapter. In other cases use 'store.queryRecord()' instead https://emberjs.com/api/data/classes/DS.Store.html#method_queryRecord`, payload.data.id === id, { - id: 'ds.store.findRecord.id-mismatch' - }); - - return store._push(payload); - }, error => { - internalModel.notFound(); - if (internalModel.isEmpty()) { - internalModel.unloadRecord(); - } - - throw error; - }, `DS: Extract payload of '${modelName}'`); + return promise.then( + adapterPayload => { + assert( + `You made a 'findRecord' request for a '${modelName}' with id '${id}', but the adapter's response did not have any data`, + payloadIsNotBlank(adapterPayload) + ); + let serializer = serializerForAdapter(store, adapter, modelName); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + id, + 'findRecord' + ); + assert( + `Ember Data expected the primary data returned from a 'findRecord' response to be an object but instead it found an array.`, + !Array.isArray(payload.data) + ); + + warn( + `You requested a record of type '${modelName}' with id '${id}' but the adapter returned a payload with primary data having an id of '${ + payload.data.id + }'. Use 'store.findRecord()' when the requested id is the same as the one returned by the adapter. In other cases use 'store.queryRecord()' instead https://emberjs.com/api/data/classes/DS.Store.html#method_queryRecord`, + payload.data.id === id, + { + id: 'ds.store.findRecord.id-mismatch', + } + ); + + return store._push(payload); + }, + error => { + internalModel.notFound(); + if (internalModel.isEmpty()) { + internalModel.unloadRecord(); + } + + throw error; + }, + `DS: Extract payload of '${modelName}'` + ); } export function _findMany(adapter, store, modelName, ids, internalModels) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let snapshots = A(internalModels).invoke('createSnapshot'); let modelClass = store.modelFor(modelName); // `adapter.findMany` gets the modelClass still let promise = adapter.findMany(store, modelClass, ids, snapshots); @@ -65,90 +92,163 @@ export function _findMany(adapter, store, modelName, ids, internalModels) { promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - assert(`You made a 'findMany' request for '${modelName}' records with ids '[${ids}]', but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload)); - let serializer = serializerForAdapter(store, adapter, modelName); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findMany'); - return store._push(payload); - }, null, `DS: Extract payload of ${modelName}`); + return promise.then( + adapterPayload => { + assert( + `You made a 'findMany' request for '${modelName}' records with ids '[${ids}]', but the adapter's response did not have any data`, + payloadIsNotBlank(adapterPayload) + ); + let serializer = serializerForAdapter(store, adapter, modelName); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'findMany' + ); + return store._push(payload); + }, + null, + `DS: Extract payload of ${modelName}` + ); } export function _findHasMany(adapter, store, internalModel, link, relationship) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let snapshot = internalModel.createSnapshot(); let modelClass = store.modelFor(relationship.type); let promise = adapter.findHasMany(store, snapshot, link, relationship); - let label = `DS: Handle Adapter#findHasMany of '${internalModel.modelName}' : '${relationship.type}'`; + let label = `DS: Handle Adapter#findHasMany of '${internalModel.modelName}' : '${ + relationship.type + }'`; promise = guardDestroyedStore(promise, store, label); promise = _guard(promise, _bind(_objectIsAlive, internalModel)); - return promise.then(adapterPayload => { - assert(`You made a 'findHasMany' request for a ${internalModel.modelName}'s '${relationship.key}' relationship, using link '${link}' , but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload)); - let serializer = serializerForAdapter(store, adapter, relationship.type); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findHasMany'); - let internalModelArray = store._push(payload); - - internalModelArray.meta = payload.meta; - return internalModelArray; - }, null, `DS: Extract payload of '${internalModel.modelName}' : hasMany '${relationship.type}'`); + return promise.then( + adapterPayload => { + assert( + `You made a 'findHasMany' request for a ${internalModel.modelName}'s '${ + relationship.key + }' relationship, using link '${link}' , but the adapter's response did not have any data`, + payloadIsNotBlank(adapterPayload) + ); + let serializer = serializerForAdapter(store, adapter, relationship.type); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'findHasMany' + ); + let internalModelArray = store._push(payload); + + internalModelArray.meta = payload.meta; + return internalModelArray; + }, + null, + `DS: Extract payload of '${internalModel.modelName}' : hasMany '${relationship.type}'` + ); } export function _findBelongsTo(adapter, store, internalModel, link, relationship) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let snapshot = internalModel.createSnapshot(); let modelClass = store.modelFor(relationship.type); let promise = adapter.findBelongsTo(store, snapshot, link, relationship); - let label = `DS: Handle Adapter#findBelongsTo of ${internalModel.modelName} : ${relationship.type}`; + let label = `DS: Handle Adapter#findBelongsTo of ${internalModel.modelName} : ${ + relationship.type + }`; promise = guardDestroyedStore(promise, store, label); promise = _guard(promise, _bind(_objectIsAlive, internalModel)); - return promise.then(adapterPayload => { - let serializer = serializerForAdapter(store, adapter, relationship.type); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo'); - - if (!payload.data) { - return null; - } - - return store._push(payload); - }, null, `DS: Extract payload of ${internalModel.modelName} : ${relationship.type}`); + return promise.then( + adapterPayload => { + let serializer = serializerForAdapter(store, adapter, relationship.type); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'findBelongsTo' + ); + + if (!payload.data) { + return null; + } + + return store._push(payload); + }, + null, + `DS: Extract payload of ${internalModel.modelName} : ${relationship.type}` + ); } export function _findAll(adapter, store, modelName, sinceToken, options) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let modelClass = store.modelFor(modelName); // adapter.findAll depends on the class let recordArray = store.peekAll(modelName); let snapshotArray = recordArray._createSnapshot(options); - let promise = Promise.resolve().then(() => adapter.findAll(store, modelClass, sinceToken, snapshotArray)); - let label = "DS: Handle Adapter#findAll of " + modelClass; + let promise = Promise.resolve().then(() => + adapter.findAll(store, modelClass, sinceToken, snapshotArray) + ); + let label = 'DS: Handle Adapter#findAll of ' + modelClass; promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - assert(`You made a 'findAll' request for '${modelName}' records, but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload)); - let serializer = serializerForAdapter(store, adapter, modelName); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findAll'); - - store._push(payload); - store._didUpdateAll(modelName); - - return recordArray; - }, null, 'DS: Extract payload of findAll ${modelName}'); + return promise.then( + adapterPayload => { + assert( + `You made a 'findAll' request for '${modelName}' records, but the adapter's response did not have any data`, + payloadIsNotBlank(adapterPayload) + ); + let serializer = serializerForAdapter(store, adapter, modelName); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'findAll' + ); + + store._push(payload); + store._didUpdateAll(modelName); + + return recordArray; + }, + null, + 'DS: Extract payload of findAll ${modelName}' + ); } export function _query(adapter, store, modelName, query, recordArray, options) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let modelClass = store.modelFor(modelName); // adapter.query needs the class let promise; - let createRecordArray = adapter.query.length > 3 || + let createRecordArray = + adapter.query.length > 3 || (adapter.query.wrappedFunction && adapter.query.wrappedFunction.length > 3); if (createRecordArray) { - recordArray = recordArray || store.recordArrayManager.createAdapterPopulatedRecordArray(modelName, query); - promise = Promise.resolve().then(() => adapter.query(store, modelClass, query, recordArray, options)); + recordArray = + recordArray || store.recordArrayManager.createAdapterPopulatedRecordArray(modelName, query); + promise = Promise.resolve().then(() => + adapter.query(store, modelClass, query, recordArray, options) + ); } else { promise = Promise.resolve().then(() => adapter.query(store, modelClass, query)); } @@ -156,42 +256,80 @@ export function _query(adapter, store, modelName, query, recordArray, options) { let label = `DS: Handle Adapter#query of ${modelName}`; promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - let serializerToken = heimdall.start('initial-serializerFor-lookup'); - let serializer = serializerForAdapter(store, adapter, modelName); - heimdall.stop(serializerToken); - let normalizeToken = heimdall.start('finders#_query::normalizeResponseHelper'); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'query'); - heimdall.stop(normalizeToken); - let internalModels = store._push(payload); - - assert('The response to store.query is expected to be an array but it was a single record. Please wrap your response in an array or use `store.queryRecord` to query for a single record.', Array.isArray(internalModels)); - if (recordArray) { - recordArray._setInternalModels(internalModels, payload); - } else { - recordArray = store.recordArrayManager.createAdapterPopulatedRecordArray(modelName, query, internalModels, payload); - } - - return recordArray; - }, null, `DS: Extract payload of query ${modelName}`); + return promise.then( + adapterPayload => { + let serializerToken = heimdall.start('initial-serializerFor-lookup'); + let serializer = serializerForAdapter(store, adapter, modelName); + heimdall.stop(serializerToken); + let normalizeToken = heimdall.start('finders#_query::normalizeResponseHelper'); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'query' + ); + heimdall.stop(normalizeToken); + let internalModels = store._push(payload); + + assert( + 'The response to store.query is expected to be an array but it was a single record. Please wrap your response in an array or use `store.queryRecord` to query for a single record.', + Array.isArray(internalModels) + ); + if (recordArray) { + recordArray._setInternalModels(internalModels, payload); + } else { + recordArray = store.recordArrayManager.createAdapterPopulatedRecordArray( + modelName, + query, + internalModels, + payload + ); + } + + return recordArray; + }, + null, + `DS: Extract payload of query ${modelName}` + ); } export function _queryRecord(adapter, store, modelName, query, options) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let modelClass = store.modelFor(modelName); // adapter.queryRecord needs the class - let promise = Promise.resolve().then(() => adapter.queryRecord(store, modelClass, query, options)); + let promise = Promise.resolve().then(() => + adapter.queryRecord(store, modelClass, query, options) + ); let label = `DS: Handle Adapter#queryRecord of ${modelName}`; promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - let serializer = serializerForAdapter(store, adapter, modelName); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'queryRecord'); - - assert(`Expected the primary data returned by the serializer for a 'queryRecord' response to be a single object or null but instead it was an array.`, !Array.isArray(payload.data), { - id: 'ds.store.queryRecord-array-response' - }); - - return store._push(payload); - }, null, `DS: Extract payload of queryRecord ${modelName}`); + return promise.then( + adapterPayload => { + let serializer = serializerForAdapter(store, adapter, modelName); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'queryRecord' + ); + + assert( + `Expected the primary data returned by the serializer for a 'queryRecord' response to be a single object or null but instead it was an array.`, + !Array.isArray(payload.data), + { + id: 'ds.store.queryRecord-array-response', + } + ); + + return store._push(payload); + }, + null, + `DS: Extract payload of queryRecord ${modelName}` + ); } diff --git a/addon/-private/system/store/serializer-response.js b/addon/-private/system/store/serializer-response.js index 155b13d0617..c4a08c6b5cf 100644 --- a/addon/-private/system/store/serializer-response.js +++ b/addon/-private/system/store/serializer-response.js @@ -16,13 +16,13 @@ export function validateDocumentStructure(doc) { if (!doc || typeof doc !== 'object') { errors.push('Top level of a JSON API document must be an object'); } else { - if (!('data' in doc) && - !('errors' in doc) && - !('meta' in doc)) { + if (!('data' in doc) && !('errors' in doc) && !('meta' in doc)) { errors.push('One or more of the following keys must be present: "data", "errors", "meta".'); } else { - if (('data' in doc) && ('errors' in doc)) { - errors.push('Top level keys "errors" and "data" cannot both be present in a JSON API document'); + if ('data' in doc && 'errors' in doc) { + errors.push( + 'Top level keys "errors" and "data" cannot both be present in a JSON API document' + ); } } if ('data' in doc) { @@ -73,12 +73,23 @@ export function validateDocumentStructure(doc) { @return {Object} JSON-API Document */ export function normalizeResponseHelper(serializer, store, modelClass, payload, id, requestType) { - let normalizedResponse = serializer.normalizeResponse(store, modelClass, payload, id, requestType); + let normalizedResponse = serializer.normalizeResponse( + store, + modelClass, + payload, + id, + requestType + ); let validationErrors = []; if (DEBUG) { validationErrors = validateDocumentStructure(normalizedResponse); } - assert(`normalizeResponse must return a valid JSON API document:\n\t* ${validationErrors.join('\n\t* ')}`, validationErrors.length === 0); + assert( + `normalizeResponse must return a valid JSON API document:\n\t* ${validationErrors.join( + '\n\t* ' + )}`, + validationErrors.length === 0 + ); return normalizedResponse; } diff --git a/addon/-private/system/store/serializers.js b/addon/-private/system/store/serializers.js index 71ca0829809..d6788427061 100644 --- a/addon/-private/system/store/serializers.js +++ b/addon/-private/system/store/serializers.js @@ -7,7 +7,9 @@ export function serializerForAdapter(store, adapter, modelName) { if (serializer === null || serializer === undefined) { serializer = { - extract(store, type, payload) { return payload; } + extract(store, type, payload) { + return payload; + }, }; } diff --git a/addon/-private/utils.js b/addon/-private/utils.js index 234af6842fa..f3bd4ed6aaf 100644 --- a/addon/-private/utils.js +++ b/addon/-private/utils.js @@ -8,7 +8,9 @@ import { get } from '@ember/object'; @param modelClass */ function modelHasAttributeOrRelationshipNamedType(modelClass) { - return get(modelClass, 'attributes').has('type') || get(modelClass, 'relationshipsByName').has('type'); + return ( + get(modelClass, 'attributes').has('type') || get(modelClass, 'relationshipsByName').has('type') + ); } /* @@ -29,7 +31,7 @@ function getOwner(context) { // `owner` is a container, we are just making this work owner._lookupFactory = function() { return owner.lookupFactory(...arguments); - } + }; owner.register = function() { let registry = owner.registry || owner._registry || owner; @@ -41,7 +43,4 @@ function getOwner(context) { return owner; } -export { - modelHasAttributeOrRelationshipNamedType, - getOwner -}; +export { modelHasAttributeOrRelationshipNamedType, getOwner }; diff --git a/addon/-record-data-rfc-private/adapters/build-url-mixin.js b/addon/-record-data-rfc-private/adapters/build-url-mixin.js index 2472a83d31a..d1552ae675f 100644 --- a/addon/-record-data-rfc-private/adapters/build-url-mixin.js +++ b/addon/-record-data-rfc-private/adapters/build-url-mixin.js @@ -94,11 +94,17 @@ export default Mixin.create({ if (modelName) { path = this.pathForType(modelName); - if (path) { url.push(path); } + if (path) { + url.push(path); + } } - if (id) { url.push(encodeURIComponent(id)); } - if (prefix) { url.unshift(prefix); } + if (id) { + url.push(encodeURIComponent(id)); + } + if (prefix) { + url.unshift(prefix); + } url = url.join('/'); if (!host && url && url.charAt(0) !== '/') { @@ -392,10 +398,10 @@ export default Mixin.create({ // Do nothing, the full host is already included. return path; - // Absolute path + // Absolute path } else if (path.charAt(0) === '/') { return `${host}${path}`; - // Relative path + // Relative path } else { return `${parentURL}/${path}`; } @@ -403,8 +409,12 @@ export default Mixin.create({ // No path provided let url = []; - if (host) { url.push(host); } - if (namespace) { url.push(namespace); } + if (host) { + url.push(host); + } + if (namespace) { + url.push(namespace); + } return url.join('/'); }, @@ -439,5 +449,5 @@ export default Mixin.create({ pathForType(modelName) { let camelized = camelize(modelName); return pluralize(camelized); - } + }, }); diff --git a/addon/-record-data-rfc-private/adapters/errors.js b/addon/-record-data-rfc-private/adapters/errors.js index ec8919818cf..8cfd7b978dd 100644 --- a/addon/-record-data-rfc-private/adapters/errors.js +++ b/addon/-record-data-rfc-private/adapters/errors.js @@ -81,8 +81,8 @@ export function AdapterError(errors, message = 'Adapter operation failed') { this.errors = errors || [ { title: 'Adapter Error', - detail: message - } + detail: message, + }, ]; } @@ -165,8 +165,10 @@ AdapterError.extend = extendFn(AdapterError); @class InvalidError @namespace DS */ -export const InvalidError = extend(AdapterError, - 'The adapter rejected the commit because it was invalid'); +export const InvalidError = extend( + AdapterError, + 'The adapter rejected the commit because it was invalid' +); /** A `DS.TimeoutError` is used by an adapter to signal that a request @@ -200,8 +202,7 @@ export const InvalidError = extend(AdapterError, @class TimeoutError @namespace DS */ -export const TimeoutError = extend(AdapterError, - 'The adapter operation timed out'); +export const TimeoutError = extend(AdapterError, 'The adapter operation timed out'); /** A `DS.AbortError` is used by an adapter to signal that a request to @@ -212,8 +213,7 @@ export const TimeoutError = extend(AdapterError, @class AbortError @namespace DS */ -export const AbortError = extend(AdapterError, - 'The adapter operation was aborted'); +export const AbortError = extend(AdapterError, 'The adapter operation was aborted'); /** A `DS.UnauthorizedError` equates to a HTTP `401 Unauthorized` response @@ -320,7 +320,10 @@ export const ConflictError = extend(AdapterError, 'The adapter operation failed @class ServerError @namespace DS */ -export const ServerError = extend(AdapterError, 'The adapter operation failed due to a server error'); +export const ServerError = extend( + AdapterError, + 'The adapter operation failed due to a server error' +); /** Convert an hash of errors into an array with errors in JSON-API format. @@ -372,7 +375,7 @@ export function errorsHashToArray(errors) { let out = []; if (isPresent(errors)) { - Object.keys(errors).forEach((key) => { + Object.keys(errors).forEach(key => { let messages = makeArray(errors[key]); for (let i = 0; i < messages.length; i++) { let title = 'Invalid Attribute'; @@ -385,8 +388,8 @@ export function errorsHashToArray(errors) { title: title, detail: messages[i], source: { - pointer: pointer - } + pointer: pointer, + }, }); } }); @@ -439,7 +442,7 @@ export function errorsArrayToHash(errors) { let out = {}; if (isPresent(errors)) { - errors.forEach((error) => { + errors.forEach(error => { if (error.source && error.source.pointer) { let key = error.source.pointer.match(SOURCE_POINTER_REGEXP); diff --git a/addon/-record-data-rfc-private/attr.js b/addon/-record-data-rfc-private/attr.js index f4b266d7ace..e2df4230ae3 100644 --- a/addon/-record-data-rfc-private/attr.js +++ b/addon/-record-data-rfc-private/attr.js @@ -10,8 +10,10 @@ function getDefaultValue(record, options, key) { return options.defaultValue.apply(null, arguments); } else { let defaultValue = options.defaultValue; - assert(`Non primitive defaultValues are not supported because they are shared between all instances. If you would like to use a complex object as a default value please provide a function that returns the complex object.`, - typeof defaultValue !== 'object' || defaultValue === null); + assert( + `Non primitive defaultValues are not supported because they are shared between all instances. If you would like to use a complex object as a default value please provide a function that returns the complex object.`, + typeof defaultValue !== 'object' || defaultValue === null + ); return defaultValue; } } @@ -116,7 +118,7 @@ export default function attr(type, options) { let meta = { type: type, isAttribute: true, - options: options + options: options, }; return computed({ @@ -130,6 +132,6 @@ export default function attr(type, options) { }, set(key, value) { return this._internalModel.setDirtyAttribute(key, value); - } + }, }).meta(meta); } diff --git a/addon/-record-data-rfc-private/core.js b/addon/-record-data-rfc-private/core.js index b16369a0ff4..70816f3c203 100644 --- a/addon/-record-data-rfc-private/core.js +++ b/addon/-record-data-rfc-private/core.js @@ -19,7 +19,7 @@ import VERSION from 'ember-data/version'; */ const DS = Ember.Namespace.create({ VERSION: VERSION, - name: "DS" + name: 'DS', }); if (Ember.libraries) { diff --git a/addon/-record-data-rfc-private/index.js b/addon/-record-data-rfc-private/index.js index c99397b872f..15e211a9de9 100644 --- a/addon/-record-data-rfc-private/index.js +++ b/addon/-record-data-rfc-private/index.js @@ -1,7 +1,7 @@ // public export { default as Model } from './system/model/model'; export { default as Errors } from './system/model/errors'; -export { default as Store } from './system/store'; +export { default as Store } from './system/store'; export { default as DS } from './core'; export { default as belongsTo } from './system/relationships/belongs-to'; export { default as hasMany } from './system/relationships/has-many'; @@ -19,7 +19,7 @@ export { TimeoutError, AbortError, errorsHashToArray, - errorsArrayToHash + errorsArrayToHash, } from './adapters/errors'; // maybe public ? @@ -34,16 +34,9 @@ export { default as RootState } from './system/model/states'; export { default as InternalModel } from './system/model/internal-model'; export { default as ModelData } from './system/model/model-data'; -export { - PromiseArray, - PromiseObject, - PromiseManyArray -} from './system/promise-proxies'; +export { PromiseArray, PromiseObject, PromiseManyArray } from './system/promise-proxies'; -export { - RecordArray, - AdapterPopulatedRecordArray -} from './system/record-arrays'; +export { RecordArray, AdapterPopulatedRecordArray } from './system/record-arrays'; export { default as ManyArray } from './system/many-array'; export { default as RecordArrayManager } from './system/record-array-manager'; diff --git a/addon/-record-data-rfc-private/system/backburner.js b/addon/-record-data-rfc-private/system/backburner.js index 266c37c3b4b..7ac43f9b390 100644 --- a/addon/-record-data-rfc-private/system/backburner.js +++ b/addon/-record-data-rfc-private/system/backburner.js @@ -1,7 +1,11 @@ import Ember from 'ember'; import { DEBUG } from '@glimmer/env'; -const backburner = new Ember._Backburner(['normalizeRelationships', 'syncRelationships', 'finished']); +const backburner = new Ember._Backburner([ + 'normalizeRelationships', + 'syncRelationships', + 'finished', +]); if (DEBUG) { Ember.Test.registerWaiter(() => { diff --git a/addon/-record-data-rfc-private/system/coerce-id.js b/addon/-record-data-rfc-private/system/coerce-id.js index 8f8c305a98d..18173352148 100644 --- a/addon/-record-data-rfc-private/system/coerce-id.js +++ b/addon/-record-data-rfc-private/system/coerce-id.js @@ -5,7 +5,11 @@ // ID into the URL, and if we later try to deserialize that URL and find the // corresponding record, we will not know if it is a string or a number. export default function coerceId(id) { - if (id === null || id === undefined || id === '') { return null; } - if (typeof id === 'string') { return id; } + if (id === null || id === undefined || id === '') { + return null; + } + if (typeof id === 'string') { + return id; + } return '' + id; } diff --git a/addon/-record-data-rfc-private/system/debug/debug-adapter.js b/addon/-record-data-rfc-private/system/debug/debug-adapter.js index eca07a7d7df..2904a93427f 100644 --- a/addon/-record-data-rfc-private/system/debug/debug-adapter.js +++ b/addon/-record-data-rfc-private/system/debug/debug-adapter.js @@ -23,7 +23,7 @@ export default DataAdapter.extend({ return [ { name: 'isNew', desc: 'New' }, { name: 'isModified', desc: 'Modified' }, - { name: 'isClean', desc: 'Clean' } + { name: 'isClean', desc: 'Clean' }, ]; }, @@ -32,14 +32,18 @@ export default DataAdapter.extend({ }, columnsForType(typeClass) { - let columns = [{ - name: 'id', - desc: 'Id' - }]; + let columns = [ + { + name: 'id', + desc: 'Id', + }, + ]; let count = 0; let self = this; get(typeClass, 'attributes').forEach((meta, name) => { - if (count++ > self.attributeLimit) { return false; } + if (count++ > self.attributeLimit) { + return false; + } let desc = capitalize(underscore(name).replace('_', ' ')); columns.push({ name: name, desc: desc }); }); @@ -57,7 +61,10 @@ export default DataAdapter.extend({ } } } - assert("Cannot find model name. Please upgrade to Ember.js >= 1.13 for Ember Inspector support", !!modelName); + assert( + 'Cannot find model name. Please upgrade to Ember.js >= 1.13 for Ember Inspector support', + !!modelName + ); return this.get('store').peekAll(modelName); }, @@ -65,7 +72,7 @@ export default DataAdapter.extend({ let count = 0; let columnValues = { id: get(record, 'id') }; - record.eachAttribute((key) => { + record.eachAttribute(key => { if (count++ > this.attributeLimit) { return false; } @@ -77,8 +84,8 @@ export default DataAdapter.extend({ getRecordKeywords(record) { let keywords = []; let keys = A(['id']); - record.eachAttribute((key) => keys.push(key)); - keys.forEach((key) => keywords.push(get(record, key))); + record.eachAttribute(key => keys.push(key)); + keys.forEach(key => keywords.push(get(record, key))); return keywords; }, @@ -86,7 +93,7 @@ export default DataAdapter.extend({ return { isNew: record.get('isNew'), isModified: record.get('hasDirtyAttributes') && !record.get('isNew'), - isClean: !record.get('hasDirtyAttributes') + isClean: !record.get('hasDirtyAttributes'), }; }, @@ -104,7 +111,7 @@ export default DataAdapter.extend({ let releaseMethods = A(); let keysToObserve = A(['id', 'isNew', 'hasDirtyAttributes']); - record.eachAttribute((key) => keysToObserve.push(key)); + record.eachAttribute(key => keysToObserve.push(key)); let adapter = this; keysToObserve.forEach(function(key) { @@ -118,9 +125,9 @@ export default DataAdapter.extend({ }); let release = function() { - releaseMethods.forEach((fn) => fn()); + releaseMethods.forEach(fn => fn()); }; return release; - } + }, }); diff --git a/addon/-record-data-rfc-private/system/diff-array.js b/addon/-record-data-rfc-private/system/diff-array.js index ae28e8e35b3..e935a525b6b 100644 --- a/addon/-record-data-rfc-private/system/diff-array.js +++ b/addon/-record-data-rfc-private/system/diff-array.js @@ -18,7 +18,7 @@ export default function diffArray(oldArray, newArray) { let firstChangeIndex = null; // null signifies no changes // find the first change - for (let i=0; i im._isDematerializing || !im.isLoaded()); + let unloaded = this.currentState.find(im => im._isDematerializing || !im.isLoaded()); return !!unloaded; }, @@ -162,7 +162,9 @@ export default EmberObject.extend(MutableArray, Evented, { } */ let internalModel = this.currentState[index]; - if (internalModel === undefined) { return; } + if (internalModel === undefined) { + return; + } return internalModel.getRecord(); }, @@ -174,7 +176,8 @@ export default EmberObject.extend(MutableArray, Evented, { } // diff to find changes let diff = diffArray(this.currentState, toSet); - if (diff.firstChangeIndex !== null) { // it's null if no change found + if (diff.firstChangeIndex !== null) { + // it's null if no change found // we found a change this.arrayContentWillChange(diff.firstChangeIndex, diff.removedCount, diff.addedCount); this.set('length', toSet.length); @@ -191,11 +194,18 @@ export default EmberObject.extend(MutableArray, Evented, { replace(idx, amt, objects) { let internalModels; if (amt > 0) { - internalModels = this.currentState.slice(idx, idx+amt); - this.get('modelData').removeFromHasMany(this.get('key'), internalModels.map((im) => im._modelData)); + internalModels = this.currentState.slice(idx, idx + amt); + this.get('modelData').removeFromHasMany( + this.get('key'), + internalModels.map(im => im._modelData) + ); } if (objects) { - this.get('modelData').addToHasMany(this.get('key'), objects.map(obj => obj._internalModel._modelData), idx); + this.get('modelData').addToHasMany( + this.get('key'), + objects.map(obj => obj._internalModel._modelData), + idx + ); //this.get('relationship').addInternalModels(objects.map(obj => obj._internalModel), idx); } this.retrieveLatest(); @@ -263,8 +273,11 @@ export default EmberObject.extend(MutableArray, Evented, { save() { let manyArray = this; let promiseLabel = 'DS: ManyArray#save ' + get(this, 'type'); - let promise = all(this.invoke("save"), promiseLabel). - then(() => manyArray, null, 'DS: ManyArray#save return ManyArray'); + let promise = all(this.invoke('save'), promiseLabel).then( + () => manyArray, + null, + 'DS: ManyArray#save return ManyArray' + ); return PromiseArray.create({ promise }); }, @@ -281,10 +294,13 @@ export default EmberObject.extend(MutableArray, Evented, { const store = get(this, 'store'); const type = get(this, 'type'); - assert(`You cannot add '${type.modelName}' records to this polymorphic relationship.`, !get(this, 'isPolymorphic')); + assert( + `You cannot add '${type.modelName}' records to this polymorphic relationship.`, + !get(this, 'isPolymorphic') + ); let record = store.createRecord(type.modelName, hash); this.pushObject(record); return record; - } + }, }); diff --git a/addon/-record-data-rfc-private/system/map.js b/addon/-record-data-rfc-private/system/map.js index 6018913a453..c7c0be9846b 100644 --- a/addon/-record-data-rfc-private/system/map.js +++ b/addon/-record-data-rfc-private/system/map.js @@ -64,7 +64,7 @@ export default class MapWithDeprecations { copy() { deprecate( 'Calling `.copy()` on a map generated by ember-data is deprecated, please migrate to using native Map functionality only.', - false, + false, { id: 'ember-data.map.copy', until: '3.5.0' } ); @@ -72,7 +72,7 @@ export default class MapWithDeprecations { // constructor args with its `Map` let newMap = new MapWithDeprecations(); this._map.forEach(function(value, key) { - newMap.set(key, value) + newMap.set(key, value); }); return newMap; @@ -81,7 +81,7 @@ export default class MapWithDeprecations { isEmpty() { deprecate( 'Calling `.isEmpty()` on a map generated by ember-data is deprecated, please migrate to using native Map functionality only.', - false, + false, { id: 'ember-data.map.isEmpty', until: '3.5.0' } ); @@ -89,14 +89,34 @@ export default class MapWithDeprecations { } // proxy all normal Map methods to the underlying Map - get size() { return this._map.size; } - clear() { return this._map.clear(...arguments) } - delete() { return this._map.delete(...arguments) } - entries() { return this._map.entries(...arguments) } - forEach() { return this._map.forEach(...arguments) } - get() { return this._map.get(...arguments) } - has() { return this._map.has(...arguments) } - keys() { return this._map.keys(...arguments) } - set() { return this._map.set(...arguments) } - values() { return this._map.values(...arguments) } + get size() { + return this._map.size; + } + clear() { + return this._map.clear(...arguments); + } + delete() { + return this._map.delete(...arguments); + } + entries() { + return this._map.entries(...arguments); + } + forEach() { + return this._map.forEach(...arguments); + } + get() { + return this._map.get(...arguments); + } + has() { + return this._map.has(...arguments); + } + keys() { + return this._map.keys(...arguments); + } + set() { + return this._map.set(...arguments); + } + values() { + return this._map.values(...arguments); + } } diff --git a/addon/-record-data-rfc-private/system/model/errors.js b/addon/-record-data-rfc-private/system/model/errors.js index b955dc1ef61..005fb9ec7ca 100644 --- a/addon/-record-data-rfc-private/system/model/errors.js +++ b/addon/-record-data-rfc-private/system/model/errors.js @@ -86,7 +86,6 @@ import { warn } from '@ember/debug'; @uses Ember.Evented */ export default ArrayProxy.extend(Evented, { - /** Register with target handler @@ -107,7 +106,7 @@ export default ArrayProxy.extend(Evented, { return new MapWithDefault({ defaultValue() { return A(); - } + }, }); }), @@ -165,7 +164,9 @@ export default ArrayProxy.extend(Evented, { */ unknownProperty(attribute) { let errors = this.errorsFor(attribute); - if (errors.length === 0) { return undefined; } + if (errors.length === 0) { + return undefined; + } return errors; }, @@ -203,7 +204,7 @@ export default ArrayProxy.extend(Evented, { */ add(attribute, messages) { warn(`Interacting with a record errors object will no longer change the record state.`, false, { - id: 'ds.errors.add' + id: 'ds.errors.add', }); let wasEmpty = get(this, 'isEmpty'); @@ -215,7 +216,6 @@ export default ArrayProxy.extend(Evented, { } }, - /** Adds error messages to a given attribute without sending event. @@ -225,7 +225,9 @@ export default ArrayProxy.extend(Evented, { _add(attribute, messages) { messages = this._findOrCreateMessages(attribute, messages); this.addObjects(messages); - get(this, 'errorsByAttributeName').get(attribute).addObjects(messages); + get(this, 'errorsByAttributeName') + .get(attribute) + .addObjects(messages); this.notifyPropertyChange(attribute); }, @@ -247,7 +249,7 @@ export default ArrayProxy.extend(Evented, { } else { _messages[i] = { attribute: attribute, - message: message + message: message, }; } } @@ -292,10 +294,12 @@ export default ArrayProxy.extend(Evented, { */ remove(attribute) { warn(`Interacting with a record errors object will no longer change the record state.`, false, { - id: 'ds.errors.remove' + id: 'ds.errors.remove', }); - if (get(this, 'isEmpty')) { return; } + if (get(this, 'isEmpty')) { + return; + } this._remove(attribute); @@ -311,7 +315,9 @@ export default ArrayProxy.extend(Evented, { @private */ _remove(attribute) { - if (get(this, 'isEmpty')) { return; } + if (get(this, 'isEmpty')) { + return; + } let content = this.rejectBy('attribute', attribute); set(this, 'content', content); @@ -345,16 +351,17 @@ export default ArrayProxy.extend(Evented, { */ clear() { warn(`Interacting with a record errors object will no longer change the record state.`, false, { - id: 'ds.errors.clear' + id: 'ds.errors.clear', }); - if (get(this, 'isEmpty')) { return; } + if (get(this, 'isEmpty')) { + return; + } this._clear(); this.trigger('becameValid'); }, - /** Removes all error messages. to the record. @@ -363,7 +370,9 @@ export default ArrayProxy.extend(Evented, { @private */ _clear() { - if (get(this, 'isEmpty')) { return; } + if (get(this, 'isEmpty')) { + return; + } let errorsByAttributeName = get(this, 'errorsByAttributeName'); let attributes = A(); @@ -380,7 +389,6 @@ export default ArrayProxy.extend(Evented, { ArrayProxy.prototype.clear.call(this); }, - /** Checks if there is error messages for the given attribute. @@ -405,5 +413,5 @@ export default ArrayProxy.extend(Evented, { */ has(attribute) { return this.errorsFor(attribute).length > 0; - } + }, }); diff --git a/addon/-record-data-rfc-private/system/model/internal-model.js b/addon/-record-data-rfc-private/system/model/internal-model.js index 3ca0b0b70c5..37c119c26e7 100644 --- a/addon/-record-data-rfc-private/system/model/internal-model.js +++ b/addon/-record-data-rfc-private/system/model/internal-model.js @@ -7,22 +7,15 @@ import RSVP, { Promise } from 'rsvp'; import Ember from 'ember'; import { DEBUG } from '@glimmer/env'; import { assert, inspect } from '@ember/debug'; -import RootState from "./states"; -import Snapshot from "../snapshot"; -import OrderedSet from "../ordered-set"; -import isArrayLike from "../is-array-like"; +import RootState from './states'; +import Snapshot from '../snapshot'; +import OrderedSet from '../ordered-set'; +import isArrayLike from '../is-array-like'; import ManyArray from '../many-array'; -import { - PromiseBelongsTo, - PromiseManyArray -} from '../promise-proxies'; +import { PromiseBelongsTo, PromiseManyArray } from '../promise-proxies'; import { getOwner } from '../../utils'; -import { - RecordReference, - BelongsToReference, - HasManyReference -} from "../references"; +import { RecordReference, BelongsToReference, HasManyReference } from '../references'; /* The TransitionChainMap caches the `state.enters`, `state.setups`, and final state reached @@ -40,15 +33,11 @@ const _extractPivotNameCache = Object.create(null); const _splitOnDotCache = Object.create(null); function splitOnDot(name) { - return _splitOnDotCache[name] || ( - _splitOnDotCache[name] = name.split('.') - ); + return _splitOnDotCache[name] || (_splitOnDotCache[name] = name.split('.')); } function extractPivotName(name) { - return _extractPivotNameCache[name] || ( - _extractPivotNameCache[name] = splitOnDot(name)[0] - ); + return _extractPivotNameCache[name] || (_extractPivotNameCache[name] = splitOnDot(name)[0]); } // this (and all heimdall instrumentation) will be stripped by a babel transform @@ -62,8 +51,9 @@ const { new_InternalModel, send, setupData, - transitionTo -} = heimdall.registerMonitor('InternalModel', + transitionTo, +} = heimdall.registerMonitor( + 'InternalModel', '_triggerDeferredTriggers', 'changedAttributes', 'createSnapshot', @@ -132,7 +122,6 @@ export default class InternalModel { this._manyArrayCache = Object.create(null); this._retainedManyArrayCache = Object.create(null); this._relationshipPromisesCache = Object.create(null); - } get modelClass() { @@ -179,11 +168,13 @@ export default class InternalModel { // `lastObject` have changed. When this happens we don't want those // models to rematerialize their records. - return this._isDematerializing || + return ( + this._isDematerializing || this.hasScheduledDestroy() || this.isDestroyed || this.currentState.stateName === 'root.deleted.saved' || - this.isEmpty(); + this.isEmpty() + ); } isRecordInUse() { @@ -249,11 +240,14 @@ export default class InternalModel { _internalModel: this, currentState: this.currentState, isError: this.isError, - adapterError: this.error + adapterError: this.error, }; if (properties !== undefined) { - assert(`You passed '${properties}' as properties for record creation instead of an object.`, typeof properties === 'object' && properties !== null); + assert( + `You passed '${properties}' as properties for record creation instead of an object.`, + typeof properties === 'object' && properties !== null + ); let classFields = this.getFields(); // TODO disentangle post-rebase let relationships = this._modelData._relationships; @@ -324,7 +318,7 @@ export default class InternalModel { this._doNotDestroy = false; if (this._record) { - Object.keys(this._relationshipPromisesCache).forEach((key) => { + Object.keys(this._relationshipPromisesCache).forEach(key => { // TODO Igor cleanup the guard // TODO there is probably relationship cleanup to do outside of the _record check if (this._relationshipPromisesCache[key].destroy) { @@ -332,7 +326,7 @@ export default class InternalModel { } delete this._relationshipPromisesCache[key]; }); - Object.keys(this._manyArrayCache).forEach((key) => { + Object.keys(this._manyArrayCache).forEach(key => { this._retainedManyArrayCache[key] = this._manyArrayCache[key]; delete this._manyArrayCache[key]; }); @@ -350,7 +344,7 @@ export default class InternalModel { } save(options) { - let promiseLabel = "DS: Model#save " + this; + let promiseLabel = 'DS: Model#save ' + this; let resolver = RSVP.defer(promiseLabel); this.store.scheduleSave(this, resolver, options); @@ -380,23 +374,28 @@ export default class InternalModel { reload(options) { this.startedReloading(); let internalModel = this; - let promiseLabel = "DS: Model#reload of " + this; + let promiseLabel = 'DS: Model#reload of ' + this; return new Promise(function(resolve) { internalModel.send('reloadRecord', { resolve, options }); - }, promiseLabel).then(function() { - internalModel.didCleanError(); - return internalModel; - }, function(error) { - internalModel.didError(error); - throw error; - }, "DS: Model#reload complete, update flags").finally(function () { - internalModel.finishedReloading(); - internalModel.updateRecordArrays(); - }); + }, promiseLabel) + .then( + function() { + internalModel.didCleanError(); + return internalModel; + }, + function(error) { + internalModel.didError(error); + throw error; + }, + 'DS: Model#reload complete, update flags' + ) + .finally(function() { + internalModel.finishedReloading(); + internalModel.updateRecordArrays(); + }); } - /* Unload the record for this internal model. This will cause the record to be destroyed and freed up for garbage collection. It will also do a check @@ -410,15 +409,24 @@ export default class InternalModel { once all models that refer to it via some relationship are also unloaded. */ unloadRecord() { - if (this.isDestroyed) { return; } + if (this.isDestroyed) { + return; + } this.send('unloadRecord'); this.dematerializeRecord(); if (this._scheduledDestroy === null) { // TODO: use run.schedule once we drop 1.13 if (!run.currentRunLoop) { - assert('You have turned on testing mode, which disabled the run-loop\'s autorun.\n You will need to wrap any code with asynchronous side-effects in a run', Ember.testing); + assert( + "You have turned on testing mode, which disabled the run-loop's autorun.\n You will need to wrap any code with asynchronous side-effects in a run", + Ember.testing + ); } - this._scheduledDestroy = run.backburner.schedule('destroy', this, '_checkForOrphanedInternalModels') + this._scheduledDestroy = run.backburner.schedule( + 'destroy', + this, + '_checkForOrphanedInternalModels' + ); } } @@ -427,7 +435,10 @@ export default class InternalModel { } cancelDestroy() { - assert(`You cannot cancel the destruction of an InternalModel once it has already been destroyed`, !this.isDestroyed); + assert( + `You cannot cancel the destruction of an InternalModel once it has already been destroyed`, + !this.isDestroyed + ); this._doNotDestroy = true; this._isDematerializing = false; @@ -451,7 +462,9 @@ export default class InternalModel { this.cancelDestroy(); } this._checkForOrphanedInternalModels(); - if (this.isDestroyed || this.isDestroying) { return; } + if (this.isDestroyed || this.isDestroying) { + return; + } // just in-case we are not one of the orphaned, we should still // still destroy ourselves @@ -461,7 +474,9 @@ export default class InternalModel { _checkForOrphanedInternalModels() { this._isDematerializing = false; this._scheduledDestroy = null; - if (this.isDestroyed) { return; } + if (this.isDestroyed) { + return; + } } eachRelationship(callback, binding) { @@ -477,11 +492,16 @@ export default class InternalModel { let isAsync = typeof async === 'undefined' ? true : async; if (isAsync) { - let internalModel = resource && resource.data ? store._internalModelForResource(resource.data) : null; + let internalModel = + resource && resource.data ? store._internalModelForResource(resource.data) : null; return PromiseBelongsTo.create({ _belongsToState: resource._relationship, - promise: store._findBelongsToByJsonApiResource(resource, parentInternalModel, relationshipMeta), - content: internalModel ? internalModel.getRecord() : null + promise: store._findBelongsToByJsonApiResource( + resource, + parentInternalModel, + relationshipMeta + ), + content: internalModel ? internalModel.getRecord() : null, }); } else { if (!resource || !resource.data) { @@ -489,7 +509,16 @@ export default class InternalModel { } else { let internalModel = store._internalModelForResource(resource.data); let toReturn = internalModel.getRecord(); - assert("You looked up the '" + key + "' relationship on a '" + parentInternalModel.modelName + "' with id " + parentInternalModel.id + " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)", toReturn === null || !toReturn.get('isEmpty')); + assert( + "You looked up the '" + + key + + "' relationship on a '" + + parentInternalModel.modelName + + "' with id " + + parentInternalModel.id + + ' but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)', + toReturn === null || !toReturn.get('isEmpty') + ); return toReturn; } } @@ -501,7 +530,10 @@ export default class InternalModel { let jsonApi = this._modelData.getHasMany(key); let manyArray = this._manyArrayCache[key]; - assert(`Error: relationship ${this.modelName}:${key} has both many array and retained many array`, !manyArray || !this._retainedManyArrayCache[key]); + assert( + `Error: relationship ${this.modelName}:${key} has both many array and retained many array`, + !manyArray || !this._retainedManyArrayCache[key] + ); if (!manyArray) { let initialState = this.store._getHasManyByJsonApiResource(jsonApi); @@ -514,7 +546,7 @@ export default class InternalModel { key, isPolymorphic: relationshipMeta.options.polymorphic, initialState: initialState.slice(), - internalModel: this + internalModel: this, }); this._manyArrayCache[key] = manyArray; } @@ -529,7 +561,7 @@ export default class InternalModel { fetchAsyncHasMany(relationshipMeta, jsonApi, manyArray) { let promise = this.store._findHasManyByJsonApiResource(jsonApi, this, relationshipMeta); - promise = promise.then((initialState) => { + promise = promise.then(initialState => { // TODO why don't we do this in the store method manyArray.retrieveLatest(); manyArray.set('isLoaded', true); @@ -552,7 +584,7 @@ export default class InternalModel { if (!promiseArray) { promiseArray = PromiseManyArray.create({ promise: this.fetchAsyncHasMany(relationshipMeta, jsonApi, manyArray), - content: manyArray + content: manyArray, }); this._relationshipPromisesCache[key] = promiseArray; } @@ -560,7 +592,12 @@ export default class InternalModel { return promiseArray; } else { manyArray.set('isLoaded', true); - assert(`You looked up the '${key}' relationship on a '${this.type.modelName}' with id ${this.id} but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async ('DS.hasMany({ async: true })')`, !manyArray.anyUnloaded()); + assert( + `You looked up the '${key}' relationship on a '${this.type.modelName}' with id ${ + this.id + } but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async ('DS.hasMany({ async: true })')`, + !manyArray.anyUnloaded() + ); return manyArray; } @@ -570,13 +607,13 @@ export default class InternalModel { let loadingPromise = this._relationshipPromisesCache[key]; if (loadingPromise) { if (content) { - loadingPromise.set('content', content) + loadingPromise.set('content', content); } - loadingPromise.set('promise', promise) + loadingPromise.set('promise', promise); } else { this._relationshipPromisesCache[key] = PromiseManyArray.create({ promise, - content + content, }); } @@ -624,9 +661,12 @@ export default class InternalModel { } destroy() { - assert("Cannot destroy an internalModel while its record is materialized", !this._record || this._record.get('isDestroyed') || this._record.get('isDestroying')); + assert( + 'Cannot destroy an internalModel while its record is materialized', + !this._record || this._record.get('isDestroyed') || this._record.get('isDestroying') + ); this.isDestroying = true; - Object.keys(this._retainedManyArrayCache).forEach((key) => { + Object.keys(this._retainedManyArrayCache).forEach(key => { this._retainedManyArrayCache[key].destroy(); delete this._retainedManyArrayCache[key]; }); @@ -658,16 +698,23 @@ export default class InternalModel { setDirtyHasMany(key, records) { assert(`You must pass an array of records to set a hasMany relationship`, isArrayLike(records)); - assert(`All elements of a hasMany relationship must be instances of DS.Model, you passed ${inspect(records)}`, (function() { - return A(records).every((record) => record.hasOwnProperty('_internalModel') === true); - })()); + assert( + `All elements of a hasMany relationship must be instances of DS.Model, you passed ${inspect( + records + )}`, + (function() { + return A(records).every(record => record.hasOwnProperty('_internalModel') === true); + })() + ); // TODO this seems like unnecessary churn - this._modelData.setDirtyHasMany(key, records.map((record) => record.get('_internalModel._modelData').getResourceIdentifier())); + this._modelData.setDirtyHasMany( + key, + records.map(record => record.get('_internalModel._modelData').getResourceIdentifier()) + ); } setDirtyBelongsTo(key, value) { - // TODO this seems like a digression from the pattern in setDirtyHasMany return this._modelData.setDirtyBelongsTo(key, value); } @@ -683,7 +730,7 @@ export default class InternalModel { let isDirty = this._modelData.isAttrDirty(key); this.send('didSetProperty', { name: key, - isDirty: isDirty + isDirty: isDirty, }); } @@ -878,7 +925,9 @@ export default class InternalModel { let transitionMapId = `${state.stateName}->${name}`; do { - if (state.exit) { state.exit(this); } + if (state.exit) { + state.exit(this); + } state = state.parentState; } while (!state[pivotName]); @@ -901,8 +950,12 @@ export default class InternalModel { for (i = 0, l = path.length; i < l; i++) { state = state[path[i]]; - if (state.enter) { enters.push(state); } - if (state.setup) { setups.push(state); } + if (state.enter) { + enters.push(state); + } + if (state.setup) { + setups.push(state); + } } TransitionChainMap[transitionMapId] = { setups, enters, state }; @@ -925,12 +978,12 @@ export default class InternalModel { } _unhandledEvent(state, name, context) { - let errorMessage = "Attempted to handle event `" + name + "` "; - errorMessage += "on " + String(this) + " while in state "; - errorMessage += state.stateName + ". "; + let errorMessage = 'Attempted to handle event `' + name + '` '; + errorMessage += 'on ' + String(this) + ' while in state '; + errorMessage += state.stateName + '. '; if (context !== undefined) { - errorMessage += "Called with " + inspect(context) + "."; + errorMessage += 'Called with ' + inspect(context) + '.'; } throw new EmberError(errorMessage); @@ -955,7 +1008,7 @@ export default class InternalModel { let triggers = this._deferredTriggers; let record = this._record; let trigger = record.trigger; - for (let i = 0, l= triggers.length; i { + Object.keys(preload).forEach(key => { let preloadValue = get(preload, key); let relationshipMeta = this.modelClass.metaForProperty(key); if (relationshipMeta.isRelationship) { @@ -1007,8 +1060,11 @@ export default class InternalModel { let modelClass = relationshipMeta.type; let data; if (relationshipMeta.kind === 'hasMany') { - assert("You need to pass in an array to set a hasMany property on a record", Array.isArray(preloadValue)); - data = preloadValue.map((value) => this._convertPreloadRelationshipToJSON(value, modelClass )); + assert( + 'You need to pass in an array to set a hasMany property on a record', + Array.isArray(preloadValue) + ); + data = preloadValue.map(value => this._convertPreloadRelationshipToJSON(value, modelClass)); } else { data = this._convertPreloadRelationshipToJSON(preloadValue, modelClass); } @@ -1040,7 +1096,10 @@ export default class InternalModel { } setId(id) { - assert('A record\'s id cannot be changed once it is in the loaded state', this.id === null || this.id === id || this.isNew()); + assert( + "A record's id cannot be changed once it is in the loaded state", + this.id === null || this.id === id || this.isNew() + ); let didChange = id !== this.id; this.id = id; @@ -1056,7 +1115,7 @@ export default class InternalModel { if (this.hasRecord) { this._record.setProperties({ isError: true, - adapterError: error + adapterError: error, }); } } @@ -1068,7 +1127,7 @@ export default class InternalModel { if (this.hasRecord) { this._record.setProperties({ isError: false, - adapterError: null + adapterError: null, }); } } @@ -1088,7 +1147,9 @@ export default class InternalModel { this.send('didCommit'); this.updateRecordArrays(); - if (!data) { return; } + if (!data) { + return; + } this._record._notifyProperties(changedKeys); } @@ -1155,15 +1216,21 @@ export default class InternalModel { if (DEBUG) { let modelName = this.modelName; - assert(`There is no ${kind} relationship named '${name}' on a model of modelClass '${modelName}'`, relationship); + assert( + `There is no ${kind} relationship named '${name}' on a model of modelClass '${modelName}'`, + relationship + ); let actualRelationshipKind = relationship.relationshipMeta.kind; - assert(`You tried to get the '${name}' relationship on a '${modelName}' via record.${kind}('${name}'), but the relationship is of kind '${actualRelationshipKind}'. Use record.${actualRelationshipKind}('${name}') instead.`, actualRelationshipKind === kind); + assert( + `You tried to get the '${name}' relationship on a '${modelName}' via record.${kind}('${name}'), but the relationship is of kind '${actualRelationshipKind}'. Use record.${actualRelationshipKind}('${name}') instead.`, + actualRelationshipKind === kind + ); } - if (kind === "belongsTo") { + if (kind === 'belongsTo') { reference = new BelongsToReference(this.store, this, relationship, name); - } else if (kind === "hasMany") { + } else if (kind === 'hasMany') { reference = new HasManyReference(this.store, this, relationship, name); } diff --git a/addon/-record-data-rfc-private/system/model/model-data.js b/addon/-record-data-rfc-private/system/model/model-data.js index dd39f9e17d6..ac677577dae 100644 --- a/addon/-record-data-rfc-private/system/model/model-data.js +++ b/addon/-record-data-rfc-private/system/model/model-data.js @@ -1,10 +1,10 @@ import isEnabled from '../../features'; import { DEBUG } from '@glimmer/env'; -import Relationships from "../relationships/state/create"; +import Relationships from '../relationships/state/create'; import { assign } from '@ember/polyfills'; import { isEqual } from '@ember/utils'; import { assert, warn, inspect } from '@ember/debug'; -import coerceId from "../coerce-id"; +import coerceId from '../coerce-id'; import { run } from '@ember/runloop'; let nextBfsId = 1; @@ -31,8 +31,8 @@ export default class ModelData { return { id: this.id, type: this.modelName, - clientId: this.clientId - } + clientId: this.clientId, + }; } pushData(data, calculateChange) { @@ -72,9 +72,7 @@ export default class ModelData { // and relationships need this info and @runspired didn't see // how to get it just yet from storeWrapper. isEmpty() { - return this.__attributes === null && - this.__inFlightAttributes === null && - this.__data === null; + return this.__attributes === null && this.__inFlightAttributes === null && this.__data === null; } reset() { @@ -86,7 +84,7 @@ export default class ModelData { _setupRelationships(data) { let relationships = this.storeWrapper.relationshipsDefinitionFor(this.modelName); let keys = Object.keys(relationships); - for (let i=0; i < keys.length; i++) { + for (let i = 0; i < keys.length; i++) { let relationshipName = keys[i]; if (!data.relationships[relationshipName]) { @@ -105,18 +103,43 @@ export default class ModelData { if (relationshipData.links) { let isAsync = relationshipMeta.options && relationshipMeta.options.async !== false; - warn(`You pushed a record of type '${this.modelName}' with a relationship '${relationshipName}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload.`, isAsync || relationshipData.data , { - id: 'ds.store.push-link-for-sync-relationship' - }); + warn( + `You pushed a record of type '${ + this.modelName + }' with a relationship '${relationshipName}' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload.`, + isAsync || relationshipData.data, + { + id: 'ds.store.push-link-for-sync-relationship', + } + ); } else if (relationshipData.data) { if (relationshipMeta.kind === 'belongsTo') { - assert(`A ${this.modelName} record was pushed into the store with the value of ${relationshipName} being ${inspect(relationshipData.data)}, but ${relationshipName} is a belongsTo relationship so the value must not be an array. You should probably check your data payload or serializer.`, !Array.isArray(relationshipData.data)); + assert( + `A ${ + this.modelName + } record was pushed into the store with the value of ${relationshipName} being ${inspect( + relationshipData.data + )}, but ${relationshipName} is a belongsTo relationship so the value must not be an array. You should probably check your data payload or serializer.`, + !Array.isArray(relationshipData.data) + ); assertRelationshipData(store, modelData, relationshipData.data, relationshipMeta); } else if (relationshipMeta.kind === 'hasMany') { - assert(`A ${this.modelName} record was pushed into the store with the value of ${relationshipName} being '${inspect(relationshipData.data)}', but ${relationshipName} is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer.`, Array.isArray(relationshipData.data)); + assert( + `A ${ + this.modelName + } record was pushed into the store with the value of ${relationshipName} being '${inspect( + relationshipData.data + )}', but ${relationshipName} is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer.`, + Array.isArray(relationshipData.data) + ); if (Array.isArray(relationshipData.data)) { for (let i = 0; i < relationshipData.data.length; i++) { - assertRelationshipData(store, modelData, relationshipData.data[i], relationshipMeta); + assertRelationshipData( + store, + modelData, + relationshipData.data[i], + relationshipMeta + ); } } } @@ -233,7 +256,11 @@ export default class ModelData { setDirtyHasMany(key, resources) { let relationship = this._relationships.get(key); relationship.clear(); - relationship.addModelDatas(resources.map(resource => this.storeWrapper.modelDataFor(resource.type, resource.id, resource.clientId))); + relationship.addModelDatas( + resources.map(resource => + this.storeWrapper.modelDataFor(resource.type, resource.id, resource.clientId) + ) + ); } // append to "current state" via ModelDatas @@ -252,7 +279,7 @@ export default class ModelData { let keys = Object.keys(this._inFlightAttributes); if (keys.length > 0) { let attrs = this._attributes; - for (let i=0; i < keys.length; i++) { + for (let i = 0; i < keys.length; i++) { if (attrs[keys[i]] === undefined) { attrs[keys[i]] = this._inFlightAttributes[keys[i]]; } @@ -306,9 +333,7 @@ export default class ModelData { } hasAttr(key) { - return key in this._attributes || - key in this._inFlightAttributes || - key in this._data; + return key in this._attributes || key in this._inFlightAttributes || key in this._data; } unloadRecord() { @@ -318,14 +343,18 @@ export default class ModelData { this._destroyRelationships(); this.reset(); if (!this._scheduledDestroy) { - this._scheduledDestroy = run.backburner.schedule('destroy', this, '_cleanupOrphanedModelDatas') + this._scheduledDestroy = run.backburner.schedule( + 'destroy', + this, + '_cleanupOrphanedModelDatas' + ); } } _cleanupOrphanedModelDatas() { let relatedModelDatas = this._allRelatedModelDatas(); if (areAllModelsUnloaded(relatedModelDatas)) { - for (let i=0; i { + Object.keys(implicitRelationships).forEach(key => { let rel = implicitRelationships[key]; rel.removeCompletelyFromInverse(); @@ -530,7 +557,7 @@ export default class ModelData { let implicitRelationships = this._implicitRelationships; this.__implicitRelationships = null; - Object.keys(implicitRelationships).forEach((key) => { + Object.keys(implicitRelationships).forEach(key => { let rel = implicitRelationships[key]; destroyRelationship(rel); }); @@ -540,7 +567,6 @@ export default class ModelData { this._isNew = true; } - /* Ember Data has 3 buckets for storing the value of an attribute on an internalModel. @@ -597,7 +623,7 @@ export default class ModelData { let hasAttrs = this.hasChangedAttributes(); let attrs; if (hasAttrs) { - attrs= this._attributes; + attrs = this._attributes; } original = assign(Object.create(null), this._data, this.__inFlightAttributes); @@ -626,7 +652,6 @@ export default class ModelData { toString() { return `<${this.modelName}:${this.id}>`; } - } if (isEnabled('ds-rollback-attribute')) { @@ -647,23 +672,38 @@ if (isEnabled('ds-rollback-attribute')) { } function assertRelationshipData(store, modelData, data, meta) { - assert(`A ${modelData.modelName} record was pushed into the store with the value of ${meta.key} being '${JSON.stringify(data)}', but ${meta.key} is a belongsTo relationship so the value must not be an array. You should probably check your data payload or serializer.`, !Array.isArray(data)); assert( - `Encountered a relationship identifier without a type for the ${meta.kind} relationship '${meta.key}' on ${modelData}, expected a json-api identifier with type '${meta.type}' but found '${JSON.stringify(data)}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, + `A ${modelData.modelName} record was pushed into the store with the value of ${ + meta.key + } being '${JSON.stringify(data)}', but ${ + meta.key + } is a belongsTo relationship so the value must not be an array. You should probably check your data payload or serializer.`, + !Array.isArray(data) + ); + assert( + `Encountered a relationship identifier without a type for the ${meta.kind} relationship '${ + meta.key + }' on ${modelData}, expected a json-api identifier with type '${ + meta.type + }' but found '${JSON.stringify( + data + )}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, data === null || (typeof data.type === 'string' && data.type.length) ); assert( - `Encountered a relationship identifier without an id for the ${meta.kind} relationship '${meta.key}' on ${modelData}, expected a json-api identifier but found '${JSON.stringify(data)}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, + `Encountered a relationship identifier without an id for the ${meta.kind} relationship '${ + meta.key + }' on ${modelData}, expected a json-api identifier but found '${JSON.stringify( + data + )}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, data === null || coerceId(data.id) ); assert( - `Encountered a relationship identifier with type '${ - data.type - }' for the ${meta.kind} relationship '${meta.key}' on ${ - modelData - }, Expected a json-api identifier with type '${ + `Encountered a relationship identifier with type '${data.type}' for the ${ + meta.kind + } relationship '${meta.key}' on ${modelData}, Expected a json-api identifier with type '${ meta.type - }'. No model was found for '${data.type}'.`, + }'. No model was found for '${data.type}'.`, data === null || !data.type || store._hasModelFor(data.type) ); } @@ -688,7 +728,7 @@ function destroyRelationship(rel) { } function areAllModelsUnloaded(modelDatas) { - for (let i=0; i { let optionsForRelationship = inverseType.metaForProperty(relationship.name).options; @@ -54,9 +53,9 @@ function findPossibleInverses(type, inverseType, name, relationshipsSoFar) { return possibleRelationships; } -function intersection (array1, array2) { +function intersection(array1, array2) { let result = []; - array1.forEach((element) => { + array1.forEach(element => { if (array2.indexOf(element) >= 0) { result.push(element); } @@ -65,9 +64,7 @@ function intersection (array1, array2) { return result; } -const RESERVED_MODEL_PROPS = [ - 'currentState', 'data', 'store' -]; +const RESERVED_MODEL_PROPS = ['currentState', 'data', 'store']; const retrieveFromCurrentState = computed('currentState', function(key) { return get(this._internalModel.currentState, key); @@ -402,13 +399,15 @@ const Model = EmberObject.extend(Evented, { errors: computed(function() { let errors = Errors.create(); - errors._registerHandlers(this._internalModel, + errors._registerHandlers( + this._internalModel, function() { this.send('becameInvalid'); }, function() { this.send('becameValid'); - }); + } + ); return errors; }).readOnly(), @@ -538,7 +537,6 @@ const Model = EmberObject.extend(Evented, { return this._internalModel.transitionTo(name); }, - /** Marks the record as deleted but does not save it. You must call `save` afterwards if you want to persist it. You might use this @@ -626,7 +624,9 @@ const Model = EmberObject.extend(Evented, { @method unloadRecord */ unloadRecord() { - if (this.isDestroyed) { return; } + if (this.isDestroyed) { + return; + } this._internalModel.unloadRecord(); }, @@ -791,7 +791,7 @@ const Model = EmberObject.extend(Evented, { */ save(options) { return PromiseObject.create({ - promise: this._internalModel.save(options).then(() => this) + promise: this._internalModel.save(options).then(() => this), }); }, @@ -828,16 +828,15 @@ const Model = EmberObject.extend(Evented, { if (typeof options === 'object' && options !== null && options.adapterOptions) { wrappedAdapterOptions = { - adapterOptions: options.adapterOptions + adapterOptions: options.adapterOptions, }; } return PromiseObject.create({ - promise: this._internalModel.reload(wrappedAdapterOptions).then(() => this) + promise: this._internalModel.reload(wrappedAdapterOptions).then(() => this), }); }, - /** Override the default event firing from Ember.Evented to also call methods with the given name. @@ -856,14 +855,17 @@ const Model = EmberObject.extend(Evented, { for (let i = 1; i < length; i++) { args[i - 1] = arguments[i]; } - fn.apply(this, args) + fn.apply(this, args); } this._super(...arguments); }, attr() { - assert("The `attr` method is not available on DS.Model, a DS.Snapshot was probably expected. Are you passing a DS.Model instead of a DS.Snapshot to your serializer?", false); + assert( + 'The `attr` method is not available on DS.Model, a DS.Snapshot was probably expected. Are you passing a DS.Model instead of a DS.Snapshot to your serializer?', + false + ); }, /** @@ -1010,7 +1012,7 @@ const Model = EmberObject.extend(Evented, { */ _debugInfo() { let attributes = ['id']; - let relationships = { }; + let relationships = {}; let expensiveProperties = []; this.eachAttribute((name, meta) => attributes.push(name)); @@ -1019,8 +1021,8 @@ const Model = EmberObject.extend(Evented, { { name: 'Attributes', properties: attributes, - expand: true - } + expand: true, + }, ]; this.eachRelationship((name, relationship) => { @@ -1031,7 +1033,7 @@ const Model = EmberObject.extend(Evented, { groups.push({ name: relationship.name, properties, - expand: true + expand: true, }); } properties.push(name); @@ -1040,7 +1042,15 @@ const Model = EmberObject.extend(Evented, { groups.push({ name: 'Flags', - properties: ['isLoaded', 'hasDirtyAttributes', 'isSaving', 'isDeleted', 'isError', 'isNew', 'isValid'] + properties: [ + 'isLoaded', + 'hasDirtyAttributes', + 'isSaving', + 'isDeleted', + 'isError', + 'isNew', + 'isValid', + ], }); return { @@ -1049,8 +1059,8 @@ const Model = EmberObject.extend(Evented, { includeOtherProperties: true, groups: groups, // don't pre-calculate unless cached - expensiveProperties: expensiveProperties - } + expensiveProperties: expensiveProperties, + }, }; }, @@ -1130,7 +1140,7 @@ const Model = EmberObject.extend(Evented, { eachAttribute(callback, binding) { this.constructor.eachAttribute(callback, binding); - } + }, }); /** @@ -1143,7 +1153,7 @@ Object.defineProperty(Model.prototype, 'data', { get() { // TODO deprecate this!!!!!!!!!!! it's private but intimate return this._internalModel._modelData._data; - } + }, }); Object.defineProperty(Model.prototype, 'id', { @@ -1157,7 +1167,7 @@ Object.defineProperty(Model.prototype, 'id', { // (addListener via validatePropertyInjections) invokes toString before the // object is real. return this._internalModel && this._internalModel.id; - } + }, }); if (DEBUG) { @@ -1166,9 +1176,11 @@ if (DEBUG) { this._super(...arguments); if (!this._internalModel) { - throw new EmberError('You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'); + throw new EmberError( + 'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.' + ); } - } + }, }); } @@ -1309,7 +1321,6 @@ Model.reopenClass({ //Calculate the inverse, ignoring the cache _findInverseFor(name, store) { - let inverseType = this.typeForRelationship(name, store); if (!inverseType) { return null; @@ -1318,7 +1329,9 @@ Model.reopenClass({ let propertyMeta = this.metaForProperty(name); //If inverse is manually specified to be null, like `comments: DS.hasMany('message', { inverse: null })` let options = propertyMeta.options; - if (options.inverse === null) { return null; } + if (options.inverse === null) { + return null; + } let inverseName, inverseKind, inverse, inverseOptions; @@ -1327,8 +1340,14 @@ Model.reopenClass({ inverseName = options.inverse; inverse = get(inverseType, 'relationshipsByName').get(inverseName); - assert("We found no inverse relationships by the name of '" + inverseName + "' on the '" + inverseType.modelName + - "' model. This is most likely due to a missing attribute on your model definition.", !isNone(inverse)); + assert( + "We found no inverse relationships by the name of '" + + inverseName + + "' on the '" + + inverseType.modelName + + "' model. This is most likely due to a missing attribute on your model definition.", + !isNone(inverse) + ); // TODO probably just return the whole inverse here inverseKind = inverse.kind; @@ -1336,44 +1355,73 @@ Model.reopenClass({ } else { //No inverse was specified manually, we need to use a heuristic to guess one if (propertyMeta.parentType && propertyMeta.type === propertyMeta.parentType.modelName) { - warn(`Detected a reflexive relationship by the name of '${name}' without an inverse option. Look at https://guides.emberjs.com/current/models/relationships/#toc_reflexive-relations for how to explicitly specify inverses.`, false, { - id: 'ds.model.reflexive-relationship-without-inverse' - }); + warn( + `Detected a reflexive relationship by the name of '${name}' without an inverse option. Look at https://guides.emberjs.com/current/models/relationships/#toc_reflexive-relations for how to explicitly specify inverses.`, + false, + { + id: 'ds.model.reflexive-relationship-without-inverse', + } + ); } let possibleRelationships = findPossibleInverses(this, inverseType, name); - if (possibleRelationships.length === 0) { return null; } + if (possibleRelationships.length === 0) { + return null; + } - let filteredRelationships = possibleRelationships.filter((possibleRelationship) => { + let filteredRelationships = possibleRelationships.filter(possibleRelationship => { let optionsForRelationship = inverseType.metaForProperty(possibleRelationship.name).options; return name === optionsForRelationship.inverse; }); - assert("You defined the '" + name + "' relationship on " + this + ", but you defined the inverse relationships of type " + - inverseType.toString() + " multiple times. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses", - filteredRelationships.length < 2); - - if (filteredRelationships.length === 1 ) { + assert( + "You defined the '" + + name + + "' relationship on " + + this + + ', but you defined the inverse relationships of type ' + + inverseType.toString() + + ' multiple times. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses', + filteredRelationships.length < 2 + ); + + if (filteredRelationships.length === 1) { possibleRelationships = filteredRelationships; } - assert("You defined the '" + name + "' relationship on " + this + ", but multiple possible inverse relationships of type " + - this + " were found on " + inverseType + ". Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses", - possibleRelationships.length === 1); + assert( + "You defined the '" + + name + + "' relationship on " + + this + + ', but multiple possible inverse relationships of type ' + + this + + ' were found on ' + + inverseType + + '. Look at https://guides.emberjs.com/current/models/relationships/#toc_explicit-inverses for how to explicitly specify inverses', + possibleRelationships.length === 1 + ); inverseName = possibleRelationships[0].name; inverseKind = possibleRelationships[0].kind; inverseOptions = possibleRelationships[0].options; } - assert(`The ${inverseType.modelName}:${inverseName} relationship declares 'inverse: null', but it was resolved as the inverse for ${this.modelName}:${name}.`, !inverseOptions || inverseOptions.inverse !== null); + assert( + `The ${ + inverseType.modelName + }:${inverseName} relationship declares 'inverse: null', but it was resolved as the inverse for ${ + this.modelName + }:${name}.`, + !inverseOptions || inverseOptions.inverse !== null + ); return { type: inverseType, name: inverseName, kind: inverseKind, - options: inverseOptions + options: inverseOptions, }; }, @@ -1457,7 +1505,7 @@ Model.reopenClass({ relationshipNames: computed(function() { let names = { hasMany: [], - belongsTo: [] + belongsTo: [], }; this.eachComputedProperty((name, meta) => { @@ -1542,7 +1590,6 @@ Model.reopenClass({ */ relationshipsByName: relationshipsByNameDescriptor, - relationshipsObject: relationshipsObjectDescriptor, /** @@ -1700,7 +1747,11 @@ Model.reopenClass({ this.eachComputedProperty((name, meta) => { if (meta.isAttribute) { - assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + this.toString(), name !== 'id'); + assert( + "You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + + this.toString(), + name !== 'id' + ); meta.name = name; map.set(name, meta); @@ -1867,7 +1918,7 @@ Model.reopenClass({ */ toString() { return `model:${get(this, 'modelName')}`; - } + }, }); if (DEBUG) { @@ -1876,8 +1927,18 @@ if (DEBUG) { // rely on the data property. willMergeMixin(props) { let constructor = this.constructor; - assert('`' + intersection(Object.keys(props), RESERVED_MODEL_PROPS)[0] + '` is a reserved property name on DS.Model objects. Please choose a different property name for ' + constructor.toString(), !intersection(Object.keys(props), RESERVED_MODEL_PROPS)[0]); - assert("You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + constructor.toString(), Object.keys(props).indexOf('id') === -1); + assert( + '`' + + intersection(Object.keys(props), RESERVED_MODEL_PROPS)[0] + + '` is a reserved property name on DS.Model objects. Please choose a different property name for ' + + constructor.toString(), + !intersection(Object.keys(props), RESERVED_MODEL_PROPS)[0] + ); + assert( + "You may not set `id` as an attribute on your model. Please remove any lines that look like: `id: DS.attr('')` from " + + constructor.toString(), + Object.keys(props).indexOf('id') === -1 + ); }, /** @@ -1909,7 +1970,6 @@ if (DEBUG) { didDefineProperty(proto, key, value) { // Check if the value being set is a computed property. if (value instanceof ComputedProperty) { - // If it is, get the metadata for the relationship. This is // populated by the `DS.belongsTo` helper when it is creating // the computed property. @@ -1921,7 +1981,7 @@ if (DEBUG) { */ meta.parentType = proto.constructor; } - } + }, }); } diff --git a/addon/-record-data-rfc-private/system/model/states.js b/addon/-record-data-rfc-private/system/model/states.js index f67bd7a0cbc..55438b134f6 100644 --- a/addon/-record-data-rfc-private/system/model/states.js +++ b/addon/-record-data-rfc-private/system/model/states.js @@ -238,10 +238,12 @@ const DirtyState = { //TODO(Igor) reloading now triggers a //loadingData event, though it seems fine? - loadingData() { }, + loadingData() {}, propertyWasReset(internalModel, name) { - if (!internalModel.hasChangedAttributes()) { internalModel.send('rolledBack'); } + if (!internalModel.hasChangedAttributes()) { + internalModel.send('rolledBack'); + } }, pushedData(internalModel) { @@ -275,7 +277,7 @@ const DirtyState = { rollback(internalModel) { internalModel.rollbackAttributes(); internalModel.triggerLater('ready'); - } + }, }, // Once a record has been handed off to the adapter to be @@ -287,13 +289,13 @@ const DirtyState = { // EVENTS didSetProperty, - becomeDirty() { }, - pushedData() { }, + becomeDirty() {}, + pushedData() {}, unloadRecord: assertAgainstUnloadRecord, // TODO: More robust semantics around save-while-in-flight - willCommit() { }, + willCommit() {}, didCommit(internalModel) { internalModel.transitionTo('saved'); @@ -312,7 +314,7 @@ const DirtyState = { becameError(internalModel) { internalModel.transitionTo('uncommitted'); internalModel.triggerLater('becameError', internalModel); - } + }, }, // A record is in the `invalid` if the adapter has indicated @@ -336,9 +338,9 @@ const DirtyState = { } }, - becameInvalid() { }, - becomeDirty() { }, - pushedData() { }, + becameInvalid() {}, + becomeDirty() {}, + pushedData() {}, willCommit(internalModel) { internalModel.clearErrorMessages(); @@ -357,8 +359,8 @@ const DirtyState = { invokeLifecycleCallbacks(internalModel) { internalModel.triggerLater('becameInvalid', internalModel); - } - } + }, + }, }; // The created and updated states are created outside the state @@ -397,7 +399,7 @@ function dirtyState(options) { const createdState = dirtyState({ dirtyType: 'created', // FLAGS - isNew: true + isNew: true, }); createdState.invalid.rolledBack = function(internalModel) { @@ -411,7 +413,7 @@ createdState.uncommitted.rolledBack = function(internalModel) { }; const updatedState = dirtyState({ - dirtyType: 'updated' + dirtyType: 'updated', }); function createdStateDeleteRecord(internalModel) { @@ -436,7 +438,7 @@ createdState.uncommitted.pushedData = function(internalModel) { createdState.uncommitted.propertyWasReset = function() {}; function assertAgainstUnloadRecord(internalModel) { - assert("You can only unload a record which is not inFlight. `" + internalModel + "`", false); + assert('You can only unload a record which is not inFlight. `' + internalModel + '`', false); } updatedState.invalid.becameValid = function(internalModel) { @@ -475,11 +477,10 @@ const 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() { }, - unloadRecord(internalModel) { - }, + rolledBack() {}, + unloadRecord(internalModel) {}, - propertyWasReset() { }, + propertyWasReset() {}, // SUBSTATES @@ -506,7 +507,7 @@ const RootState = { internalModel.transitionTo('loaded.saved'); internalModel.triggerLater('didLoad'); internalModel.triggerLater('ready'); - } + }, }, // A record enters this state when the store asks @@ -538,7 +539,7 @@ const RootState = { notFound(internalModel) { internalModel.transitionTo('empty'); - } + }, }, // A record enters this state when its data is populated. @@ -552,7 +553,7 @@ const RootState = { //TODO(Igor) Reloading now triggers a loadingData event, //but it should be ok? - loadingData() { }, + loadingData() {}, // SUBSTATES @@ -568,7 +569,7 @@ const RootState = { // EVENTS didSetProperty, - pushedData() { }, + pushedData() {}, becomeDirty(internalModel) { internalModel.transitionTo('updated.uncommitted'); @@ -586,14 +587,13 @@ const RootState = { internalModel.transitionTo('deleted.uncommitted'); }, - unloadRecord(internalModel) { - }, + unloadRecord(internalModel) {}, didCommit() {}, // loaded.saved.notFound would be triggered by a failed // `reload()` on an unchanged record - notFound() { } + notFound() {}, }, // A record is in this state after it has been locally @@ -604,7 +604,7 @@ const RootState = { // A record is in this state if it has already been // saved to the server, but there are new local changes // that have not yet been saved. - updated: updatedState + updated: updatedState, }, // A record is in this state if it was deleted from the store. @@ -628,7 +628,6 @@ const RootState = { // state. It will exit this state when the record // starts to commit. uncommitted: { - // EVENTS willCommit(internalModel) { @@ -640,15 +639,15 @@ const RootState = { internalModel.triggerLater('ready'); }, - pushedData() { }, - becomeDirty() { }, - deleteRecord() { }, + pushedData() {}, + becomeDirty() {}, + deleteRecord() {}, rolledBack(internalModel) { internalModel.transitionTo('loaded.saved'); internalModel.triggerLater('ready'); internalModel.triggerLater('rolledBack'); - } + }, }, // After a record starts committing, but @@ -664,7 +663,7 @@ const RootState = { unloadRecord: assertAgainstUnloadRecord, // TODO: More robust semantics around save-while-in-flight - willCommit() { }, + willCommit() {}, didCommit(internalModel) { internalModel.transitionTo('saved'); @@ -679,7 +678,7 @@ const RootState = { becameInvalid(internalModel) { internalModel.transitionTo('invalid'); internalModel.triggerLater('becameInvalid', internalModel); - } + }, }, // Once the adapter indicates that the deletion has @@ -698,9 +697,9 @@ const RootState = { internalModel.triggerLater('didCommit', internalModel); }, - willCommit() { }, - didCommit() { }, - pushedData() {} + willCommit() {}, + didCommit() {}, + pushedData() {}, }, invalid: { @@ -716,10 +715,10 @@ const RootState = { } }, - becameInvalid() { }, - becomeDirty() { }, - deleteRecord() { }, - willCommit() { }, + becameInvalid() {}, + becomeDirty() {}, + deleteRecord() {}, + willCommit() {}, rolledBack(internalModel) { internalModel.clearErrorMessages(); @@ -729,9 +728,8 @@ const RootState = { becameValid(internalModel) { internalModel.transitionTo('uncommitted'); - } - - } + }, + }, }, invokeLifecycleCallbacks(internalModel, dirtyType) { @@ -742,7 +740,7 @@ const RootState = { } internalModel.triggerLater('didCommit', internalModel); - } + }, }; function wireState(object, parent, name) { @@ -752,7 +750,9 @@ function wireState(object, parent, name) { object.stateName = name; for (let prop in object) { - if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') { continue; } + if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') { + continue; + } if (typeof object[prop] === 'object') { object[prop] = wireState(object[prop], object, name + '.' + prop); } diff --git a/addon/-record-data-rfc-private/system/normalize-link.js b/addon/-record-data-rfc-private/system/normalize-link.js index 59d9d6536e8..33e7a31ad97 100644 --- a/addon/-record-data-rfc-private/system/normalize-link.js +++ b/addon/-record-data-rfc-private/system/normalize-link.js @@ -12,8 +12,10 @@ */ export default function _normalizeLink(link) { switch (typeof link) { - case 'object': return link; - case 'string': return { href: link }; + case 'object': + return link; + case 'string': + return { href: link }; } return null; } diff --git a/addon/-record-data-rfc-private/system/promise-proxies.js b/addon/-record-data-rfc-private/system/promise-proxies.js index 07adef6523e..a34330d0c59 100644 --- a/addon/-record-data-rfc-private/system/promise-proxies.js +++ b/addon/-record-data-rfc-private/system/promise-proxies.js @@ -36,7 +36,7 @@ import { assert } from '@ember/debug'; @uses Ember.PromiseProxyMixin */ export const PromiseArray = ArrayProxy.extend(PromiseProxyMixin, { - meta: reads('content.meta') + meta: reads('content.meta'), }); /** @@ -72,41 +72,44 @@ export let PromiseObject = ObjectProxy.extend(PromiseProxyMixin); export function promiseObject(promise, label) { return PromiseObject.create({ - promise: Promise.resolve(promise, label) + promise: Promise.resolve(promise, label), }); } export function promiseArray(promise, label) { return PromiseArray.create({ - promise: Promise.resolve(promise, label) + promise: Promise.resolve(promise, label), }); } export const PromiseBelongsTo = PromiseObject.extend({ - // we don't proxy meta because we would need to proxy it to the relationship state container // however, meta on relationships does not trigger change notifications. // if you need relationship meta, you should do `record.belongsTo(relationshipName).meta()` meta: computed(function() { assert( 'You attempted to access meta on the promise for the async belongsTo relationship ' + - `${this.get('_belongsToState').internalModel.modelName}:${this.get('_belongsToState').key}'.` + - '\nUse `record.belongsTo(relationshipName).meta()` instead.', + `${this.get('_belongsToState').internalModel.modelName}:${ + this.get('_belongsToState').key + }'.` + + '\nUse `record.belongsTo(relationshipName).meta()` instead.', false ); }), reload() { - assert('You are trying to reload an async belongsTo before it has been created', this.get('content') !== undefined); + assert( + 'You are trying to reload an async belongsTo before it has been created', + this.get('content') !== undefined + ); let state = this.get('_belongsToState'); let key = state.key; let store = state.store; let resource = state.modelData.getResourceIdentifier(); let internalModel = store._internalModelForResource(resource); - return store.reloadBelongsTo(this, internalModel, key) - .then(() => this); - } + return store.reloadBelongsTo(this, internalModel, key).then(() => this); + }, }); /** @@ -135,7 +138,10 @@ export function proxyToContent(method) { export const PromiseManyArray = PromiseArray.extend({ reload() { - assert('You are trying to reload an async manyArray before it has been created', get(this, 'content')); + assert( + 'You are trying to reload an async manyArray before it has been created', + get(this, 'content') + ); this.set('promise', this.get('content').reload()); return this; }, @@ -150,11 +156,11 @@ export const PromiseManyArray = PromiseArray.extend({ off: proxyToContent('off'), - has: proxyToContent('has') + has: proxyToContent('has'), }); export function promiseManyArray(promise, label) { return PromiseManyArray.create({ - promise: Promise.resolve(promise, label) + promise: Promise.resolve(promise, label), }); } diff --git a/addon/-record-data-rfc-private/system/record-array-manager.js b/addon/-record-data-rfc-private/system/record-array-manager.js index b61d6289fe1..e8e3ae6c5b8 100644 --- a/addon/-record-data-rfc-private/system/record-array-manager.js +++ b/addon/-record-data-rfc-private/system/record-array-manager.js @@ -7,10 +7,7 @@ import { set, get } from '@ember/object'; import { run as emberRun } from '@ember/runloop'; import { assert } from '@ember/debug'; import cloneNull from './clone-null'; -import { - RecordArray, - AdapterPopulatedRecordArray -} from './record-arrays'; +import { RecordArray, AdapterPopulatedRecordArray } from './record-arrays'; const { _flush, @@ -20,8 +17,9 @@ const { createRecordArray, liveRecordArrayFor, recordDidChange, - unregisterRecordArray -} = heimdall.registerMonitor('recordArrayManager', + unregisterRecordArray, +} = heimdall.registerMonitor( + 'recordArrayManager', '_flush', 'array_remove', 'create', @@ -72,7 +70,7 @@ export default class RecordArrayManager { internalModel._pendingRecordArrayManagerFlush = true; let pending = this._pending; - let models = pending[modelName] = pending[modelName] || []; + let models = (pending[modelName] = pending[modelName] || []); if (models.push(internalModel) !== 1) { return; } @@ -123,7 +121,10 @@ export default class RecordArrayManager { } _syncLiveRecordArray(array, modelName) { - assert(`recordArrayManger.syncLiveRecordArray expects modelName not modelClass as the second param`, typeof modelName === 'string'); + assert( + `recordArrayManger.syncLiveRecordArray expects modelName not modelClass as the second param`, + typeof modelName === 'string' + ); let pending = this._pending[modelName]; let hasPendingChanges = Array.isArray(pending); let hasNoPotentialDeletions = !hasPendingChanges || pending.length === 0; @@ -177,7 +178,10 @@ export default class RecordArrayManager { @return {DS.RecordArray} */ liveRecordArrayFor(modelName) { - assert(`recordArrayManger.liveRecordArrayFor expects modelName not modelClass as the param`, typeof modelName === 'string'); + assert( + `recordArrayManger.liveRecordArrayFor expects modelName not modelClass as the param`, + typeof modelName === 'string' + ); heimdall.increment(liveRecordArrayFor); @@ -218,7 +222,10 @@ export default class RecordArrayManager { @return {DS.RecordArray} */ createRecordArray(modelName, content) { - assert(`recordArrayManger.createRecordArray expects modelName not modelClass as the param`, typeof modelName === 'string'); + assert( + `recordArrayManger.createRecordArray expects modelName not modelClass as the param`, + typeof modelName === 'string' + ); heimdall.increment(createRecordArray); let array = RecordArray.create({ @@ -226,7 +233,7 @@ export default class RecordArrayManager { content: A(content || []), store: this.store, isLoaded: true, - manager: this + manager: this, }); if (Array.isArray(content)) { @@ -246,7 +253,10 @@ export default class RecordArrayManager { */ createAdapterPopulatedRecordArray(modelName, query, internalModels, payload) { heimdall.increment(createAdapterPopulatedRecordArray); - assert(`recordArrayManger.createAdapterPopulatedRecordArray expects modelName not modelClass as the first param, received ${modelName}`, typeof modelName === 'string'); + assert( + `recordArrayManger.createAdapterPopulatedRecordArray expects modelName not modelClass as the first param, received ${modelName}`, + typeof modelName === 'string' + ); let array; if (Array.isArray(internalModels)) { @@ -259,7 +269,7 @@ export default class RecordArrayManager { isLoaded: true, isUpdating: false, meta: cloneNull(payload.meta), - links: cloneNull(payload.links) + links: cloneNull(payload.links), }); associateWithRecordArray(internalModels, array); @@ -269,7 +279,7 @@ export default class RecordArrayManager { query: query, content: A(), store: this.store, - manager: this + manager: this, }); } @@ -294,7 +304,6 @@ export default class RecordArrayManager { let removedFromAdapterPopulated = remove(this._adapterPopulatedRecordArrays, array); if (!removedFromAdapterPopulated) { - let liveRecordArrayForType = this._liveRecordArrays[modelName]; // unregister live record array if (liveRecordArrayForType) { @@ -305,12 +314,14 @@ export default class RecordArrayManager { } } - _associateWithRecordArray(internalModels, array) { + _associateWithRecordArray(internalModels, array) { associateWithRecordArray(internalModels, array); } willDestroy() { - Object.keys(this._liveRecordArrays).forEach(modelName => this._liveRecordArrays[modelName].destroy()); + Object.keys(this._liveRecordArrays).forEach(modelName => + this._liveRecordArrays[modelName].destroy() + ); this._adapterPopulatedRecordArrays.forEach(destroy); this.isDestroyed = true; } @@ -355,12 +366,16 @@ function updateLiveRecordArray(array, internalModels) { if (isDeleted) { modelsToRemove.push(internalModel); - recordArrays.delete(array) + recordArrays.delete(array); } } - if (modelsToAdd.length > 0) { array._pushInternalModels(modelsToAdd); } - if (modelsToRemove.length > 0) { array._removeInternalModels(modelsToRemove); } + if (modelsToAdd.length > 0) { + array._pushInternalModels(modelsToAdd); + } + if (modelsToRemove.length > 0) { + array._removeInternalModels(modelsToRemove); + } // return whether we performed an update. // Necessary until 3.5 allows us to finish off ember-data-filter support. diff --git a/addon/-record-data-rfc-private/system/record-arrays.js b/addon/-record-data-rfc-private/system/record-arrays.js index d65107ed72a..5439899ad81 100644 --- a/addon/-record-data-rfc-private/system/record-arrays.js +++ b/addon/-record-data-rfc-private/system/record-arrays.js @@ -2,10 +2,7 @@ @module ember-data */ -import RecordArray from "./record-arrays/record-array"; -import AdapterPopulatedRecordArray from "./record-arrays/adapter-populated-record-array"; +import RecordArray from './record-arrays/record-array'; +import AdapterPopulatedRecordArray from './record-arrays/adapter-populated-record-array'; -export { - RecordArray, - AdapterPopulatedRecordArray -}; +export { RecordArray, AdapterPopulatedRecordArray }; diff --git a/addon/-record-data-rfc-private/system/record-arrays/adapter-populated-record-array.js b/addon/-record-data-rfc-private/system/record-arrays/adapter-populated-record-array.js index 7ccf8e89085..d3cc1e68a91 100644 --- a/addon/-record-data-rfc-private/system/record-arrays/adapter-populated-record-array.js +++ b/addon/-record-data-rfc-private/system/record-arrays/adapter-populated-record-array.js @@ -1,8 +1,8 @@ import { once } from '@ember/runloop'; import { A } from '@ember/array'; import { get } from '@ember/object'; -import RecordArray from "./record-array"; -import cloneNull from "../clone-null"; +import RecordArray from './record-array'; +import cloneNull from '../clone-null'; /** Represents an ordered list of records whose order and membership is @@ -80,7 +80,7 @@ export default RecordArray.extend({ isLoaded: true, isUpdating: false, meta: cloneNull(payload.meta), - links: cloneNull(payload.links) + links: cloneNull(payload.links), }); this.manager._associateWithRecordArray(internalModels, this); @@ -88,5 +88,5 @@ export default RecordArray.extend({ // TODO: should triggering didLoad event be the last action of the runLoop? once(this, 'trigger', 'didLoad'); heimdall.stop(token); - } + }, }); diff --git a/addon/-record-data-rfc-private/system/record-arrays/record-array.js b/addon/-record-data-rfc-private/system/record-arrays/record-array.js index 71d2ffdef1c..78afefda737 100644 --- a/addon/-record-data-rfc-private/system/record-arrays/record-array.js +++ b/addon/-record-data-rfc-private/system/record-arrays/record-array.js @@ -7,8 +7,8 @@ import Evented from '@ember/object/evented'; import ArrayProxy from '@ember/array/proxy'; import { set, get, computed } from '@ember/object'; import { Promise } from 'rsvp'; -import { PromiseArray } from "../promise-proxies"; -import SnapshotRecordArray from "../snapshot-record-array"; +import { PromiseArray } from '../promise-proxies'; +import SnapshotRecordArray from '../snapshot-record-array'; /** A record array is an array that contains records of a certain modelName. The record @@ -53,7 +53,7 @@ export default ArrayProxy.extend(Evented, { @type Boolean */ this.isLoaded = this.isLoaded || false; - /** + /** The flag to signal a `RecordArray` is currently loading data. Example @@ -70,7 +70,7 @@ export default ArrayProxy.extend(Evented, { */ this.isUpdating = false; - /** + /** The store that created this record array. @property store @@ -82,7 +82,11 @@ export default ArrayProxy.extend(Evented, { }, replace() { - throw new Error(`The result of a server query (for all ${this.modelName} types) is immutable. To modify contents, use toArray()`); + throw new Error( + `The result of a server query (for all ${ + this.modelName + } types) is immutable. To modify contents, use toArray()` + ); }, /** @@ -131,13 +135,17 @@ export default ArrayProxy.extend(Evented, { @method update */ update() { - if (get(this, 'isUpdating')) { return this._updatingPromise; } + if (get(this, 'isUpdating')) { + return this._updatingPromise; + } this.set('isUpdating', true); let updatingPromise = this._update().finally(() => { this._updatingPromise = null; - if (this.get('isDestroying') || this.get('isDestroyed')) { return } + if (this.get('isDestroying') || this.get('isDestroyed')) { + return; + } this.set('isUpdating', false); }); @@ -197,8 +205,11 @@ export default ArrayProxy.extend(Evented, { */ save() { let promiseLabel = `DS: RecordArray#save ${this.modelName}`; - let promise = Promise.all(this.invoke('save'), promiseLabel) - .then(() => this, null, 'DS: RecordArray#save return RecordArray'); + let promise = Promise.all(this.invoke('save'), promiseLabel).then( + () => this, + null, + 'DS: RecordArray#save return RecordArray' + ); return PromiseArray.create({ promise }); }, @@ -251,5 +262,5 @@ export default ArrayProxy.extend(Evented, { */ _takeSnapshot() { return get(this, 'content').map(internalModel => internalModel.createSnapshot()); - } + }, }); diff --git a/addon/-record-data-rfc-private/system/references/belongs-to.js b/addon/-record-data-rfc-private/system/references/belongs-to.js index 8938e8265eb..29a679eea92 100644 --- a/addon/-record-data-rfc-private/system/references/belongs-to.js +++ b/addon/-record-data-rfc-private/system/references/belongs-to.js @@ -122,22 +122,31 @@ export default class BelongsToReference extends Reference { @return {Promise} A promise that resolves with the new value in this belongs-to relationship. */ push(objectOrPromise) { - return resolve(objectOrPromise).then((data) => { + return resolve(objectOrPromise).then(data => { let record; if (data instanceof Model) { if (isEnabled('ds-overhaul-references')) { - deprecate("BelongsToReference#push(DS.Model) is deprecated. Update relationship via `model.set('relationshipName', value)` instead.", false, { - id: 'ds.references.belongs-to.push-record', - until: '4.0.0' - }); + deprecate( + "BelongsToReference#push(DS.Model) is deprecated. Update relationship via `model.set('relationshipName', value)` instead.", + false, + { + id: 'ds.references.belongs-to.push-record', + until: '4.0.0', + } + ); } record = data; } else { record = this.store.push(data); } - assertPolymorphicType(this.internalModel, this.belongsToRelationship.relationshipMeta, record._internalModel, this.store); + assertPolymorphicType( + this.internalModel, + this.belongsToRelationship.relationshipMeta, + record._internalModel, + this.store + ); //TODO Igor cleanup, maybe move to relationship push this.belongsToRelationship.setCanonicalModelData(record._internalModel._modelData); @@ -246,7 +255,6 @@ export default class BelongsToReference extends Reference { return this.parentInternalModel.getBelongsTo(this.key); } - /** Triggers a reload of the value in this relationship. If the remoteType is `"link"` Ember Data will use the relationship link to @@ -286,13 +294,17 @@ export default class BelongsToReference extends Reference { reload() { let resource = this._resource(); if (resource && resource.links && resource.links.related) { - return this.store._fetchBelongsToLinkFromResource(resource, this.parentInternalModel, this.belongsToRelationship.relationshipMeta); + return this.store._fetchBelongsToLinkFromResource( + resource, + this.parentInternalModel, + this.belongsToRelationship.relationshipMeta + ); } if (resource && resource.data) { if (resource.data && (resource.data.id || resource.data.clientId)) { let internalModel = this.store._internalModelForResource(resource.data); if (internalModel.isLoaded()) { - return internalModel.reload().then((internalModel) => { + return internalModel.reload().then(internalModel => { if (internalModel) { return internalModel.getRecord(); } diff --git a/addon/-record-data-rfc-private/system/references/has-many.js b/addon/-record-data-rfc-private/system/references/has-many.js index f0a44b728b9..d74fe7871dc 100644 --- a/addon/-record-data-rfc-private/system/references/has-many.js +++ b/addon/-record-data-rfc-private/system/references/has-many.js @@ -69,13 +69,12 @@ export default class HasManyReference extends Reference { remoteType() { let value = this._resource(); if (value && value.links && value.links.related) { - return "link"; + return 'link'; } - return "ids"; + return 'ids'; } - /** `ids()` returns an array of the record ids in this relationship. @@ -113,14 +112,12 @@ export default class HasManyReference extends Reference { let ids = []; if (resource.data) { - ids = resource.data.map((data) => data.id); + ids = resource.data.map(data => data.id); } return ids; } - - /** `push` can be used to update the data in the relationship and Ember Data will treat the new data as the canonical value of this @@ -164,19 +161,24 @@ export default class HasManyReference extends Reference { @return {DS.ManyArray} */ push(objectOrPromise) { - return resolve(objectOrPromise).then((payload) => { + return resolve(objectOrPromise).then(payload => { let array = payload; - if (typeof payload === "object" && payload.data) { + if (typeof payload === 'object' && payload.data) { array = payload.data; } - let internalModels = array.map((obj) => { + let internalModels = array.map(obj => { let record = this.store.push(obj); if (DEBUG) { let relationshipMeta = this.hasManyRelationship.relationshipMeta; - assertPolymorphicType(this.internalModel, relationshipMeta, record._internalModel, this.store); + assertPolymorphicType( + this.internalModel, + relationshipMeta, + record._internalModel, + this.store + ); } return record._internalModel._modelData; }); @@ -198,7 +200,7 @@ export default class HasManyReference extends Reference { let members = this.hasManyRelationship.members.toArray(); //TODO Igor cleanup - return members.every((modelData) => { + return members.every(modelData => { let store = this.parentInternalModel.store; let internalModel = store._internalModelForModelData(modelData); return internalModel.isLoaded() === true; diff --git a/addon/-record-data-rfc-private/system/references/record.js b/addon/-record-data-rfc-private/system/references/record.js index 086945b3a22..56bb3338192 100644 --- a/addon/-record-data-rfc-private/system/references/record.js +++ b/addon/-record-data-rfc-private/system/references/record.js @@ -87,7 +87,7 @@ export default class RecordReference extends Reference { @return Promise a promise for the value (record or relationship) */ push(objectOrPromise) { - return resolve(objectOrPromise).then((data) => { + return resolve(objectOrPromise).then(data => { return this.store.push(data); }); } @@ -159,5 +159,4 @@ export default class RecordReference extends Reference { return this.load(); } - } diff --git a/addon/-record-data-rfc-private/system/references/reference.js b/addon/-record-data-rfc-private/system/references/reference.js index 6c54cf75ba1..a764bd83293 100644 --- a/addon/-record-data-rfc-private/system/references/reference.js +++ b/addon/-record-data-rfc-private/system/references/reference.js @@ -5,7 +5,7 @@ var Reference = function(store, internalModel) { }; Reference.prototype = { - constructor: Reference + constructor: Reference, }; /** @@ -50,10 +50,10 @@ Reference.prototype = { Reference.prototype.remoteType = function() { let value = this._resource(); if (value && value.links && value.links.related) { - return "link"; + return 'link'; } - return "id"; + return 'id'; }; /** diff --git a/addon/-record-data-rfc-private/system/relationships/belongs-to.js b/addon/-record-data-rfc-private/system/relationships/belongs-to.js index f979a8a7fc2..5cd2516357f 100644 --- a/addon/-record-data-rfc-private/system/relationships/belongs-to.js +++ b/addon/-record-data-rfc-private/system/relationships/belongs-to.js @@ -1,6 +1,6 @@ import { computed } from '@ember/object'; import { assert, warn, inspect } from '@ember/debug'; -import normalizeModelName from "../normalize-model-name"; +import normalizeModelName from '../normalize-model-name'; /** `DS.belongsTo` is used to define One-To-One and One-To-Many @@ -88,7 +88,12 @@ export default function belongsTo(modelName, options) { userEnteredModelName = normalizeModelName(userEnteredModelName); } - assert("The first argument to DS.belongsTo must be a string representing a model type key, not an instance of " + inspect(userEnteredModelName) + ". E.g., to define a relation to the Person model, use DS.belongsTo('person')", typeof userEnteredModelName === 'string' || typeof userEnteredModelName === 'undefined'); + assert( + 'The first argument to DS.belongsTo must be a string representing a model type key, not an instance of ' + + inspect(userEnteredModelName) + + ". E.g., to define a relation to the Person model, use DS.belongsTo('person')", + typeof userEnteredModelName === 'string' || typeof userEnteredModelName === 'undefined' + ); opts = opts || {}; @@ -98,21 +103,33 @@ export default function belongsTo(modelName, options) { options: opts, kind: 'belongsTo', name: 'Belongs To', - key: null + key: null, }; return computed({ get(key) { if (opts.hasOwnProperty('serialize')) { - warn(`You provided a serialize option on the "${key}" property in the "${this._internalModel.modelName}" class, this belongs in the serializer. See DS.Serializer and it's implementations https://emberjs.com/api/data/classes/DS.Serializer.html`, false, { - id: 'ds.model.serialize-option-in-belongs-to' - }); + warn( + `You provided a serialize option on the "${key}" property in the "${ + this._internalModel.modelName + }" class, this belongs in the serializer. See DS.Serializer and it's implementations https://emberjs.com/api/data/classes/DS.Serializer.html`, + false, + { + id: 'ds.model.serialize-option-in-belongs-to', + } + ); } if (opts.hasOwnProperty('embedded')) { - warn(`You provided an embedded option on the "${key}" property in the "${this._internalModel.modelName}" class, this belongs in the serializer. See DS.EmbeddedRecordsMixin https://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html`, false, { - id: 'ds.model.embedded-option-in-belongs-to' - }); + warn( + `You provided an embedded option on the "${key}" property in the "${ + this._internalModel.modelName + }" class, this belongs in the serializer. See DS.EmbeddedRecordsMixin https://emberjs.com/api/data/classes/DS.EmbeddedRecordsMixin.html`, + false, + { + id: 'ds.model.embedded-option-in-belongs-to', + } + ); } return this._internalModel.getBelongsTo(key); @@ -121,6 +138,6 @@ export default function belongsTo(modelName, options) { this._internalModel.setDirtyBelongsTo(key, value); return this._internalModel.getBelongsTo(key); - } + }, }).meta(meta); } diff --git a/addon/-record-data-rfc-private/system/relationships/ext.js b/addon/-record-data-rfc-private/system/relationships/ext.js index 058de16a08c..d1087e680a9 100644 --- a/addon/-record-data-rfc-private/system/relationships/ext.js +++ b/addon/-record-data-rfc-private/system/relationships/ext.js @@ -3,14 +3,13 @@ import { computed, get } from '@ember/object'; import MapWithDefault from '../map-with-default'; import Map from '../map'; import { assert } from '@ember/debug'; -import { - typeForRelationshipMeta, - relationshipFromMeta -} from "../relationship-meta"; +import { typeForRelationshipMeta, relationshipFromMeta } from '../relationship-meta'; export const relationshipsDescriptor = computed(function() { let map = new MapWithDefault({ - defaultValue() { return []; } + defaultValue() { + return []; + }, }); let relationshipsByName = get(this, 'relationshipsByName'); @@ -36,10 +35,18 @@ export const relatedTypesDescriptor = computed(function() { meta.key = name; modelName = typeForRelationshipMeta(meta); - assert(`You specified a hasMany (${meta.type}) on ${meta.parentType} but ${meta.type} was not found.`, modelName); + assert( + `You specified a hasMany (${meta.type}) on ${meta.parentType} but ${ + meta.type + } was not found.`, + modelName + ); if (!types.includes(modelName)) { - assert(`Trying to sideload ${name} on ${this.toString()} but the type doesn't exist.`, !!modelName); + assert( + `Trying to sideload ${name} on ${this.toString()} but the type doesn't exist.`, + !!modelName + ); types.push(modelName); } } @@ -65,7 +72,7 @@ export const relationshipsByNameDescriptor = computed(function() { let rels = get(this, 'relationshipsObject'); let relationships = Object.keys(rels); - for (let i=0; i < relationships.length; i++) { + for (let i = 0; i < relationships.length; i++) { let key = relationships[i]; let value = rels[key]; diff --git a/addon/-record-data-rfc-private/system/relationships/has-many.js b/addon/-record-data-rfc-private/system/relationships/has-many.js index be80f3bf32b..b4e782bbf49 100644 --- a/addon/-record-data-rfc-private/system/relationships/has-many.js +++ b/addon/-record-data-rfc-private/system/relationships/has-many.js @@ -3,7 +3,7 @@ */ import { computed } from '@ember/object'; import { assert, inspect } from '@ember/debug'; -import normalizeModelName from "../normalize-model-name"; +import normalizeModelName from '../normalize-model-name'; /** `DS.hasMany` is used to define One-To-Many and Many-To-Many @@ -117,7 +117,12 @@ export default function hasMany(type, options) { type = undefined; } - assert(`The first argument to DS.hasMany must be a string representing a model type key, not an instance of ${inspect(type)}. E.g., to define a relation to the Comment model, use DS.hasMany('comment')`, typeof type === 'string' || typeof type === 'undefined'); + assert( + `The first argument to DS.hasMany must be a string representing a model type key, not an instance of ${inspect( + type + )}. E.g., to define a relation to the Comment model, use DS.hasMany('comment')`, + typeof type === 'string' || typeof type === 'undefined' + ); options = options || {}; @@ -135,7 +140,7 @@ export default function hasMany(type, options) { isRelationship: true, kind: 'hasMany', name: 'Has Many', - key: null + key: null, }; return computed({ @@ -147,6 +152,6 @@ export default function hasMany(type, options) { internalModel.setDirtyHasMany(key, records); return internalModel.getHasMany(key); - } + }, }).meta(meta); } diff --git a/addon/-record-data-rfc-private/system/relationships/state/belongs-to.js b/addon/-record-data-rfc-private/system/relationships/state/belongs-to.js index 85d46804c97..231c9e78d5f 100644 --- a/addon/-record-data-rfc-private/system/relationships/state/belongs-to.js +++ b/addon/-record-data-rfc-private/system/relationships/state/belongs-to.js @@ -1,7 +1,7 @@ import { assert, inspect } from '@ember/debug'; import { assertPolymorphicType } from 'ember-data/-debug'; import { isNone } from '@ember/utils'; -import Relationship from "./relationship"; +import Relationship from './relationship'; export default class BelongsToRelationship extends Relationship { constructor(store, inverseKey, relationshipMeta, modelData, inverseIsAsync) { @@ -33,7 +33,9 @@ export default class BelongsToRelationship extends Relationship { } setInitialCanonicalModelData(modelData) { - if (!modelData) { return; } + if (!modelData) { + return; + } // When we initialize a belongsTo relationship, we want to avoid work like // notifying our internalModel that we've "changed" and excessive thrash on @@ -45,7 +47,9 @@ export default class BelongsToRelationship extends Relationship { } addCanonicalModelData(modelData) { - if (this.canonicalMembers.has(modelData)) { return;} + if (this.canonicalMembers.has(modelData)) { + return; + } if (this.canonicalState) { this.removeCanonicalModelData(this.canonicalState); @@ -73,7 +77,6 @@ export default class BelongsToRelationship extends Relationship { } } - removeCompletelyFromInverse() { super.removeCompletelyFromInverse(); @@ -95,7 +98,9 @@ export default class BelongsToRelationship extends Relationship { } addModelData(modelData) { - if (this.members.has(modelData)) { return; } + if (this.members.has(modelData)) { + return; + } // TODO Igor cleanup assertPolymorphicType(this.modelData, this.relationshipMeta, modelData, this.store); @@ -111,13 +116,18 @@ export default class BelongsToRelationship extends Relationship { setRecordPromise(newPromise) { let content = newPromise.get && newPromise.get('content'); - assert("You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.", content !== undefined); + assert( + 'You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.', + content !== undefined + ); // TODO Igor deal with this this.setModelData(content ? content._internalModel._modelData : content); } removeModelDataFromOwn(modelData) { - if (!this.members.has(modelData)) { return;} + if (!this.members.has(modelData)) { + return; + } this.inverseModelData = null; super.removeModelDataFromOwn(modelData); this.notifyBelongsToChanged(); @@ -132,11 +142,18 @@ export default class BelongsToRelationship extends Relationship { notifyBelongsToChanged() { let modelData = this.modelData; let storeWrapper = this.modelData.storeWrapper; - storeWrapper.notifyBelongsToChange(modelData.modelName, modelData.id, modelData.clientId, this.key); + storeWrapper.notifyBelongsToChange( + modelData.modelName, + modelData.id, + modelData.clientId, + this.key + ); } removeCanonicalModelDataFromOwn(modelData) { - if (!this.canonicalMembers.has(modelData)) { return;} + if (!this.canonicalMembers.has(modelData)) { + return; + } this.canonicalState = null; super.removeCanonicalModelDataFromOwn(modelData); } @@ -157,8 +174,8 @@ export default class BelongsToRelationship extends Relationship { } if (this.link) { payload.links = { - related: this.link - } + related: this.link, + }; } if (data !== undefined) { payload.data = data; @@ -182,7 +199,14 @@ export default class BelongsToRelationship extends Relationship { if (isNone(data)) { modelData = null; } - assert(`Ember Data expected the data for the ${this.key} relationship on a ${this.modelData.toString()} to be in a JSON API format and include an \`id\` and \`type\` property but it found ${inspect(data)}. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, data === null || data.id !== undefined && data.type !== undefined); + assert( + `Ember Data expected the data for the ${ + this.key + } relationship on a ${this.modelData.toString()} to be in a JSON API format and include an \`id\` and \`type\` property but it found ${inspect( + data + )}. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`, + data === null || (data.id !== undefined && data.type !== undefined) + ); if (modelData !== null) { modelData = this.modelData.storeWrapper.modelDataFor(data.type, data.id); diff --git a/addon/-record-data-rfc-private/system/relationships/state/create.js b/addon/-record-data-rfc-private/system/relationships/state/create.js index fa69818b8c8..61e20400804 100644 --- a/addon/-record-data-rfc-private/system/relationships/state/create.js +++ b/addon/-record-data-rfc-private/system/relationships/state/create.js @@ -1,14 +1,23 @@ -import ManyRelationship from "./has-many"; -import BelongsToRelationship from "./belongs-to"; +import ManyRelationship from './has-many'; +import BelongsToRelationship from './belongs-to'; function createRelationshipFor(relationshipMeta, store, modelData, key) { let inverseKey = modelData.storeWrapper.inverseForRelationship(modelData.modelName, key); - let inverseIsAsync = modelData.storeWrapper.inverseIsAsyncForRelationship(modelData.modelName, key); + let inverseIsAsync = modelData.storeWrapper.inverseIsAsyncForRelationship( + modelData.modelName, + key + ); if (relationshipMeta.kind === 'hasMany') { return new ManyRelationship(store, inverseKey, relationshipMeta, modelData, inverseIsAsync); } else { - return new BelongsToRelationship(store, inverseKey, relationshipMeta, modelData, inverseIsAsync); + return new BelongsToRelationship( + store, + inverseKey, + relationshipMeta, + modelData, + inverseIsAsync + ); } } @@ -35,10 +44,17 @@ export default class Relationships { if (!relationship) { let modelData = this.modelData; - let rel = this.modelData.storeWrapper.relationshipsDefinitionFor(this.modelData.modelName)[key]; + let rel = this.modelData.storeWrapper.relationshipsDefinitionFor(this.modelData.modelName)[ + key + ]; if (rel) { - relationship = relationships[key] = createRelationshipFor(rel, modelData.store, modelData, key); + relationship = relationships[key] = createRelationshipFor( + rel, + modelData.store, + modelData, + key + ); } } diff --git a/addon/-record-data-rfc-private/system/relationships/state/has-many.js b/addon/-record-data-rfc-private/system/relationships/state/has-many.js index bf3514fbabb..2a0e2df719e 100755 --- a/addon/-record-data-rfc-private/system/relationships/state/has-many.js +++ b/addon/-record-data-rfc-private/system/relationships/state/has-many.js @@ -44,7 +44,12 @@ export default class ManyRelationship extends Relationship { notifyManyArrayIsStale() { let storeWrapper = this.modelData.storeWrapper; let modelData = this.modelData; - storeWrapper.notifyPropertyChange(modelData.modelName, modelData.id, modelData.clientId, this.key); + storeWrapper.notifyPropertyChange( + modelData.modelName, + modelData.id, + modelData.clientId, + this.key + ); } addModelData(modelData, idx) { @@ -112,7 +117,7 @@ export default class ManyRelationship extends Relationship { // been 'acknowleged' to be in the relationship via a store.push) //TODO Igor deal with this - (modelData) => modelData.isNew() && toSet.indexOf(modelData) === -1 + modelData => modelData.isNew() && toSet.indexOf(modelData) === -1 ); toSet = toSet.concat(newModelDatas); @@ -140,7 +145,7 @@ export default class ManyRelationship extends Relationship { // TODO Igor consider making direct to remove the indirection // We are not lazily accessing the manyArray here because the change is coming from app side this.notifyHasManyChanged(); - // this.manyArray.flushCanonical(this.currentState); + // this.manyArray.flushCanonical(this.currentState); } notifyRecordRelationshipAdded() { @@ -153,7 +158,9 @@ export default class ManyRelationship extends Relationship { let modelDatasSet = setForArray(modelDatas); members.forEach(member => { - if (modelDatasSet.has(member)) { return; } + if (modelDatasSet.has(member)) { + return; + } modelDatasToRemove.push(member); }); @@ -172,7 +179,7 @@ export default class ManyRelationship extends Relationship { return; } - for (let i = 0; i< modelDatas.length; i++) { + for (let i = 0; i < modelDatas.length; i++) { let modelData = modelDatas[i]; if (this.canonicalMembers.has(modelData)) { continue; @@ -189,18 +196,23 @@ export default class ManyRelationship extends Relationship { notifyHasManyChanged() { let modelData = this.modelData; let storeWrapper = this.modelData.storeWrapper; - storeWrapper.notifyHasManyChange(modelData.modelName, modelData.id, modelData.clientId, this.key); + storeWrapper.notifyHasManyChange( + modelData.modelName, + modelData.id, + modelData.clientId, + this.key + ); } getData() { let payload = {}; if (this.hasAnyRelationshipData) { - payload.data = this.currentState.map((modelData) => modelData.getResourceIdentifier()); + payload.data = this.currentState.map(modelData => modelData.getResourceIdentifier()); } if (this.link) { payload.links = { - related: this.link - } + related: this.link, + }; } if (this.meta) { payload.meta = this.meta; @@ -248,7 +260,7 @@ function setForArray(array) { var set = new OrderedSet(); if (array) { - for (var i=0, l=array.length; i { + this.forAllMembers(inverseModelData => { let relationship = inverseModelData._relationships.get(this.inverseKey); relationship.inverseDidDematerialize(this.modelData); }); @@ -275,7 +277,7 @@ export default class Relationship { removeModelDatas(modelDatas) { heimdall.increment(removeModelDatas); - modelDatas.forEach((modelData) => this.removeModelData(modelData)); + modelDatas.forEach(modelData => this.removeModelData(modelData)); } addModelDatas(modelDatas, idx) { @@ -290,9 +292,9 @@ export default class Relationship { addCanonicalModelDatas(modelDatas, idx) { heimdall.increment(addCanonicalModelDatas); - for (let i=0; i true */ if (hasRelationshipDataProperty) { - let relationshipIsEmpty = payload.data === null || - (Array.isArray(payload.data) && payload.data.length === 0); + let relationshipIsEmpty = + payload.data === null || (Array.isArray(payload.data) && payload.data.length === 0); this.setHasAnyRelationshipData(true); this.setRelationshipIsStale(false); diff --git a/addon/-record-data-rfc-private/system/snapshot.js b/addon/-record-data-rfc-private/system/snapshot.js index daeb46e2d3e..f61b9591660 100644 --- a/addon/-record-data-rfc-private/system/snapshot.js +++ b/addon/-record-data-rfc-private/system/snapshot.js @@ -91,7 +91,7 @@ export default class Snapshot { let record = this.record; attributes = this.__attributes = Object.create(null); - record.eachAttribute((keyName) => attributes[keyName] = get(record, keyName)); + record.eachAttribute(keyName => (attributes[keyName] = get(record, keyName))); } return attributes; @@ -131,7 +131,9 @@ export default class Snapshot { if (keyName in this._attributes) { return this._attributes[keyName]; } - throw new EmberError("Model '" + inspect(this.record) + "' has no attribute named '" + keyName + "' defined."); + throw new EmberError( + "Model '" + inspect(this.record) + "' has no attribute named '" + keyName + "' defined." + ); } /** @@ -169,7 +171,7 @@ export default class Snapshot { let changedAttributes = Object.create(null); let changedAttributeKeys = Object.keys(this._changedAttributes); - for (let i=0, length = changedAttributeKeys.length; i < length; i++) { + for (let i = 0, length = changedAttributeKeys.length; i < length; i++) { let key = changedAttributeKeys[i]; changedAttributes[key] = this._changedAttributes[key].slice(); } @@ -229,7 +231,13 @@ export default class Snapshot { let relationshipMeta = store._relationshipMetaFor(this.modelName, null, keyName); if (!(relationshipMeta && relationshipMeta.kind === 'belongsTo')) { - throw new EmberError("Model '" + inspect(this.record) + "' has no belongsTo relationship named '" + keyName + "' defined."); + throw new EmberError( + "Model '" + + inspect(this.record) + + "' has no belongsTo relationship named '" + + keyName + + "' defined." + ); } relationship = this._internalModel._modelData._relationships.get(keyName); @@ -305,7 +313,13 @@ export default class Snapshot { let store = this._internalModel.store; let relationshipMeta = store._relationshipMetaFor(this.modelName, null, keyName); if (!(relationshipMeta && relationshipMeta.kind === 'hasMany')) { - throw new EmberError("Model '" + inspect(this.record) + "' has no hasMany relationship named '" + keyName + "' defined."); + throw new EmberError( + "Model '" + + inspect(this.record) + + "' has no hasMany relationship named '" + + keyName + + "' defined." + ); } relationship = this._internalModel._modelData._relationships.get(keyName); @@ -314,7 +328,7 @@ export default class Snapshot { if (value.data) { results = []; - value.data.forEach((member) => { + value.data.forEach(member => { let internalModel = store._internalModelForResource(member); if (!internalModel.isDeleted()) { if (ids) { diff --git a/addon/-record-data-rfc-private/system/store.js b/addon/-record-data-rfc-private/system/store.js index 98d66becabf..f0bc6a7ff38 100644 --- a/addon/-record-data-rfc-private/system/store.js +++ b/addon/-record-data-rfc-private/system/store.js @@ -17,25 +17,22 @@ import { instrument } from 'ember-data/-debug'; import { assert, deprecate, warn, inspect } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; import Model from './model/model'; -import normalizeModelName from "./normalize-model-name"; +import normalizeModelName from './normalize-model-name'; import IdentityMap from './identity-map'; import ModelDataWrapper from './store/model-data-wrapper'; -import { - promiseArray, - promiseObject -} from "./promise-proxies"; +import { promiseArray, promiseObject } from './promise-proxies'; import { _bind, _guard, _objectIsAlive, guardDestroyedStore, - incrementRequestCount -} from "./store/common"; + incrementRequestCount, +} from './store/common'; -import { normalizeResponseHelper } from "./store/serializer-response"; -import { serializerForAdapter } from "./store/serializers"; +import { normalizeResponseHelper } from './store/serializer-response'; +import { serializerForAdapter } from './store/serializers'; import { _find, @@ -44,14 +41,14 @@ import { _findBelongsTo, _findAll, _query, - _queryRecord -} from "./store/finders"; + _queryRecord, +} from './store/finders'; import { getOwner } from '../utils'; -import coerceId from "./coerce-id"; -import RecordArrayManager from "./record-array-manager"; -import InternalModel from "./model/internal-model"; -import ModelData from "./model/model-data"; +import coerceId from './coerce-id'; +import RecordArrayManager from './record-array-manager'; +import InternalModel from './model/internal-model'; +import ModelData from './model/model-data'; import edBackburner from './backburner'; const badIdFormatAssertion = '`id` passed to `findRecord()` has to be non-empty string or number'; @@ -97,8 +94,9 @@ const { peekAll, peekRecord, serializerFor, - _internalModelsFor -} = heimdall.registerMonitor('store', + _internalModelsFor, +} = heimdall.registerMonitor( + 'store', '_generateId', '_internalModelForId', '_load', @@ -187,7 +185,6 @@ const { @extends Ember.Service */ Store = Service.extend({ - /** @method init @private @@ -219,9 +216,12 @@ Store = Service.extend({ // used for coalescing internal model updates this._updatedInternalModels = []; - // used to keep track of all the find requests that need to be coalesced - this._pendingFetch = new MapWithDefault({ defaultValue() { return []; } }); + this._pendingFetch = new MapWithDefault({ + defaultValue() { + return []; + }, + }); this._adapterCache = Object.create(null); this._serializerCache = Object.create(null); @@ -268,7 +268,10 @@ Store = Service.extend({ defaultAdapter: computed('adapter', function() { let adapter = get(this, 'adapter'); - assert('You tried to set `adapter` property to an instance of `DS.Adapter`, where it should be a name', typeof adapter === 'string'); + assert( + 'You tried to set `adapter` property to an instance of `DS.Adapter`, where it should be a name', + typeof adapter === 'string' + ); return this.adapterFor(adapter); }), @@ -306,8 +309,14 @@ Store = Service.extend({ @return {DS.Model} record */ createRecord(modelName, inputProperties) { - assert(`You need to pass a model name to the store's createRecord method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's createRecord method`, + isPresent(modelName) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); // This is wrapped in a `run.join` so that in test environments users do not need to manually wrap // calls to `createRecord`. The run loop usage here is because we batch the joining and updating @@ -421,12 +430,30 @@ Store = Service.extend({ // The default `model` hook in 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. - assert(`Using store.find(type) has been removed. Use store.findAll(modelName) to retrieve all records for a given type.`, arguments.length !== 1); - assert(`Calling store.find(modelName, id, { preload: preload }) is no longer supported. Use store.findRecord(modelName, id, { preload: preload }) instead.`, !options); - assert(`You need to pass the model name and id to the store's find method`, arguments.length === 2); - assert(`You cannot pass '${id}' as id to the store's find method`, typeof id === 'string' || typeof id === 'number'); - assert(`Calling store.find() with a query object is no longer supported. Use store.query() instead.`, typeof id !== 'object'); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Using store.find(type) has been removed. Use store.findAll(modelName) to retrieve all records for a given type.`, + arguments.length !== 1 + ); + assert( + `Calling store.find(modelName, id, { preload: preload }) is no longer supported. Use store.findRecord(modelName, id, { preload: preload }) instead.`, + !options + ); + assert( + `You need to pass the model name and id to the store's find method`, + arguments.length === 2 + ); + assert( + `You cannot pass '${id}' as id to the store's find method`, + typeof id === 'string' || typeof id === 'number' + ); + assert( + `Calling store.find() with a query object is no longer supported. Use store.query() instead.`, + typeof id !== 'object' + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); return this.findRecord(modelName, id); }, @@ -654,8 +681,14 @@ Store = Service.extend({ */ findRecord(modelName, id, options) { assert(`You need to pass a model name to the store's findRecord method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); - assert(badIdFormatAssertion, (typeof id === 'string' && id.length > 0) || (typeof id === 'number' && !isNaN(id))); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); + assert( + badIdFormatAssertion, + (typeof id === 'string' && id.length > 0) || (typeof id === 'number' && !isNaN(id)) + ); let normalizedModelName = normalizeModelName(modelName); @@ -668,7 +701,10 @@ Store = Service.extend({ let fetchedInternalModel = this._findRecord(internalModel, options); - return promiseRecord(fetchedInternalModel, `DS: Store#findRecord ${normalizedModelName} with id: ${id}`); + return promiseRecord( + fetchedInternalModel, + `DS: Store#findRecord ${normalizedModelName} with id: ${id}` + ); }, _findRecord(internalModel, options) { @@ -705,7 +741,10 @@ Store = Service.extend({ let fetchedInternalModel = this._findEmptyInternalModel(internalModel, options); - return promiseRecord(fetchedInternalModel, `DS: Store#findRecord ${internalModel.modelName} with id: ${internalModel.id}`); + return promiseRecord( + fetchedInternalModel, + `DS: Store#findRecord ${internalModel.modelName} with id: ${internalModel.id}` + ); }, _findEmptyInternalModel(internalModel, options) { @@ -733,7 +772,10 @@ Store = Service.extend({ */ findByIds(modelName, ids) { assert(`You need to pass a model name to the store's findByIds method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let promises = new Array(ids.length); @@ -743,7 +785,9 @@ Store = Service.extend({ promises[i] = this.findRecord(normalizedModelName, ids[i]); } - return promiseArray(RSVP.all(promises).then(A, null, `DS: Store#findByIds of ${normalizedModelName} complete`)); + return promiseArray( + RSVP.all(promises).then(A, null, `DS: Store#findByIds of ${normalizedModelName} complete`) + ); }, /** @@ -761,7 +805,10 @@ Store = Service.extend({ let adapter = this.adapterFor(modelName); assert(`You tried to find a record but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to find a record but your adapter (for ${modelName}) does not implement 'findRecord'`, typeof adapter.findRecord === 'function'); + assert( + `You tried to find a record but your adapter (for ${modelName}) does not implement 'findRecord'`, + typeof adapter.findRecord === 'function' + ); return _find(adapter, this, internalModel.type, internalModel.id, internalModel, options); }, @@ -786,7 +833,7 @@ Store = Service.extend({ let pendingFetchItem = { internalModel, resolver, - options + options, }; let promise = resolver.promise; @@ -841,7 +888,7 @@ Store = Service.extend({ let recordFetch = store._fetchRecord( recordResolverPair.internalModel, recordResolverPair.options - ); // TODO adapter options + ); // TODO adapter options recordResolverPair.resolver.resolve(recordFetch); } @@ -878,7 +925,7 @@ Store = Service.extend({ '" ]', false, { - id: 'ds.store.missing-records-from-adapter' + id: 'ds.store.missing-records-from-adapter', } ); rejectInternalModels(missingInternalModels); @@ -891,7 +938,12 @@ Store = Service.extend({ let pair = seeking[internalModel.id]; if (pair) { - pair.resolver.reject(error || new Error(`Expected: '${internalModel}' to be present in the adapter provided payload, but it was not found.`)); + pair.resolver.reject( + error || + new Error( + `Expected: '${internalModel}' to be present in the adapter provided payload, but it was not found.` + ) + ); } } } @@ -936,12 +988,15 @@ Store = Service.extend({ .catch(function(error) { rejectInternalModels(groupedInternalModels, error); }); - }(groupedInternalModels)); + })(groupedInternalModels); } else if (ids.length === 1) { var pair = seeking[groupedInternalModels[0].id]; _fetchRecord(pair); } else { - assert("You cannot return an empty array from adapter's method groupRecordsForFindMany", false); + assert( + "You cannot return an empty array from adapter's method groupRecordsForFindMany", + false + ); } } } else { @@ -1020,8 +1075,14 @@ Store = Service.extend({ peekRecord(modelName, id) { heimdall.increment(peekRecord); assert(`You need to pass a model name to the store's peekRecord method`, isPresent(modelName)); - assert(`You need to pass both a model name and id to the store's peekRecord method`, isPresent(modelName) && isPresent(id)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass both a model name and id to the store's peekRecord method`, + isPresent(modelName) && isPresent(id) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); if (this.hasRecordForId(normalizedModelName, id)) { @@ -1050,7 +1111,10 @@ Store = Service.extend({ assert(`You cannot reload a record without an ID`, id); assert(`You tried to reload a record but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to reload a record but your adapter does not implement 'findRecord'`, typeof adapter.findRecord === 'function' || typeof adapter.find === 'function'); + assert( + `You tried to reload a record but your adapter does not implement 'findRecord'`, + typeof adapter.findRecord === 'function' || typeof adapter.find === 'function' + ); return this._scheduleFetch(internalModel, options); }, @@ -1075,8 +1139,14 @@ Store = Service.extend({ @return {Boolean} */ hasRecordForId(modelName, id) { - assert(`You need to pass a model name to the store's hasRecordForId method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's hasRecordForId method`, + isPresent(modelName) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); @@ -1098,12 +1168,14 @@ Store = Service.extend({ */ recordForId(modelName, id) { assert(`You need to pass a model name to the store's recordForId method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); return this._internalModelForId(modelName, id).getRecord(); }, - // directly get an internal model from ID map if it is there, without doing any // processing _getInternalModelForId(modelName, id, clientId) { @@ -1140,8 +1212,6 @@ Store = Service.extend({ return this._buildInternalModel(modelName, trueId, null, clientId); }, - - /** @method findMany @private @@ -1158,7 +1228,6 @@ Store = Service.extend({ return Promise.all(finds); }, - /** If a relationship was originally populated by the adapter as a link (as opposed to a list of IDs), this method is called when the @@ -1180,8 +1249,16 @@ Store = Service.extend({ findHasMany(internalModel, link, relationship) { let adapter = this.adapterFor(internalModel.modelName); - assert(`You tried to load a hasMany relationship but you have no adapter (for ${internalModel.modelName})`, adapter); - assert(`You tried to load a hasMany relationship from a specified 'link' in the original payload but your adapter does not implement 'findHasMany'`, typeof adapter.findHasMany === 'function'); + assert( + `You tried to load a hasMany relationship but you have no adapter (for ${ + internalModel.modelName + })`, + adapter + ); + assert( + `You tried to load a hasMany relationship from a specified 'link' in the original payload but your adapter does not implement 'findHasMany'`, + typeof adapter.findHasMany === 'function' + ); return _findHasMany(adapter, this, internalModel, link, relationship); }, @@ -1196,36 +1273,41 @@ Store = Service.extend({ hasRelatedResources, hasDematerializedInverse, hasAnyRelationshipData, - relationshipIsEmpty + relationshipIsEmpty, } = resource._relationship; - let shouldFindViaLink = resource.links && resource.links.related - && (hasDematerializedInverse || relationshipIsStale || + let shouldFindViaLink = + resource.links && + resource.links.related && + (hasDematerializedInverse || + relationshipIsStale || (!hasRelatedResources && !relationshipIsEmpty)); // fetch via link if (shouldFindViaLink) { - return this.findHasMany(parentInternalModel, resource.links.related, relationshipMeta).then(internalModels => { - let payload = { data: internalModels.map((im) => im._modelData.getResourceIdentifier()) }; - if (internalModels.meta !== undefined) { - payload.meta = internalModels.meta; + return this.findHasMany(parentInternalModel, resource.links.related, relationshipMeta).then( + internalModels => { + let payload = { data: internalModels.map(im => im._modelData.getResourceIdentifier()) }; + if (internalModels.meta !== undefined) { + payload.meta = internalModels.meta; + } + parentInternalModel.linkWasLoadedForRelationship(relationshipMeta.key, payload); + return internalModels; } - parentInternalModel.linkWasLoadedForRelationship(relationshipMeta.key, payload); - return internalModels; - }); + ); } - let preferLocalCache = hasAnyRelationshipData && + let preferLocalCache = + hasAnyRelationshipData && // hasRelatedResources && !relationshipIsEmpty; - let hasLocalPartialData = hasDematerializedInverse || - (relationshipIsEmpty && - Array.isArray(resource.data) && - resource.data.length > 0); + let hasLocalPartialData = + hasDematerializedInverse || + (relationshipIsEmpty && Array.isArray(resource.data) && resource.data.length > 0); // fetch using data, pulling from local cache if possible if (!relationshipIsStale && (preferLocalCache || hasLocalPartialData)) { - let internalModels = resource.data.map((json) => this._internalModelForResource(json)); + let internalModels = resource.data.map(json => this._internalModelForResource(json)); return this.findMany(internalModels); } @@ -1234,7 +1316,7 @@ Store = Service.extend({ // fetch by data if (hasData || hasLocalPartialData) { - let internalModels = resource.data.map((json) => this._internalModelForResource(json)); + let internalModels = resource.data.map(json => this._internalModelForResource(json)); return this._scheduleFetchMany(internalModels); } @@ -1247,12 +1329,11 @@ Store = Service.extend({ _getHasManyByJsonApiResource(resource) { let internalModels = []; if (resource && resource.data) { - internalModels = resource.data.map((reference) => this._internalModelForResource(reference)); + internalModels = resource.data.map(reference => this._internalModelForResource(reference)); } return internalModels; }, - /** @method findBelongsTo @private @@ -1264,8 +1345,16 @@ Store = Service.extend({ findBelongsTo(internalModel, link, relationship) { let adapter = this.adapterFor(internalModel.modelName); - assert(`You tried to load a belongsTo relationship but you have no adapter (for ${internalModel.modelName})`, adapter); - assert(`You tried to load a belongsTo relationship from a specified 'link' in the original payload but your adapter does not implement 'findBelongsTo'`, typeof adapter.findBelongsTo === 'function'); + assert( + `You tried to load a belongsTo relationship but you have no adapter (for ${ + internalModel.modelName + })`, + adapter + ); + assert( + `You tried to load a belongsTo relationship from a specified 'link' in the original payload but your adapter does not implement 'findBelongsTo'`, + typeof adapter.findBelongsTo === 'function' + ); return _findBelongsTo(adapter, this, internalModel, link, relationship); }, @@ -1275,15 +1364,17 @@ Store = Service.extend({ // should we warn here, not sure cause its an internal method return RSVP.resolve(null); } - return this.findBelongsTo(parentInternalModel, resource.links.related, relationshipMeta).then((internalModel) => { - let response = internalModel && internalModel._modelData.getResourceIdentifier(); - parentInternalModel.linkWasLoadedForRelationship(relationshipMeta.key, { data: response }); - if (internalModel === null) { - return null; + return this.findBelongsTo(parentInternalModel, resource.links.related, relationshipMeta).then( + internalModel => { + let response = internalModel && internalModel._modelData.getResourceIdentifier(); + parentInternalModel.linkWasLoadedForRelationship(relationshipMeta.key, { data: response }); + if (internalModel === null) { + return null; + } + // TODO Igor this doesn't seem like the right boundary, probably the caller method should extract the record out + return internalModel.getRecord(); } - // TODO Igor this doesn't seem like the right boundary, probably the caller method should extract the record out - return internalModel.getRecord(); - }); + ); }, _findBelongsToByJsonApiResource(resource, parentInternalModel, relationshipMeta) { @@ -1296,11 +1387,14 @@ Store = Service.extend({ hasRelatedResources, hasDematerializedInverse, hasAnyRelationshipData, - relationshipIsEmpty + relationshipIsEmpty, } = resource._relationship; - let shouldFindViaLink = resource.links && resource.links.related - && (hasDematerializedInverse || relationshipIsStale || + let shouldFindViaLink = + resource.links && + resource.links.related && + (hasDematerializedInverse || + relationshipIsStale || (!hasRelatedResources && !relationshipIsEmpty)); // fetch via link @@ -1308,11 +1402,8 @@ Store = Service.extend({ return this._fetchBelongsToLinkFromResource(resource, parentInternalModel, relationshipMeta); } - let preferLocalCache = hasAnyRelationshipData && - hasRelatedResources && - !relationshipIsEmpty; - let hasLocalPartialData = hasDematerializedInverse || - (relationshipIsEmpty && resource.data); + let preferLocalCache = hasAnyRelationshipData && hasRelatedResources && !relationshipIsEmpty; + let hasLocalPartialData = hasDematerializedInverse || (relationshipIsEmpty && resource.data); // fetch using data, pulling from local cache if possible if (!relationshipIsStale && (preferLocalCache || hasLocalPartialData)) { @@ -1345,7 +1436,6 @@ Store = Service.extend({ return RSVP.resolve(null); }, - /** This method delegates a query to the adapter. This is the one place where adapter-level semantics are exposed to the application. @@ -1402,12 +1492,15 @@ Store = Service.extend({ query(modelName, query, options) { assert(`You need to pass a model name to the store's query method`, isPresent(modelName)); assert(`You need to pass a query hash to the store's query method`, query); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let adapterOptionsWrapper = {}; if (options && options.adapterOptions) { - adapterOptionsWrapper.adapterOptions = options.adapterOptions + adapterOptionsWrapper.adapterOptions = options.adapterOptions; } let normalizedModelName = normalizeModelName(modelName); @@ -1418,7 +1511,10 @@ Store = Service.extend({ let token = heimdall.start('store._query'); assert(`You need to pass a model name to the store's query method`, isPresent(modelName)); assert(`You need to pass a query hash to the store's query method`, query); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let modelToken = heimdall.start('initial-modelFor-lookup'); heimdall.stop(modelToken); @@ -1428,11 +1524,16 @@ Store = Service.extend({ heimdall.stop(adapterToken); assert(`You tried to load a query but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to load a query but your adapter does not implement 'query'`, typeof adapter.query === 'function'); + assert( + `You tried to load a query but your adapter does not implement 'query'`, + typeof adapter.query === 'function' + ); let pA = promiseArray(_query(adapter, this, modelName, query, array, options)); instrument(() => { - pA.finally(() => { heimdall.stop(token); }); + pA.finally(() => { + heimdall.stop(token); + }); }); return pA; }, @@ -1537,28 +1638,39 @@ Store = Service.extend({ queryRecord(modelName, query, options) { assert(`You need to pass a model name to the store's queryRecord method`, isPresent(modelName)); assert(`You need to pass a query hash to the store's queryRecord method`, query); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let adapter = this.adapterFor(normalizedModelName); let adapterOptionsWrapper = {}; if (options && options.adapterOptions) { - adapterOptionsWrapper.adapterOptions = options.adapterOptions + adapterOptionsWrapper.adapterOptions = options.adapterOptions; } - assert(`You tried to make a query but you have no adapter (for ${normalizedModelName})`, adapter); - assert(`You tried to make a query but your adapter does not implement 'queryRecord'`, typeof adapter.queryRecord === 'function'); + assert( + `You tried to make a query but you have no adapter (for ${normalizedModelName})`, + adapter + ); + assert( + `You tried to make a query but your adapter does not implement 'queryRecord'`, + typeof adapter.queryRecord === 'function' + ); - return promiseObject(_queryRecord(adapter, this, modelName, query, adapterOptionsWrapper).then(internalModel => { - // the promise returned by store.queryRecord is expected to resolve with - // an instance of DS.Model - if (internalModel) { - return internalModel.getRecord(); - } + return promiseObject( + _queryRecord(adapter, this, modelName, query, adapterOptionsWrapper).then(internalModel => { + // the promise returned by store.queryRecord is expected to resolve with + // an instance of DS.Model + if (internalModel) { + return internalModel.getRecord(); + } - return null; - })); + return null; + }) + ); }, /** @@ -1751,14 +1863,19 @@ Store = Service.extend({ */ findAll(modelName, options) { assert(`You need to pass a model name to the store's findAll method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let token = heimdall.start('store.findAll'); let normalizedModelName = normalizeModelName(modelName); let fetch = this._fetchAll(normalizedModelName, this.peekAll(normalizedModelName), options); instrument(() => { - fetch.finally(() => { heimdall.stop(token); }); + fetch.finally(() => { + heimdall.stop(token); + }); }); return fetch; @@ -1776,7 +1893,10 @@ Store = Service.extend({ let sinceToken = this._internalModelsFor(modelName).metadata.since; assert(`You tried to load all records but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to load all records but your adapter does not implement 'findAll'`, typeof adapter.findAll === 'function'); + assert( + `You tried to load all records but your adapter does not implement 'findAll'`, + typeof adapter.findAll === 'function' + ); if (options.reload) { set(array, 'isUpdating', true); @@ -1839,7 +1959,10 @@ Store = Service.extend({ peekAll(modelName) { heimdall.increment(peekAll); assert(`You need to pass a model name to the store's peekAll method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); return this.recordArrayManager.liveRecordArrayFor(normalizedModelName); }, @@ -1859,7 +1982,10 @@ Store = Service.extend({ @param {String} modelName */ unloadAll(modelName) { - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, !modelName || typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + !modelName || typeof modelName === 'string' + ); if (arguments.length === 0) { this._identityMap.clear(); @@ -1870,7 +1996,10 @@ Store = Service.extend({ }, filter() { - assert('The filter API has been moved to a plugin. To enable store.filter using an environment flag, or to use an alternative, you can visit the ember-data-filter addon page. https://github.com/ember-data/ember-data-filter', false); + assert( + 'The filter API has been moved to a plugin. To enable store.filter using an environment flag, or to use an alternative, you can visit the ember-data-filter addon page. https://github.com/ember-data/ember-data-filter', + false + ); }, // .............. @@ -1894,7 +2023,7 @@ Store = Service.extend({ internalModel.adapterWillCommit(); this._pendingSave.push({ snapshot: snapshot, - resolver: resolver + resolver: resolver, }); emberRun.once(this, this.flushPendingSave); }, @@ -1931,7 +2060,6 @@ Store = Service.extend({ resolver.resolve(_commit(adapter, this, operation, snapshot)); } - }, /** @@ -1953,7 +2081,12 @@ Store = Service.extend({ data = dataArg.data; } if (!data) { - assert(`Your ${internalModel.modelName} record was saved to the server, but the response does not have an id and no id has been set client side. Records must have ids. Please update the server response to provide an id in the response or generate the id on the client side either before saving the record or while normalizing the response.`, internalModel.id); + assert( + `Your ${ + internalModel.modelName + } record was saved to the server, but the response does not have an id and no id has been set client side. Records must have ids. Please update the server response to provide an id in the response or generate the id on the client side either before saving the record or while normalizing the response.`, + internalModel.id + ); } //We first make sure the primary data has been updated @@ -2008,7 +2141,7 @@ Store = Service.extend({ updateId(internalModel, data) { deprecate('store.updateId was documented as private and will be removed.', false, { id: 'ds.store.updateId', - until: '3.5' + until: '3.5', }); this._setRecordId(internalModel, coerceId(data.id)); }, @@ -2018,22 +2151,33 @@ Store = Service.extend({ let modelName = internalModel.modelName; // ID absolutely can't be missing if the oldID is empty (missing Id in response for a new record) - assert(`'${modelName}' was saved to the server, but the response does not have an id and your record does not either.`, !(id === null && oldId === null)); + assert( + `'${modelName}' was saved to the server, but the response does not have an id and your record does not either.`, + !(id === null && oldId === null) + ); // ID absolutely can't be different than oldID if oldID is not null - assert(`'${modelName}:${oldId}' was saved to the server, but the response returned the new id '${id}'. The store cannot assign a new id to a record that already has an id.`, !(oldId !== null && id !== oldId)); + assert( + `'${modelName}:${oldId}' was saved to the server, but the response returned the new id '${id}'. The store cannot assign a new id to a record that already has an id.`, + !(oldId !== null && id !== oldId) + ); // ID can be null if oldID is not null (altered ID in response for a record) // however, this is more than likely a developer error. if (oldId !== null && id === null) { - warn(`Your ${modelName} record was saved to the server, but the response does not have an id.`, !(oldId !== null && id === null)); + warn( + `Your ${modelName} record was saved to the server, but the response does not have an id.`, + !(oldId !== null && id === null) + ); return; } let existingInternalModel = this._existingInternalModelForId(modelName, id); - assert(`'${modelName}' was saved to the server, but the response returned the new id '${id}', which has already been used with another record.'`, - isNone(existingInternalModel) || existingInternalModel === internalModel); + assert( + `'${modelName}' was saved to the server, but the response returned the new id '${id}', which has already been used with another record.'`, + isNone(existingInternalModel) || existingInternalModel === internalModel + ); this._internalModelsFor(internalModel.modelName).set(id, internalModel); this._newlyCreatedModelsFor(internalModel.modelName).remove(internalModel, clientId); @@ -2097,11 +2241,17 @@ Store = Service.extend({ false, { id: 'ember-data:_modelForMixin', - until: '3.5' + until: '3.5', } ); - assert(`You need to pass a model name to the store's _modelForMixin method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's _modelForMixin method`, + isPresent(modelName) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); return _modelForMixin(this, normalizedModelName); @@ -2121,7 +2271,10 @@ Store = Service.extend({ */ modelFor(modelName) { assert(`You need to pass a model name to the store's modelFor method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let maybeFactory = this._modelFactoryFor(modelName); @@ -2134,20 +2287,22 @@ Store = Service.extend({ @private */ _modelFor(modelName) { - deprecate( - '_modelFor is private and deprecated, you should use modelFor instead', - false, - { - id: 'ember-data:_modelFor', - until: '3.5' - } - ); + deprecate('_modelFor is private and deprecated, you should use modelFor instead', false, { + id: 'ember-data:_modelFor', + until: '3.5', + }); return this.modelFor(modelName); }, _modelFactoryFor(modelName) { - assert(`You need to pass a model name to the store's _modelFactoryFor method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's _modelFactoryFor method`, + isPresent(modelName) + ); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let factory = getModelFactory(this, this._modelFactoryCache, normalizedModelName); @@ -2165,7 +2320,7 @@ Store = Service.extend({ modelFactoryFor(modelName) { deprecate('modelFactoryFor is private and deprecated', false, { id: 'ember-data:modelFactoryFor', - until: '3.5' + until: '3.5', }); return this._modelFactoryFor(modelName); }, @@ -2183,7 +2338,10 @@ Store = Service.extend({ */ _hasModelFor(modelName) { assert(`You need to pass a model name to the store's hasModelFor method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let factory = getModelFactory(this, this._modelFactoryCache, normalizedModelName); @@ -2395,7 +2553,12 @@ Store = Service.extend({ return null; } - assert(`Expected an object in the 'data' property in a call to 'push' for ${jsonApiDoc.type}, but was ${typeOf(jsonApiDoc.data)}`, typeOf(jsonApiDoc.data) === 'object'); + assert( + `Expected an object in the 'data' property in a call to 'push' for ${ + jsonApiDoc.type + }, but was ${typeOf(jsonApiDoc.data)}`, + typeOf(jsonApiDoc.data) === 'object' + ); return this._pushInternalModel(jsonApiDoc.data); }); @@ -2406,8 +2569,14 @@ Store = Service.extend({ _pushInternalModel(data) { heimdall.increment(_pushInternalModel); let modelName = data.type; - assert(`You must include an 'id' for ${modelName} in an object passed to 'push'`, data.id !== null && data.id !== undefined && data.id !== ''); - assert(`You tried to push data with a type '${modelName}' but no model could be found with that name.`, this._hasModelFor(modelName)); + assert( + `You must include an 'id' for ${modelName} in an object passed to 'push'`, + data.id !== null && data.id !== undefined && data.id !== '' + ); + assert( + `You tried to push data with a type '${modelName}' but no model could be found with that name.`, + this._hasModelFor(modelName) + ); if (DEBUG) { // If ENV.DS_WARN_ON_UNKNOWN_KEYS is set to true and the payload @@ -2417,25 +2586,29 @@ Store = Service.extend({ let modelClass = this.modelFor(modelName); // Check unknown attributes - let unknownAttributes = Object.keys(data.attributes || {}).filter((key) => { + let unknownAttributes = Object.keys(data.attributes || {}).filter(key => { return !get(modelClass, 'fields').has(key); }); let unknownAttributesMessage = `The payload for '${modelName}' contains these unknown attributes: ${unknownAttributes}. Make sure they've been defined in your model.`; - warn(unknownAttributesMessage, unknownAttributes.length === 0, { id: 'ds.store.unknown-keys-in-payload' }); + warn(unknownAttributesMessage, unknownAttributes.length === 0, { + id: 'ds.store.unknown-keys-in-payload', + }); // Check unknown relationships - let unknownRelationships = Object.keys(data.relationships || {}).filter((key) => { + let unknownRelationships = Object.keys(data.relationships || {}).filter(key => { return !get(modelClass, 'fields').has(key); }); let unknownRelationshipsMessage = `The payload for '${modelName}' contains these unknown relationships: ${unknownRelationships}. Make sure they've been defined in your model.`; - warn(unknownRelationshipsMessage, unknownRelationships.length === 0, { id: 'ds.store.unknown-keys-in-payload' }); + warn(unknownRelationshipsMessage, unknownRelationships.length === 0, { + id: 'ds.store.unknown-keys-in-payload', + }); } } // Actually load the record into the store. let internalModel = this._load(data); -// this._setupRelationshipsForModel(internalModel, data); + // this._setupRelationshipsForModel(internalModel, data); return internalModel; }, @@ -2501,10 +2674,16 @@ Store = Service.extend({ if (!inputPayload) { payload = modelName; serializer = defaultSerializer(this); - assert(`You cannot use 'store#pushPayload' without a modelName unless your default serializer defines 'pushPayload'`, typeof serializer.pushPayload === 'function'); + assert( + `You cannot use 'store#pushPayload' without a modelName unless your default serializer defines 'pushPayload'`, + typeof serializer.pushPayload === 'function' + ); } else { payload = inputPayload; - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); serializer = this.serializerFor(normalizedModelName); } @@ -2516,7 +2695,7 @@ Store = Service.extend({ }, reloadBelongsTo(belongsToProxy, internalModel, key) { - return internalModel.reloadBelongsTo(key) + return internalModel.reloadBelongsTo(key); }, _relationshipMetaFor(modelName, id, key) { @@ -2575,7 +2754,12 @@ Store = Service.extend({ normalize(modelName, payload) { heimdall.increment(normalize); assert(`You need to pass a model name to the store's normalize method`, isPresent(modelName)); - assert(`Passing classes to store methods has been removed. Please pass a dasherized string instead of ${inspect(modelName)}`, typeof modelName === 'string'); + assert( + `Passing classes to store methods has been removed. Please pass a dasherized string instead of ${inspect( + modelName + )}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let serializer = this.serializerFor(normalizedModelName); let model = this.modelFor(normalizedModelName); @@ -2599,11 +2783,17 @@ Store = Service.extend({ _buildInternalModel(modelName, id, data, clientId) { heimdall.increment(_buildInternalModel); - assert(`You can no longer pass a modelClass as the first argument to store._buildInternalModel. Pass modelName instead.`, typeof modelName === 'string'); + assert( + `You can no longer pass a modelClass as the first argument to store._buildInternalModel. Pass modelName instead.`, + typeof modelName === 'string' + ); let existingInternalModel = this._existingInternalModelForId(modelName, id); - assert(`The id ${id} has already been used with another record for modelClass '${modelName}'.`, !existingInternalModel); + assert( + `The id ${id} has already been used with another record for modelClass '${modelName}'.`, + !existingInternalModel + ); if (id === null && !clientId) { clientId = this.newClientId(); @@ -2685,12 +2875,17 @@ Store = Service.extend({ adapterFor(modelName) { heimdall.increment(adapterFor); assert(`You need to pass a model name to the store's adapterFor method`, isPresent(modelName)); - assert(`Passing classes to store.adapterFor has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `Passing classes to store.adapterFor has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let { _adapterCache } = this; let adapter = _adapterCache[normalizedModelName]; - if (adapter) { return adapter; } + if (adapter) { + return adapter; + } let owner = getOwner(this); @@ -2757,13 +2952,21 @@ Store = Service.extend({ */ serializerFor(modelName) { heimdall.increment(serializerFor); - assert(`You need to pass a model name to the store's serializerFor method`, isPresent(modelName)); - assert(`Passing classes to store.serializerFor has been removed. Please pass a dasherized string instead of ${modelName}`, typeof modelName === 'string'); + assert( + `You need to pass a model name to the store's serializerFor method`, + isPresent(modelName) + ); + assert( + `Passing classes to store.serializerFor has been removed. Please pass a dasherized string instead of ${modelName}`, + typeof modelName === 'string' + ); let normalizedModelName = normalizeModelName(modelName); let { _serializerCache } = this; let serializer = _serializerCache[normalizedModelName]; - if (serializer) { return serializer; } + if (serializer) { + return serializer; + } let owner = getOwner(this); @@ -2859,7 +3062,16 @@ Store = Service.extend({ return; } - assert(`A ${relationship.internalModel.modelName} record was pushed into the store with the value of ${relationship.key} being ${inspect(resourceIdentifier)}, but ${relationship.key} is a belongsTo relationship so the value must not be an array. You should probably check your data payload or serializer.`, !Array.isArray(resourceIdentifier)); + assert( + `A ${ + relationship.internalModel.modelName + } record was pushed into the store with the value of ${relationship.key} being ${inspect( + resourceIdentifier + )}, but ${ + relationship.key + } is a belongsTo relationship so the value must not be an array. You should probably check your data payload or serializer.`, + !Array.isArray(resourceIdentifier) + ); //TODO:Better asserts return this._internalModelForId(resourceIdentifier.type, resourceIdentifier.id); @@ -2870,20 +3082,27 @@ Store = Service.extend({ return; } - assert(`A ${relationship.internalModel.modelName} record was pushed into the store with the value of ${relationship.key} being '${inspect(resourceIdentifiers)}', but ${relationship.key} is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer.`, Array.isArray(resourceIdentifiers)); + assert( + `A ${ + relationship.internalModel.modelName + } record was pushed into the store with the value of ${relationship.key} being '${inspect( + resourceIdentifiers + )}', but ${ + relationship.key + } is a hasMany relationship so the value must be an array. You should probably check your data payload or serializer.`, + Array.isArray(resourceIdentifiers) + ); let _internalModels = new Array(resourceIdentifiers.length); for (let i = 0; i < resourceIdentifiers.length; i++) { _internalModels[i] = this._pushResourceIdentifier(relationship, resourceIdentifiers[i]); } return _internalModels; - } + }, }); // Delegation to the adapter and promise management - - function defaultSerializer(store) { return store.serializerFor('application'); } @@ -2893,21 +3112,30 @@ function _commit(adapter, store, operation, snapshot) { let modelName = snapshot.modelName; let modelClass = store.modelFor(modelName); assert(`You tried to update a record but you have no adapter (for ${modelName})`, adapter); - assert(`You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`, typeof adapter[operation] === 'function'); + assert( + `You tried to update a record but your adapter (for ${modelName}) does not implement '${operation}'`, + typeof adapter[operation] === 'function' + ); - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let promise = Promise.resolve().then(() => adapter[operation](store, modelClass, snapshot)); let serializer = serializerForAdapter(store, adapter, modelName); let label = `DS: Extract and notify about ${operation} completion of ${internalModel}`; - assert(`Your adapter's '${operation}' method must return a value, but it returned 'undefined'`, promise !==undefined); + assert( + `Your adapter's '${operation}' method must return a value, but it returned 'undefined'`, + promise !== undefined + ); promise = guardDestroyedStore(promise, store, label); promise = _guard(promise, _bind(_objectIsAlive, internalModel)); - return promise.then((adapterPayload) => { - /* + return promise.then( + adapterPayload => { + /* Note to future spelunkers hoping to optimize. We rely on this `run` to create a run loop if needed that `store._push` and `store.didSaveRecord` will both share. @@ -2916,34 +3144,44 @@ function _commit(adapter, store, operation, snapshot) { have an outer run loop available still from the first call to `store._push`; */ - store._backburner.join(() => { - let payload, data, sideloaded; - if (adapterPayload) { - payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, snapshot.id, operation); - if (payload.included) { - sideloaded = payload.included; + store._backburner.join(() => { + let payload, data, sideloaded; + if (adapterPayload) { + payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + snapshot.id, + operation + ); + if (payload.included) { + sideloaded = payload.included; + } + data = payload.data; } - data = payload.data; - } - store.didSaveRecord(internalModel, { data }); - // seems risky, but if the tests pass might be fine? - if (sideloaded) { - store._push({ data: null, included: sideloaded }); - } - }); + store.didSaveRecord(internalModel, { data }); + // seems risky, but if the tests pass might be fine? + if (sideloaded) { + store._push({ data: null, included: sideloaded }); + } + }); - return internalModel; - }, function(error) { - if (error instanceof InvalidError) { - let errors = serializer.extractErrors(store, modelClass, error, snapshot.id); + return internalModel; + }, + function(error) { + if (error instanceof InvalidError) { + let errors = serializer.extractErrors(store, modelClass, error, snapshot.id); - store.recordWasInvalid(internalModel, errors); - } else { - store.recordWasError(internalModel, error); - } + store.recordWasInvalid(internalModel, errors); + } else { + store.recordWasError(internalModel, error); + } - throw error; - }, label); + throw error; + }, + label + ); } /** @@ -2995,7 +3233,6 @@ function _lookupModelFactory(store, normalizedModelName) { } } - /* In case someone defined a relationship to a mixin, for example: ``` @@ -3029,7 +3266,7 @@ function _modelForMixin(store, normalizedModelName) { let ModelForMixin = Model.extend(mixin); ModelForMixin.reopenClass({ __isMixin: true, - __mixin: mixin + __mixin: mixin, }); //Cache the class as a model diff --git a/addon/-record-data-rfc-private/system/store/common.js b/addon/-record-data-rfc-private/system/store/common.js index 007671f5114..c095fe701c8 100644 --- a/addon/-record-data-rfc-private/system/store/common.js +++ b/addon/-record-data-rfc-private/system/store/common.js @@ -3,11 +3,8 @@ import { DEBUG } from '@glimmer/env'; import Ember from 'ember'; import { Promise } from 'rsvp'; -const { - __bind, - __guard, - __objectIsAlive -} = heimdall.registerMonitor('system.store.common', +const { __bind, __guard, __objectIsAlive } = heimdall.registerMonitor( + 'system.store.common', '_bind', '_guard', '_objectIsAlive' @@ -34,7 +31,7 @@ export function _guard(promise, test) { export function _objectIsAlive(object) { heimdall.increment(__objectIsAlive); - return !(get(object, "isDestroyed") || get(object, "isDestroying")); + return !(get(object, 'isDestroyed') || get(object, 'isDestroying')); } let ASYNC_REQUEST_COUNT = 0; @@ -51,5 +48,10 @@ if (DEBUG) { export function guardDestroyedStore(promise, store, label) { promise = Promise.resolve(promise, label); - return _guard(promise, () => { if (DEBUG) { ASYNC_REQUEST_COUNT--; } return _objectIsAlive(store); }); + return _guard(promise, () => { + if (DEBUG) { + ASYNC_REQUEST_COUNT--; + } + return _objectIsAlive(store); + }); } diff --git a/addon/-record-data-rfc-private/system/store/finders.js b/addon/-record-data-rfc-private/system/store/finders.js index d9923eaf29a..1709a79cb39 100644 --- a/addon/-record-data-rfc-private/system/store/finders.js +++ b/addon/-record-data-rfc-private/system/store/finders.js @@ -8,11 +8,11 @@ import { _guard, _objectIsAlive, guardDestroyedStore, - incrementRequestCount -} from "./common"; + incrementRequestCount, +} from './common'; -import { normalizeResponseHelper } from "./serializer-response"; -import { serializerForAdapter } from "./serializers"; +import { normalizeResponseHelper } from './serializer-response'; +import { serializerForAdapter } from './serializers'; function payloadIsNotBlank(adapterPayload) { if (Array.isArray(adapterPayload)) { @@ -23,7 +23,9 @@ function payloadIsNotBlank(adapterPayload) { } export function _find(adapter, store, modelClass, id, internalModel, options) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let snapshot = internalModel.createSnapshot(options); let { modelName } = internalModel; let promise = Promise.resolve().then(() => adapter.findRecord(store, modelClass, id, snapshot)); @@ -31,29 +33,54 @@ export function _find(adapter, store, modelClass, id, internalModel, options) { promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - assert(`You made a 'findRecord' request for a '${modelName}' with id '${id}', but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload)); - let serializer = serializerForAdapter(store, adapter, modelName); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, id, 'findRecord'); - assert(`Ember Data expected the primary data returned from a 'findRecord' response to be an object but instead it found an array.`, !Array.isArray(payload.data)); - - warn(`You requested a record of type '${modelName}' with id '${id}' but the adapter returned a payload with primary data having an id of '${payload.data.id}'. Use 'store.findRecord()' when the requested id is the same as the one returned by the adapter. In other cases use 'store.queryRecord()' instead https://emberjs.com/api/data/classes/DS.Store.html#method_queryRecord`, payload.data.id === id, { - id: 'ds.store.findRecord.id-mismatch' - }); - - return store._push(payload); - }, error => { - internalModel.notFound(); - if (internalModel.isEmpty()) { - internalModel.unloadRecord(); - } - - throw error; - }, `DS: Extract payload of '${modelName}'`); + return promise.then( + adapterPayload => { + assert( + `You made a 'findRecord' request for a '${modelName}' with id '${id}', but the adapter's response did not have any data`, + payloadIsNotBlank(adapterPayload) + ); + let serializer = serializerForAdapter(store, adapter, modelName); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + id, + 'findRecord' + ); + assert( + `Ember Data expected the primary data returned from a 'findRecord' response to be an object but instead it found an array.`, + !Array.isArray(payload.data) + ); + + warn( + `You requested a record of type '${modelName}' with id '${id}' but the adapter returned a payload with primary data having an id of '${ + payload.data.id + }'. Use 'store.findRecord()' when the requested id is the same as the one returned by the adapter. In other cases use 'store.queryRecord()' instead https://emberjs.com/api/data/classes/DS.Store.html#method_queryRecord`, + payload.data.id === id, + { + id: 'ds.store.findRecord.id-mismatch', + } + ); + + return store._push(payload); + }, + error => { + internalModel.notFound(); + if (internalModel.isEmpty()) { + internalModel.unloadRecord(); + } + + throw error; + }, + `DS: Extract payload of '${modelName}'` + ); } export function _findMany(adapter, store, modelName, ids, internalModels) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let snapshots = A(internalModels).invoke('createSnapshot'); let modelClass = store.modelFor(modelName); // `adapter.findMany` gets the modelClass still let promise = adapter.findMany(store, modelClass, ids, snapshots); @@ -65,90 +92,163 @@ export function _findMany(adapter, store, modelName, ids, internalModels) { promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - assert(`You made a 'findMany' request for '${modelName}' records with ids '[${ids}]', but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload)); - let serializer = serializerForAdapter(store, adapter, modelName); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findMany'); - return store._push(payload); - }, null, `DS: Extract payload of ${modelName}`); + return promise.then( + adapterPayload => { + assert( + `You made a 'findMany' request for '${modelName}' records with ids '[${ids}]', but the adapter's response did not have any data`, + payloadIsNotBlank(adapterPayload) + ); + let serializer = serializerForAdapter(store, adapter, modelName); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'findMany' + ); + return store._push(payload); + }, + null, + `DS: Extract payload of ${modelName}` + ); } export function _findHasMany(adapter, store, internalModel, link, relationship) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let snapshot = internalModel.createSnapshot(); let modelClass = store.modelFor(relationship.type); let promise = adapter.findHasMany(store, snapshot, link, relationship); - let label = `DS: Handle Adapter#findHasMany of '${internalModel.modelName}' : '${relationship.type}'`; + let label = `DS: Handle Adapter#findHasMany of '${internalModel.modelName}' : '${ + relationship.type + }'`; promise = guardDestroyedStore(promise, store, label); promise = _guard(promise, _bind(_objectIsAlive, internalModel)); - return promise.then(adapterPayload => { - assert(`You made a 'findHasMany' request for a ${internalModel.modelName}'s '${relationship.key}' relationship, using link '${link}' , but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload)); - let serializer = serializerForAdapter(store, adapter, relationship.type); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findHasMany'); - let internalModelArray = store._push(payload); - - internalModelArray.meta = payload.meta; - return internalModelArray; - }, null, `DS: Extract payload of '${internalModel.modelName}' : hasMany '${relationship.type}'`); + return promise.then( + adapterPayload => { + assert( + `You made a 'findHasMany' request for a ${internalModel.modelName}'s '${ + relationship.key + }' relationship, using link '${link}' , but the adapter's response did not have any data`, + payloadIsNotBlank(adapterPayload) + ); + let serializer = serializerForAdapter(store, adapter, relationship.type); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'findHasMany' + ); + let internalModelArray = store._push(payload); + + internalModelArray.meta = payload.meta; + return internalModelArray; + }, + null, + `DS: Extract payload of '${internalModel.modelName}' : hasMany '${relationship.type}'` + ); } export function _findBelongsTo(adapter, store, internalModel, link, relationship) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let snapshot = internalModel.createSnapshot(); let modelClass = store.modelFor(relationship.type); let promise = adapter.findBelongsTo(store, snapshot, link, relationship); - let label = `DS: Handle Adapter#findBelongsTo of ${internalModel.modelName} : ${relationship.type}`; + let label = `DS: Handle Adapter#findBelongsTo of ${internalModel.modelName} : ${ + relationship.type + }`; promise = guardDestroyedStore(promise, store, label); promise = _guard(promise, _bind(_objectIsAlive, internalModel)); - return promise.then(adapterPayload => { - let serializer = serializerForAdapter(store, adapter, relationship.type); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findBelongsTo'); - - if (!payload.data) { - return null; - } - - return store._push(payload); - }, null, `DS: Extract payload of ${internalModel.modelName} : ${relationship.type}`); + return promise.then( + adapterPayload => { + let serializer = serializerForAdapter(store, adapter, relationship.type); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'findBelongsTo' + ); + + if (!payload.data) { + return null; + } + + return store._push(payload); + }, + null, + `DS: Extract payload of ${internalModel.modelName} : ${relationship.type}` + ); } export function _findAll(adapter, store, modelName, sinceToken, options) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let modelClass = store.modelFor(modelName); // adapter.findAll depends on the class let recordArray = store.peekAll(modelName); let snapshotArray = recordArray._createSnapshot(options); - let promise = Promise.resolve().then(() => adapter.findAll(store, modelClass, sinceToken, snapshotArray)); - let label = "DS: Handle Adapter#findAll of " + modelClass; + let promise = Promise.resolve().then(() => + adapter.findAll(store, modelClass, sinceToken, snapshotArray) + ); + let label = 'DS: Handle Adapter#findAll of ' + modelClass; promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - assert(`You made a 'findAll' request for '${modelName}' records, but the adapter's response did not have any data`, payloadIsNotBlank(adapterPayload)); - let serializer = serializerForAdapter(store, adapter, modelName); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'findAll'); - - store._push(payload); - store._didUpdateAll(modelName); - - return recordArray; - }, null, 'DS: Extract payload of findAll ${modelName}'); + return promise.then( + adapterPayload => { + assert( + `You made a 'findAll' request for '${modelName}' records, but the adapter's response did not have any data`, + payloadIsNotBlank(adapterPayload) + ); + let serializer = serializerForAdapter(store, adapter, modelName); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'findAll' + ); + + store._push(payload); + store._didUpdateAll(modelName); + + return recordArray; + }, + null, + 'DS: Extract payload of findAll ${modelName}' + ); } export function _query(adapter, store, modelName, query, recordArray, options) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let modelClass = store.modelFor(modelName); // adapter.query needs the class let promise; - let createRecordArray = adapter.query.length > 3 || + let createRecordArray = + adapter.query.length > 3 || (adapter.query.wrappedFunction && adapter.query.wrappedFunction.length > 3); if (createRecordArray) { - recordArray = recordArray || store.recordArrayManager.createAdapterPopulatedRecordArray(modelName, query); - promise = Promise.resolve().then(() => adapter.query(store, modelClass, query, recordArray, options)); + recordArray = + recordArray || store.recordArrayManager.createAdapterPopulatedRecordArray(modelName, query); + promise = Promise.resolve().then(() => + adapter.query(store, modelClass, query, recordArray, options) + ); } else { promise = Promise.resolve().then(() => adapter.query(store, modelClass, query)); } @@ -156,42 +256,80 @@ export function _query(adapter, store, modelName, query, recordArray, options) { let label = `DS: Handle Adapter#query of ${modelName}`; promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - let serializerToken = heimdall.start('initial-serializerFor-lookup'); - let serializer = serializerForAdapter(store, adapter, modelName); - heimdall.stop(serializerToken); - let normalizeToken = heimdall.start('finders#_query::normalizeResponseHelper'); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'query'); - heimdall.stop(normalizeToken); - let internalModels = store._push(payload); - - assert('The response to store.query is expected to be an array but it was a single record. Please wrap your response in an array or use `store.queryRecord` to query for a single record.', Array.isArray(internalModels)); - if (recordArray) { - recordArray._setInternalModels(internalModels, payload); - } else { - recordArray = store.recordArrayManager.createAdapterPopulatedRecordArray(modelName, query, internalModels, payload); - } - - return recordArray; - }, null, `DS: Extract payload of query ${modelName}`); + return promise.then( + adapterPayload => { + let serializerToken = heimdall.start('initial-serializerFor-lookup'); + let serializer = serializerForAdapter(store, adapter, modelName); + heimdall.stop(serializerToken); + let normalizeToken = heimdall.start('finders#_query::normalizeResponseHelper'); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'query' + ); + heimdall.stop(normalizeToken); + let internalModels = store._push(payload); + + assert( + 'The response to store.query is expected to be an array but it was a single record. Please wrap your response in an array or use `store.queryRecord` to query for a single record.', + Array.isArray(internalModels) + ); + if (recordArray) { + recordArray._setInternalModels(internalModels, payload); + } else { + recordArray = store.recordArrayManager.createAdapterPopulatedRecordArray( + modelName, + query, + internalModels, + payload + ); + } + + return recordArray; + }, + null, + `DS: Extract payload of query ${modelName}` + ); } export function _queryRecord(adapter, store, modelName, query, options) { - if (DEBUG) { incrementRequestCount(); } + if (DEBUG) { + incrementRequestCount(); + } let modelClass = store.modelFor(modelName); // adapter.queryRecord needs the class - let promise = Promise.resolve().then(() => adapter.queryRecord(store, modelClass, query, options)); + let promise = Promise.resolve().then(() => + adapter.queryRecord(store, modelClass, query, options) + ); let label = `DS: Handle Adapter#queryRecord of ${modelName}`; promise = guardDestroyedStore(promise, store, label); - return promise.then(adapterPayload => { - let serializer = serializerForAdapter(store, adapter, modelName); - let payload = normalizeResponseHelper(serializer, store, modelClass, adapterPayload, null, 'queryRecord'); - - assert(`Expected the primary data returned by the serializer for a 'queryRecord' response to be a single object or null but instead it was an array.`, !Array.isArray(payload.data), { - id: 'ds.store.queryRecord-array-response' - }); - - return store._push(payload); - }, null, `DS: Extract payload of queryRecord ${modelName}`); + return promise.then( + adapterPayload => { + let serializer = serializerForAdapter(store, adapter, modelName); + let payload = normalizeResponseHelper( + serializer, + store, + modelClass, + adapterPayload, + null, + 'queryRecord' + ); + + assert( + `Expected the primary data returned by the serializer for a 'queryRecord' response to be a single object or null but instead it was an array.`, + !Array.isArray(payload.data), + { + id: 'ds.store.queryRecord-array-response', + } + ); + + return store._push(payload); + }, + null, + `DS: Extract payload of queryRecord ${modelName}` + ); } diff --git a/addon/-record-data-rfc-private/system/store/model-data-wrapper.js b/addon/-record-data-rfc-private/system/store/model-data-wrapper.js index 46411b95eb0..0ddb9cf94aa 100644 --- a/addon/-record-data-rfc-private/system/store/model-data-wrapper.js +++ b/addon/-record-data-rfc-private/system/store/model-data-wrapper.js @@ -10,7 +10,7 @@ export default class ModelDataWrapper { } _scheduleManyArrayUpdate(modelName, id, clientId, key) { - let pending = this._pendingManyArrayUpdates = this._pendingManyArrayUpdates || []; + let pending = (this._pendingManyArrayUpdates = this._pendingManyArrayUpdates || []); pending.push(modelName, id, clientId, key); if (this._willUpdateManyArrays === true) { @@ -100,7 +100,7 @@ export default class ModelDataWrapper { isRecordInUse(modelName, id, clientId) { let internalModel = this.store._getInternalModelForId(modelName, id, clientId); if (!internalModel) { - return false + return false; } return internalModel.isRecordInUse(); } @@ -111,5 +111,4 @@ export default class ModelDataWrapper { internalModel.destroyFromModelData(); } } - } diff --git a/addon/-record-data-rfc-private/system/store/serializer-response.js b/addon/-record-data-rfc-private/system/store/serializer-response.js index 155b13d0617..c4a08c6b5cf 100644 --- a/addon/-record-data-rfc-private/system/store/serializer-response.js +++ b/addon/-record-data-rfc-private/system/store/serializer-response.js @@ -16,13 +16,13 @@ export function validateDocumentStructure(doc) { if (!doc || typeof doc !== 'object') { errors.push('Top level of a JSON API document must be an object'); } else { - if (!('data' in doc) && - !('errors' in doc) && - !('meta' in doc)) { + if (!('data' in doc) && !('errors' in doc) && !('meta' in doc)) { errors.push('One or more of the following keys must be present: "data", "errors", "meta".'); } else { - if (('data' in doc) && ('errors' in doc)) { - errors.push('Top level keys "errors" and "data" cannot both be present in a JSON API document'); + if ('data' in doc && 'errors' in doc) { + errors.push( + 'Top level keys "errors" and "data" cannot both be present in a JSON API document' + ); } } if ('data' in doc) { @@ -73,12 +73,23 @@ export function validateDocumentStructure(doc) { @return {Object} JSON-API Document */ export function normalizeResponseHelper(serializer, store, modelClass, payload, id, requestType) { - let normalizedResponse = serializer.normalizeResponse(store, modelClass, payload, id, requestType); + let normalizedResponse = serializer.normalizeResponse( + store, + modelClass, + payload, + id, + requestType + ); let validationErrors = []; if (DEBUG) { validationErrors = validateDocumentStructure(normalizedResponse); } - assert(`normalizeResponse must return a valid JSON API document:\n\t* ${validationErrors.join('\n\t* ')}`, validationErrors.length === 0); + assert( + `normalizeResponse must return a valid JSON API document:\n\t* ${validationErrors.join( + '\n\t* ' + )}`, + validationErrors.length === 0 + ); return normalizedResponse; } diff --git a/addon/-record-data-rfc-private/system/store/serializers.js b/addon/-record-data-rfc-private/system/store/serializers.js index 71ca0829809..d6788427061 100644 --- a/addon/-record-data-rfc-private/system/store/serializers.js +++ b/addon/-record-data-rfc-private/system/store/serializers.js @@ -7,7 +7,9 @@ export function serializerForAdapter(store, adapter, modelName) { if (serializer === null || serializer === undefined) { serializer = { - extract(store, type, payload) { return payload; } + extract(store, type, payload) { + return payload; + }, }; } diff --git a/addon/-record-data-rfc-private/utils.js b/addon/-record-data-rfc-private/utils.js index 234af6842fa..f3bd4ed6aaf 100644 --- a/addon/-record-data-rfc-private/utils.js +++ b/addon/-record-data-rfc-private/utils.js @@ -8,7 +8,9 @@ import { get } from '@ember/object'; @param modelClass */ function modelHasAttributeOrRelationshipNamedType(modelClass) { - return get(modelClass, 'attributes').has('type') || get(modelClass, 'relationshipsByName').has('type'); + return ( + get(modelClass, 'attributes').has('type') || get(modelClass, 'relationshipsByName').has('type') + ); } /* @@ -29,7 +31,7 @@ function getOwner(context) { // `owner` is a container, we are just making this work owner._lookupFactory = function() { return owner.lookupFactory(...arguments); - } + }; owner.register = function() { let registry = owner.registry || owner._registry || owner; @@ -41,7 +43,4 @@ function getOwner(context) { return owner; } -export { - modelHasAttributeOrRelationshipNamedType, - getOwner -}; +export { modelHasAttributeOrRelationshipNamedType, getOwner }; diff --git a/addon/adapter.js b/addon/adapter.js index ed121c640dd..fec86b72db6 100644 --- a/addon/adapter.js +++ b/addon/adapter.js @@ -61,7 +61,6 @@ import EmberObject from '@ember/object'; */ export default EmberObject.extend({ - /** If you would like your adapter to use a custom serializer you can set the `defaultSerializer` property to be the name of the custom @@ -282,7 +281,7 @@ export default EmberObject.extend({ @return {Object} serialized snapshot */ serialize(snapshot, options) { - return snapshot.serialize(options) + return snapshot.serialize(options); }, /** @@ -493,7 +492,6 @@ export default EmberObject.extend({ return [snapshots]; }, - /** This method is used by the store to determine if the store should reload a record from the adapter when a record is requested by @@ -677,5 +675,5 @@ export default EmberObject.extend({ */ shouldBackgroundReloadAll(store, snapshotRecordArray) { return true; - } + }, }); diff --git a/addon/adapters/errors.js b/addon/adapters/errors.js index 051e090262c..b9a59d69abc 100644 --- a/addon/adapters/errors.js +++ b/addon/adapters/errors.js @@ -9,5 +9,5 @@ export { TimeoutError, AbortError, errorsHashToArray, - errorsArrayToHash + errorsArrayToHash, } from '../-private'; diff --git a/addon/adapters/json-api.js b/addon/adapters/json-api.js index 9d59c572f78..f23aa34eb20 100644 --- a/addon/adapters/json-api.js +++ b/addon/adapters/json-api.js @@ -3,7 +3,7 @@ @module ember-data */ import { dasherize } from '@ember/string'; -import RESTAdapter from "./rest"; +import RESTAdapter from './rest'; import { instrument } from 'ember-data/-debug'; import { pluralize } from 'ember-inflector'; @@ -173,7 +173,7 @@ const JSONAPIAdapter = RESTAdapter.extend({ } heimdall.stop(token); return json; - } + }, }; }); @@ -265,7 +265,7 @@ const JSONAPIAdapter = RESTAdapter.extend({ let url = this.buildURL(type.modelName, snapshot.id, snapshot, 'updateRecord'); return this.ajax(url, 'PATCH', { data: data }); - } + }, }); export default JSONAPIAdapter; diff --git a/addon/adapters/rest.js b/addon/adapters/rest.js index 140126fceca..a8cd88d2532 100644 --- a/addon/adapters/rest.js +++ b/addon/adapters/rest.js @@ -10,7 +10,7 @@ import { Promise as EmberPromise } from 'rsvp'; import { get, computed } from '@ember/object'; import { getOwner } from '@ember/application'; import { run } from '@ember/runloop'; -import Adapter from "../adapter"; +import Adapter from '../adapter'; import { parseResponseHeaders, BuildURLMixin, @@ -23,7 +23,7 @@ import { ServerError, TimeoutError, AbortError, - MapWithDefault + MapWithDefault, } from '../-private'; import { instrument } from 'ember-data/-debug'; import { warn } from '@ember/debug'; @@ -644,7 +644,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { @return {Promise} promise */ findHasMany(store, snapshot, url, relationship) { - let id = snapshot.id; + let id = snapshot.id; let type = snapshot.modelName; url = this.urlPrefix(url, this.buildURL(type, id, snapshot, 'findHasMany')); @@ -689,7 +689,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { @return {Promise} promise */ findBelongsTo(store, snapshot, url, relationship) { - let id = snapshot.id; + let id = snapshot.id; let type = snapshot.modelName; url = this.urlPrefix(url, this.buildURL(type, id, snapshot, 'findBelongsTo')); @@ -719,7 +719,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { serializer.serializeIntoHash(data, type, snapshot, { includeId: true }); - return this.ajax(url, "POST", { data: data }); + return this.ajax(url, 'POST', { data: data }); }, /** @@ -747,7 +747,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { let id = snapshot.id; let url = this.buildURL(type.modelName, id, snapshot, 'updateRecord'); - return this.ajax(url, "PUT", { data: data }); + return this.ajax(url, 'PUT', { data: data }); }, /** @@ -764,7 +764,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { deleteRecord(store, type, snapshot) { let id = snapshot.id; - return this.ajax(this.buildURL(type.modelName, id, snapshot, 'deleteRecord'), "DELETE"); + return this.ajax(this.buildURL(type.modelName, id, snapshot, 'deleteRecord'), 'DELETE'); }, _stripIDFromURL(store, snapshot) { @@ -779,10 +779,13 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { let lastSegment = expandedURL[expandedURL.length - 1]; let id = snapshot.id; if (decodeURIComponent(lastSegment) === id) { - expandedURL[expandedURL.length - 1] = ""; + expandedURL[expandedURL.length - 1] = ''; } else if (endsWith(lastSegment, '?id=' + id)) { //Case when the url is of the format ...something?id=:id - expandedURL[expandedURL.length - 1] = lastSegment.substring(0, lastSegment.length - id.length - 1); + expandedURL[expandedURL.length - 1] = lastSegment.substring( + 0, + lastSegment.length - id.length - 1 + ); } return expandedURL.join('/'); @@ -814,11 +817,15 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { loaded separately by `findMany`. */ groupRecordsForFindMany(store, snapshots) { - let groups = new MapWithDefault({ defaultValue() { return []; } }); + let groups = new MapWithDefault({ + defaultValue() { + return []; + }, + }); let adapter = this; let maxURLLength = this.maxURLLength; - snapshots.forEach((snapshot) => { + snapshots.forEach(snapshot => { let baseUrl = adapter._stripIDFromURL(store, snapshot); groups.get(baseUrl).push(snapshot); }); @@ -828,7 +835,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { let baseUrl = adapter._stripIDFromURL(store, group[0]); let splitGroups = [[]]; - group.forEach((snapshot) => { + group.forEach(snapshot => { let additionalLength = encodeURIComponent(snapshot.id).length + paramNameLength; if (baseUrl.length + idsSize + additionalLength >= maxURLLength) { idsSize = 0; @@ -849,7 +856,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { let paramNameLength = '&ids%5B%5D='.length; let splitGroups = splitGroupToFitInUrl(group, maxURLLength, paramNameLength); - splitGroups.forEach((splitGroup) => groupsArray.push(splitGroup)); + splitGroups.forEach(splitGroup => groupsArray.push(splitGroup)); }); return groupsArray; @@ -891,7 +898,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { return new InvalidError(payload.errors); } - let errors = this.normalizeErrorResponse(status, headers, payload); + let errors = this.normalizeErrorResponse(status, headers, payload); let detailedMessage = this.generatedDetailedMessage(status, headers, payload, requestData); switch (status) { @@ -924,7 +931,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { @return {Boolean} */ isSuccess(status, headers, payload) { - return status >= 200 && status < 300 || status === 304; + return (status >= 200 && status < 300) || status === 304; }, /** @@ -971,8 +978,8 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { let adapter = this; let requestData = { - url: url, - method: type + url: url, + method: type, }; let hash = adapter.ajaxOptions(url, type, options); @@ -1010,7 +1017,9 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { if (typeof najax !== 'undefined') { najax(options); } else { - throw new Error('najax does not seem to be defined in your app. Did you override it via `addOrOverrideSandboxGlobals` in the fastboot server?'); + throw new Error( + 'najax does not seem to be defined in your app. Did you override it via `addOrOverrideSandboxGlobals` in the fastboot server?' + ); } }, @@ -1048,7 +1057,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { } heimdall.stop(token); return json; - } + }, }; }); @@ -1059,8 +1068,8 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { let headers = get(this, 'headers'); if (headers !== undefined) { - hash.beforeSend = function (xhr) { - Object.keys(headers).forEach((key) => xhr.setRequestHeader(key, headers[key])); + hash.beforeSend = function(xhr) { + Object.keys(headers).forEach(key => xhr.setRequestHeader(key, headers[key])); }; } @@ -1082,7 +1091,10 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { try { return `${protocol}//${host}${url}`; } catch (fbError) { - throw new Error('You are using Ember Data with no host defined in your adapter. This will attempt to use the host of the FastBoot request, which is not configured for the current host of this request. Please set the hostWhitelist property for in your environment.js. FastBoot Error: ' + fbError.message); + throw new Error( + 'You are using Ember Data with no host defined in your adapter. This will attempt to use the host of the FastBoot request, which is not configured for the current host of this request. Please set the hostWhitelist property for in your environment.js. FastBoot Error: ' + + fbError.message + ); } } } @@ -1123,9 +1135,9 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { return [ { status: `${status}`, - title: "The backend responded with an error", - detail: `${payload}` - } + title: 'The backend responded with an error', + detail: `${payload}`, + }, ]; } }, @@ -1144,10 +1156,10 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { */ generatedDetailedMessage: function(status, headers, payload, requestData) { let shortenedPayload; - let payloadContentType = headers["Content-Type"] || "Empty Content-Type"; + let payloadContentType = headers['Content-Type'] || 'Empty Content-Type'; - if (payloadContentType === "text/html" && payload.length > 250) { - shortenedPayload = "[Omitted Lengthy HTML]"; + if (payloadContentType === 'text/html' && payload.length > 250) { + shortenedPayload = '[Omitted Lengthy HTML]'; } else { shortenedPayload = payload; } @@ -1155,9 +1167,11 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { let requestDescription = requestData.method + ' ' + requestData.url; let payloadDescription = 'Payload (' + payloadContentType + ')'; - return ['Ember Data Request ' + requestDescription + ' returned a ' + status, - payloadDescription, - shortenedPayload].join('\n'); + return [ + 'Ember Data Request ' + requestDescription + ' returned a ' + status, + payloadDescription, + shortenedPayload, + ].join('\n'); }, // @since 2.5.0 @@ -1173,7 +1187,7 @@ const RESTAdapter = Adapter.extend(BuildURLMixin, { } return query; - } + }, }); function ajaxSuccess(adapter, payload, requestData, responseData) { @@ -1198,10 +1212,12 @@ function ajaxSuccess(adapter, payload, requestData, responseData) { function ajaxError(adapter, payload, requestData, responseData) { if (DEBUG) { - let message = `The server returned an empty string for ${requestData.method} ${requestData.url}, which cannot be parsed into a valid JSON. Return either null or {}.`; - let validJSONString = !(responseData.textStatus === "parsererror" && payload === ""); + let message = `The server returned an empty string for ${requestData.method} ${ + requestData.url + }, which cannot be parsed into a valid JSON. Return either null or {}.`; + let validJSONString = !(responseData.textStatus === 'parsererror' && payload === ''); warn(message, validJSONString, { - id: 'ds.adapter.returned-empty-string-as-JSON' + id: 'ds.adapter.returned-empty-string-as-JSON', }); } @@ -1254,7 +1270,7 @@ function ajaxResponseData(jqXHR) { return { status: jqXHR.status, textStatus: jqXHR.textStatus, - headers: parseResponseHeaders(jqXHR.getAllResponseHeaders()) + headers: parseResponseHeaders(jqXHR.getAllResponseHeaders()), }; } diff --git a/addon/index.js b/addon/index.js index 90968d071f1..0064e81d076 100644 --- a/addon/index.js +++ b/addon/index.js @@ -1,5 +1,5 @@ import EmberError from '@ember/error'; -import Ember from "ember"; +import Ember from 'ember'; /** Ember Data @@ -8,9 +8,11 @@ import Ember from "ember"; */ if (Ember.VERSION.match(/^1\.([0-9]|1[0-2])\./)) { - throw new EmberError("Ember Data requires at least Ember 1.13.0, but you have " + - Ember.VERSION + - ". Please upgrade your version of Ember, then upgrade Ember Data."); + throw new EmberError( + 'Ember Data requires at least Ember 1.13.0, but you have ' + + Ember.VERSION + + '. Please upgrade your version of Ember, then upgrade Ember Data.' + ); } import { @@ -44,11 +46,11 @@ import { TimeoutError, AbortError, errorsHashToArray, - errorsArrayToHash + errorsArrayToHash, } from './-private'; -import "ember-inflector"; -import setupContainer from "./setup-container"; +import 'ember-inflector'; +import setupContainer from './setup-container'; import initializeStoreService from './initialize-store-service'; import Transform from './transforms/transform'; @@ -57,44 +59,44 @@ import DateTransform from './transforms/date'; import StringTransform from './transforms/string'; import BooleanTransform from './transforms/boolean'; -import Adapter from "./adapter"; +import Adapter from './adapter'; import JSONAPIAdapter from './adapters/json-api'; import RESTAdapter from './adapters/rest'; -import Serializer from "./serializer"; +import Serializer from './serializer'; import JSONAPISerializer from './serializers/json-api'; import JSONSerializer from './serializers/json'; import RESTSerializer from './serializers/rest'; -import EmbeddedRecordsMixin from "./serializers/embedded-records-mixin"; +import EmbeddedRecordsMixin from './serializers/embedded-records-mixin'; import attr from './attr'; -DS.Store = Store; -DS.PromiseArray = PromiseArray; +DS.Store = Store; +DS.PromiseArray = PromiseArray; DS.PromiseObject = PromiseObject; DS.PromiseManyArray = PromiseManyArray; -DS.Model = Model; +DS.Model = Model; DS.RootState = RootState; -DS.attr = attr; -DS.Errors = Errors; +DS.attr = attr; +DS.Errors = Errors; DS.InternalModel = InternalModel; DS.Snapshot = Snapshot; -DS.Adapter = Adapter; +DS.Adapter = Adapter; DS.AdapterError = AdapterError; DS.InvalidError = InvalidError; DS.TimeoutError = TimeoutError; -DS.AbortError = AbortError; +DS.AbortError = AbortError; DS.UnauthorizedError = UnauthorizedError; -DS.ForbiddenError = ForbiddenError; -DS.NotFoundError = NotFoundError; -DS.ConflictError = ConflictError; -DS.ServerError = ServerError; +DS.ForbiddenError = ForbiddenError; +DS.NotFoundError = NotFoundError; +DS.ConflictError = ConflictError; +DS.ServerError = ServerError; DS.errorsHashToArray = errorsHashToArray; DS.errorsArrayToHash = errorsArrayToHash; @@ -103,14 +105,14 @@ DS.Serializer = Serializer; DS.DebugAdapter = DebugAdapter; -DS.RecordArray = RecordArray; +DS.RecordArray = RecordArray; DS.AdapterPopulatedRecordArray = AdapterPopulatedRecordArray; -DS.ManyArray = ManyArray; +DS.ManyArray = ManyArray; DS.RecordArrayManager = RecordArrayManager; -DS.RESTAdapter = RESTAdapter; -DS.BuildURLMixin = BuildURLMixin; +DS.RESTAdapter = RESTAdapter; +DS.BuildURLMixin = BuildURLMixin; DS.RESTSerializer = RESTSerializer; DS.JSONSerializer = JSONSerializer; @@ -118,18 +120,18 @@ DS.JSONSerializer = JSONSerializer; DS.JSONAPIAdapter = JSONAPIAdapter; DS.JSONAPISerializer = JSONAPISerializer; -DS.Transform = Transform; -DS.DateTransform = DateTransform; +DS.Transform = Transform; +DS.DateTransform = DateTransform; DS.StringTransform = StringTransform; DS.NumberTransform = NumberTransform; DS.BooleanTransform = BooleanTransform; -DS.EmbeddedRecordsMixin = EmbeddedRecordsMixin; +DS.EmbeddedRecordsMixin = EmbeddedRecordsMixin; DS.belongsTo = belongsTo; -DS.hasMany = hasMany; +DS.hasMany = hasMany; -DS.Relationship = Relationship; +DS.Relationship = Relationship; DS._setupContainer = setupContainer; DS._initializeStoreService = initializeStoreService; @@ -138,7 +140,7 @@ Object.defineProperty(DS, 'normalizeModelName', { enumerable: true, writable: false, configurable: false, - value: normalizeModelName + value: normalizeModelName, }); export default DS; diff --git a/addon/serializer.js b/addon/serializer.js index 67f1daf2085..cf9d47cbbd7 100644 --- a/addon/serializer.js +++ b/addon/serializer.js @@ -25,7 +25,6 @@ import EmberObject from '@ember/object'; */ export default EmberObject.extend({ - /** The `store` property is the application's `store` that contains all records. It can be used to look up serializers for other model @@ -154,6 +153,5 @@ export default EmberObject.extend({ */ normalize(typeClass, hash) { return hash; - } - + }, }); diff --git a/addon/serializers/embedded-records-mixin.js b/addon/serializers/embedded-records-mixin.js index 8bd9c347e3c..9868f15033c 100644 --- a/addon/serializers/embedded-records-mixin.js +++ b/addon/serializers/embedded-records-mixin.js @@ -98,7 +98,6 @@ import { warn } from '@ember/debug'; @namespace DS */ export default Mixin.create({ - /** Normalize the record and recursively normalize/extract all the embedded records while pushing them into the store as they are encountered @@ -132,8 +131,10 @@ export default Mixin.create({ }, keyForRelationship(key, typeClass, method) { - if ((method === 'serialize' && this.hasSerializeRecordsOption(key)) || - (method === 'deserialize' && this.hasDeserializeRecordsOption(key))) { + if ( + (method === 'serialize' && this.hasSerializeRecordsOption(key)) || + (method === 'deserialize' && this.hasDeserializeRecordsOption(key)) + ) { return this.keyForAttribute(key, method); } else { return this._super(key, typeClass, method) || key; @@ -203,7 +204,7 @@ export default Mixin.create({ if (includeIds) { let serializedKey = this._getMappedKey(relationship.key, snapshot.type); if (serializedKey === relationship.key && this.keyForRelationship) { - serializedKey = this.keyForRelationship(relationship.key, relationship.kind, "serialize"); + serializedKey = this.keyForRelationship(relationship.key, relationship.kind, 'serialize'); } if (!embeddedSnapshot) { @@ -224,7 +225,7 @@ export default Mixin.create({ let embeddedSnapshot = snapshot.belongsTo(relationship.key); let serializedKey = this._getMappedKey(relationship.key, snapshot.type); if (serializedKey === relationship.key && this.keyForRelationship) { - serializedKey = this.keyForRelationship(relationship.key, relationship.kind, "serialize"); + serializedKey = this.keyForRelationship(relationship.key, relationship.kind, 'serialize'); } if (!embeddedSnapshot) { @@ -384,7 +385,7 @@ export default Mixin.create({ if (this.hasSerializeIdsOption(attr)) { let serializedKey = this._getMappedKey(relationship.key, snapshot.type); if (serializedKey === relationship.key && this.keyForRelationship) { - serializedKey = this.keyForRelationship(relationship.key, relationship.kind, "serialize"); + serializedKey = this.keyForRelationship(relationship.key, relationship.kind, 'serialize'); } json[serializedKey] = snapshot.hasMany(attr, { ids: true }); @@ -409,7 +410,7 @@ export default Mixin.create({ let serializedKey = this.keyForAttribute(relationship.key, 'serialize'); let hasMany = snapshot.hasMany(relationship.key); - json[serializedKey] = A(hasMany).map(function (recordSnapshot) { + json[serializedKey] = A(hasMany).map(function(recordSnapshot) { // // I'm sure I'm being utterly naive here. Propably id is a configurate property and // type too, and the modelName has to be normalized somehow. @@ -421,12 +422,13 @@ export default Mixin.create({ _serializeEmbeddedHasMany(snapshot, json, relationship) { let serializedKey = this._getMappedKey(relationship.key, snapshot.type); if (serializedKey === relationship.key && this.keyForRelationship) { - serializedKey = this.keyForRelationship(relationship.key, relationship.kind, "serialize"); + serializedKey = this.keyForRelationship(relationship.key, relationship.kind, 'serialize'); } - warn( - `The embedded relationship '${serializedKey}' is undefined for '${snapshot.modelName}' with id '${snapshot.id}'. Please include it in your original payload.`, + `The embedded relationship '${serializedKey}' is undefined for '${ + snapshot.modelName + }' with id '${snapshot.id}'. Please include it in your original payload.`, typeOf(snapshot.hasMany(relationship.key)) !== 'undefined', { id: 'ds.serializer.embedded-relationship-undefined' } ); @@ -474,7 +476,11 @@ export default Mixin.create({ if (parentRecord) { let name = parentRecord.name; let embeddedSerializer = this.store.serializerFor(embeddedSnapshot.modelName); - let parentKey = embeddedSerializer.keyForRelationship(name, parentRecord.kind, 'deserialize'); + let parentKey = embeddedSerializer.keyForRelationship( + name, + parentRecord.kind, + 'deserialize' + ); if (parentKey) { delete json[parentKey]; } @@ -494,7 +500,7 @@ export default Mixin.create({ hasSerializeRecordsOption(attr) { let alwaysEmbed = this.hasEmbeddedAlwaysOption(attr); let option = this.attrsOption(attr); - return alwaysEmbed || (option && (option.serialize === 'records')); + return alwaysEmbed || (option && option.serialize === 'records'); }, // checks config for attrs option to serialize records @@ -536,10 +542,10 @@ export default Mixin.create({ _extractEmbeddedRecords(serializer, store, typeClass, partial) { typeClass.eachRelationship((key, relationship) => { if (serializer.hasDeserializeRecordsOption(key)) { - if (relationship.kind === "hasMany") { + if (relationship.kind === 'hasMany') { this._extractEmbeddedHasMany(store, key, partial, relationship); } - if (relationship.kind === "belongsTo") { + if (relationship.kind === 'belongsTo') { this._extractEmbeddedBelongsTo(store, key, partial, relationship); } } @@ -586,7 +592,11 @@ export default Mixin.create({ return; } - let { data, included } = this._normalizeEmbeddedRelationship(store, relationshipMeta, relationshipHash); + let { data, included } = this._normalizeEmbeddedRelationship( + store, + relationshipMeta, + relationshipHash + ); hash.included = hash.included || []; hash.included.push(data); if (included) { @@ -613,5 +623,5 @@ export default Mixin.create({ return serializer.normalize(modelClass, relationshipHash, null); }, - isEmbeddedRecordsMixin: true + isEmbeddedRecordsMixin: true, }); diff --git a/addon/serializers/json-api.js b/addon/serializers/json-api.js index b9c587f11aa..923b769eb09 100644 --- a/addon/serializers/json-api.js +++ b/addon/serializers/json-api.js @@ -129,7 +129,6 @@ import { normalizeModelName } from '../-private'; @extends DS.JSONSerializer */ const JSONAPISerializer = JSONSerializer.extend({ - /** @method _normalizeDocumentHelper @param {Object} documentHash @@ -137,7 +136,6 @@ const JSONAPISerializer = JSONSerializer.extend({ @private */ _normalizeDocumentHelper(documentHash) { - if (typeOf(documentHash.data) === 'object') { documentHash.data = this._normalizeResourceHelper(documentHash.data); } else if (Array.isArray(documentHash.data)) { @@ -156,7 +154,8 @@ const JSONAPISerializer = JSONSerializer.extend({ for (let i = 0; i < documentHash.included.length; i++) { let included = documentHash.included[i]; let normalized = this._normalizeResourceHelper(included); - if (normalized !== null) { // can be null when unknown type is encountered + if (normalized !== null) { + // can be null when unknown type is encountered ret.push(normalized); } } @@ -187,7 +186,7 @@ const JSONAPISerializer = JSONSerializer.extend({ */ _normalizeResourceHelper(resourceHash) { assert(this.warnMessageForUndefinedType(), !isNone(resourceHash.type), { - id: 'ds.serializer.type-is-undefined' + id: 'ds.serializer.type-is-undefined', }); let modelName, usedLookup; @@ -197,7 +196,7 @@ const JSONAPISerializer = JSONSerializer.extend({ if (!this.store._hasModelFor(modelName)) { warn(this.warnMessageNoModelForType(modelName, resourceHash.type, usedLookup), false, { - id: 'ds.serializer.model-for-type-missing' + id: 'ds.serializer.model-for-type-missing', }); return null; } @@ -237,9 +236,13 @@ const JSONAPISerializer = JSONSerializer.extend({ normalizeQueryRecordResponse() { let normalized = this._super(...arguments); - assert('Expected the primary data returned by the serializer for a `queryRecord` response to be a single object but instead it was an array.', !Array.isArray(normalized.data), { - id: 'ds.serializer.json-api.queryRecord-array-response' - }); + assert( + 'Expected the primary data returned by the serializer for a `queryRecord` response to be a single object but instead it was an array.', + !Array.isArray(normalized.data), + { + id: 'ds.serializer.json-api.queryRecord-array-response', + } + ); return normalized; }, @@ -248,14 +251,22 @@ const JSONAPISerializer = JSONSerializer.extend({ let attributes = {}; if (resourceHash.attributes) { - modelClass.eachAttribute((key) => { + modelClass.eachAttribute(key => { let attributeKey = this.keyForAttribute(key, 'deserialize'); if (resourceHash.attributes[attributeKey] !== undefined) { attributes[key] = resourceHash.attributes[attributeKey]; } if (DEBUG) { - if (resourceHash.attributes[attributeKey] === undefined && resourceHash.attributes[key] !== undefined) { - assert(`Your payload for '${modelClass.modelName}' contains '${key}', but your serializer is setup to look for '${attributeKey}'. This is most likely because Ember Data's JSON API serializer dasherizes attribute keys by default. You should subclass JSONAPISerializer and implement 'keyForAttribute(key) { return key; }' to prevent Ember Data from customizing your attribute keys.`, false); + if ( + resourceHash.attributes[attributeKey] === undefined && + resourceHash.attributes[key] !== undefined + ) { + assert( + `Your payload for '${ + modelClass.modelName + }' contains '${key}', but your serializer is setup to look for '${attributeKey}'. This is most likely because Ember Data's JSON API serializer dasherizes attribute keys by default. You should subclass JSONAPISerializer and implement 'keyForAttribute(key) { return key; }' to prevent Ember Data from customizing your attribute keys.`, + false + ); } } }); @@ -274,7 +285,6 @@ const JSONAPISerializer = JSONSerializer.extend({ @return {Object} */ extractRelationship(relationshipHash) { - if (typeOf(relationshipHash.data) === 'object') { relationshipHash.data = this._normalizeRelationshipDataHelper(relationshipHash.data); } @@ -310,14 +320,20 @@ const JSONAPISerializer = JSONSerializer.extend({ modelClass.eachRelationship((key, relationshipMeta) => { let relationshipKey = this.keyForRelationship(key, relationshipMeta.kind, 'deserialize'); if (resourceHash.relationships[relationshipKey] !== undefined) { - let relationshipHash = resourceHash.relationships[relationshipKey]; relationships[key] = this.extractRelationship(relationshipHash); - } if (DEBUG) { - if (resourceHash.relationships[relationshipKey] === undefined && resourceHash.relationships[key] !== undefined) { - assert(`Your payload for '${modelClass.modelName}' contains '${key}', but your serializer is setup to look for '${relationshipKey}'. This is most likely because Ember Data's JSON API serializer dasherizes relationship keys by default. You should subclass JSONAPISerializer and implement 'keyForRelationship(key) { return key; }' to prevent Ember Data from customizing your relationship keys.`, false); + if ( + resourceHash.relationships[relationshipKey] === undefined && + resourceHash.relationships[key] !== undefined + ) { + assert( + `Your payload for '${ + modelClass.modelName + }' contains '${key}', but your serializer is setup to look for '${relationshipKey}'. This is most likely because Ember Data's JSON API serializer dasherizes relationship keys by default. You should subclass JSONAPISerializer and implement 'keyForRelationship(key) { return key; }' to prevent Ember Data from customizing your relationship keys.`, + false + ); } } }); @@ -378,10 +394,10 @@ const JSONAPISerializer = JSONSerializer.extend({ } let data = { - id: this.extractId(modelClass, resourceHash), - type: this._extractType(modelClass, resourceHash), - attributes: this.extractAttributes(modelClass, resourceHash), - relationships: this.extractRelationships(modelClass, resourceHash) + id: this.extractId(modelClass, resourceHash), + type: this._extractType(modelClass, resourceHash), + attributes: this.extractAttributes(modelClass, resourceHash), + relationships: this.extractRelationships(modelClass, resourceHash), }; this.applyTransforms(modelClass, data.attributes); @@ -501,7 +517,7 @@ const JSONAPISerializer = JSONSerializer.extend({ data = { type: payloadType, - id: belongsTo.id + id: belongsTo.id, }; } @@ -516,7 +532,6 @@ const JSONAPISerializer = JSONSerializer.extend({ if (this.shouldSerializeHasMany(snapshot, key, relationship)) { let hasMany = snapshot.hasMany(key); if (hasMany !== undefined) { - json.relationships = json.relationships || {}; let payloadKey = this._getMappedKey(key, snapshot.type); @@ -534,33 +549,45 @@ const JSONAPISerializer = JSONSerializer.extend({ data[i] = { type: payloadType, - id: item.id + id: item.id, }; } json.relationships[payloadKey] = { data }; } } - } + }, }); if (DEBUG) { JSONAPISerializer.reopen({ willMergeMixin(props) { let constructor = this.constructor; - warn(`You've defined 'extractMeta' in ${constructor.toString()} which is not used for serializers extending JSONAPISerializer. Read more at https://emberjs.com/api/data/classes/DS.JSONAPISerializer.html#toc_customizing-meta on how to customize meta when using JSON API.`, isNone(props.extractMeta) || props.extractMeta === JSONSerializer.prototype.extractMeta, { - id: 'ds.serializer.json-api.extractMeta' - }); - warn('The JSONAPISerializer does not work with the EmbeddedRecordsMixin because the JSON API spec does not describe how to format embedded resources.', !props.isEmbeddedRecordsMixin, { - id: 'ds.serializer.embedded-records-mixin-not-supported' - }); + warn( + `You've defined 'extractMeta' in ${constructor.toString()} which is not used for serializers extending JSONAPISerializer. Read more at https://emberjs.com/api/data/classes/DS.JSONAPISerializer.html#toc_customizing-meta on how to customize meta when using JSON API.`, + isNone(props.extractMeta) || props.extractMeta === JSONSerializer.prototype.extractMeta, + { + id: 'ds.serializer.json-api.extractMeta', + } + ); + warn( + 'The JSONAPISerializer does not work with the EmbeddedRecordsMixin because the JSON API spec does not describe how to format embedded resources.', + !props.isEmbeddedRecordsMixin, + { + id: 'ds.serializer.embedded-records-mixin-not-supported', + } + ); }, warnMessageForUndefinedType() { - return 'Encountered a resource object with an undefined type (resolved resource using ' + this.constructor.toString() + ')'; + return ( + 'Encountered a resource object with an undefined type (resolved resource using ' + + this.constructor.toString() + + ')' + ); }, warnMessageNoModelForType(modelName, originalType, usedLookup) { return `Encountered a resource object with type "${originalType}", but no model was found for model name "${modelName}" (resolved model name using '${this.constructor.toString()}.${usedLookup}("${originalType}")').`; - } + }, }); } diff --git a/addon/serializers/json.js b/addon/serializers/json.js index 88d9c1a33d3..8fd59410393 100644 --- a/addon/serializers/json.js +++ b/addon/serializers/json.js @@ -2,13 +2,13 @@ import { assign, merge } from '@ember/polyfills'; import { isNone, typeOf } from '@ember/utils'; import { get } from '@ember/object'; import { assert, warn } from '@ember/debug'; -import Serializer from "../serializer"; +import Serializer from '../serializer'; import { getOwner, coerceId, modelHasAttributeOrRelationshipNamedType, normalizeModelName, - errorsArrayToHash + errorsArrayToHash, } from '../-private'; const emberAssign = assign || merge; @@ -80,7 +80,6 @@ const emberAssign = assign || merge; @extends DS.Serializer */ const JSONSerializer = Serializer.extend({ - /** The `primaryKey` is used when serializing and deserializing data. Ember Data always uses the `id` property to store the id of @@ -186,7 +185,9 @@ const JSONSerializer = Serializer.extend({ let attributes = get(typeClass, 'attributes'); typeClass.eachTransformedAttribute((key, typeClass) => { - if (data[key] === undefined) { return; } + if (data[key] === undefined) { + return; + } let transform = this.transformFor(typeClass); let transformMeta = attributes.get(key); @@ -452,12 +453,15 @@ const JSONSerializer = Serializer.extend({ _normalizeResponse(store, primaryModelClass, payload, id, requestType, isSingle) { let documentHash = { data: null, - included: [] + included: [], }; let meta = this.extractMeta(store, primaryModelClass, payload); if (meta) { - assert('The `meta` returned from `extractMeta` has to be an object, not "' + typeOf(meta) + '".', typeOf(meta) === 'object'); + assert( + 'The `meta` returned from `extractMeta` has to be an object, not "' + typeOf(meta) + '".', + typeOf(meta) === 'object' + ); documentHash.meta = meta; } @@ -484,7 +488,6 @@ const JSONSerializer = Serializer.extend({ return documentHash; }, - /** Normalizes a part of the JSON payload returned by the server. You should override this method, munge the hash @@ -536,10 +539,10 @@ const JSONSerializer = Serializer.extend({ } data = { - id: this.extractId(modelClass, resourceHash), - type: modelClass.modelName, - attributes: this.extractAttributes(modelClass, resourceHash), - relationships: this.extractRelationships(modelClass, resourceHash) + id: this.extractId(modelClass, resourceHash), + type: modelClass.modelName, + attributes: this.extractAttributes(modelClass, resourceHash), + relationships: this.extractRelationships(modelClass, resourceHash), }; this.applyTransforms(modelClass, data.attributes); @@ -576,7 +579,7 @@ const JSONSerializer = Serializer.extend({ let attributeKey; let attributes = {}; - modelClass.eachAttribute((key) => { + modelClass.eachAttribute(key => { attributeKey = this.keyForAttribute(key, 'deserialize'); if (resourceHash[attributeKey] !== undefined) { attributes[key] = resourceHash[attributeKey]; @@ -597,7 +600,9 @@ const JSONSerializer = Serializer.extend({ @return {Object} */ extractRelationship(relationshipModelName, relationshipHash) { - if (isNone(relationshipHash)) { return null; } + if (isNone(relationshipHash)) { + return null; + } /* When `relationshipHash` is an object it usually means that the relationship is polymorphic. It could however also be embedded resources that the @@ -666,7 +671,11 @@ const JSONSerializer = Serializer.extend({ // than the type and the hash (which might only be an id) for the // relationship, hence we pass the key, resource and // relationshipMeta too - data = this.extractPolymorphicRelationship(relationshipMeta.type, relationshipHash, { key, resourceHash, relationshipMeta }); + data = this.extractPolymorphicRelationship(relationshipMeta.type, relationshipHash, { + key, + resourceHash, + relationshipMeta, + }); } else { data = this.extractRelationship(relationshipMeta.type, relationshipHash); } @@ -717,8 +726,12 @@ const JSONSerializer = Serializer.extend({ if (this.keyForRelationship) { typeClass.eachRelationship((key, relationship) => { payloadKey = this.keyForRelationship(key, relationship.kind, 'deserialize'); - if (key === payloadKey) { return; } - if (hash[payloadKey] === undefined) { return; } + if (key === payloadKey) { + return; + } + if (hash[payloadKey] === undefined) { + return; + } hash[key] = hash[payloadKey]; delete hash[payloadKey]; @@ -739,7 +752,9 @@ const JSONSerializer = Serializer.extend({ for (let key in attrs) { normalizedKey = payloadKey = this._getMappedKey(key, modelClass); - if (hash[payloadKey] === undefined) { continue; } + if (hash[payloadKey] === undefined) { + continue; + } if (get(modelClass, 'attributes').has(key)) { normalizedKey = this.keyForAttribute(key); @@ -767,9 +782,17 @@ const JSONSerializer = Serializer.extend({ @return {String} key */ _getMappedKey(key, modelClass) { - warn('There is no attribute or relationship with the name `' + key + '` on `' + modelClass.modelName + '`. Check your serializers attrs hash.', get(modelClass, 'attributes').has(key) || get(modelClass, 'relationshipsByName').has(key), { - id: 'ds.serializer.no-mapped-attrs-key' - }); + warn( + 'There is no attribute or relationship with the name `' + + key + + '` on `' + + modelClass.modelName + + '`. Check your serializers attrs hash.', + get(modelClass, 'attributes').has(key) || get(modelClass, 'relationshipsByName').has(key), + { + id: 'ds.serializer.no-mapped-attrs-key', + } + ); let attrs = get(this, 'attrs'); let mappedKey; @@ -833,10 +856,12 @@ const JSONSerializer = Serializer.extend({ if (this._mustSerialize(key)) { return true; } - return this._canSerialize(key) && (relationshipType === 'manyToNone' || relationshipType === 'manyToMany'); + return ( + this._canSerialize(key) && + (relationshipType === 'manyToNone' || relationshipType === 'manyToMany') + ); }, - // SERIALIZE /** Called when a record is saved in order to convert the @@ -1073,7 +1098,6 @@ const JSONSerializer = Serializer.extend({ @param {Object} attribute */ serializeAttribute(snapshot, json, key, attribute) { - if (this._canSerialize(key)) { let type = attribute.type; let value = snapshot.attr(key); @@ -1084,7 +1108,7 @@ const JSONSerializer = Serializer.extend({ // if provided, use the mapping provided by `attrs` in // the serializer - let payloadKey = this._getMappedKey(key, snapshot.type); + let payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key && this.keyForAttribute) { payloadKey = this.keyForAttribute(key, 'serialize'); @@ -1131,7 +1155,7 @@ const JSONSerializer = Serializer.extend({ // the serializer let payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key && this.keyForRelationship) { - payloadKey = this.keyForRelationship(key, "belongsTo", "serialize"); + payloadKey = this.keyForRelationship(key, 'belongsTo', 'serialize'); } //Need to check whether the id is there for new&async records @@ -1183,7 +1207,7 @@ const JSONSerializer = Serializer.extend({ // the serializer let payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key && this.keyForRelationship) { - payloadKey = this.keyForRelationship(key, "hasMany", "serialize"); + payloadKey = this.keyForRelationship(key, 'hasMany', 'serialize'); } json[payloadKey] = hasMany; @@ -1352,7 +1376,7 @@ const JSONSerializer = Serializer.extend({ this.normalizeUsingDeclaredMapping(typeClass, payload); - typeClass.eachAttribute((name) => { + typeClass.eachAttribute(name => { let key = this.keyForAttribute(name, 'deserialize'); if (key !== name && payload[key] !== undefined) { payload[name] = payload[key]; @@ -1360,7 +1384,7 @@ const JSONSerializer = Serializer.extend({ } }); - typeClass.eachRelationship((name) => { + typeClass.eachRelationship(name => { let key = this.keyForRelationship(name, 'deserialize'); if (key !== name && payload[key] !== undefined) { payload[name] = payload[key]; @@ -1454,7 +1478,7 @@ const JSONSerializer = Serializer.extend({ assert("Unable to find transform for '" + attributeType + "'", skipAssertion || !!transform); return transform; - } + }, }); export default JSONSerializer; diff --git a/addon/serializers/rest.js b/addon/serializers/rest.js index 84acff2610b..8987067e4f7 100644 --- a/addon/serializers/rest.js +++ b/addon/serializers/rest.js @@ -6,15 +6,15 @@ import { typeOf, isNone } from '@ember/utils'; import { makeArray } from '@ember/array'; import { camelize } from '@ember/string'; -import { singularize } from "ember-inflector"; +import { singularize } from 'ember-inflector'; import { assert, deprecate, warn } from '@ember/debug'; import { DEBUG } from '@glimmer/env'; -import JSONSerializer from "../serializers/json"; +import JSONSerializer from '../serializers/json'; import { coerceId, modelHasAttributeOrRelationshipNamedType, - normalizeModelName + normalizeModelName, } from '../-private'; /** @@ -61,7 +61,6 @@ import { @extends DS.JSONSerializer */ const RESTSerializer = JSONSerializer.extend({ - /** `keyForPolymorphicType` can be used to define a custom key when serializing and deserializing a polymorphic type. By default, the @@ -175,14 +174,20 @@ const RESTSerializer = JSONSerializer.extend({ _normalizeArray(store, modelName, arrayHash, prop) { let documentHash = { data: [], - included: [] + included: [], }; let modelClass = store.modelFor(modelName); let serializer = store.serializerFor(modelName); - makeArray(arrayHash).forEach((hash) => { - let { data, included } = this._normalizePolymorphicRecord(store, hash, prop, modelClass, serializer); + makeArray(arrayHash).forEach(hash => { + let { data, included } = this._normalizePolymorphicRecord( + store, + hash, + prop, + modelClass, + serializer + ); documentHash.data.push(data); if (included) { documentHash.included.push(...included); @@ -225,12 +230,15 @@ const RESTSerializer = JSONSerializer.extend({ _normalizeResponse(store, primaryModelClass, payload, id, requestType, isSingle) { let documentHash = { data: null, - included: [] + included: [], }; let meta = this.extractMeta(store, primaryModelClass, payload); if (meta) { - assert('The `meta` returned from `extractMeta` has to be an object, not "' + typeOf(meta) + '".', typeOf(meta) === 'object'); + assert( + 'The `meta` returned from `extractMeta` has to be an object, not "' + typeOf(meta) + '".', + typeOf(meta) === 'object' + ); documentHash.meta = meta; } @@ -269,12 +277,12 @@ const RESTSerializer = JSONSerializer.extend({ var typeName = this.modelNameFromPayloadKey(modelName); if (!store._hasModelFor(typeName)) { warn(this.warnMessageNoModelForKey(modelName, typeName), false, { - id: 'ds.serializer.model-for-key-missing' + id: 'ds.serializer.model-for-key-missing', }); continue; } - var isPrimary = (!forcedSecondary && this.isPrimaryType(store, typeName, primaryModelClass)); + var isPrimary = !forcedSecondary && this.isPrimaryType(store, typeName, primaryModelClass); var value = payload[prop]; if (value === null) { @@ -282,12 +290,14 @@ const RESTSerializer = JSONSerializer.extend({ } if (DEBUG) { - let isQueryRecordAnArray = requestType === 'queryRecord' && isPrimary && Array.isArray(value); - let message = "The adapter returned an array for the primary data of a `queryRecord` response. This is deprecated as `queryRecord` should return a single record."; + let isQueryRecordAnArray = + requestType === 'queryRecord' && isPrimary && Array.isArray(value); + let message = + 'The adapter returned an array for the primary data of a `queryRecord` response. This is deprecated as `queryRecord` should return a single record.'; deprecate(message, !isQueryRecordAnArray, { id: 'ds.serializer.rest.queryRecord-array-response', - until: '3.0' + until: '3.0', }); } @@ -303,7 +313,13 @@ const RESTSerializer = JSONSerializer.extend({ ``` */ if (isPrimary && !Array.isArray(value)) { - let { data, included } = this._normalizePolymorphicRecord(store, value, prop, primaryModelClass, this); + let { data, included } = this._normalizePolymorphicRecord( + store, + value, + prop, + primaryModelClass, + this + ); documentHash.data = data; if (included) { documentHash.included.push(...included); @@ -319,7 +335,6 @@ const RESTSerializer = JSONSerializer.extend({ if (isSingle) { data.forEach(resource => { - /* Figures out if this is the primary record or not. @@ -390,14 +405,14 @@ const RESTSerializer = JSONSerializer.extend({ pushPayload(store, payload) { let documentHash = { data: [], - included: [] + included: [], }; for (var prop in payload) { var modelName = this.modelNameFromPayloadKey(prop); if (!store._hasModelFor(modelName)) { warn(this.warnMessageNoModelForKey(prop, modelName), false, { - id: 'ds.serializer.model-for-key-missing' + id: 'ds.serializer.model-for-key-missing', }); continue; } @@ -772,23 +787,37 @@ const RESTSerializer = JSONSerializer.extend({ let isPolymorphic = relationshipMeta.options.polymorphic; let typeProperty = this.keyForPolymorphicType(key, relationshipType, 'deserialize'); - if (isPolymorphic && resourceHash[typeProperty] !== undefined && typeof relationshipHash !== 'object') { + if ( + isPolymorphic && + resourceHash[typeProperty] !== undefined && + typeof relationshipHash !== 'object' + ) { let type = this.modelNameFromPayloadKey(resourceHash[typeProperty]); return { id: relationshipHash, - type: type + type: type, }; } return this._super(...arguments); - } + }, }); if (DEBUG) { RESTSerializer.reopen({ warnMessageNoModelForKey(prop, typeKey) { - return 'Encountered "' + prop + '" in payload, but no model was found for model name "' + typeKey + '" (resolved model name using ' + this.constructor.toString() + '.modelNameFromPayloadKey("' + prop + '"))'; - } + return ( + 'Encountered "' + + prop + + '" in payload, but no model was found for model name "' + + typeKey + + '" (resolved model name using ' + + this.constructor.toString() + + '.modelNameFromPayloadKey("' + + prop + + '"))' + ); + }, }); } diff --git a/addon/setup-container.js b/addon/setup-container.js index 9b78e973ff7..1040478a339 100644 --- a/addon/setup-container.js +++ b/addon/setup-container.js @@ -1,7 +1,4 @@ -import { - DebugAdapter, - Store -} from './-private'; +import { DebugAdapter, Store } from './-private'; import JSONAPISerializer from './serializers/json-api'; import JSONSerializer from './serializers/json'; import RESTSerializer from './serializers/rest'; @@ -41,7 +38,6 @@ function initializeStore(registry) { registry.register('adapter:-json-api', JSONAPIAdapter); registry.register('serializer:-json-api', JSONAPISerializer); - if (!has(registry, 'service:store')) { registry.register('service:store', Store); } diff --git a/addon/transforms/boolean.js b/addon/transforms/boolean.js index b7d1a5a9b1e..241084ba3a0 100644 --- a/addon/transforms/boolean.js +++ b/addon/transforms/boolean.js @@ -44,11 +44,11 @@ export default Transform.extend({ } let type = typeof serialized; - if (type === "boolean") { + if (type === 'boolean') { return serialized; - } else if (type === "string") { + } else if (type === 'string') { return /^(true|t|1)$/i.test(serialized); - } else if (type === "number") { + } else if (type === 'number') { return serialized === 1; } else { return false; @@ -61,5 +61,5 @@ export default Transform.extend({ } return Boolean(deserialized); - } + }, }); diff --git a/addon/transforms/date.js b/addon/transforms/date.js index e984ca9f448..8fef1da008e 100644 --- a/addon/transforms/date.js +++ b/addon/transforms/date.js @@ -26,7 +26,7 @@ export default Transform.extend({ deserialize(serialized) { let type = typeof serialized; - if (type === "string") { + if (type === 'string') { let offset = serialized.indexOf('+'); if (offset !== -1 && serialized.length - 5 === offset) { @@ -34,8 +34,8 @@ export default Transform.extend({ return new Date(serialized.slice(0, offset) + ':' + serialized.slice(offset)); } return new Date(serialized); - } else if (type === "number") { - return new Date(serialized) + } else if (type === 'number') { + return new Date(serialized); } else if (serialized === null || serialized === undefined) { // if the value is null return null // if the value is not present in the data return undefined @@ -51,5 +51,5 @@ export default Transform.extend({ } else { return null; } - } + }, }); diff --git a/addon/transforms/number.js b/addon/transforms/number.js index 75b35eda250..267df17e6f6 100644 --- a/addon/transforms/number.js +++ b/addon/transforms/number.js @@ -49,5 +49,5 @@ export default Transform.extend({ return isNumber(transformed) ? transformed : null; } - } + }, }); diff --git a/addon/transforms/string.js b/addon/transforms/string.js index 2c071006920..c4aeac50781 100644 --- a/addon/transforms/string.js +++ b/addon/transforms/string.js @@ -29,5 +29,5 @@ export default Transform.extend({ }, serialize(deserialized) { return none(deserialized) ? null : String(deserialized); - } + }, }); diff --git a/addon/transforms/transform.js b/addon/transforms/transform.js index c04986d1f44..5cbdb20a1ce 100644 --- a/addon/transforms/transform.js +++ b/addon/transforms/transform.js @@ -106,5 +106,5 @@ export default EmberObject.extend({ @param options hash of options passed to `DS.attr` @return The deserialized value */ - deserialize: null + deserialize: null, }); diff --git a/app/initializers/ember-data.js b/app/initializers/ember-data.js index fba3329b260..8d185c5c98b 100644 --- a/app/initializers/ember-data.js +++ b/app/initializers/ember-data.js @@ -42,5 +42,5 @@ import 'ember-data'; export default { name: 'ember-data', - initialize: setupContainer + initialize: setupContainer, }; diff --git a/app/instance-initializers/ember-data.js b/app/instance-initializers/ember-data.js index 50b27f03026..6b0dee68e7b 100644 --- a/app/instance-initializers/ember-data.js +++ b/app/instance-initializers/ember-data.js @@ -1,6 +1,6 @@ import initializeStoreService from 'ember-data/initialize-store-service'; export default { - name: "ember-data", - initialize: initializeStoreService + name: 'ember-data', + initialize: initializeStoreService, }; diff --git a/bin/publish-builds b/bin/publish-builds index 1842d996b27..6d23a328c40 100755 --- a/bin/publish-builds +++ b/bin/publish-builds @@ -4,5 +4,5 @@ echo -e "CURRENT_BRANCH: ${TRAVIS_BRANCH}\n" echo -e "PULL_REQUEST: ${TRAVIS_PULL_REQUEST}\n" if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then - ./bin/publish-to-s3.js + node ./bin/publish-to-s3.js fi diff --git a/bin/publish-to-s3.js b/bin/publish-to-s3.js index d01b3febc36..80d9b39d07b 100755 --- a/bin/publish-to-s3.js +++ b/bin/publish-to-s3.js @@ -1,5 +1,3 @@ -#!/usr/bin/env node - // This publish script remains in order to publish the yui-docs to S3, builds no // longer need to be published to S3. // @@ -19,5 +17,5 @@ // ``` var S3Publisher = require('ember-publisher'); var configPath = require('path').join(__dirname, '../config/s3ProjectConfig.js'); -var publisher = new S3Publisher({projectConfigPath: configPath}); +var publisher = new S3Publisher({ projectConfigPath: configPath }); publisher.publish(); diff --git a/blueprints/adapter-test/index.js b/blueprints/adapter-test/index.js index 1373dc62c71..8fb29a4621d 100644 --- a/blueprints/adapter-test/index.js +++ b/blueprints/adapter-test/index.js @@ -1,5 +1,3 @@ -/* eslint-env node */ - var testInfo = require('ember-cli-test-info'); var useTestFrameworkDetector = require('../test-framework-detector'); @@ -8,7 +6,7 @@ module.exports = useTestFrameworkDetector({ locals: function(options) { return { - friendlyTestDescription: testInfo.description(options.entity.name, "Unit", "Adapter") + friendlyTestDescription: testInfo.description(options.entity.name, 'Unit', 'Adapter'), }; - } + }, }); diff --git a/blueprints/adapter/index.js b/blueprints/adapter/index.js index b3ecab8c23f..d8db9642bb3 100644 --- a/blueprints/adapter/index.js +++ b/blueprints/adapter/index.js @@ -1,15 +1,11 @@ -/* eslint-env node */ - var extendFromApplicationEntity = require('../../lib/utilities/extend-from-application-entity'); module.exports = { description: 'Generates an ember-data adapter.', - availableOptions: [ - { name: 'base-class', type: String } - ], + availableOptions: [{ name: 'base-class', type: String }], locals: function(options) { return extendFromApplicationEntity('adapter', 'DS.JSONAPIAdapter', options); - } + }, }; diff --git a/blueprints/model-test/index.js b/blueprints/model-test/index.js index d4406a1c08f..d8e0f7f1092 100644 --- a/blueprints/model-test/index.js +++ b/blueprints/model-test/index.js @@ -1,5 +1,3 @@ -/* eslint-env node */ - var ModelBlueprint = require('../model'); var testInfo = require('ember-cli-test-info'); var useTestFrameworkDetector = require('../test-framework-detector'); @@ -10,8 +8,8 @@ module.exports = useTestFrameworkDetector({ locals: function(options) { var result = ModelBlueprint.locals.apply(this, arguments); - result.friendlyTestDescription = testInfo.description(options.entity.name, "Unit", "Model"); + result.friendlyTestDescription = testInfo.description(options.entity.name, 'Unit', 'Model'); return result; - } + }, }); diff --git a/blueprints/model/index.js b/blueprints/model/index.js index 6f49c9a3a6a..9ea731000dd 100644 --- a/blueprints/model/index.js +++ b/blueprints/model/index.js @@ -1,16 +1,11 @@ -/* eslint-env node */ - -var inflection = require('inflection'); +var inflection = require('inflection'); var stringUtils = require('ember-cli-string-utils'); -var EOL = require('os').EOL; +var EOL = require('os').EOL; module.exports = { description: 'Generates an ember-data model.', - anonymousOptions: [ - 'name', - 'attr:type' - ], + anonymousOptions: ['name', 'attr:type'], locals: function(options) { var attrs = []; @@ -57,22 +52,22 @@ module.exports = { return { attrs: attrs, - needs: needs + needs: needs, }; - } + }, }; function dsAttr(name, type) { switch (type) { - case 'belongs-to': - return 'DS.belongsTo(\'' + name + '\')'; - case 'has-many': - return 'DS.hasMany(\'' + name + '\')'; - case '': - //"If you don't specify the type of the attribute, it will be whatever was provided by the server" - //https://emberjs.com/guides/models/defining-models/ - return 'DS.attr()'; - default: - return 'DS.attr(\'' + type + '\')'; + case 'belongs-to': + return "DS.belongsTo('" + name + "')"; + case 'has-many': + return "DS.hasMany('" + name + "')"; + case '': + //"If you don't specify the type of the attribute, it will be whatever was provided by the server" + //https://emberjs.com/guides/models/defining-models/ + return 'DS.attr()'; + default: + return "DS.attr('" + type + "')"; } } diff --git a/blueprints/serializer-test/index.js b/blueprints/serializer-test/index.js index 3216223b666..a7388eb4efc 100644 --- a/blueprints/serializer-test/index.js +++ b/blueprints/serializer-test/index.js @@ -1,5 +1,3 @@ -/* eslint-env node */ - var testInfo = require('ember-cli-test-info'); var useTestFrameworkDetector = require('../test-framework-detector'); @@ -8,7 +6,7 @@ module.exports = useTestFrameworkDetector({ locals: function(options) { return { - friendlyTestDescription: testInfo.description(options.entity.name, "Unit", "Serializer") + friendlyTestDescription: testInfo.description(options.entity.name, 'Unit', 'Serializer'), }; - } + }, }); diff --git a/blueprints/serializer/index.js b/blueprints/serializer/index.js index b5b278ae70a..704014851f4 100644 --- a/blueprints/serializer/index.js +++ b/blueprints/serializer/index.js @@ -1,15 +1,11 @@ -/* eslint-env node */ - var extendFromApplicationEntity = require('../../lib/utilities/extend-from-application-entity'); module.exports = { description: 'Generates an ember-data serializer.', - availableOptions: [ - { name: 'base-class', type: String } - ], + availableOptions: [{ name: 'base-class', type: String }], locals: function(options) { return extendFromApplicationEntity('serializer', 'DS.JSONAPISerializer', options); - } + }, }; diff --git a/blueprints/test-framework-detector.js b/blueprints/test-framework-detector.js index 6b7ef9d3a01..2fa3da77255 100644 --- a/blueprints/test-framework-detector.js +++ b/blueprints/test-framework-detector.js @@ -15,20 +15,20 @@ module.exports = function(blueprint) { let dependencies = this.project.dependencies(); if ('ember-qunit' in dependencies) { type = 'qunit-rfc-232'; - } else if ('ember-cli-qunit' in dependencies) { let checker = new VersionChecker(this.project); - if (fs.existsSync(this.path + '/qunit-rfc-232-files') && checker.for('ember-cli-qunit', 'npm').gte('4.2.0')) { + if ( + fs.existsSync(this.path + '/qunit-rfc-232-files') && + checker.for('ember-cli-qunit', 'npm').gte('4.2.0') + ) { type = 'qunit-rfc-232'; } else { type = 'qunit'; } - } else if ('ember-cli-mocha' in dependencies) { type = 'mocha'; - } else { - this.ui.writeLine('Couldn\'t determine test style - using QUnit'); + this.ui.writeLine("Couldn't determine test style - using QUnit"); type = 'qunit'; } diff --git a/blueprints/transform-test/index.js b/blueprints/transform-test/index.js index fe0ed6781f6..35d846c0d64 100644 --- a/blueprints/transform-test/index.js +++ b/blueprints/transform-test/index.js @@ -1,5 +1,3 @@ -/* eslint-env node */ - var testInfo = require('ember-cli-test-info'); var useTestFrameworkDetector = require('../test-framework-detector'); @@ -8,7 +6,7 @@ module.exports = useTestFrameworkDetector({ locals: function(options) { return { - friendlyTestDescription: testInfo.description(options.entity.name, "Unit", "Transform") + friendlyTestDescription: testInfo.description(options.entity.name, 'Unit', 'Transform'), }; - } + }, }); diff --git a/blueprints/transform/index.js b/blueprints/transform/index.js index a272e5162ed..476ff90924a 100644 --- a/blueprints/transform/index.js +++ b/blueprints/transform/index.js @@ -1,5 +1,3 @@ -/* eslint-env node */ - module.exports = { - description: 'Generates an ember-data value transform.' + description: 'Generates an ember-data value transform.', }; diff --git a/config/ember-try.js b/config/ember-try.js index 44c3e0be73e..fdaa5362d1b 100644 --- a/config/ember-try.js +++ b/config/ember-try.js @@ -1,4 +1,4 @@ -/* eslint-env node, es6 */ +'use strict'; const getChannelURL = require('ember-source-channel-url'); @@ -6,57 +6,57 @@ module.exports = function() { return Promise.all([ getChannelURL('release'), getChannelURL('beta'), - getChannelURL('canary') - ]).then((urls) => { + getChannelURL('canary'), + ]).then(urls => { return { useYarn: true, scenarios: [ { name: 'default', - bower: { }, - npm: { } + bower: {}, + npm: {}, }, { name: 'ember-lts-2.12', npm: { devDependencies: { - 'ember-source': '~2.12.0' - } - } + 'ember-source': '~2.12.0', + }, + }, }, { name: 'ember-lts-2.16', npm: { devDependencies: { - 'ember-source': '~2.16.0' - } - } + 'ember-source': '~2.16.0', + }, + }, }, { name: 'ember-release', npm: { devDependencies: { - 'ember-source': urls[0] - } - } + 'ember-source': urls[0], + }, + }, }, { name: 'ember-beta', npm: { devDependencies: { - 'ember-source': urls[1] - } - } + 'ember-source': urls[1], + }, + }, }, { name: 'ember-canary', npm: { devDependencies: { - 'ember-source': urls[2] - } - } - } - ] + 'ember-source': urls[2], + }, + }, + }, + ], }; }); }; diff --git a/config/environment.js b/config/environment.js index 28a787b62f4..b5300869ad2 100644 --- a/config/environment.js +++ b/config/environment.js @@ -2,5 +2,5 @@ 'use strict'; module.exports = function(/* environment, appConfig */) { - return { }; + return {}; }; diff --git a/config/s3ProjectConfig.js b/config/s3ProjectConfig.js index 8a45d8e1177..40f5e770d64 100644 --- a/config/s3ProjectConfig.js +++ b/config/s3ProjectConfig.js @@ -1,42 +1,49 @@ -function fileMap(revision,tag,date) { +function fileMap(revision, tag, date) { return { - 'docs/data.json': fileObject('ember-data-docs', '.json', 'application/json', revision, tag, date) + 'docs/data.json': fileObject( + 'ember-data-docs', + '.json', + 'application/json', + revision, + tag, + date + ), }; } -function fileObject(baseName, extension, contentType, currentRevision, tag, date){ +function fileObject(baseName, extension, contentType, currentRevision, tag, date) { var fullName = '/' + baseName + extension; - var obj = { + var obj = { contentType: contentType, - destinations: { - canary: [ - 'latest' + fullName, - 'canary' + fullName, - 'canary/daily/' + date + fullName, - 'canary/shas/' + currentRevision + fullName - ], - release: [ - 'stable' + fullName, - 'release' + fullName, - 'release/daily/' + date + fullName, - 'release/shas/' + currentRevision + fullName - ], - beta: [ - 'beta' + fullName, - 'beta/daily/' + date + fullName, - 'beta/shas/' + currentRevision + fullName - ], - wildcard: [] - } - }; + destinations: { + canary: [ + 'latest' + fullName, + 'canary' + fullName, + 'canary/daily/' + date + fullName, + 'canary/shas/' + currentRevision + fullName, + ], + release: [ + 'stable' + fullName, + 'release' + fullName, + 'release/daily/' + date + fullName, + 'release/shas/' + currentRevision + fullName, + ], + beta: [ + 'beta' + fullName, + 'beta/daily/' + date + fullName, + 'beta/shas/' + currentRevision + fullName, + ], + wildcard: [], + }, + }; - if (tag) { - for (var key in obj.destinations) { - obj.destinations[key].push('tags/' + tag + fullName); - } - } + if (tag) { + for (var key in obj.destinations) { + obj.destinations[key].push('tags/' + tag + fullName); + } + } - return obj; + return obj; } module.exports = fileMap; diff --git a/ember-cli-build.js b/ember-cli-build.js index d2b879664e8..432afc11cd1 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -1,8 +1,8 @@ -"use strict"; -/* eslint-env node */ +'use strict'; + const EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); -const merge = require('broccoli-merge-trees'); -const yuidoc = require('./lib/yuidoc'); +const merge = require('broccoli-merge-trees'); +const yuidoc = require('./lib/yuidoc'); module.exports = function(defaults) { let app = new EmberAddon(defaults, {}); diff --git a/index.js b/index.js index 8fb58cb5d27..0cee37ca2af 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,3 @@ -/* eslint-env node */ 'use strict'; const path = require('path'); @@ -46,8 +45,10 @@ module.exports = { _prodLikeWarning() { let emberEnv = process.env.EMBER_ENV; - if(emberEnv !== 'production' && /production/.test(emberEnv)) { - this._warn(`Production-like values for EMBER_ENV are deprecated (your EMBER_ENV is "${emberEnv}") and support will be removed in Ember Data 4.0.0. If using ember-cli-deploy, please configure your build using 'production'. Otherwise please set your EMBER_ENV to 'production' for production builds.`); + if (emberEnv !== 'production' && /production/.test(emberEnv)) { + this._warn( + `Production-like values for EMBER_ENV are deprecated (your EMBER_ENV is "${emberEnv}") and support will be removed in Ember Data 4.0.0. If using ember-cli-deploy, please configure your build using 'production'. Otherwise please set your EMBER_ENV to 'production' for production builds.` + ); } }, @@ -60,6 +61,7 @@ module.exports = { } else if (this.ui) { this.ui.writeLine(warning); } else { + // eslint-disable-next-line no-console console.log(warning); } }, @@ -84,8 +86,8 @@ module.exports = { config() { return { emberData: { - enableRecordDataRFCBuild: USE_RECORD_DATA_RFC - } + enableRecordDataRFCBuild: USE_RECORD_DATA_RFC, + }, }; }, @@ -100,15 +102,15 @@ module.exports = { let treeWithVersion = merge([ tree, - version() // compile the VERSION into the build + version(), // compile the VERSION into the build ]); let withPrivate; if (USE_RECORD_DATA_RFC) { withPrivate = new Funnel(tree, { - include: ['-record-data-rfc-private/**'] - }); + include: ['-record-data-rfc-private/**'], + }); } else { withPrivate = new Funnel(tree, { include: ['-private/**'] }); } @@ -117,17 +119,17 @@ module.exports = { exclude: [ '-private', '-record-data-rfc-private', - isProductionEnv() && !isInstrumentedBuild() ? '-debug' : false + isProductionEnv() && !isInstrumentedBuild() ? '-debug' : false, ].filter(Boolean), - destDir: 'ember-data' + destDir: 'ember-data', }); let privateTree = babel.transpileTree(this.debugTree(withPrivate, 'babel-private:input'), { babel: this.buildBabelOptions(), 'ember-cli-babel': { - compileModules: false - } + compileModules: false, + }, }); privateTree = this.debugTree(privateTree, 'babel-private:output'); @@ -146,7 +148,7 @@ module.exports = { format: babel.shouldCompileModules() ? 'amd' : 'es', amd: { id: 'ember-data/-private' }, exports: 'named', - } + }, ], external: [ 'ember', @@ -154,23 +156,20 @@ module.exports = { 'ember-data/version', 'ember-data/-debug', 'ember-data/adapters/errors', - '@ember/ordered-set' + '@ember/ordered-set', ], // cache: true|false Defaults to true - } + }, }); privateTree = this.debugTree(privateTree, 'rollup-output'); let destDir = this.getOutputDirForVersion(); - publicTree = new Funnel(publicTree, { destDir }); + publicTree = new Funnel(publicTree, { destDir }); privateTree = new Funnel(privateTree, { destDir }); - return this.debugTree(merge([ - publicTree, - privateTree - ]), 'final'); + return this.debugTree(merge([publicTree, privateTree]), 'final'); }, buildBabelOptions() { @@ -180,10 +179,7 @@ module.exports = { loose: true, plugins: customPlugins.plugins, postTransformPlugins: customPlugins.postTransformPlugins, - exclude: [ - 'transform-es2015-block-scoping', - 'transform-es2015-typeof-symbol' - ] + exclude: ['transform-es2015-block-scoping', 'transform-es2015-typeof-symbol'], }; }, @@ -205,5 +201,5 @@ module.exports = { cacheKeyForTree(treeType) { return calculateCacheKeyForTree(treeType, this); - } + }, }; diff --git a/lib/.eslintrc.js b/lib/.eslintrc.js deleted file mode 100644 index e8efd22a07f..00000000000 --- a/lib/.eslintrc.js +++ /dev/null @@ -1,10 +0,0 @@ -/* global module */ -module.exports = { - parserOptions: { - ecmaVersion: 6, - }, - - env: { - node: true, - } -}; diff --git a/lib/babel-build.js b/lib/babel-build.js index 4f36eadbb90..89ac0e7854c 100644 --- a/lib/babel-build.js +++ b/lib/babel-build.js @@ -1,7 +1,6 @@ 'use strict'; var babel = require('broccoli-babel-transpiler'); -var path = require('path'); var moduleResolve = require('amd-name-resolver').moduleResolve; function getDebugMacroPlugins() { @@ -11,16 +10,16 @@ function getDebugMacroPlugins() { let options = { envFlags: { source: '@glimmer/env', - flags: { DEBUG: !isProduction, CI: !!process.env.CI } + flags: { DEBUG: !isProduction, CI: !!process.env.CI }, }, externalizeHelpers: { - global: 'Ember' + global: 'Ember', }, debugTools: { - source: '@ember/debug' - } + source: '@ember/debug', + }, }; return [DebugMacros, options]; @@ -36,33 +35,41 @@ function babelOptions(libraryName, _options) { moduleRoot: libraryName, moduleIds: true, // Transforms /index.js files to use their containing directory name - getModuleId: function (name) { + getModuleId: function(name) { return name.replace(/\/index$/g, ''); }, resolveModuleSource: function(source, fileName) { return moduleResolve.call(this, source, libraryName + '/' + fileName); - } + }, }; Object.keys(_options).forEach(function(opt) { options[opt] = _options[opt]; }); - options.plugins = options.plugins.concat([ - getDebugMacroPlugins(), - ['ember-modules-api-polyfill', { blacklist: { '@ember/debug': ['assert', 'deprecate', 'warn']} }], - ['transform-es2015-modules-amd', { noInterop: true, loose: true }], - 'transform-es2015-arrow-functions', - 'transform-es2015-computed-properties', - 'transform-es2015-shorthand-properties', - 'transform-es2015-template-literals', - 'transform-es2015-parameters', - 'transform-es2015-destructuring', - 'transform-es2015-spread', - 'transform-es2015-block-scoping', - 'transform-es2015-constants', - ['transform-es2015-classes', { loose: true }], - ], options.postTransformPlugins).filter(Boolean); + options.plugins = options.plugins + .concat( + [ + getDebugMacroPlugins(), + [ + 'ember-modules-api-polyfill', + { blacklist: { '@ember/debug': ['assert', 'deprecate', 'warn'] } }, + ], + ['transform-es2015-modules-amd', { noInterop: true, loose: true }], + 'transform-es2015-arrow-functions', + 'transform-es2015-computed-properties', + 'transform-es2015-shorthand-properties', + 'transform-es2015-template-literals', + 'transform-es2015-parameters', + 'transform-es2015-destructuring', + 'transform-es2015-spread', + 'transform-es2015-block-scoping', + 'transform-es2015-constants', + ['transform-es2015-classes', { loose: true }], + ], + options.postTransformPlugins + ) + .filter(Boolean); // this is not a "real" babel option, so we delete it delete options.postTransformPlugins; diff --git a/lib/calculate-version.js b/lib/calculate-version.js index f3d937c3c9b..4ad045dd94f 100644 --- a/lib/calculate-version.js +++ b/lib/calculate-version.js @@ -9,15 +9,16 @@ module.exports = function() { var packageVersion = package.version; var suffix = ''; + var info; if (fs.existsSync(gitPath)) { - var info = gitRepoInfo(gitPath); + info = gitRepoInfo(gitPath); if (info.tag) { return info.tag.replace(/^v/, ''); } suffix = '+' + info.sha.slice(0, 10); } else { - var info = npmGitInfo(package); + info = npmGitInfo(package); if (info.isInstalledAsNpmPackage() && !info.hasVersionInRef()) { suffix = '+' + info.abbreviatedSha; } diff --git a/lib/enable-optional-features-via-url/index.js b/lib/enable-optional-features-via-url/index.js index 28986444d1c..2819bec72c2 100644 --- a/lib/enable-optional-features-via-url/index.js +++ b/lib/enable-optional-features-via-url/index.js @@ -1,4 +1,3 @@ -/* eslint-env node */ module.exports = { name: 'enable-optional-features-via-url', @@ -12,25 +11,25 @@ module.exports = { the flag to true when there is a `enableoptionalfeatures` query parameter. */ contentFor: function(name) { - if (name === "enable-optional-features") { + if (name === 'enable-optional-features') { var array = [ - "", + ' }', + ' return this._EmberENV;', + ' },', + ' set(value) {', + ' this._EmberENV = value;', + ' }', + '});', + '', ]; return array.join('\n'); } - } + }, }; diff --git a/lib/jscs-rules/disallow-multiple-var-decl-with-assignment.js b/lib/jscs-rules/disallow-multiple-var-decl-with-assignment.js index 838e3e18f3f..dd851874a4d 100644 --- a/lib/jscs-rules/disallow-multiple-var-decl-with-assignment.js +++ b/lib/jscs-rules/disallow-multiple-var-decl-with-assignment.js @@ -22,18 +22,22 @@ module.exports.prototype = { file.iterateNodesByType('VariableDeclaration', function(node) { // allow multiple var declarations in for statement // for (var i = 0, j = myArray.length; i < j; i++) {} - if (node.parentNode.type === 'ForStatement') { return; } + if (node.parentNode.type === 'ForStatement') { + return; + } var hasAssignment = false; var multiDeclaration = node.declarations.length > 1; node.declarations.forEach(function(declaration) { - if (declaration.init) { hasAssignment = true; } + if (declaration.init) { + hasAssignment = true; + } }); if (hasAssignment && multiDeclaration) { errors.add('Multiple assigning variable declarations', node.loc.start); } }); - } + }, }; diff --git a/lib/jscs-rules/disallow-space-before-semicolon.js b/lib/jscs-rules/disallow-space-before-semicolon.js index d755672d1cf..c7c711b38c2 100644 --- a/lib/jscs-rules/disallow-space-before-semicolon.js +++ b/lib/jscs-rules/disallow-space-before-semicolon.js @@ -25,5 +25,5 @@ module.exports.prototype = { errors.add('Spaces are disallowed before semicolons.', i + 1, lines[i].length - 2); } } - } + }, }; diff --git a/lib/jscs-rules/disallow-space-inside-round-braces-in-call-expression.js b/lib/jscs-rules/disallow-space-inside-round-braces-in-call-expression.js index 1245ee81680..cae0a4d67b1 100644 --- a/lib/jscs-rules/disallow-space-inside-round-braces-in-call-expression.js +++ b/lib/jscs-rules/disallow-space-inside-round-braces-in-call-expression.js @@ -43,32 +43,29 @@ module.exports.prototype = { } var roundBraceTokenStart = file.getTokenByRangeStart(nodeBeforeRoundBrace.range[0]); - var roundBraceTokenEnd = file.getTokenByRangeStart(nodeBeforeRoundBrace.range[0]); + var roundBraceTokenEnd = file.getTokenByRangeStart(nodeBeforeRoundBrace.range[0]); do { roundBraceTokenStart = file.findNextToken(roundBraceTokenStart, 'Punctuator', '('); - roundBraceTokenEnd = file.findNextToken(roundBraceTokenEnd, 'Punctuator', ')'); + roundBraceTokenEnd = file.findNextToken(roundBraceTokenEnd, 'Punctuator', ')'); } while (roundBraceTokenStart.range[0] < nodeBeforeRoundBrace.range[1]); var firstArg = nodeBeforeRoundBrace.parentNode.arguments[0]; - var lastArg = nodeBeforeRoundBrace.parentNode.arguments[nodeBeforeRoundBrace.parentNode.arguments.length - 1]; + var lastArg = + nodeBeforeRoundBrace.parentNode.arguments[ + nodeBeforeRoundBrace.parentNode.arguments.length - 1 + ]; - var spaceAfterOpeningRoundBraceExists = spaceAfterBrace(firstArg, roundBraceTokenStart); + var spaceAfterOpeningRoundBraceExists = spaceAfterBrace(firstArg, roundBraceTokenStart); var spaceBeforeClosingRoundBraceExists = spaceBeforeBrace(lastArg, roundBraceTokenEnd); if (spaceAfterOpeningRoundBraceExists) { - errors.add( - 'Illegal space after opening round brace', - roundBraceTokenStart.loc.start - ); + errors.add('Illegal space after opening round brace', roundBraceTokenStart.loc.start); } if (spaceBeforeClosingRoundBraceExists) { - errors.add( - 'Illegal space before closing round brace', - roundBraceTokenEnd.loc.start - ); + errors.add('Illegal space before closing round brace', roundBraceTokenEnd.loc.start); } }); - } + }, }; diff --git a/lib/jscs-rules/require-spaces-after-closing-parenthesis-in-function-declaration.js b/lib/jscs-rules/require-spaces-after-closing-parenthesis-in-function-declaration.js index 690574ad3a3..62120235446 100644 --- a/lib/jscs-rules/require-spaces-after-closing-parenthesis-in-function-declaration.js +++ b/lib/jscs-rules/require-spaces-after-closing-parenthesis-in-function-declaration.js @@ -32,17 +32,11 @@ module.exports.prototype = { if (beforeOpeningRoundBrace) { if (nextToken) { - errors.add( - 'Missing space before opening round brace', - nextToken.loc.start - ); + errors.add('Missing space before opening round brace', nextToken.loc.start); } } else { if (!nextToken) { - errors.add( - 'Illegal space before opening round brace', - functionToken.loc.end - ); + errors.add('Illegal space before opening round brace', functionToken.loc.end); } } @@ -51,19 +45,13 @@ module.exports.prototype = { if (beforeOpeningCurlyBrace) { if (tokenBeforeBody) { - errors.add( - 'Missing space before opening curly brace', - tokenBeforeBody.loc.start - ); + errors.add('Missing space before opening curly brace', tokenBeforeBody.loc.start); } } else { if (!tokenBeforeBody) { - errors.add( - 'Illegal space before opening curly brace', - node.body.loc.end - ); + errors.add('Illegal space before opening curly brace', node.body.loc.end); } } }); - } + }, }; diff --git a/lib/stripped-build-plugins.js b/lib/stripped-build-plugins.js index 9e76f19f56e..4806655243e 100644 --- a/lib/stripped-build-plugins.js +++ b/lib/stripped-build-plugins.js @@ -5,14 +5,14 @@ var fs = require('fs'); var resolve = require('resolve'); var FilterImports = requireBabelPlugin('babel-plugin-filter-imports'); -var FeatureFlags = requireBabelPlugin('babel-plugin-feature-flags'); +var FeatureFlags = requireBabelPlugin('babel-plugin-feature-flags'); var StripHeimdall = requireBabelPlugin('babel6-plugin-strip-heimdall'); var StripClassCallCheck = requireBabelPlugin('babel6-plugin-strip-class-callcheck'); var StripFilteredImports = require('./transforms/babel-plugin-remove-imports'); var TransformBlockScoping = requireBabelPlugin('babel-plugin-transform-es2015-block-scoping'); function uniqueAdd(obj, key, values) { - var a = obj[key] = obj[key] || []; + var a = (obj[key] = obj[key] || []); for (var i = 0; i < values.length; i++) { if (a.indexOf(values[i]) === -1) { @@ -60,30 +60,32 @@ module.exports = function(environment) { var postTransformPlugins = []; var plugins = [ - [FeatureFlags, { - import: { module: 'ember-data/-private/features' }, - features: features - }] + [ + FeatureFlags, + { + import: { module: 'ember-data/-private/features' }, + features: features, + }, + ], ]; if (process.env.INSTRUMENT_HEIMDALL === 'false') { plugins.push([StripHeimdall]); uniqueAdd(filteredImports, 'ember-data/-debug', ['instrument']); } else { + // eslint-disable-next-line no-console console.warn('NOT STRIPPING HEIMDALL'); } if (/production/.test(environment) || process.env.INSTRUMENT_HEIMDALL === 'true') { postTransformPlugins.push([StripClassCallCheck]); - uniqueAdd(filteredImports, 'ember-data/-debug', [ - 'assertPolymorphicType' - ]); + uniqueAdd(filteredImports, 'ember-data/-debug', ['assertPolymorphicType']); } plugins.push( [FilterImports, filteredImports], [StripFilteredImports, filteredImports], - [TransformBlockScoping, { 'throwIfClosureRequired': true }] + [TransformBlockScoping, { throwIfClosureRequired: true }] ); return { plugins, postTransformPlugins }; diff --git a/lib/stripped-build.js b/lib/stripped-build.js index d59b2677a67..f70e7a8723c 100644 --- a/lib/stripped-build.js +++ b/lib/stripped-build.js @@ -1,8 +1,4 @@ -var fs = require('fs'); -var path = require('path'); -var filterImports = require('babel-plugin-filter-imports'); -var featureFlags = require('babel-plugin-feature-flags'); -var babelBuild = require('./babel-build'); +var babelBuild = require('./babel-build'); var strippedBuildPlugins = require('./stripped-build-plugins'); module.exports = function(packageName, tree, environmentBuildingFor) { diff --git a/lib/transforms/babel-plugin-remove-imports.js b/lib/transforms/babel-plugin-remove-imports.js index 2b4b92631ab..4d39e5b59bb 100644 --- a/lib/transforms/babel-plugin-remove-imports.js +++ b/lib/transforms/babel-plugin-remove-imports.js @@ -20,7 +20,7 @@ function PluginRemoveFilteredImports() { }); importDeclarationsToRemove = undefined; - } + }, }, ImportDeclaration: function(path) { @@ -56,9 +56,8 @@ function PluginRemoveFilteredImports() { } } } - } - - } + }, + }, }; } diff --git a/lib/utilities/extend-from-application-entity.js b/lib/utilities/extend-from-application-entity.js index cd958854cb7..0cdcac2431c 100644 --- a/lib/utilities/extend-from-application-entity.js +++ b/lib/utilities/extend-from-application-entity.js @@ -1,38 +1,46 @@ -var stringUtil = require('ember-cli-string-utils'); +var stringUtil = require('ember-cli-string-utils'); var SilentError = require('silent-error'); -var pathUtil = require('ember-cli-path-utils'); -var fs = require('fs'); -var path = require('path'); +var pathUtil = require('ember-cli-path-utils'); +var fs = require('fs'); +var path = require('path'); module.exports = function(type, baseClass, options) { - var entityName = options.entity.name; - var isAddon = options.inRepoAddon || options.project.isEmberCLIAddon(); - var relativePath = pathUtil.getRelativePath(options.entity.name); + var entityName = options.entity.name; + var isAddon = options.inRepoAddon || options.project.isEmberCLIAddon(); + var relativePath = pathUtil.getRelativePath(options.entity.name); if (options.pod && options.podPath) { relativePath = pathUtil.getRelativePath(options.podPath + options.entity.name); } var entityDirectory = type + 's'; - var applicationEntityPath = path.join(options.project.root, 'app', entityDirectory, 'application.js'); + var applicationEntityPath = path.join( + options.project.root, + 'app', + entityDirectory, + 'application.js' + ); var hasApplicationEntity = fs.existsSync(applicationEntityPath); if (!isAddon && !options.baseClass && entityName !== 'application' && hasApplicationEntity) { options.baseClass = 'application'; } if (options.baseClass === entityName) { - throw new SilentError(stringUtil.classify(type) + 's cannot extend from themself. To resolve this, remove the `--base-class` option or change to a different base-class.'); + throw new SilentError( + stringUtil.classify(type) + + 's cannot extend from themself. To resolve this, remove the `--base-class` option or change to a different base-class.' + ); } - var importStatement = 'import DS from \'ember-data\';'; + var importStatement = "import DS from 'ember-data';"; if (options.baseClass) { - baseClass = stringUtil.classify(options.baseClass.replace('\/', '-')); + baseClass = stringUtil.classify(options.baseClass.replace('/', '-')); baseClass = baseClass + stringUtil.classify(type); - importStatement = 'import ' + baseClass + ' from \'' + relativePath + options.baseClass + '\';'; + importStatement = 'import ' + baseClass + " from '" + relativePath + options.baseClass + "';"; } return { importStatement: importStatement, - baseClass: baseClass + baseClass: baseClass, }; }; diff --git a/lib/version-replace.js b/lib/version-replace.js index 56eeb8f1574..d8d694855e3 100644 --- a/lib/version-replace.js +++ b/lib/version-replace.js @@ -7,7 +7,7 @@ module.exports = function configFiles(tree) { files: ['*.{json,js}'], pattern: { match: /VERSION_STRING_PLACEHOLDER/g, - replacement: version - } + replacement: version, + }, }); }; diff --git a/lib/yuidoc.js b/lib/yuidoc.js index 3292300894f..7b560eb2ee5 100644 --- a/lib/yuidoc.js +++ b/lib/yuidoc.js @@ -1,21 +1,19 @@ -var YUIDoc = require('broccoli-yuidoc'); +var YUIDoc = require('broccoli-yuidoc'); var calculateVersion = require('./calculate-version'); -var path = require('path'); module.exports = function yui() { return new YUIDoc(['addon', 'node_modules/ember-inflector/addon'], { destDir: 'docs', yuidoc: { - "name": "The ember-data API", - "description": "The ember-data API: a data persistence library for Ember.js", - "version": calculateVersion(), - "logo": "http://f.cl.ly/items/1A1L432s022u1O1q1V3p/ember%20logo.png", - "url": "https://github.com/emberjs/data", - "options": { - "exclude": "vendor", - "outdir": "docs/build" - } - } + name: 'The ember-data API', + description: 'The ember-data API: a data persistence library for Ember.js', + version: calculateVersion(), + logo: 'http://f.cl.ly/items/1A1L432s022u1O1q1V3p/ember%20logo.png', + url: 'https://github.com/emberjs/data', + options: { + exclude: 'vendor', + outdir: 'docs/build', + }, + }, }); }; - diff --git a/node-tests/blueprints/adapter-test.js b/node-tests/blueprints/adapter-test.js index a4e244cd00b..23dbcc55f76 100644 --- a/node-tests/blueprints/adapter-test.js +++ b/node-tests/blueprints/adapter-test.js @@ -22,74 +22,81 @@ describe('Acceptance: generate and destroy adapter blueprints', function() { return emberNew(); }); - it('adapter', function() { let args = ['adapter', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('app/adapters/foo.js')) - .to.contain('import DS from \'ember-data\';') - .to.contain('export default DS.JSONAPIAdapter.extend({'); + expect(_file('app/adapters/foo.js')) + .to.contain("import DS from 'ember-data';") + .to.contain('export default DS.JSONAPIAdapter.extend({'); - expect(_file('tests/unit/adapters/foo-test.js')) - .to.equal(fixture('adapter-test/foo-default.js')); - }); + expect(_file('tests/unit/adapters/foo-test.js')).to.equal( + fixture('adapter-test/foo-default.js') + ); + }); }); it('adapter extends application adapter if it exists', function() { let args = ['adapter', 'foo']; - return emberGenerate(['adapter', 'application']) - .then(() => emberGenerateDestroy(args, _file => { + return emberGenerate(['adapter', 'application']).then(() => + emberGenerateDestroy(args, _file => { expect(_file('app/adapters/foo.js')) - .to.contain('import ApplicationAdapter from \'./application\';') + .to.contain("import ApplicationAdapter from './application';") .to.contain('export default ApplicationAdapter.extend({'); - expect(_file('tests/unit/adapters/foo-test.js')) - .to.equal(fixture('adapter-test/foo-default.js')); - })); + expect(_file('tests/unit/adapters/foo-test.js')).to.equal( + fixture('adapter-test/foo-default.js') + ); + }) + ); }); it('adapter with --base-class', function() { let args = ['adapter', 'foo', '--base-class=bar']; return emberGenerateDestroy(args, _file => { - expect(_file('app/adapters/foo.js')) - .to.contain('import BarAdapter from \'./bar\';') - .to.contain('export default BarAdapter.extend({'); + expect(_file('app/adapters/foo.js')) + .to.contain("import BarAdapter from './bar';") + .to.contain('export default BarAdapter.extend({'); - expect(_file('tests/unit/adapters/foo-test.js')) - .to.equal(fixture('adapter-test/foo-default.js')); - }); + expect(_file('tests/unit/adapters/foo-test.js')).to.equal( + fixture('adapter-test/foo-default.js') + ); + }); }); xit('adapter throws when --base-class is same as name', function() { let args = ['adapter', 'foo', '--base-class=foo']; - return expect(emberGenerate(args)) - .to.be.rejectedWith(SilentError, /Adapters cannot extend from themself/); + return expect(emberGenerate(args)).to.be.rejectedWith( + SilentError, + /Adapters cannot extend from themself/ + ); }); it('adapter when is named "application"', function() { let args = ['adapter', 'application']; return emberGenerateDestroy(args, _file => { - expect(_file('app/adapters/application.js')) - .to.contain('import DS from \'ember-data\';') - .to.contain('export default DS.JSONAPIAdapter.extend({'); + expect(_file('app/adapters/application.js')) + .to.contain("import DS from 'ember-data';") + .to.contain('export default DS.JSONAPIAdapter.extend({'); - expect(_file('tests/unit/adapters/application-test.js')) - .to.equal(fixture('adapter-test/application-default.js')); - }); + expect(_file('tests/unit/adapters/application-test.js')).to.equal( + fixture('adapter-test/application-default.js') + ); + }); }); it('adapter-test', function() { let args = ['adapter-test', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('tests/unit/adapters/foo-test.js')) - .to.equal(fixture('adapter-test/foo-default.js')); - }); + expect(_file('tests/unit/adapters/foo-test.js')).to.equal( + fixture('adapter-test/foo-default.js') + ); + }); }); describe('adapter-test with ember-cli-qunit@4.2.0', function() { @@ -99,18 +106,18 @@ describe('Acceptance: generate and destroy adapter blueprints', function() { it('adapter-test-test foo', function() { return emberGenerateDestroy(['adapter-test', 'foo'], _file => { - expect(_file('tests/unit/adapters/foo-test.js')) - .to.equal(fixture('adapter-test/rfc232.js')); + expect(_file('tests/unit/adapters/foo-test.js')).to.equal( + fixture('adapter-test/rfc232.js') + ); }); }); }); - describe('with ember-cli-mocha v0.12+', function() { beforeEach(function() { modifyPackages([ { name: 'ember-cli-qunit', delete: true }, - { name: 'ember-cli-mocha', dev: true } + { name: 'ember-cli-mocha', dev: true }, ]); generateFakePackageManifest('ember-cli-mocha', '0.12.0'); }); @@ -119,10 +126,10 @@ describe('Acceptance: generate and destroy adapter blueprints', function() { let args = ['adapter-test', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('tests/unit/adapters/foo-test.js')) - .to.equal(fixture('adapter-test/foo-mocha-0.12.js')); + expect(_file('tests/unit/adapters/foo-test.js')).to.equal( + fixture('adapter-test/foo-mocha-0.12.js') + ); }); }); }); - }); diff --git a/node-tests/blueprints/model-test.js b/node-tests/blueprints/model-test.js index 53ddf1352ab..820411b1d27 100644 --- a/node-tests/blueprints/model-test.js +++ b/node-tests/blueprints/model-test.js @@ -12,7 +12,6 @@ const expect = chai.expect; const generateFakePackageManifest = require('../helpers/generate-fake-package-manifest'); const fixture = require('../helpers/fixture'); - describe('Acceptance: generate and destroy model blueprints', function() { setupTestHooks(this); @@ -20,18 +19,16 @@ describe('Acceptance: generate and destroy model blueprints', function() { return emberNew(); }); - it('model', function() { let args = ['model', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('app/models/foo.js')) - .to.contain('import DS from \'ember-data\';') - .to.contain('export default DS.Model.extend('); + expect(_file('app/models/foo.js')) + .to.contain("import DS from 'ember-data';") + .to.contain('export default DS.Model.extend('); - expect(_file('tests/unit/models/foo-test.js')) - .to.equal(fixture('model-test/foo-default.js')); - }); + expect(_file('tests/unit/models/foo-test.js')).to.equal(fixture('model-test/foo-default.js')); + }); }); it('model with attrs', function() { @@ -45,64 +42,64 @@ describe('Acceptance: generate and destroy model blueprints', function() { 'someObject:object', 'age:number', 'name:string', - 'customAttr:custom-transform' + 'customAttr:custom-transform', ]; return emberGenerateDestroy(args, _file => { - expect(_file('app/models/foo.js')) - .to.contain('import DS from \'ember-data\';') - .to.contain('export default DS.Model.extend(') - .to.contain('misc: DS.attr()') - .to.contain('skills: DS.attr(\'array\')') - .to.contain('isActive: DS.attr(\'boolean\')') - .to.contain('birthday: DS.attr(\'date\')') - .to.contain('someObject: DS.attr(\'object\')') - .to.contain('age: DS.attr(\'number\')') - .to.contain('name: DS.attr(\'string\')') - .to.contain('customAttr: DS.attr(\'custom-transform\')'); - - expect(_file('tests/unit/models/foo-test.js')) - .to.equal(fixture('model-test/foo-default.js')); - }); + expect(_file('app/models/foo.js')) + .to.contain("import DS from 'ember-data';") + .to.contain('export default DS.Model.extend(') + .to.contain('misc: DS.attr()') + .to.contain("skills: DS.attr('array')") + .to.contain("isActive: DS.attr('boolean')") + .to.contain("birthday: DS.attr('date')") + .to.contain("someObject: DS.attr('object')") + .to.contain("age: DS.attr('number')") + .to.contain("name: DS.attr('string')") + .to.contain("customAttr: DS.attr('custom-transform')"); + + expect(_file('tests/unit/models/foo-test.js')).to.equal(fixture('model-test/foo-default.js')); + }); }); it('model with belongsTo', function() { let args = ['model', 'comment', 'post:belongs-to', 'author:belongs-to:user']; return emberGenerateDestroy(args, _file => { - expect(_file('app/models/comment.js')) - .to.contain('import DS from \'ember-data\';') - .to.contain('export default DS.Model.extend(') - .to.contain('post: DS.belongsTo(\'post\')') - .to.contain('author: DS.belongsTo(\'user\')'); - - expect(_file('tests/unit/models/comment-test.js')) - .to.equal(fixture('model-test/comment-default.js')); - }); + expect(_file('app/models/comment.js')) + .to.contain("import DS from 'ember-data';") + .to.contain('export default DS.Model.extend(') + .to.contain("post: DS.belongsTo('post')") + .to.contain("author: DS.belongsTo('user')"); + + expect(_file('tests/unit/models/comment-test.js')).to.equal( + fixture('model-test/comment-default.js') + ); + }); }); it('model with hasMany', function() { let args = ['model', 'post', 'comments:has-many', 'otherComments:has-many:comment']; return emberGenerateDestroy(args, _file => { - expect(_file('app/models/post.js')) - .to.contain('import DS from \'ember-data\';') - .to.contain('export default DS.Model.extend(') - .to.contain('comments: DS.hasMany(\'comment\')') - .to.contain('otherComments: DS.hasMany(\'comment\')'); - - expect(_file('tests/unit/models/post-test.js')) - .to.equal(fixture('model-test/post-default.js')); - }); + expect(_file('app/models/post.js')) + .to.contain("import DS from 'ember-data';") + .to.contain('export default DS.Model.extend(') + .to.contain("comments: DS.hasMany('comment')") + .to.contain("otherComments: DS.hasMany('comment')"); + + expect(_file('tests/unit/models/post-test.js')).to.equal( + fixture('model-test/post-default.js') + ); + }); }); it('model-test', function() { let args = ['model-test', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('tests/unit/models/foo-test.js')) - .to.equal(fixture('model-test/foo-default.js')); - }); + expect(_file('tests/unit/models/foo-test.js')).to.equal(fixture('model-test/foo-default.js')); + }); }); describe('model-test with ember-cli-qunit@4.2.0', function() { @@ -112,18 +109,16 @@ describe('Acceptance: generate and destroy model blueprints', function() { it('model-test-test foo', function() { return emberGenerateDestroy(['model-test', 'foo'], _file => { - expect(_file('tests/unit/models/foo-test.js')) - .to.equal(fixture('model-test/rfc232.js')); + expect(_file('tests/unit/models/foo-test.js')).to.equal(fixture('model-test/rfc232.js')); }); }); }); - describe('with ember-cli-mocha v0.12+', function() { beforeEach(function() { modifyPackages([ { name: 'ember-cli-qunit', delete: true }, - { name: 'ember-cli-mocha', dev: true } + { name: 'ember-cli-mocha', dev: true }, ]); generateFakePackageManifest('ember-cli-mocha', '0.12.0'); }); @@ -132,8 +127,9 @@ describe('Acceptance: generate and destroy model blueprints', function() { let args = ['model-test', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('tests/unit/models/foo-test.js')) - .to.equal(fixture('model-test/foo-mocha-0.12.js')); + expect(_file('tests/unit/models/foo-test.js')).to.equal( + fixture('model-test/foo-mocha-0.12.js') + ); }); }); }); diff --git a/node-tests/blueprints/serializer-test.js b/node-tests/blueprints/serializer-test.js index 76ccf58623c..0c67640092a 100644 --- a/node-tests/blueprints/serializer-test.js +++ b/node-tests/blueprints/serializer-test.js @@ -18,7 +18,6 @@ const fixture = require('../helpers/fixture'); describe('Acceptance: generate and destroy serializer blueprints', function() { setupTestHooks(this); - beforeEach(function() { return emberNew(); }); @@ -27,69 +26,77 @@ describe('Acceptance: generate and destroy serializer blueprints', function() { let args = ['serializer', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('app/serializers/foo.js')) - .to.contain('import DS from \'ember-data\';') - .to.contain('export default DS.JSONAPISerializer.extend('); + expect(_file('app/serializers/foo.js')) + .to.contain("import DS from 'ember-data';") + .to.contain('export default DS.JSONAPISerializer.extend('); - expect(_file('tests/unit/serializers/foo-test.js')) - .to.equal(fixture('serializer-test/foo-default.js')); - }); + expect(_file('tests/unit/serializers/foo-test.js')).to.equal( + fixture('serializer-test/foo-default.js') + ); + }); }); it('serializer extends application serializer if it exists', function() { let args = ['serializer', 'foo']; - return emberGenerate(['serializer', 'application']) - .then(() => emberGenerateDestroy(args, _file => { + return emberGenerate(['serializer', 'application']).then(() => + emberGenerateDestroy(args, _file => { expect(_file('app/serializers/foo.js')) - .to.contain('import ApplicationSerializer from \'./application\';') + .to.contain("import ApplicationSerializer from './application';") .to.contain('export default ApplicationSerializer.extend({'); - expect(_file('tests/unit/serializers/foo-test.js')) - .to.equal(fixture('serializer-test/foo-default.js')); - })); + expect(_file('tests/unit/serializers/foo-test.js')).to.equal( + fixture('serializer-test/foo-default.js') + ); + }) + ); }); it('serializer with --base-class', function() { let args = ['serializer', 'foo', '--base-class=bar']; return emberGenerateDestroy(args, _file => { - expect(_file('app/serializers/foo.js')) - .to.contain('import BarSerializer from \'./bar\';') - .to.contain('export default BarSerializer.extend({'); + expect(_file('app/serializers/foo.js')) + .to.contain("import BarSerializer from './bar';") + .to.contain('export default BarSerializer.extend({'); - expect(_file('tests/unit/serializers/foo-test.js')) - .to.equal(fixture('serializer-test/foo-default.js')); - }); + expect(_file('tests/unit/serializers/foo-test.js')).to.equal( + fixture('serializer-test/foo-default.js') + ); + }); }); xit('serializer throws when --base-class is same as name', function() { let args = ['serializer', 'foo', '--base-class=foo']; - return expect(emberGenerate(args)) - .to.be.rejectedWith(SilentError, /Serializers cannot extend from themself/); + return expect(emberGenerate(args)).to.be.rejectedWith( + SilentError, + /Serializers cannot extend from themself/ + ); }); it('serializer when is named "application"', function() { let args = ['serializer', 'application']; return emberGenerateDestroy(args, _file => { - expect(_file('app/serializers/application.js')) - .to.contain('import DS from \'ember-data\';') - .to.contain('export default DS.JSONAPISerializer.extend({'); + expect(_file('app/serializers/application.js')) + .to.contain("import DS from 'ember-data';") + .to.contain('export default DS.JSONAPISerializer.extend({'); - expect(_file('tests/unit/serializers/application-test.js')) - .to.equal(fixture('serializer-test/application-default.js')); - }); + expect(_file('tests/unit/serializers/application-test.js')).to.equal( + fixture('serializer-test/application-default.js') + ); + }); }); it('serializer-test', function() { let args = ['serializer-test', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('tests/unit/serializers/foo-test.js')) - .to.equal(fixture('serializer-test/foo-default.js')); - }); + expect(_file('tests/unit/serializers/foo-test.js')).to.equal( + fixture('serializer-test/foo-default.js') + ); + }); }); describe('serializer-test with ember-cli-qunit@4.2.0', function() { @@ -99,8 +106,9 @@ describe('Acceptance: generate and destroy serializer blueprints', function() { it('serializer-test-test foo', function() { return emberGenerateDestroy(['serializer-test', 'foo'], _file => { - expect(_file('tests/unit/serializers/foo-test.js')) - .to.equal(fixture('serializer-test/rfc232.js')); + expect(_file('tests/unit/serializers/foo-test.js')).to.equal( + fixture('serializer-test/rfc232.js') + ); }); }); }); @@ -109,7 +117,7 @@ describe('Acceptance: generate and destroy serializer blueprints', function() { beforeEach(function() { modifyPackages([ { name: 'ember-cli-qunit', delete: true }, - { name: 'ember-cli-mocha', dev: true } + { name: 'ember-cli-mocha', dev: true }, ]); generateFakePackageManifest('ember-cli-mocha', '0.12.0'); }); @@ -118,10 +126,10 @@ describe('Acceptance: generate and destroy serializer blueprints', function() { let args = ['serializer-test', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('tests/unit/serializers/foo-test.js')) - .to.equal(fixture('serializer-test/foo-mocha-0.12.js')); + expect(_file('tests/unit/serializers/foo-test.js')).to.equal( + fixture('serializer-test/foo-mocha-0.12.js') + ); }); }); }); - }); diff --git a/node-tests/blueprints/transform-test.js b/node-tests/blueprints/transform-test.js index 525c34c4604..29add489003 100644 --- a/node-tests/blueprints/transform-test.js +++ b/node-tests/blueprints/transform-test.js @@ -20,19 +20,19 @@ describe('Acceptance: generate and destroy transform blueprints', function() { return emberNew(); }); - it('transform', function() { let args = ['transform', 'foo']; return emberGenerateDestroy(args, _file => { expect(_file('app/transforms/foo.js')) - .to.contain('import DS from \'ember-data\';') + .to.contain("import DS from 'ember-data';") .to.contain('export default DS.Transform.extend(') .to.contain('deserialize(serialized) {') .to.contain('serialize(deserialized) {'); - expect(_file('tests/unit/transforms/foo-test.js')) - .to.equal(fixture('transform-test/default.js')); + expect(_file('tests/unit/transforms/foo-test.js')).to.equal( + fixture('transform-test/default.js') + ); }); }); @@ -40,8 +40,9 @@ describe('Acceptance: generate and destroy transform blueprints', function() { let args = ['transform-test', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('tests/unit/transforms/foo-test.js')) - .to.equal(fixture('transform-test/default.js')); + expect(_file('tests/unit/transforms/foo-test.js')).to.equal( + fixture('transform-test/default.js') + ); }); }); @@ -52,18 +53,18 @@ describe('Acceptance: generate and destroy transform blueprints', function() { it('transform-test-test foo', function() { return emberGenerateDestroy(['transform-test', 'foo'], _file => { - expect(_file('tests/unit/transforms/foo-test.js')) - .to.equal(fixture('transform-test/rfc232.js')); + expect(_file('tests/unit/transforms/foo-test.js')).to.equal( + fixture('transform-test/rfc232.js') + ); }); }); }); - describe('with ember-cli-mocha v0.12+', function() { beforeEach(function() { modifyPackages([ { name: 'ember-cli-qunit', delete: true }, - { name: 'ember-cli-mocha', dev: true } + { name: 'ember-cli-mocha', dev: true }, ]); generateFakePackageManifest('ember-cli-mocha', '0.12.0'); }); @@ -72,8 +73,9 @@ describe('Acceptance: generate and destroy transform blueprints', function() { let args = ['transform-test', 'foo']; return emberGenerateDestroy(args, _file => { - expect(_file('tests/unit/transforms/foo-test.js')) - .to.equal(fixture('transform-test/mocha-0.12.js')); + expect(_file('tests/unit/transforms/foo-test.js')).to.equal( + fixture('transform-test/mocha-0.12.js') + ); }); }); }); diff --git a/node-tests/helpers/generate-fake-package-manifest.js b/node-tests/helpers/generate-fake-package-manifest.js index d6f92f1f5a9..ca16d36cc44 100644 --- a/node-tests/helpers/generate-fake-package-manifest.js +++ b/node-tests/helpers/generate-fake-package-manifest.js @@ -7,7 +7,10 @@ module.exports = function generateFakePackageManifest(name, version) { if (!fs.existsSync('node_modules/' + name)) { fs.mkdirSync('node_modules/' + name); } - fs.writeFileSync('node_modules/' + name + '/package.json', JSON.stringify({ - version: version, - })); + fs.writeFileSync( + 'node_modules/' + name + '/package.json', + JSON.stringify({ + version: version, + }) + ); }; diff --git a/node-tests/nodetest-runner.js b/node-tests/nodetest-runner.js index 4f3fb1b12a6..e909e06564d 100644 --- a/node-tests/nodetest-runner.js +++ b/node-tests/nodetest-runner.js @@ -1,6 +1,8 @@ 'use strict'; -if (/^win/.test(require('os').platform())){ +/* eslint-disable no-console, no-process-exit */ + +if (/^win/.test(require('os').platform())) { // don't run these tests in windows right now, they don't work process.exit(0); } @@ -15,11 +17,13 @@ rimraf.sync('.node_modules-tmp'); rimraf.sync('.bower_components-tmp'); var root = 'node-tests/{blueprints,acceptance,unit}'; -var _checkOnlyInTests = RSVP.denodeify(mochaOnlyDetector.checkFolder.bind(null, root + '/**/*{-test}.js')); +var _checkOnlyInTests = RSVP.denodeify( + mochaOnlyDetector.checkFolder.bind(null, root + '/**/*{-test}.js') +); var optionOrFile = process.argv[2]; var mocha = new Mocha({ timeout: 5000, - reporter: 'spec' + reporter: 'spec', }); var testFiles = glob.sync(root + '/**/*-test.js'); /*var jshintPosition = testFiles.indexOf('tests/unit/jshint-test.js'); @@ -31,14 +35,14 @@ if (optionOrFile === 'all') { addFiles(mocha, testFiles); addFiles(mocha, 'node-tests/**/*-test.js'); addFiles(mocha, '/**/*-test-slow.js'); -} else if (process.argv.length > 2) { +} else if (process.argv.length > 2) { addFiles(mocha, process.argv.slice(2)); } else { addFiles(mocha, testFiles); } function addFiles(mocha, files) { - files = (typeof files === 'string') ? glob.sync(root + files) : files; + files = typeof files === 'string' ? glob.sync(root + files) : files; files.forEach(mocha.addFile.bind(mocha)); } diff --git a/node-tests/unit/babel-plugin-remove-imports-test.js b/node-tests/unit/babel-plugin-remove-imports-test.js index c2816d57c90..b01980d9b4c 100644 --- a/node-tests/unit/babel-plugin-remove-imports-test.js +++ b/node-tests/unit/babel-plugin-remove-imports-test.js @@ -20,10 +20,10 @@ describe('Unit: babel-plugin-remove-filtered-imports', function() { let input, output; function transform(code) { - return co.wrap(function* () { + return co.wrap(function*() { input.write({ 'test.js': code }); let babel = new Babel(input.path(), { - plugins + plugins, }); output = createBuilder(babel); @@ -36,26 +36,28 @@ describe('Unit: babel-plugin-remove-filtered-imports', function() { })(); } - beforeEach(co.wrap(function* () { - pluginOptions = {}; + beforeEach( + co.wrap(function*() { + pluginOptions = {}; - plugins = [ - [StripFilteredImports, pluginOptions] - ]; + plugins = [[StripFilteredImports, pluginOptions]]; - input = yield createTempDir(); - })); + input = yield createTempDir(); + }) + ); - afterEach(co.wrap(function* () { - if (input) { - yield input.dispose(); - } - if (output) { - yield output.dispose(); - } + afterEach( + co.wrap(function*() { + if (input) { + yield input.dispose(); + } + if (output) { + yield output.dispose(); + } - input = output = undefined; - })); + input = output = undefined; + }) + ); it('Returns a plugin', function() { let plugin = StripFilteredImports(); @@ -63,20 +65,25 @@ describe('Unit: babel-plugin-remove-filtered-imports', function() { expect(plugin).to.be.ok; }); - it('Does not alter a file if no imports are meant to be filtered', co.wrap(function*() { - const input = stripIndent` + it( + 'Does not alter a file if no imports are meant to be filtered', + co.wrap(function*() { + const input = stripIndent` import Foo from 'bar'; import { baz } from 'none'; import * as drinks from 'drinks'; import 'bem'; `; - const result = yield transform(input); + const result = yield transform(input); - expect(result).to.equal(stripNewlines(input)); - })); + expect(result).to.equal(stripNewlines(input)); + }) + ); - it('Properly strips desired imports and specifiers', co.wrap(function*() { - const input = stripIndent` + it( + 'Properly strips desired imports and specifiers', + co.wrap(function*() { + const input = stripIndent` import Foo from 'bar'; import { bit } from 'wow'; import { baz, bell } from 'none'; @@ -88,23 +95,24 @@ describe('Unit: babel-plugin-remove-filtered-imports', function() { import 'bell'; `; - pluginOptions.none = ['baz']; - pluginOptions.bar = true; - pluginOptions.drinks = '*'; - pluginOptions.wow = ['bit']; - pluginOptions.bem = ['biz']; - pluginOptions.bosh = '*'; - pluginOptions.dranks = ['bex']; - pluginOptions.bell = true; + pluginOptions.none = ['baz']; + pluginOptions.bar = true; + pluginOptions.drinks = '*'; + pluginOptions.wow = ['bit']; + pluginOptions.bem = ['biz']; + pluginOptions.bosh = '*'; + pluginOptions.dranks = ['bex']; + pluginOptions.bell = true; - const expectedOutput = stripNewlines(stripIndent` + const expectedOutput = stripNewlines(stripIndent` import { bell } from 'none'; import { foo } from 'happy'; import * as dranks from 'dranks'; import 'bem'; `); - const result = yield transform(input); + const result = yield transform(input); - expect(result).to.equal(expectedOutput); - })); + expect(result).to.equal(expectedOutput); + }) + ); }); diff --git a/package.json b/package.json index 9ee9d6d90cb..375a360cd77 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "scripts": { "build": "ember build", "build:production": "ember build --environment=production", + "lint:js": "eslint .", "start": "ember server", "test": "ember test && ember test --record-data-rfc-build", "test:all": "ember try:each", @@ -22,6 +23,7 @@ "dependencies": { "@ember/ordered-set": "^1.0.0", "amd-name-resolver": "0.0.7", + "babel-plugin-debug-macros": "^0.1.11", "babel-plugin-ember-modules-api-polyfill": "^1.4.2", "babel-plugin-feature-flags": "^0.3.1", "babel-plugin-filter-imports": "^0.3.1", @@ -52,7 +54,6 @@ "silent-error": "^1.0.0" }, "devDependencies": { - "babel-plugin-debug-macros": "^0.1.7", "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", "babel-plugin-transform-es2015-classes": "^6.23.0", "babel-plugin-transform-es2015-computed-properties": "^6.22.0", @@ -76,13 +77,12 @@ "ember-cli-app-version": "^3.0.0", "ember-cli-blueprint-test-helpers": "^0.18.3", "ember-cli-dependency-checker": "^2.1.0", - "ember-cli-eslint": "1.3.0", + "ember-cli-eslint": "^4.2.3", "ember-cli-htmlbars": "^2.0.1", "ember-cli-htmlbars-inline-precompile": "^0.4.3", "ember-cli-inject-live-reload": "^1.4.1", "ember-cli-internal-test-helpers": "^0.8.1", "ember-cli-pretender": "^1.0.1", - "ember-qunit": "^3.4.0", "ember-cli-release": "^0.2.9", "ember-cli-shims": "^1.0.2", "ember-cli-sri": "^2.1.0", @@ -93,17 +93,22 @@ "ember-export-application-global": "^1.0.5", "ember-load-initializers": "^0.6.0", "ember-publisher": "0.0.7", + "ember-qunit": "^3.4.0", "ember-qunit-assert-helpers": "^0.2.1", "ember-resolver": "^4.1.0", "ember-source": "~3.0.0", "ember-source-channel-url": "^1.0.1", "ember-try": "^0.2.23", "ember-watson": "^0.7.0", + "eslint-config-prettier": "^2.9.0", + "eslint-plugin-node": "^6.0.1", + "eslint-plugin-prettier": "^2.6.0", "github": "^1.1.1", "glob": "^5.0.13", "loader.js": "^4.5.0", "mocha": "^2.4.5", "mocha-only-detector": "0.0.2", + "prettier": "^1.12.1", "rimraf": "2.5.2", "rsvp": "4.8.0", "testdouble": "^3.2.6", diff --git a/testem.js b/testem.js index 158a909be30..cc773d51c58 100644 --- a/testem.js +++ b/testem.js @@ -1,15 +1,10 @@ -/* eslint-env node */ module.exports = { - "framework": "qunit", - "test_page": "tests/index.html?hidepassed", - "disable_watching": true, - "reporter": "dot", - "launch_in_ci": [ - "Chrome" - ], - "launch_in_dev": [ - "Chrome" - ], + framework: 'qunit', + test_page: 'tests/index.html?hidepassed', + disable_watching: true, + reporter: 'dot', + launch_in_ci: ['Chrome'], + launch_in_dev: ['Chrome'], browser_args: { Chrome: { mode: 'ci', @@ -18,8 +13,8 @@ module.exports = { '--headless', '--remote-debugging-port=0', '--window-size=1440,900', - '--no-sandbox' - ] - } - } + '--no-sandbox', + ], + }, + }, }; diff --git a/tests/.eslintrc.js b/tests/.eslintrc.js deleted file mode 100644 index 3a43edc6e04..00000000000 --- a/tests/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -/* global module */ -module.exports = { - rules: { - 'no-console': 0 - }, - globals: { - 'heimdall': true - } -}; diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js index b3b2bd677e0..f08aaaf0304 100644 --- a/tests/dummy/app/app.js +++ b/tests/dummy/app/app.js @@ -6,7 +6,7 @@ import config from './config/environment'; const App = Application.extend({ modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix, - Resolver + Resolver, }); loadInitializers(App, config.modulePrefix); diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js index 53c53c6c075..8f6f4598916 100644 --- a/tests/dummy/app/router.js +++ b/tests/dummy/app/router.js @@ -3,7 +3,7 @@ import config from './config/environment'; const Router = EmberRouter.extend({ location: config.locationType, - rootURL: config.rootURL + rootURL: config.rootURL, }); Router.map(function() {}); diff --git a/tests/dummy/app/routes/application/route.js b/tests/dummy/app/routes/application/route.js index 6c74252aa1b..d09f667b240 100644 --- a/tests/dummy/app/routes/application/route.js +++ b/tests/dummy/app/routes/application/route.js @@ -1,4 +1,3 @@ import Route from '@ember/routing/route'; -export default Route.extend({ -}); +export default Route.extend({}); diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js index 0d8efda6eee..8f6ea148349 100644 --- a/tests/dummy/config/environment.js +++ b/tests/dummy/config/environment.js @@ -1,4 +1,4 @@ -/* eslint-env node */ +'use strict'; var fs = require('fs'); var path = require('path'); @@ -15,13 +15,13 @@ module.exports = function(environment) { locationType: 'auto', EmberENV: { FEATURES: featureFlags, - RAISE_ON_DEPRECATION: false + RAISE_ON_DEPRECATION: false, }, APP: { // Here you can pass flags/options to your application instance // when it is created - } + }, }; if (environment === 'test-optional-features') { @@ -47,9 +47,5 @@ module.exports = function(environment) { ENV.APP.rootElement = '#ember-testing'; } - if (environment === 'production') { - - } - return ENV; }; diff --git a/tests/helpers/async.js b/tests/helpers/async.js index 5a0e787af55..40a5e12c93d 100644 --- a/tests/helpers/async.js +++ b/tests/helpers/async.js @@ -5,7 +5,7 @@ export function wait(callback, timeout) { let done = this.async(); let timer = setTimeout(() => { - this.ok(false, "Timeout was reached"); + this.ok(false, 'Timeout was reached'); done(); }, timeout || 200); @@ -24,15 +24,13 @@ export function wait(callback, timeout) { } export function asyncEqual(a, b, message) { - return all([ - resolve(a), - resolve(b) - ]).then(this.wait((array) => { - this.push(array[0] === array[1], array[0], array[1], message); - })); + return all([resolve(a), resolve(b)]).then( + this.wait(array => { + this.push(array[0] === array[1], array[0], array[1], message); + }) + ); } export function invokeAsync(callback, timeout = 1) { setTimeout(this.wait(callback, timeout + 100), timeout); } - diff --git a/tests/helpers/module-for-acceptance.js b/tests/helpers/module-for-acceptance.js index 0daf9c9a7e2..53ef0cfac24 100644 --- a/tests/helpers/module-for-acceptance.js +++ b/tests/helpers/module-for-acceptance.js @@ -16,6 +16,6 @@ export default function(name, options = {}) { afterEach() { let afterEach = options.afterEach && options.afterEach.apply(this, arguments); return Promise.resolve(afterEach).then(() => destroyApp(this.application)); - } + }, }); } diff --git a/tests/helpers/resolver.js b/tests/helpers/resolver.js index b208d38d097..319b45fc1c2 100644 --- a/tests/helpers/resolver.js +++ b/tests/helpers/resolver.js @@ -5,7 +5,7 @@ const resolver = Resolver.create(); resolver.namespace = { modulePrefix: config.modulePrefix, - podModulePrefix: config.podModulePrefix + podModulePrefix: config.podModulePrefix, }; export default resolver; diff --git a/tests/helpers/store.js b/tests/helpers/store.js index 5cbea0dd3f8..b2297944a58 100644 --- a/tests/helpers/store.js +++ b/tests/helpers/store.js @@ -11,10 +11,10 @@ export default function setupStore(options) { if (Ember.Registry) { registry = env.registry = new Ember.Registry(); owner = Owner.create({ - __registry__: registry + __registry__: registry, }); container = env.container = registry.container({ - owner: owner + owner: owner, }); owner.__container__ = container; } else { @@ -30,7 +30,7 @@ export default function setupStore(options) { } }; - let adapter = env.adapter = (options.adapter || '-default'); + let adapter = (env.adapter = options.adapter || '-default'); delete options.adapter; if (typeof adapter !== 'string') { @@ -42,9 +42,12 @@ export default function setupStore(options) { registry.register('model:' + dasherize(prop), options[prop]); } - registry.register('service:store', DS.Store.extend({ - adapter: adapter - })); + registry.register( + 'service:store', + DS.Store.extend({ + adapter: adapter, + }) + ); registry.optionsForType('serializer', { singleton: false }); registry.optionsForType('adapter', { singleton: false }); @@ -78,7 +81,7 @@ export default function setupStore(options) { this._adapter = adapter; }, enumerable: true, - configurable: true + configurable: true, }); return env; diff --git a/tests/helpers/watch-property.js b/tests/helpers/watch-property.js index 9b88dd8277a..d8df6e9e898 100644 --- a/tests/helpers/watch-property.js +++ b/tests/helpers/watch-property.js @@ -1,21 +1,22 @@ import Ember from 'ember'; import QUnit from 'qunit'; -const { - addObserver, - removeObserver -} = Ember; +const { addObserver, removeObserver } = Ember; function makeCounter() { let count = 0; const counter = Object.create(null); - counter.reset = function resetCounter() { count = 0; }; + counter.reset = function resetCounter() { + count = 0; + }; Object.defineProperty(counter, 'count', { - get() { return count; }, + get() { + return count; + }, set() {}, configurable: false, - enumerable: true + enumerable: true, }); Object.freeze(counter); @@ -48,7 +49,9 @@ export function watchProperties(obj, propertyNames) { let counters = {}; if (!Array.isArray(propertyNames)) { - throw new Error(`Must call watchProperties with an array of propertyNames to watch, received ${propertyNames}`); + throw new Error( + `Must call watchProperties with an array of propertyNames to watch, received ${propertyNames}` + ); } for (let i = 0; i < propertyNames.length; i++) { @@ -66,7 +69,7 @@ export function watchProperties(obj, propertyNames) { } function unwatch() { - Object.keys(watched).forEach((propertyName) => { + Object.keys(watched).forEach(propertyName => { removeObserver(obj, propertyName, watched[propertyName]); }); } @@ -74,14 +77,20 @@ export function watchProperties(obj, propertyNames) { return { counters, unwatch }; } -QUnit.assert.watchedPropertyCounts = function assertWatchedPropertyCount(watchedObject, expectedCounts, label = '') { +QUnit.assert.watchedPropertyCounts = function assertWatchedPropertyCount( + watchedObject, + expectedCounts, + label = '' +) { if (!watchedObject || !watchedObject.counters) { - throw new Error('Expected to receive the return value of watchProperties: an object containing counters'); + throw new Error( + 'Expected to receive the return value of watchProperties: an object containing counters' + ); } let counters = watchedObject.counters; - Object.keys(expectedCounts).forEach((propertyName) => { + Object.keys(expectedCounts).forEach(propertyName => { let counter = counters[propertyName]; let expectedCount = expectedCounts[propertyName]; let assertionText = label; @@ -91,22 +100,30 @@ QUnit.assert.watchedPropertyCounts = function assertWatchedPropertyCount(watched expectedCount = expectedCount[0]; } - assertionText += ` | Expected ${expectedCount} change notifications for ${propertyName} but recieved ${counter.count}`; + assertionText += ` | Expected ${expectedCount} change notifications for ${propertyName} but recieved ${ + counter.count + }`; if (counter === undefined) { - throw new Error(`Cannot assert expected count for ${propertyName} as there is no watcher for that property`); + throw new Error( + `Cannot assert expected count for ${propertyName} as there is no watcher for that property` + ); } this.pushResult({ result: counter.count === expectedCount, actual: counter.count, expected: expectedCount, - message: assertionText + message: assertionText, }); }); }; -QUnit.assert.watchedPropertyCount = function assertWatchedPropertyCount(watcher, expectedCount, label) { +QUnit.assert.watchedPropertyCount = function assertWatchedPropertyCount( + watcher, + expectedCount, + label +) { let counter; if (!watcher) { throw new Error(`Expected to receive a watcher`); @@ -123,7 +140,7 @@ QUnit.assert.watchedPropertyCount = function assertWatchedPropertyCount(watcher, result: counter.count === expectedCount, actual: counter.count, expected: expectedCount, - message: label + message: label, }); }; @@ -136,9 +153,7 @@ QUnit.assert.dirties = function assertDirties(options, updateMethodCallback, lab result: counter.count === count, actual: counter.count, expected: count, - message: label + message: label, }); unwatch(); }; - - diff --git a/tests/integration/adapter/build-url-mixin-test.js b/tests/integration/adapter/build-url-mixin-test.js index e97535f32b1..5bbdaa461d6 100644 --- a/tests/integration/adapter/build-url-mixin-test.js +++ b/tests/integration/adapter/build-url-mixin-test.js @@ -12,14 +12,14 @@ import DS from 'ember-data'; let env, store, adapter, Post, Comment, SuperUser; let passedUrl; -module("integration/adapter/build-url-mixin - BuildURLMixin with RESTAdapter", { +module('integration/adapter/build-url-mixin - BuildURLMixin with RESTAdapter', { beforeEach() { Post = DS.Model.extend({ - name: DS.attr("string") + name: DS.attr('string'), }); Comment = DS.Model.extend({ - name: DS.attr("string") + name: DS.attr('string'), }); SuperUser = DS.Model.extend(); @@ -28,7 +28,7 @@ module("integration/adapter/build-url-mixin - BuildURLMixin with RESTAdapter", { post: Post, comment: Comment, superUser: SuperUser, - adapter: DS.RESTAdapter + adapter: DS.RESTAdapter, }); store = env.store; @@ -39,7 +39,7 @@ module("integration/adapter/build-url-mixin - BuildURLMixin with RESTAdapter", { SuperUser = store.modelFor('super-user'); passedUrl = null; - } + }, }); function ajaxResponse(value) { @@ -50,27 +50,28 @@ function ajaxResponse(value) { }; } - test('buildURL - with host and namespace', function(assert) { run(() => { adapter.setProperties({ host: 'http://example.com', - namespace: 'api/v1' + namespace: 'api/v1', }); }); ajaxResponse({ posts: [{ id: 1 }] }); - return run(() => store.findRecord('post', 1).then(post => { - assert.equal(passedUrl, "http://example.com/api/v1/posts/1"); - })); + return run(() => + store.findRecord('post', 1).then(post => { + assert.equal(passedUrl, 'http://example.com/api/v1/posts/1'); + }) + ); }); test('buildURL - with relative paths in links', function(assert) { run(() => { adapter.setProperties({ host: 'http://example.com', - namespace: 'api/v1' + namespace: 'api/v1', }); }); @@ -79,19 +80,24 @@ test('buildURL - with relative paths in links', function(assert) { ajaxResponse({ posts: [{ id: 1, links: { comments: 'comments' } }] }); - return run(() => store.findRecord('post', 1).then(post => { - ajaxResponse({ comments: [{ id: 1 }] }); - return post.get('comments'); - }).then(comments => { - assert.equal(passedUrl, "http://example.com/api/v1/posts/1/comments"); - })); + return run(() => + store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ comments: [{ id: 1 }] }); + return post.get('comments'); + }) + .then(comments => { + assert.equal(passedUrl, 'http://example.com/api/v1/posts/1/comments'); + }) + ); }); test('buildURL - with absolute paths in links', function(assert) { run(() => { adapter.setProperties({ host: 'http://example.com', - namespace: 'api/v1' + namespace: 'api/v1', }); }); Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); @@ -99,20 +105,24 @@ test('buildURL - with absolute paths in links', function(assert) { ajaxResponse({ posts: [{ id: 1, links: { comments: '/api/v1/posts/1/comments' } }] }); - return run(() => store.findRecord('post', 1).then(post => { - ajaxResponse({ comments: [{ id: 1 }] }); - return post.get('comments'); - }).then(comments => { - assert.equal(passedUrl, "http://example.com/api/v1/posts/1/comments"); - })); + return run(() => + store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ comments: [{ id: 1 }] }); + return post.get('comments'); + }) + .then(comments => { + assert.equal(passedUrl, 'http://example.com/api/v1/posts/1/comments'); + }) + ); }); - test('buildURL - with absolute paths in links and protocol relative host', function(assert) { run(() => { adapter.setProperties({ host: '//example.com', - namespace: 'api/v1' + namespace: 'api/v1', }); }); Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); @@ -120,19 +130,24 @@ test('buildURL - with absolute paths in links and protocol relative host', funct ajaxResponse({ posts: [{ id: 1, links: { comments: '/api/v1/posts/1/comments' } }] }); - return run(() => store.findRecord('post', 1).then(post => { - ajaxResponse({ comments: [{ id: 1 }] }); - return post.get('comments'); - }).then(comments => { - assert.equal(passedUrl, "//example.com/api/v1/posts/1/comments"); - })); + return run(() => + store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ comments: [{ id: 1 }] }); + return post.get('comments'); + }) + .then(comments => { + assert.equal(passedUrl, '//example.com/api/v1/posts/1/comments'); + }) + ); }); test('buildURL - with absolute paths in links and host is /', function(assert) { run(() => { adapter.setProperties({ host: '/', - namespace: 'api/v1' + namespace: 'api/v1', }); }); Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); @@ -140,37 +155,46 @@ test('buildURL - with absolute paths in links and host is /', function(assert) { ajaxResponse({ posts: [{ id: 1, links: { comments: '/api/v1/posts/1/comments' } }] }); - return run(() => store.findRecord('post', 1).then(post => { - ajaxResponse({ comments: [{ id: 1 }] }); - return post.get('comments'); - }).then(comments => { - assert.equal(passedUrl, '/api/v1/posts/1/comments', 'host stripped out properly'); - })); + return run(() => + store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ comments: [{ id: 1 }] }); + return post.get('comments'); + }) + .then(comments => { + assert.equal(passedUrl, '/api/v1/posts/1/comments', 'host stripped out properly'); + }) + ); }); test('buildURL - with full URLs in links', function(assert) { adapter.setProperties({ host: 'http://example.com', - namespace: 'api/v1' + namespace: 'api/v1', }); Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); ajaxResponse({ posts: [ - { id: 1, - links: { comments: 'http://example.com/api/v1/posts/1/comments' } - } - ] + { + id: 1, + links: { comments: 'http://example.com/api/v1/posts/1/comments' }, + }, + ], }); return run(() => { - return store.findRecord('post', 1).then(post => { - ajaxResponse({ comments: [{ id: 1 }] }); - return post.get('comments'); - }).then(comments => { - assert.equal(passedUrl, "http://example.com/api/v1/posts/1/comments"); - }); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ comments: [{ id: 1 }] }); + return post.get('comments'); + }) + .then(comments => { + assert.equal(passedUrl, 'http://example.com/api/v1/posts/1/comments'); + }); }); }); @@ -179,14 +203,14 @@ test('buildURL - with camelized names', function(assert) { pathForType(type) { let decamelized = decamelize(type); return underscore(pluralize(decamelized)); - } + }, }); ajaxResponse({ superUsers: [{ id: 1 }] }); return run(() => { return store.findRecord('super-user', 1).then(post => { - assert.equal(passedUrl, "/super_users/1"); + assert.equal(passedUrl, '/super_users/1'); }); }); }); @@ -194,7 +218,7 @@ test('buildURL - with camelized names', function(assert) { test('buildURL - buildURL takes a record from find', function(assert) { Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); adapter.buildURL = function(type, id, snapshot) { - return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; + return '/posts/' + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; }; ajaxResponse({ comments: [{ id: 1 }] }); @@ -204,14 +228,14 @@ test('buildURL - buildURL takes a record from find', function(assert) { post = store.push({ data: { type: 'post', - id: '2' - } + id: '2', + }, }); }); return run(() => { return store.findRecord('comment', 1, { preload: { post: post } }).then(post => { - assert.equal(passedUrl, "/posts/2/comments/1"); + assert.equal(passedUrl, '/posts/2/comments/1'); }); }); }); @@ -222,16 +246,18 @@ test('buildURL - buildURL takes the records from findMany', function(assert) { adapter.buildURL = function(type, ids, snapshots) { if (Array.isArray(snapshots)) { - return "/posts/" + snapshots.get('firstObject').belongsTo('post', { id: true }) + '/comments/'; + return ( + '/posts/' + snapshots.get('firstObject').belongsTo('post', { id: true }) + '/comments/' + ); } - return ""; + return ''; }; adapter.coalesceFindRequests = true; ajaxResponse({ comments: [{ id: 1 }, { id: 2 }, { id: 3 }] }); let post; - return run(() => { + return run(() => { post = store.push({ data: { type: 'post', @@ -241,15 +267,15 @@ test('buildURL - buildURL takes the records from findMany', function(assert) { data: [ { id: '1', type: 'comment' }, { id: '2', type: 'comment' }, - { id: '3', type: 'comment' } - ] - } - } - } + { id: '3', type: 'comment' }, + ], + }, + }, + }, }); return post.get('comments').then(post => { - assert.equal(passedUrl, "/posts/2/comments/"); + assert.equal(passedUrl, '/posts/2/comments/'); }); }); }); @@ -257,7 +283,7 @@ test('buildURL - buildURL takes the records from findMany', function(assert) { test('buildURL - buildURL takes a record from create', function(assert) { Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); adapter.buildURL = function(type, id, snapshot) { - return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/'; + return '/posts/' + snapshot.belongsTo('post', { id: true }) + '/comments/'; }; ajaxResponse({ comments: [{ id: 1 }] }); @@ -266,13 +292,13 @@ test('buildURL - buildURL takes a record from create', function(assert) { let post = store.push({ data: { type: 'post', - id: '2' - } + id: '2', + }, }); let comment = store.createRecord('comment'); comment.set('post', post); return comment.save().then(post => { - assert.equal(passedUrl, "/posts/2/comments/"); + assert.equal(passedUrl, '/posts/2/comments/'); }); }); }); @@ -287,7 +313,7 @@ test('buildURL - buildURL takes a record from create to query a resolved async b assert.equal(post.get('id'), 2); adapter.buildURL = function(type, id, snapshot) { - return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/'; + return '/posts/' + snapshot.belongsTo('post', { id: true }) + '/comments/'; }; ajaxResponse({ comments: [{ id: 1 }] }); @@ -295,7 +321,7 @@ test('buildURL - buildURL takes a record from create to query a resolved async b let comment = store.createRecord('comment'); comment.set('post', post); return comment.save().then(post => { - assert.equal(passedUrl, "/posts/2/comments/"); + assert.equal(passedUrl, '/posts/2/comments/'); }); }); }); @@ -304,7 +330,7 @@ test('buildURL - buildURL takes a record from create to query a resolved async b test('buildURL - buildURL takes a record from update', function(assert) { Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); adapter.buildURL = function(type, id, snapshot) { - return "/posts/" + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; + return '/posts/' + snapshot.belongsTo('post', { id: true }) + '/comments/' + snapshot.id; }; ajaxResponse({ comments: [{ id: 1 }] }); @@ -314,21 +340,21 @@ test('buildURL - buildURL takes a record from update', function(assert) { post = store.push({ data: { type: 'post', - id: '2' - } + id: '2', + }, }); comment = store.push({ data: { type: 'comment', - id: '1' - } + id: '1', + }, }); comment.set('post', post); }); return run(() => { return comment.save().then(post => { - assert.equal(passedUrl, "/posts/2/comments/1"); + assert.equal(passedUrl, '/posts/2/comments/1'); }); }); }); @@ -348,14 +374,14 @@ test('buildURL - buildURL takes a record from delete', function(assert) { post = store.push({ data: { type: 'post', - id: '2' - } + id: '2', + }, }); comment = store.push({ data: { type: 'comment', - id: '1' - } + id: '1', + }, }); comment.set('post', post); @@ -364,7 +390,7 @@ test('buildURL - buildURL takes a record from delete', function(assert) { return run(() => { return comment.save().then(post => { - assert.equal(passedUrl, "posts/2/comments/1"); + assert.equal(passedUrl, 'posts/2/comments/1'); }); }); }); @@ -372,13 +398,13 @@ test('buildURL - buildURL takes a record from delete', function(assert) { test('buildURL - with absolute namespace', function(assert) { run(() => { adapter.setProperties({ - namespace: '/api/v1' + namespace: '/api/v1', }); }); ajaxResponse({ posts: [{ id: 1 }] }); return run(store, 'findRecord', 'post', 1).then(post => { - assert.equal(passedUrl, "/api/v1/posts/1"); + assert.equal(passedUrl, '/api/v1/posts/1'); }); }); diff --git a/tests/integration/adapter/client-side-delete-test.js b/tests/integration/adapter/client-side-delete-test.js index 38693df8dd5..c755de89971 100644 --- a/tests/integration/adapter/client-side-delete-test.js +++ b/tests/integration/adapter/client-side-delete-test.js @@ -9,15 +9,15 @@ import DS from 'ember-data'; module('integration/adapter/store-adapter - client-side delete', { beforeEach() { this.Bookstore = DS.Model.extend({ - books: DS.hasMany('book', { async: false, inverse: 'bookstore' }) + books: DS.hasMany('book', { async: false, inverse: 'bookstore' }), }); this.Book = DS.Model.extend({ - bookstore: DS.belongsTo('bookstore', { inverse: 'books' }) + bookstore: DS.belongsTo('bookstore', { inverse: 'books' }), }); this.env = setupStore({ bookstore: this.Bookstore, - book: this.Book + book: this.Book, }); this.store = this.env.store; this.adapter = this.env.adapter; @@ -25,39 +25,50 @@ module('integration/adapter/store-adapter - client-side delete', { afterEach() { run(this.env.container, 'destroy'); - } + }, }); test('client-side deleted records can be added back from an inverse', function(assert) { - this.adapter.deleteRecord = function (store, modelClass, snapshot) { + this.adapter.deleteRecord = function(store, modelClass, snapshot) { if (snapshot.adapterOptions.clientSideDelete) { return resolve(); } assert.ok(false, 'unreachable'); - } + }; - run(() => this.store.push({ - data: { - id: '1', - type: 'bookstore', - relationships: { - books: { - data: [{ - id: '1', type: 'book' - }, { - id: '2', type: 'book' - }] - } - } - }, included: [{ - id: '1', - type: 'book' - }, { - id: '2', - type: 'book' - }] - })); + run(() => + this.store.push({ + data: { + id: '1', + type: 'bookstore', + relationships: { + books: { + data: [ + { + id: '1', + type: 'book', + }, + { + id: '2', + type: 'book', + }, + ], + }, + }, + }, + included: [ + { + id: '1', + type: 'book', + }, + { + id: '2', + type: 'book', + }, + ], + }) + ); let bookstore = this.store.peekRecord('bookstore', '1'); assert.deepEqual(bookstore.get('books').mapBy('id'), ['1', '2'], 'initial hasmany loaded'); @@ -68,21 +79,27 @@ test('client-side deleted records can be added back from an inverse', function(a assert.equal(this.store.hasRecordForId('book', '2'), false, 'book 2 unloaded'); assert.deepEqual(bookstore.get('books').mapBy('id'), ['1'], 'one book client-side deleted'); - run(() => this.store.push({ - data: { - id: '2', - type: 'book', - relationships: { - bookstore: { - data: { - id: '1', - type: 'bookstore' - } - } - } - } - })); + run(() => + this.store.push({ + data: { + id: '2', + type: 'book', + relationships: { + bookstore: { + data: { + id: '1', + type: 'bookstore', + }, + }, + }, + }, + }) + ); - assert.deepEqual(bookstore.get('books').mapBy('id'), ['1', '2'], 'the deleted book (with same id) is pushed back into the store'); + assert.deepEqual( + bookstore.get('books').mapBy('id'), + ['1', '2'], + 'the deleted book (with same id) is pushed back into the store' + ); }); }); diff --git a/tests/integration/adapter/find-all-test.js b/tests/integration/adapter/find-all-test.js index c787fe11b01..1d1b2b01cab 100644 --- a/tests/integration/adapter/find-all-test.js +++ b/tests/integration/adapter/find-all-test.js @@ -11,103 +11,146 @@ const { attr } = DS; let Person, store, allRecords, env; -module("integration/adapter/find-all - Finding All Records of a Type", { +module('integration/adapter/find-all - Finding All Records of a Type', { beforeEach() { Person = DS.Model.extend({ updatedAt: attr('string'), name: attr('string'), firstName: attr('string'), - lastName: attr('string') + lastName: attr('string'), + }); + Person.reopenClass({ + toString() { + return 'Person'; + }, }); - Person.reopenClass({ toString() { return 'Person'; } }); allRecords = null; env = setupStore({ - person: Person + person: Person, }); store = env.store; }, afterEach() { run(() => { - if (allRecords) { allRecords.destroy(); } + if (allRecords) { + allRecords.destroy(); + } store.destroy(); }); - } + }, }); -test("When all records for a type are requested, the store should call the adapter's `findAll` method.", (assert) => { +test("When all records for a type are requested, the store should call the adapter's `findAll` method.", assert => { assert.expect(5); - env.registry.register('adapter:person', DS.Adapter.extend({ - findAll() { - // this will get called twice - assert.ok(true, "the adapter's findAll method should be invoked"); - - return resolve({ data: [{ - id: 1, - type: 'person', - attributes: { - name: "Braaaahm Dale" - } - }]}); - } - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findAll() { + // this will get called twice + assert.ok(true, "the adapter's findAll method should be invoked"); + + return resolve({ + data: [ + { + id: 1, + type: 'person', + attributes: { + name: 'Braaaahm Dale', + }, + }, + ], + }); + }, + }) + ); return run(() => { return store.findAll('person').then(all => { let allRecords = all; - assert.equal(get(all, 'length'), 1, "the record array's length is 1 after a record is loaded into it"); - assert.equal(all.objectAt(0).get('name'), "Braaaahm Dale", "the first item in the record array is Braaaahm Dale"); + assert.equal( + get(all, 'length'), + 1, + "the record array's length is 1 after a record is loaded into it" + ); + assert.equal( + all.objectAt(0).get('name'), + 'Braaaahm Dale', + 'the first item in the record array is Braaaahm Dale' + ); return store.findAll('person').then(all => { // Only one record array per type should ever be created (identity map) - assert.strictEqual(allRecords, all, "the same record array is returned every time all records of a type are requested"); + assert.strictEqual( + allRecords, + all, + 'the same record array is returned every time all records of a type are requested' + ); }); }); }); }); -test("When all records for a type are requested, a rejection should reject the promise", (assert) => { +test('When all records for a type are requested, a rejection should reject the promise', assert => { assert.expect(5); let count = 0; - env.registry.register('adapter:person', DS.Adapter.extend({ - findAll() { - // this will get called twice - assert.ok(true, "the adapter's findAll method should be invoked"); - - if (count++ === 0) { - return reject(); - } else { - return resolve({ data: [{ - id: 1, - type: 'person', - attributes: { - name: "Braaaahm Dale" - } - }]}); - } - } - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findAll() { + // this will get called twice + assert.ok(true, "the adapter's findAll method should be invoked"); + + if (count++ === 0) { + return reject(); + } else { + return resolve({ + data: [ + { + id: 1, + type: 'person', + attributes: { + name: 'Braaaahm Dale', + }, + }, + ], + }); + } + }, + }) + ); return run(() => { - return store.findAll('person').catch(() => { - assert.ok(true, "The rejection should get here"); - return store.findAll('person'); - }).then(all => { - assert.equal(get(all, 'length'), 1, "the record array's length is 1 after a record is loaded into it"); - assert.equal(all.objectAt(0).get('name'), "Braaaahm Dale", "the first item in the record array is Braaaahm Dale"); - }); + return store + .findAll('person') + .catch(() => { + assert.ok(true, 'The rejection should get here'); + return store.findAll('person'); + }) + .then(all => { + assert.equal( + get(all, 'length'), + 1, + "the record array's length is 1 after a record is loaded into it" + ); + assert.equal( + all.objectAt(0).get('name'), + 'Braaaahm Dale', + 'the first item in the record array is Braaaahm Dale' + ); + }); }); }); -test("When all records for a type are requested, records that are already loaded should be returned immediately.", (assert) => { +test('When all records for a type are requested, records that are already loaded should be returned immediately.', assert => { assert.expect(3); store = createStore({ adapter: DS.Adapter.extend(), - person: Person + person: Person, }); run(() => { @@ -117,119 +160,148 @@ test("When all records for a type are requested, records that are already loaded type: 'person', id: '1', attributes: { - name: 'Jeremy Ashkenas' - } - } + name: 'Jeremy Ashkenas', + }, + }, }); // Create a new, unsaved record in the store - store.createRecord('person', { name: "Alex MacCaw" }); + store.createRecord('person', { name: 'Alex MacCaw' }); }); allRecords = store.peekAll('person'); assert.equal(get(allRecords, 'length'), 2, "the record array's length is 2"); - assert.equal(allRecords.objectAt(0).get('name'), "Jeremy Ashkenas", "the first item in the record array is Jeremy Ashkenas"); - assert.equal(allRecords.objectAt(1).get('name'), "Alex MacCaw", "the second item in the record array is Alex MacCaw"); + assert.equal( + allRecords.objectAt(0).get('name'), + 'Jeremy Ashkenas', + 'the first item in the record array is Jeremy Ashkenas' + ); + assert.equal( + allRecords.objectAt(1).get('name'), + 'Alex MacCaw', + 'the second item in the record array is Alex MacCaw' + ); }); -test("When all records for a type are requested, records that are created on the client should be added to the record array.", (assert) => { +test('When all records for a type are requested, records that are created on the client should be added to the record array.', assert => { assert.expect(3); store = createStore({ adapter: DS.Adapter.extend(), - person: Person + person: Person, }); allRecords = store.peekAll('person'); - assert.equal(get(allRecords, 'length'), 0, "precond - the record array's length is zero before any records are loaded"); + assert.equal( + get(allRecords, 'length'), + 0, + "precond - the record array's length is zero before any records are loaded" + ); - store.createRecord('person', { name: "Carsten Nielsen" }); + store.createRecord('person', { name: 'Carsten Nielsen' }); assert.equal(get(allRecords, 'length'), 1, "the record array's length is 1"); - assert.equal(allRecords.objectAt(0).get('name'), "Carsten Nielsen", "the first item in the record array is Carsten Nielsen"); + assert.equal( + allRecords.objectAt(0).get('name'), + 'Carsten Nielsen', + 'the first item in the record array is Carsten Nielsen' + ); }); -testInDebug('When all records are requested, assert the payload is not blank', (assert) => { - env.registry.register('adapter:person', DS.Adapter.extend({ - findAll: () => resolve({}) - })); +testInDebug('When all records are requested, assert the payload is not blank', assert => { + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findAll: () => resolve({}), + }) + ); assert.expectAssertion(() => { run(() => store.findAll('person')); }, /You made a 'findAll' request for 'person' records, but the adapter's response did not have any data/); }); -test("isUpdating is true while records are fetched", function(assert) { +test('isUpdating is true while records are fetched', function(assert) { let findAllDeferred = defer(); - env.registry.register('adapter:person', DS.Adapter.extend({ - findAll() { - return findAllDeferred.promise; - }, + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findAll() { + return findAllDeferred.promise; + }, - shouldReloadAll: () => true - })); + shouldReloadAll: () => true, + }) + ); run(() => { store.push({ - data: [{ - type: 'person', - id: 1 - }] + data: [ + { + type: 'person', + id: 1, + }, + ], }); }); let persons = store.peekAll('person'); - assert.equal(persons.get("length"), 1); + assert.equal(persons.get('length'), 1); let wait = run(() => { return store.findAll('person').then(persons => { - assert.equal(persons.get("isUpdating"), false); - assert.equal(persons.get("length"), 2); + assert.equal(persons.get('isUpdating'), false); + assert.equal(persons.get('length'), 2); }); }); - assert.equal(persons.get("isUpdating"), true); + assert.equal(persons.get('isUpdating'), true); findAllDeferred.resolve({ data: [{ id: 2, type: 'person' }] }); return wait; }); -test("isUpdating is true while records are fetched in the background", function(assert) { +test('isUpdating is true while records are fetched in the background', function(assert) { let findAllDeferred = defer(); - env.registry.register('adapter:person', DS.Adapter.extend({ - findAll() { - return findAllDeferred.promise; - }, - - shouldReloadAll() { - return false; - }, - shouldBackgroundReloadAll() { - return true; - } - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findAll() { + return findAllDeferred.promise; + }, + + shouldReloadAll() { + return false; + }, + shouldBackgroundReloadAll() { + return true; + }, + }) + ); run(() => { store.push({ - data: [{ - type: 'person', - id: 1 - }] + data: [ + { + type: 'person', + id: 1, + }, + ], }); }); let persons = store.peekAll('person'); - assert.equal(persons.get("length"), 1); + assert.equal(persons.get('length'), 1); return run(() => { return store.findAll('person').then(persons => { - assert.equal(persons.get("isUpdating"), true); - assert.equal(persons.get("length"), 1, "persons are updated in the background"); + assert.equal(persons.get('isUpdating'), true); + assert.equal(persons.get('length'), 1, 'persons are updated in the background'); }); }).then(() => { - assert.equal(persons.get("isUpdating"), true); + assert.equal(persons.get('isUpdating'), true); run(() => { findAllDeferred.resolve({ data: [{ id: 2, type: 'person' }] }); @@ -237,40 +309,45 @@ test("isUpdating is true while records are fetched in the background", function( return run(() => { return findAllDeferred.promise.then(() => { - assert.equal(persons.get("isUpdating"), false); - assert.equal(persons.get("length"), 2); + assert.equal(persons.get('isUpdating'), false); + assert.equal(persons.get('length'), 2); }); }); }); }); -test("isUpdating is false if records are not fetched in the background", function(assert) { +test('isUpdating is false if records are not fetched in the background', function(assert) { let findAllDeferred = defer(); - env.registry.register('adapter:person', DS.Adapter.extend({ - findAll() { - return findAllDeferred.promise; - }, - shouldReloadAll: () => false, - shouldBackgroundReloadAll: () => false - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findAll() { + return findAllDeferred.promise; + }, + shouldReloadAll: () => false, + shouldBackgroundReloadAll: () => false, + }) + ); run(() => { store.push({ - data: [{ - type: 'person', - id: 1 - }] + data: [ + { + type: 'person', + id: 1, + }, + ], }); }); let persons = store.peekAll('person'); - assert.equal(persons.get("length"), 1); + assert.equal(persons.get('length'), 1); return run(() => { return store.findAll('person').then(persons => { - assert.equal(persons.get("isUpdating"), false); + assert.equal(persons.get('isUpdating'), false); }); }).then(() => { - assert.equal(persons.get("isUpdating"), false); + assert.equal(persons.get('isUpdating'), false); }); }); diff --git a/tests/integration/adapter/find-test.js b/tests/integration/adapter/find-test.js index b537c3c6dfc..00cf5c73791 100644 --- a/tests/integration/adapter/find-test.js +++ b/tests/integration/adapter/find-test.js @@ -9,27 +9,27 @@ const { attr } = DS; let Person, store, env; -module("integration/adapter/find - Finding Records", { +module('integration/adapter/find - Finding Records', { beforeEach() { Person = DS.Model.extend({ updatedAt: attr('string'), name: attr('string'), firstName: attr('string'), - lastName: attr('string') + lastName: attr('string'), }); env = setupStore({ - person: Person + person: Person, }); store = env.store; }, afterEach() { run(store, 'destroy'); - } + }, }); -testInDebug("It raises an assertion when `undefined` is passed as id (#1705)", function(assert) { +testInDebug('It raises an assertion when `undefined` is passed as id (#1705)', function(assert) { assert.expectAssertion(() => { store.find('person', undefined); }, `You cannot pass 'undefined' as id to the store's find method`); @@ -44,23 +44,26 @@ test("When a single record is requested, the adapter's find method should be cal let count = 0; - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord(_, type) { - assert.equal(type, Person, "the find method is called with the correct type"); - assert.equal(count, 0, "the find method is only called once"); - - count++; - return { - data: { - id: 1, - type: "person", - attributes: { - name: "Braaaahm Dale" - } - } - }; - } - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord(_, type) { + assert.equal(type, Person, 'the find method is called with the correct type'); + assert.equal(count, 0, 'the find method is only called once'); + + count++; + return { + data: { + id: 1, + type: 'person', + attributes: { + name: 'Braaaahm Dale', + }, + }, + }; + }, + }) + ); run(() => { store.findRecord('person', 1); @@ -68,26 +71,29 @@ test("When a single record is requested, the adapter's find method should be cal }); }); -test("When a single record is requested multiple times, all .findRecord() calls are resolved after the promise is resolved", function(assert) { +test('When a single record is requested multiple times, all .findRecord() calls are resolved after the promise is resolved', function(assert) { let deferred = defer(); - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord() { - return deferred.promise; - } - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord() { + return deferred.promise; + }, + }) + ); let requestOne = run(() => { return store.findRecord('person', 1).then(person => { - assert.equal(person.get('id'), "1"); - assert.equal(person.get('name'), "Braaaahm Dale"); + assert.equal(person.get('id'), '1'); + assert.equal(person.get('name'), 'Braaaahm Dale'); }); }); let requestTwo = run(() => { return store.findRecord('person', 1).then(post => { - assert.equal(post.get('id'), "1"); - assert.equal(post.get('name'), "Braaaahm Dale"); + assert.equal(post.get('id'), '1'); + assert.equal(post.get('name'), 'Braaaahm Dale'); }); }); @@ -95,26 +101,26 @@ test("When a single record is requested multiple times, all .findRecord() calls deferred.resolve({ data: { id: 1, - type: "person", + type: 'person', attributes: { - name: "Braaaahm Dale" - } - } + name: 'Braaaahm Dale', + }, + }, }); }); - return Promise.all([ - requestOne, - requestTwo - ]) + return Promise.all([requestOne, requestTwo]); }); -test("When a single record is requested, and the promise is rejected, .findRecord() is rejected.", function(assert) { - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord() { - return reject(); - } - })); +test('When a single record is requested, and the promise is rejected, .findRecord() is rejected.', function(assert) { + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord() { + return reject(); + }, + }) + ); return run(() => { return store.findRecord('person', 1).catch(() => { @@ -123,27 +129,33 @@ test("When a single record is requested, and the promise is rejected, .findRecor }); }); -test("When a single record is requested, and the promise is rejected, the record should be unloaded.", function(assert) { +test('When a single record is requested, and the promise is rejected, the record should be unloaded.', function(assert) { assert.expect(2); - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord() { - return reject(); - } - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord() { + return reject(); + }, + }) + ); return run(() => { return store.findRecord('person', 1).catch(reason => { - assert.ok(true, "The rejection handler was called"); - assert.ok(!store.hasRecordForId('person', 1), "The record has been unloaded"); + assert.ok(true, 'The rejection handler was called'); + assert.ok(!store.hasRecordForId('person', 1), 'The record has been unloaded'); }); }); }); testInDebug('When a single record is requested, and the payload is blank', function(assert) { - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord: () => resolve({}) - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord: () => resolve({}), + }) + ); assert.expectAssertion(() => { run(() => store.findRecord('person', 'the-id')); @@ -151,10 +163,13 @@ testInDebug('When a single record is requested, and the payload is blank', funct }); testInDebug('When multiple records are requested, and the payload is blank', function(assert) { - env.registry.register('adapter:person', DS.Adapter.extend({ - coalesceFindRequests: true, - findMany: () => resolve({}) - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + coalesceFindRequests: true, + findMany: () => resolve({}), + }) + ); assert.expectAssertion(() => { run(() => { @@ -164,22 +179,26 @@ testInDebug('When multiple records are requested, and the payload is blank', fun }, /You made a 'findMany' request for 'person' records with ids '\[1,2\]', but the adapter's response did not have any data/); }); -testInDebug("warns when returned record has different id", function(assert) { - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord() { - return { - data: { - id: 1, - type: "person", - attributes: { - name: "Braaaahm Dale" - } - } - }; - } - })); +testInDebug('warns when returned record has different id', function(assert) { + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord() { + return { + data: { + id: 1, + type: 'person', + attributes: { + name: 'Braaaahm Dale', + }, + }, + }; + }, + }) + ); assert.expectWarning( () => run(() => env.store.findRecord('person', 'me')), - /You requested a record of type 'person' with id 'me' but the adapter returned a payload with primary data having an id of '1'/); + /You requested a record of type 'person' with id 'me' but the adapter returned a payload with primary data having an id of '1'/ + ); }); diff --git a/tests/integration/adapter/json-api-adapter-test.js b/tests/integration/adapter/json-api-adapter-test.js index c945eeb51cf..67e49141b8c 100644 --- a/tests/integration/adapter/json-api-adapter-test.js +++ b/tests/integration/adapter/json-api-adapter-test.js @@ -10,7 +10,15 @@ import DS from 'ember-data'; let env, store, adapter; let passedUrl, passedVerb, passedHash; -let User, Post, Comment, Handle, GithubHandle, TwitterHandle, Company, DevelopmentShop, DesignStudio; +let User, + Post, + Comment, + Handle, + GithubHandle, + TwitterHandle, + Company, + DevelopmentShop, + DesignStudio; module('integration/adapter/json-api-adapter - JSONAPIAdapter', { beforeEach() { @@ -19,57 +27,57 @@ module('integration/adapter/json-api-adapter - JSONAPIAdapter', { lastName: DS.attr('string'), posts: DS.hasMany('post', { async: true }), handles: DS.hasMany('handle', { async: true, polymorphic: true }), - company: DS.belongsTo('company', { async: true, polymorphic: true }) + company: DS.belongsTo('company', { async: true, polymorphic: true }), }); Post = DS.Model.extend({ title: DS.attr('string'), author: DS.belongsTo('user', { async: true }), - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); Comment = DS.Model.extend({ text: DS.attr('string'), - post: DS.belongsTo('post', { async: true }) + post: DS.belongsTo('post', { async: true }), }); Handle = DS.Model.extend({ - user: DS.belongsTo('user', { async: true }) + user: DS.belongsTo('user', { async: true }), }); GithubHandle = Handle.extend({ - username: DS.attr('string') + username: DS.attr('string'), }); TwitterHandle = Handle.extend({ - nickname: DS.attr('string') + nickname: DS.attr('string'), }); Company = DS.Model.extend({ name: DS.attr('string'), - employees: DS.hasMany('user', { async: true }) + employees: DS.hasMany('user', { async: true }), }); DevelopmentShop = Company.extend({ - coffee: DS.attr('boolean') + coffee: DS.attr('boolean'), }); DesignStudio = Company.extend({ - hipsters: DS.attr('number') + hipsters: DS.attr('number'), }); env = setupStore({ adapter: DS.JSONAPIAdapter.extend(), - 'user': User, - 'post': Post, - 'comment': Comment, - 'handle': Handle, + user: User, + post: Post, + comment: Comment, + handle: Handle, 'github-handle': GithubHandle, 'twitter-handle': TwitterHandle, - 'company': Company, + company: Company, 'development-shop': DevelopmentShop, - 'design-studio': DesignStudio + 'design-studio': DesignStudio, }); store = env.store; @@ -78,7 +86,7 @@ module('integration/adapter/json-api-adapter - JSONAPIAdapter', { afterEach() { run(env.store, 'destroy'); - } + }, }); function ajaxResponse(responses) { @@ -103,15 +111,17 @@ function ajaxResponse(responses) { test('find a single record', function(assert) { assert.expect(3); - ajaxResponse([{ - data: { - type: 'post', - id: '1', - attributes: { - title: 'Ember.js rocks' - } - } - }]); + ajaxResponse([ + { + data: { + type: 'post', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + }, + }, + ]); return run(() => { return store.findRecord('post', 1).then(post => { @@ -126,57 +136,63 @@ test('find a single record', function(assert) { test('find all records with sideloaded relationships', function(assert) { assert.expect(9); - ajaxResponse([{ - data: [{ - type: 'posts', - id: '1', - attributes: { - title: 'Ember.js rocks' - }, - relationships: { - author: { - data: { type: 'users', id: '3' } - } - } - }, { - type: 'posts', - id: '2', - attributes: { - title: 'Tomster rules' - }, - relationships: { - author: { - data: { type: 'users', id: '3' } - }, - comments: { - data: [ - { type: 'comments', id: '4' }, - { type: 'comments', id: '5' } - ] - } - } - }], - included: [{ - type: 'users', - id: '3', - attributes: { - 'first-name': 'Yehuda', - 'last-name': 'Katz' - } - }, { - type: 'comments', - id: '4', - attributes: { - text: 'This is the first comment' - } - }, { - type: 'comments', - id: '5', - attributes: { - text: 'This is the second comment' - } - }] - }]); + ajaxResponse([ + { + data: [ + { + type: 'posts', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + relationships: { + author: { + data: { type: 'users', id: '3' }, + }, + }, + }, + { + type: 'posts', + id: '2', + attributes: { + title: 'Tomster rules', + }, + relationships: { + author: { + data: { type: 'users', id: '3' }, + }, + comments: { + data: [{ type: 'comments', id: '4' }, { type: 'comments', id: '5' }], + }, + }, + }, + ], + included: [ + { + type: 'users', + id: '3', + attributes: { + 'first-name': 'Yehuda', + 'last-name': 'Katz', + }, + }, + { + type: 'comments', + id: '4', + attributes: { + text: 'This is the first comment', + }, + }, + { + type: 'comments', + id: '5', + attributes: { + text: 'This is the second comment', + }, + }, + ], + }, + ]); return run(() => { return store.findAll('post').then(posts => { @@ -200,15 +216,19 @@ test('find all records with sideloaded relationships', function(assert) { test('find many records', function(assert) { assert.expect(4); - ajaxResponse([{ - data: [{ - type: 'posts', - id: '1', - attributes: { - title: 'Ember.js rocks' - } - }] - }]); + ajaxResponse([ + { + data: [ + { + type: 'posts', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + }, + ], + }, + ]); return run(() => { return store.query('post', { filter: { id: 1 } }).then(posts => { @@ -222,15 +242,17 @@ test('find many records', function(assert) { }); test('queryRecord - primary data being a single record', function(assert) { - ajaxResponse([{ - data: { - type: 'posts', - id: '1', - attributes: { - title: 'Ember.js rocks' - } - } - }]); + ajaxResponse([ + { + data: { + type: 'posts', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + }, + }, + ]); return run(() => { return store.queryRecord('post', {}).then(post => { @@ -242,9 +264,11 @@ test('queryRecord - primary data being a single record', function(assert) { }); test('queryRecord - primary data being null', function(assert) { - ajaxResponse([{ - data: null - }]); + ajaxResponse([ + { + data: null, + }, + ]); return run(() => { return store.queryRecord('post', {}).then(post => { @@ -256,46 +280,53 @@ test('queryRecord - primary data being null', function(assert) { }); testInDebug('queryRecord - primary data being an array throws an assertion', function(assert) { - ajaxResponse([{ - data: [{ - type: 'posts', - id: '1' - }] - }]); + ajaxResponse([ + { + data: [ + { + type: 'posts', + id: '1', + }, + ], + }, + ]); assert.expectAssertion(() => { run(() => store.queryRecord('post', {})); - }, "Expected the primary data returned by the serializer for a `queryRecord` response to be a single object but instead it was an array."); + }, 'Expected the primary data returned by the serializer for a `queryRecord` response to be a single object but instead it was an array.'); }); test('find a single record with belongsTo link as object { related }', function(assert) { assert.expect(7); - ajaxResponse([{ - data: { - type: 'posts', - id: '1', - attributes: { - title: 'Ember.js rocks' + ajaxResponse([ + { + data: { + type: 'posts', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + relationships: { + author: { + links: { + related: 'http://example.com/user/2', + }, + }, + }, }, - relationships: { - author: { - links: { - related: 'http://example.com/user/2' - } - } - } - } - }, { - data: { - type: 'users', - id: '2', - attributes: { - 'first-name': 'Yehuda', - 'last-name': 'Katz' - } - } - }]); + }, + { + data: { + type: 'users', + id: '2', + attributes: { + 'first-name': 'Yehuda', + 'last-name': 'Katz', + }, + }, + }, + ]); return run(() => { return store.findRecord('post', 1).then(post => { @@ -318,29 +349,32 @@ test('find a single record with belongsTo link as object { related }', function( test('find a single record with belongsTo link as object { data }', function(assert) { assert.expect(7); - ajaxResponse([{ - data: { - type: 'posts', - id: '1', - attributes: { - title: 'Ember.js rocks' + ajaxResponse([ + { + data: { + type: 'posts', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + relationships: { + author: { + data: { type: 'users', id: '2' }, + }, + }, + }, + }, + { + data: { + type: 'users', + id: '2', + attributes: { + 'first-name': 'Yehuda', + 'last-name': 'Katz', + }, }, - relationships: { - author: { - data: { type: 'users', id: '2' } - } - } - } - }, { - data: { - type: 'users', - id: '2', - attributes: { - 'first-name': 'Yehuda', - 'last-name': 'Katz' - } - } - }]); + }, + ]); return run(() => { return store.findRecord('post', 1).then(post => { @@ -363,30 +397,33 @@ test('find a single record with belongsTo link as object { data }', function(ass test('find a single record with belongsTo link as object { data } (polymorphic)', function(assert) { assert.expect(8); - ajaxResponse([{ - data: { - type: 'users', - id: '1', - attributes: { - 'first-name': 'Yehuda', - 'last-name': 'Katz' + ajaxResponse([ + { + data: { + type: 'users', + id: '1', + attributes: { + 'first-name': 'Yehuda', + 'last-name': 'Katz', + }, + relationships: { + company: { + data: { type: 'development-shops', id: '2' }, + }, + }, }, - relationships: { - company: { - data: { type: 'development-shops', id: '2' } - } - } - } - }, { - data: { - type: 'development-shop', - id: '2', - attributes: { - name: 'Tilde', - coffee: true - } - } - }]); + }, + { + data: { + type: 'development-shop', + id: '2', + attributes: { + name: 'Tilde', + coffee: true, + }, + }, + }, + ]); return run(() => { return store.findRecord('user', 1).then(user => { @@ -410,28 +447,32 @@ test('find a single record with belongsTo link as object { data } (polymorphic)' test('find a single record with sideloaded belongsTo link as object { data }', function(assert) { assert.expect(7); - ajaxResponse([{ - data: { - type: 'post', - id: '1', - attributes: { - title: 'Ember.js rocks' + ajaxResponse([ + { + data: { + type: 'post', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + relationships: { + author: { + data: { type: 'user', id: '2' }, + }, + }, }, - relationships: { - author: { - data: { type: 'user', id: '2' } - } - } + included: [ + { + type: 'user', + id: '2', + attributes: { + 'first-name': 'Yehuda', + 'last-name': 'Katz', + }, + }, + ], }, - included: [{ - type: 'user', - id: '2', - attributes: { - 'first-name': 'Yehuda', - 'last-name': 'Katz' - } - }] - }]); + ]); return run(() => { return store.findRecord('post', 1).then(post => { @@ -454,36 +495,42 @@ test('find a single record with sideloaded belongsTo link as object { data }', f test('find a single record with hasMany link as object { related }', function(assert) { assert.expect(7); - ajaxResponse([{ - data: { - type: 'post', - id: '1', - attributes: { - title: 'Ember.js rocks' + ajaxResponse([ + { + data: { + type: 'post', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + relationships: { + comments: { + links: { + related: 'http://example.com/post/1/comments', + }, + }, + }, }, - relationships: { - comments: { - links: { - related: 'http://example.com/post/1/comments' - } - } - } - } - }, { - data: [{ - type: 'comment', - id: '2', - attributes: { - text: 'This is the first comment' - } - }, { - type: 'comment', - id: '3', - attributes: { - text: 'This is the second comment' - } - }] - }]); + }, + { + data: [ + { + type: 'comment', + id: '2', + attributes: { + text: 'This is the first comment', + }, + }, + { + type: 'comment', + id: '3', + attributes: { + text: 'This is the second comment', + }, + }, + ], + }, + ]); return run(() => { return store.findRecord('post', 1).then(post => { @@ -506,39 +553,40 @@ test('find a single record with hasMany link as object { related }', function(as test('find a single record with hasMany link as object { data }', function(assert) { assert.expect(8); - ajaxResponse([{ - data: { - type: 'post', - id: '1', - attributes: { - title: 'Ember.js rocks' + ajaxResponse([ + { + data: { + type: 'post', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + relationships: { + comments: { + data: [{ type: 'comment', id: '2' }, { type: 'comment', id: '3' }], + }, + }, }, - relationships: { - comments: { - data: [ - { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } - }, { - data: { - type: 'comment', - id: '2', - attributes: { - text: 'This is the first comment' - } - } - }, { - data: { - type: 'comment', - id: '3', - attributes: { - text: 'This is the second comment' - } - } - }]); + }, + { + data: { + type: 'comment', + id: '2', + attributes: { + text: 'This is the first comment', + }, + }, + }, + { + data: { + type: 'comment', + id: '3', + attributes: { + text: 'This is the second comment', + }, + }, + }, + ]); return run(() => { return store.findRecord('post', 1).then(post => { @@ -562,40 +610,41 @@ test('find a single record with hasMany link as object { data }', function(asser test('find a single record with hasMany link as object { data } (polymorphic)', function(assert) { assert.expect(9); - ajaxResponse([{ - data: { - type: 'user', - id: '1', - attributes: { - 'first-name': 'Yehuda', - 'last-name': 'Katz' + ajaxResponse([ + { + data: { + type: 'user', + id: '1', + attributes: { + 'first-name': 'Yehuda', + 'last-name': 'Katz', + }, + relationships: { + handles: { + data: [{ type: 'github-handle', id: '2' }, { type: 'twitter-handle', id: '3' }], + }, + }, }, - relationships: { - handles: { - data: [ - { type: 'github-handle', id: '2' }, - { type: 'twitter-handle', id: '3' } - ] - } - } - } - }, { - data: { - type: 'github-handle', - id: '2', - attributes: { - username: 'wycats' - } - } - }, { - data: { - type: 'twitter-handle', - id: '3', - attributes: { - nickname: '@wycats' - } - } - }]); + }, + { + data: { + type: 'github-handle', + id: '2', + attributes: { + username: 'wycats', + }, + }, + }, + { + data: { + type: 'twitter-handle', + id: '3', + attributes: { + nickname: '@wycats', + }, + }, + }, + ]); return run(() => { return store.findRecord('user', 1).then(user => { @@ -620,36 +669,38 @@ test('find a single record with hasMany link as object { data } (polymorphic)', test('find a single record with sideloaded hasMany link as object { data }', function(assert) { assert.expect(7); - ajaxResponse([{ - data: { - type: 'post', - id: '1', - attributes: { - title: 'Ember.js rocks' + ajaxResponse([ + { + data: { + type: 'post', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + relationships: { + comments: { + data: [{ type: 'comment', id: '2' }, { type: 'comment', id: '3' }], + }, + }, }, - relationships: { - comments: { - data: [ - { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } + included: [ + { + type: 'comment', + id: '2', + attributes: { + text: 'This is the first comment', + }, + }, + { + type: 'comment', + id: '3', + attributes: { + text: 'This is the second comment', + }, + }, + ], }, - included: [{ - type: 'comment', - id: '2', - attributes: { - text: 'This is the first comment' - } - }, { - type: 'comment', - id: '3', - attributes: { - text: 'This is the second comment' - } - }] - }]); + ]); return run(() => { return store.findRecord('post', 1).then(post => { @@ -672,37 +723,39 @@ test('find a single record with sideloaded hasMany link as object { data }', fun test('find a single record with sideloaded hasMany link as object { data } (polymorphic)', function(assert) { assert.expect(8); - ajaxResponse([{ - data: { - type: 'user', - id: '1', - attributes: { - 'first-name': 'Yehuda', - 'last-name': 'Katz' + ajaxResponse([ + { + data: { + type: 'user', + id: '1', + attributes: { + 'first-name': 'Yehuda', + 'last-name': 'Katz', + }, + relationships: { + handles: { + data: [{ type: 'github-handle', id: '2' }, { type: 'twitter-handle', id: '3' }], + }, + }, }, - relationships: { - handles: { - data: [ - { type: 'github-handle', id: '2' }, - { type: 'twitter-handle', id: '3' } - ] - } - } + included: [ + { + type: 'github-handle', + id: '2', + attributes: { + username: 'wycats', + }, + }, + { + type: 'twitter-handle', + id: '3', + attributes: { + nickname: '@wycats', + }, + }, + ], }, - included: [{ - type: 'github-handle', - id: '2', - attributes: { - username: 'wycats' - } - }, { - type: 'twitter-handle', - id: '3', - attributes: { - nickname: '@wycats' - } - }] - }]); + ]); return run(() => { return store.findRecord('user', 1).then(user => { @@ -726,35 +779,40 @@ test('find a single record with sideloaded hasMany link as object { data } (poly test('create record', function(assert) { assert.expect(3); - ajaxResponse([{ - data: { - type: 'users', - id: '3' - } - }]); + ajaxResponse([ + { + data: { + type: 'users', + id: '3', + }, + }, + ]); return run(() => { + let company = store.push({ + data: { + type: 'company', + id: '1', + attributes: { + name: 'Tilde Inc.', + }, + }, + }); - let company = store.push({ data: { - type: 'company', - id: '1', - attributes: { - name: 'Tilde Inc.' - } - } }); - - let githubHandle = store.push({ data: { - type: 'github-handle', - id: '2', - attributes: { - username: 'wycats' - } - } }); + let githubHandle = store.push({ + data: { + type: 'github-handle', + id: '2', + attributes: { + username: 'wycats', + }, + }, + }); let user = store.createRecord('user', { firstName: 'Yehuda', lastName: 'Katz', - company: company + company: company, }); return user.get('handles').then(handles => { @@ -765,19 +823,19 @@ test('create record', function(assert) { assert.equal(passedVerb[0], 'POST'); assert.deepEqual(passedHash[0], { data: { - data : { + data: { type: 'users', attributes: { 'first-name': 'Yehuda', - 'last-name': 'Katz' + 'last-name': 'Katz', }, relationships: { company: { - data: { type: 'companies', id: '1' } - } - } - } - } + data: { type: 'companies', id: '1' }, + }, + }, + }, + }, }); }); }); @@ -787,38 +845,46 @@ test('create record', function(assert) { test('update record', function(assert) { assert.expect(3); - ajaxResponse([{ - data: { - type: 'users', - id: '1' - } - }]); + ajaxResponse([ + { + data: { + type: 'users', + id: '1', + }, + }, + ]); return run(() => { - let user = store.push({ data: { - type: 'user', - id: '1', - attributes: { - firstName: 'Yehuda', - lastName: 'Katz' - } - } }); - - let company = store.push({ data: { - type: 'company', - id: '2', - attributes: { - name: 'Tilde Inc.' - } - } }); - - let githubHandle = store.push({ data: { - type: 'github-handle', - id: '3', - attributes: { - username: 'wycats' - } - } }); + let user = store.push({ + data: { + type: 'user', + id: '1', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz', + }, + }, + }); + + let company = store.push({ + data: { + type: 'company', + id: '2', + attributes: { + name: 'Tilde Inc.', + }, + }, + }); + + let githubHandle = store.push({ + data: { + type: 'github-handle', + id: '3', + attributes: { + username: 'wycats', + }, + }, + }); user.set('firstName', 'Yehuda!'); user.set('company', company); @@ -831,20 +897,20 @@ test('update record', function(assert) { assert.equal(passedVerb[0], 'PATCH'); assert.deepEqual(passedHash[0], { data: { - data : { + data: { type: 'users', id: '1', attributes: { 'first-name': 'Yehuda!', - 'last-name': 'Katz' + 'last-name': 'Katz', }, relationships: { company: { - data: { type: 'companies', id: '2' } - } - } - } - } + data: { type: 'companies', id: '2' }, + }, + }, + }, + }, }); }); }); @@ -854,44 +920,55 @@ test('update record', function(assert) { test('update record - serialize hasMany', function(assert) { assert.expect(3); - ajaxResponse([{ - data: { - type: 'users', - id: '1' - } - }]); + ajaxResponse([ + { + data: { + type: 'users', + id: '1', + }, + }, + ]); - env.registry.register('serializer:user', DS.JSONAPISerializer.extend({ - attrs: { - handles: { serialize: true } - } - })); + env.registry.register( + 'serializer:user', + DS.JSONAPISerializer.extend({ + attrs: { + handles: { serialize: true }, + }, + }) + ); return run(() => { - let user = store.push({ data: { - type: 'user', - id: '1', - attributes: { - firstName: 'Yehuda', - lastName: 'Katz' - } - } }); - - let githubHandle = store.push({ data: { - type: 'github-handle', - id: '2', - attributes: { - username: 'wycats' - } - } }); - - let twitterHandle = store.push({ data: { - type: 'twitter-handle', - id: '3', - attributes: { - nickname: '@wycats' - } - } }); + let user = store.push({ + data: { + type: 'user', + id: '1', + attributes: { + firstName: 'Yehuda', + lastName: 'Katz', + }, + }, + }); + + let githubHandle = store.push({ + data: { + type: 'github-handle', + id: '2', + attributes: { + username: 'wycats', + }, + }, + }); + + let twitterHandle = store.push({ + data: { + type: 'twitter-handle', + id: '3', + attributes: { + nickname: '@wycats', + }, + }, + }); user.set('firstName', 'Yehuda!'); @@ -904,23 +981,20 @@ test('update record - serialize hasMany', function(assert) { assert.equal(passedVerb[0], 'PATCH'); assert.deepEqual(passedHash[0], { data: { - data : { + data: { type: 'users', id: '1', attributes: { 'first-name': 'Yehuda!', - 'last-name': 'Katz' + 'last-name': 'Katz', }, relationships: { handles: { - data: [ - { type: 'github-handles', id: '2' }, - { type: 'twitter-handles', id: '3' } - ] - } - } - } - } + data: [{ type: 'github-handles', id: '2' }, { type: 'twitter-handles', id: '3' }], + }, + }, + }, + }, }); }); }); @@ -930,32 +1004,38 @@ test('update record - serialize hasMany', function(assert) { test('fetching a belongsTo relationship link that returns null', function(assert) { assert.expect(3); - ajaxResponse([{ - data: { - type: 'post', - id: '1', - attributes: { - title: 'Ember.js rocks' + ajaxResponse([ + { + data: { + type: 'post', + id: '1', + attributes: { + title: 'Ember.js rocks', + }, + relationships: { + author: { + links: { + related: 'http://example.com/post/1/author', + }, + }, + }, }, - relationships: { - author: { - links: { - related: 'http://example.com/post/1/author' - } - } - } - } - }, { - data: null - }]); + }, + { + data: null, + }, + ]); return run(() => { - return store.findRecord('post', 1).then(post => { - assert.equal(passedUrl[0], '/posts/1'); - return post.get('author'); - }).then(author => { - assert.equal(passedUrl[1], 'http://example.com/post/1/author'); - assert.strictEqual(author, null); - }); + return store + .findRecord('post', 1) + .then(post => { + assert.equal(passedUrl[0], '/posts/1'); + return post.get('author'); + }) + .then(author => { + assert.equal(passedUrl[1], 'http://example.com/post/1/author'); + assert.strictEqual(author, null); + }); }); }); diff --git a/tests/integration/adapter/queries-test.js b/tests/integration/adapter/queries-test.js index d42574d137f..7ae4e1f7250 100644 --- a/tests/integration/adapter/queries-test.js +++ b/tests/integration/adapter/queries-test.js @@ -10,13 +10,13 @@ import DS from 'ember-data'; let Person, env, store, adapter; -module("integration/adapter/queries - Queries", { +module('integration/adapter/queries - Queries', { beforeEach() { Person = DS.Model.extend({ updatedAt: DS.attr('string'), name: DS.attr('string'), firstName: DS.attr('string'), - lastName: DS.attr('string') + lastName: DS.attr('string'), }); env = setupStore({ person: Person }); @@ -26,24 +26,24 @@ module("integration/adapter/queries - Queries", { afterEach() { run(env.container, 'destroy'); - } + }, }); -testInDebug("It raises an assertion when no type is passed", function(assert) { +testInDebug('It raises an assertion when no type is passed', function(assert) { assert.expectAssertion(() => { store.query(); }, "You need to pass a model name to the store's query method"); }); -testInDebug("It raises an assertion when no query hash is passed", function(assert) { +testInDebug('It raises an assertion when no query hash is passed', function(assert) { assert.expectAssertion(() => { store.query('person'); }, "You need to pass a query hash to the store's query method"); }); -test("When a query is made, the adapter should receive a record array it can populate with the results of the query.", function(assert) { +test('When a query is made, the adapter should receive a record array it can populate with the results of the query.', function(assert) { adapter.query = function(store, type, query, recordArray) { - assert.equal(type, Person, "the query method is called with the correct type"); + assert.equal(type, Person, 'the query method is called with the correct type'); return EmberPromise.resolve({ data: [ @@ -51,72 +51,93 @@ test("When a query is made, the adapter should receive a record array it can pop id: 1, type: 'person', attributes: { - name: "Peter Wagenet" - } + name: 'Peter Wagenet', + }, }, { id: 2, - type: "person", + type: 'person', attributes: { - name: "Brohuda Katz" - } - } - ] + name: 'Brohuda Katz', + }, + }, + ], }); - } + }; return store.query('person', { page: 1 }).then(queryResults => { - assert.equal(get(queryResults, 'length'), 2, "the record array has a length of 2 after the results are loaded"); - assert.equal(get(queryResults, 'isLoaded'), true, "the record array's `isLoaded` property should be true"); - - assert.equal(queryResults.objectAt(0).get('name'), "Peter Wagenet", "the first record is 'Peter Wagenet'"); - assert.equal(queryResults.objectAt(1).get('name'), "Brohuda Katz", "the second record is 'Brohuda Katz'"); + assert.equal( + get(queryResults, 'length'), + 2, + 'the record array has a length of 2 after the results are loaded' + ); + assert.equal( + get(queryResults, 'isLoaded'), + true, + "the record array's `isLoaded` property should be true" + ); + + assert.equal( + queryResults.objectAt(0).get('name'), + 'Peter Wagenet', + "the first record is 'Peter Wagenet'" + ); + assert.equal( + queryResults.objectAt(1).get('name'), + 'Brohuda Katz', + "the second record is 'Brohuda Katz'" + ); }); }); -test("a query can be updated via `update()`", function(assert) { +test('a query can be updated via `update()`', function(assert) { adapter.query = function() { return resolve({ data: [{ id: 'first', type: 'person' }] }); }; return run(() => { - return store.query('person', {}).then(query => { - assert.equal(query.get('length'), 1); - assert.equal(query.get('firstObject.id'), 'first'); - assert.equal(query.get('isUpdating'), false); - - adapter.query = function() { - assert.ok('query is called a second time'); - return resolve({data: [{ id: 'second', type: 'person' }] }); - }; - - let updateQuery = query.update(); - - assert.equal(query.get('isUpdating'), true); - - return updateQuery; - - }).then(query => { - assert.equal(query.get('length'), 1); - assert.equal(query.get('firstObject.id'), 'second'); - - assert.equal(query.get('isUpdating'), false); - }); + return store + .query('person', {}) + .then(query => { + assert.equal(query.get('length'), 1); + assert.equal(query.get('firstObject.id'), 'first'); + assert.equal(query.get('isUpdating'), false); + + adapter.query = function() { + assert.ok('query is called a second time'); + return resolve({ data: [{ id: 'second', type: 'person' }] }); + }; + + let updateQuery = query.update(); + + assert.equal(query.get('isUpdating'), true); + + return updateQuery; + }) + .then(query => { + assert.equal(query.get('length'), 1); + assert.equal(query.get('firstObject.id'), 'second'); + + assert.equal(query.get('isUpdating'), false); + }); }); }); -testInDebug("The store asserts when query is made and the adapter responses with a single record.", function(assert) { - env = setupStore({ person: Person, adapter: DS.RESTAdapter }); - store = env.store; - adapter = env.adapter; +testInDebug( + 'The store asserts when query is made and the adapter responses with a single record.', + function(assert) { + env = setupStore({ person: Person, adapter: DS.RESTAdapter }); + store = env.store; + adapter = env.adapter; - adapter.query = function(store, type, query, recordArray) { - assert.equal(type, Person, "the query method is called with the correct type"); + adapter.query = function(store, type, query, recordArray) { + assert.equal(type, Person, 'the query method is called with the correct type'); - return resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Peter Wagenet" } }] }); - }; + return resolve({ data: [{ id: 1, type: 'person', attributes: { name: 'Peter Wagenet' } }] }); + }; - assert.expectAssertion(() => { - run(() => store.query('person', { page: 1 })); - }, /The response to store.query is expected to be an array but it was a single record/); -}); + assert.expectAssertion(() => { + run(() => store.query('person', { page: 1 })); + }, /The response to store.query is expected to be an array but it was a single record/); + } +); diff --git a/tests/integration/adapter/record-persistence-test.js b/tests/integration/adapter/record-persistence-test.js index 62da7acd16f..1ce033654ca 100644 --- a/tests/integration/adapter/record-persistence-test.js +++ b/tests/integration/adapter/record-persistence-test.js @@ -11,35 +11,35 @@ const { attr } = DS; let Person, env, store; -module("integration/adapter/record_persistence - Persisting Records", { +module('integration/adapter/record_persistence - Persisting Records', { beforeEach() { Person = DS.Model.extend({ updatedAt: attr('string'), name: attr('string'), firstName: attr('string'), - lastName: attr('string') + lastName: attr('string'), }); env = setupStore({ adapter: DS.Adapter.extend({ - shouldBackgroundReloadRecord: () => false + shouldBackgroundReloadRecord: () => false, }), - person: Person + person: Person, }); store = env.store; }, afterEach() { run(env.container, 'destroy'); - } + }, }); test("When a store is committed, the adapter's `commit` method should be called with records that have been changed.", function(assert) { assert.expect(2); env.adapter.updateRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); - assert.equal(snapshot.record, tom, "the record is correct"); + assert.equal(type, Person, 'the type is correct'); + assert.equal(snapshot.record, tom, 'the record is correct'); return run(RSVP, 'resolve'); }; @@ -50,9 +50,9 @@ test("When a store is committed, the adapter's `commit` method should be called type: 'person', id: '1', attributes: { - name: 'Braaaahm Dale' - } - } + name: 'Braaaahm Dale', + }, + }, }); }); @@ -61,7 +61,7 @@ test("When a store is committed, the adapter's `commit` method should be called return run(() => { return env.store.findRecord('person', 1).then(person => { tom = person; - set(tom, "name", "Tom Dale"); + set(tom, 'name', 'Tom Dale'); return tom.save(); }); }); @@ -72,40 +72,40 @@ test("When a store is committed, the adapter's `commit` method should be called let tom; env.adapter.createRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); - assert.equal(snapshot.record, tom, "the record is correct"); + assert.equal(type, Person, 'the type is correct'); + assert.equal(snapshot.record, tom, 'the record is correct'); - return resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale" } } }); + return resolve({ data: { id: 1, type: 'person', attributes: { name: 'Tom Dale' } } }); }; return run(() => { - tom = env.store.createRecord('person', { name: "Tom Dale" }); + tom = env.store.createRecord('person', { name: 'Tom Dale' }); return tom.save(); }); }); -test("After a created record has been assigned an ID, finding a record by that ID returns the original record.", function(assert) { +test('After a created record has been assigned an ID, finding a record by that ID returns the original record.', function(assert) { assert.expect(1); let tom; env.adapter.createRecord = function(store, type, snapshot) { - return resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale" } } }); + return resolve({ data: { id: 1, type: 'person', attributes: { name: 'Tom Dale' } } }); }; return run(() => { - tom = env.store.createRecord('person', { name: "Tom Dale" }); + tom = env.store.createRecord('person', { name: 'Tom Dale' }); return tom.save(); }).then(tom => { return env.store.find('person', 1).then(nextTom => { - assert.equal(tom, nextTom, "the retrieved record is the same as the created record"); + assert.equal(tom, nextTom, 'the retrieved record is the same as the created record'); }); }); }); test("when a store is committed, the adapter's `commit` method should be called with records that have been deleted.", function(assert) { env.adapter.deleteRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); - assert.equal(snapshot.record, tom, "the record is correct"); + assert.equal(type, Person, 'the type is correct'); + assert.equal(snapshot.record, tom, 'the record is correct'); return run(RSVP, 'resolve'); }; @@ -118,22 +118,25 @@ test("when a store is committed, the adapter's `commit` method should be called type: 'person', id: '1', attributes: { - name: "Tom Dale" - } - } + name: 'Tom Dale', + }, + }, }); }); - return env.store.findRecord('person', 1).then(person => { - tom = person; - tom.deleteRecord(); - return tom.save(); - }).then(tom => { - assert.equal(get(tom, 'isDeleted'), true, "record is marked as deleted"); - }); + return env.store + .findRecord('person', 1) + .then(person => { + tom = person; + tom.deleteRecord(); + return tom.save(); + }) + .then(tom => { + assert.equal(get(tom, 'isDeleted'), true, 'record is marked as deleted'); + }); }); -test("An adapter can notify the store that records were updated by calling `didSaveRecords`.", function(assert) { +test('An adapter can notify the store that records were updated by calling `didSaveRecords`.', function(assert) { assert.expect(6); let tom, yehuda; @@ -144,196 +147,252 @@ test("An adapter can notify the store that records were updated by calling `didS run(() => { env.store.push({ - data: [{ - type: 'person', - id: '1' - }, { - type: 'person', - id: '2' - }] + data: [ + { + type: 'person', + id: '1', + }, + { + type: 'person', + id: '2', + }, + ], }); }); - return all([ - env.store.findRecord('person', 1), - env.store.findRecord('person', 2) - ]) - .then(array => { - tom = array[0]; - yehuda = array[1]; + return all([env.store.findRecord('person', 1), env.store.findRecord('person', 2)]).then(array => { + tom = array[0]; + yehuda = array[1]; - tom.set('name', "Michael Phelps"); - yehuda.set('name', "Usain Bolt"); + tom.set('name', 'Michael Phelps'); + yehuda.set('name', 'Usain Bolt'); - assert.ok(tom.get('hasDirtyAttributes'), "tom is dirty"); - assert.ok(yehuda.get('hasDirtyAttributes'), "yehuda is dirty"); - - let savedTom = assert.assertClean(tom.save()).then(record => { - assert.equal(record, tom, "The record is correct"); - }); + assert.ok(tom.get('hasDirtyAttributes'), 'tom is dirty'); + assert.ok(yehuda.get('hasDirtyAttributes'), 'yehuda is dirty'); - let savedYehuda = assert.assertClean(yehuda.save()).then(record => { - assert.equal(record, yehuda, "The record is correct"); - }); + let savedTom = assert.assertClean(tom.save()).then(record => { + assert.equal(record, tom, 'The record is correct'); + }); - return all([ - savedTom, - savedYehuda - ]); + let savedYehuda = assert.assertClean(yehuda.save()).then(record => { + assert.equal(record, yehuda, 'The record is correct'); }); + + return all([savedTom, savedYehuda]); + }); }); -test("An adapter can notify the store that records were updated and provide new data by calling `didSaveRecords`.", function(assert) { +test('An adapter can notify the store that records were updated and provide new data by calling `didSaveRecords`.', function(assert) { env.adapter.updateRecord = function(store, type, snapshot) { - if (snapshot.id === "1") { - return resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale", "updated-at": "now" } } }); - } else if (snapshot.id === "2") { - return resolve({ data: { id: 2, type: "person", attributes: { name: "Yehuda Katz", "updated-at": "now!" } } }); + if (snapshot.id === '1') { + return resolve({ + data: { id: 1, type: 'person', attributes: { name: 'Tom Dale', 'updated-at': 'now' } }, + }); + } else if (snapshot.id === '2') { + return resolve({ + data: { id: 2, type: 'person', attributes: { name: 'Yehuda Katz', 'updated-at': 'now!' } }, + }); } }; run(() => { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Braaaahm Dale' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Gentile Katz' - } - }] + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale', + }, + }, + { + type: 'person', + id: '2', + attributes: { + name: 'Gentile Katz', + }, + }, + ], }); }); return hash({ tom: env.store.findRecord('person', 1), - yehuda: env.store.findRecord('person', 2) - }).then(people => { - people.tom.set('name', "Draaaaaahm Dale"); - people.yehuda.set('name', "Goy Katz"); - - return hash({ - tom: people.tom.save(), - yehuda: people.yehuda.save() + yehuda: env.store.findRecord('person', 2), + }) + .then(people => { + people.tom.set('name', 'Draaaaaahm Dale'); + people.yehuda.set('name', 'Goy Katz'); + + return hash({ + tom: people.tom.save(), + yehuda: people.yehuda.save(), + }); + }) + .then(people => { + assert.equal( + people.tom.get('name'), + 'Tom Dale', + 'name attribute should reflect value of hash passed to didSaveRecords' + ); + assert.equal( + people.tom.get('updatedAt'), + 'now', + 'updatedAt attribute should reflect value of hash passed to didSaveRecords' + ); + assert.equal( + people.yehuda.get('name'), + 'Yehuda Katz', + 'name attribute should reflect value of hash passed to didSaveRecords' + ); + assert.equal( + people.yehuda.get('updatedAt'), + 'now!', + 'updatedAt attribute should reflect value of hash passed to didSaveRecords' + ); }); - }).then(people => { - assert.equal(people.tom.get('name'), "Tom Dale", "name attribute should reflect value of hash passed to didSaveRecords"); - assert.equal(people.tom.get('updatedAt'), "now", "updatedAt attribute should reflect value of hash passed to didSaveRecords"); - assert.equal(people.yehuda.get('name'), "Yehuda Katz", "name attribute should reflect value of hash passed to didSaveRecords"); - assert.equal(people.yehuda.get('updatedAt'), "now!", "updatedAt attribute should reflect value of hash passed to didSaveRecords"); - }); }); -test("An adapter can notify the store that a record was updated by calling `didSaveRecord`.", function(assert) { +test('An adapter can notify the store that a record was updated by calling `didSaveRecord`.', function(assert) { env.adapter.updateRecord = function(store, type, snapshot) { return resolve(); }; run(() => { store.push({ - data: [{ - type: 'person', - id: '1' - }, { - type: 'person', - id: '2' - }] + data: [ + { + type: 'person', + id: '1', + }, + { + type: 'person', + id: '2', + }, + ], }); }); return hash({ tom: store.findRecord('person', 1), - yehuda: store.findRecord('person', 2) + yehuda: store.findRecord('person', 2), }).then(people => { - people.tom.set('name', "Tom Dale"); - people.yehuda.set('name', "Yehuda Katz"); + people.tom.set('name', 'Tom Dale'); + people.yehuda.set('name', 'Yehuda Katz'); - assert.ok(people.tom.get('hasDirtyAttributes'), "tom is dirty"); - assert.ok(people.yehuda.get('hasDirtyAttributes'), "yehuda is dirty"); + assert.ok(people.tom.get('hasDirtyAttributes'), 'tom is dirty'); + assert.ok(people.yehuda.get('hasDirtyAttributes'), 'yehuda is dirty'); assert.assertClean(people.tom.save()); assert.assertClean(people.yehuda.save()); }); }); -test("An adapter can notify the store that a record was updated and provide new data by calling `didSaveRecord`.", function(assert) { +test('An adapter can notify the store that a record was updated and provide new data by calling `didSaveRecord`.', function(assert) { env.adapter.updateRecord = function(store, type, snapshot) { switch (snapshot.id) { - case "1": - return resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale", "updated-at": "now" } } }); - case "2": - return resolve({ data: { id: 2, type: "person", attributes: { name: "Yehuda Katz", "updated-at": "now!" } } }); + case '1': + return resolve({ + data: { id: 1, type: 'person', attributes: { name: 'Tom Dale', 'updated-at': 'now' } }, + }); + case '2': + return resolve({ + data: { + id: 2, + type: 'person', + attributes: { name: 'Yehuda Katz', 'updated-at': 'now!' }, + }, + }); } }; run(() => { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Braaaahm Dale' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Gentile Katz' - } - }] + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale', + }, + }, + { + type: 'person', + id: '2', + attributes: { + name: 'Gentile Katz', + }, + }, + ], }); }); return hash({ tom: store.findRecord('person', 1), - yehuda: store.findRecord('person', 2) - }).then(people => { - people.tom.set('name', "Draaaaaahm Dale"); - people.yehuda.set('name', "Goy Katz"); - - return hash({ - tom: people.tom.save(), - yehuda: people.yehuda.save() + yehuda: store.findRecord('person', 2), + }) + .then(people => { + people.tom.set('name', 'Draaaaaahm Dale'); + people.yehuda.set('name', 'Goy Katz'); + + return hash({ + tom: people.tom.save(), + yehuda: people.yehuda.save(), + }); + }) + .then(people => { + assert.equal( + people.tom.get('name'), + 'Tom Dale', + 'name attribute should reflect value of hash passed to didSaveRecords' + ); + assert.equal( + people.tom.get('updatedAt'), + 'now', + 'updatedAt attribute should reflect value of hash passed to didSaveRecords' + ); + assert.equal( + people.yehuda.get('name'), + 'Yehuda Katz', + 'name attribute should reflect value of hash passed to didSaveRecords' + ); + assert.equal( + people.yehuda.get('updatedAt'), + 'now!', + 'updatedAt attribute should reflect value of hash passed to didSaveRecords' + ); }); - }).then(people => { - assert.equal(people.tom.get('name'), "Tom Dale", "name attribute should reflect value of hash passed to didSaveRecords"); - assert.equal(people.tom.get('updatedAt'), "now", "updatedAt attribute should reflect value of hash passed to didSaveRecords"); - assert.equal(people.yehuda.get('name'), "Yehuda Katz", "name attribute should reflect value of hash passed to didSaveRecords"); - assert.equal(people.yehuda.get('updatedAt'), "now!", "updatedAt attribute should reflect value of hash passed to didSaveRecords"); - }); }); -test("An adapter can notify the store that records were deleted by calling `didSaveRecords`.", function(assert) { +test('An adapter can notify the store that records were deleted by calling `didSaveRecords`.', function(assert) { env.adapter.deleteRecord = function(store, type, snapshot) { return resolve(); }; run(() => { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Braaaahm Dale' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Gentile Katz' - } - }] + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale', + }, + }, + { + type: 'person', + id: '2', + attributes: { + name: 'Gentile Katz', + }, + }, + ], }); }); return hash({ tom: store.findRecord('person', 1), - yehuda: store.findRecord('person', 2) + yehuda: store.findRecord('person', 2), }).then(people => { people.tom.deleteRecord(); people.yehuda.deleteRecord(); diff --git a/tests/integration/adapter/rest-adapter-test.js b/tests/integration/adapter/rest-adapter-test.js index 61ca6b3f822..af83bc8ff4d 100644 --- a/tests/integration/adapter/rest-adapter-test.js +++ b/tests/integration/adapter/rest-adapter-test.js @@ -8,7 +8,7 @@ import deepCopy from 'dummy/tests/helpers/deep-copy'; import testInDebug from 'dummy/tests/helpers/test-in-debug'; import { module, test } from 'qunit'; -import Pretender from "pretender"; +import Pretender from 'pretender'; import DS from 'ember-data'; @@ -16,14 +16,14 @@ let env, store, adapter, Post, Comment, SuperUser; let passedUrl, passedVerb, passedHash; let server; -module("integration/adapter/rest_adapter - REST Adapter", { +module('integration/adapter/rest_adapter - REST Adapter', { beforeEach() { Post = DS.Model.extend({ - name: DS.attr("string") + name: DS.attr('string'), }); Comment = DS.Model.extend({ - name: DS.attr("string") + name: DS.attr('string'), }); SuperUser = DS.Model.extend(); @@ -32,7 +32,7 @@ module("integration/adapter/rest_adapter - REST Adapter", { post: Post, comment: Comment, superUser: SuperUser, - adapter: DS.RESTAdapter + adapter: DS.RESTAdapter, }); server = new Pretender(); @@ -46,7 +46,7 @@ module("integration/adapter/rest_adapter - REST Adapter", { server.shutdown(); server = null; } - } + }, }); function ajaxResponse(value) { @@ -64,213 +64,235 @@ function ajaxError(responseText, status = 400, headers = '') { let jqXHR = { status, responseText, - getAllResponseHeaders() { return headers; } + getAllResponseHeaders() { + return headers; + }, }; hash.error(jqXHR, responseText); }; } -test("findRecord - basic payload", function(assert) { - ajaxResponse({ posts: [{ id: 1, name: "Rails is omakase" }] }); - - return run(() => store.findRecord('post', 1).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "GET"); - assert.deepEqual(passedHash.data, {}); +test('findRecord - basic payload', function(assert) { + ajaxResponse({ posts: [{ id: 1, name: 'Rails is omakase' }] }); - assert.equal(post.get('id'), "1"); - assert.equal(post.get('name'), "Rails is omakase"); - })); + return run(() => + store.findRecord('post', 1).then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'GET'); + assert.deepEqual(passedHash.data, {}); + + assert.equal(post.get('id'), '1'); + assert.equal(post.get('name'), 'Rails is omakase'); + }) + ); }); - -test("findRecord - passes buildURL a requestType", function(assert) { +test('findRecord - passes buildURL a requestType', function(assert) { adapter.buildURL = function(type, id, snapshot, requestType) { - return "/" + requestType + "/post/" + id; + return '/' + requestType + '/post/' + id; }; - ajaxResponse({ posts: [{ id: 1, name: "Rails is omakase" }] }); + ajaxResponse({ posts: [{ id: 1, name: 'Rails is omakase' }] }); - - return run(() => store.findRecord('post', 1).then(post => { - assert.equal(passedUrl, "/findRecord/post/1"); - })); + return run(() => + store.findRecord('post', 1).then(post => { + assert.equal(passedUrl, '/findRecord/post/1'); + }) + ); }); -test("findRecord - basic payload (with legacy singular name)", function(assert) { - ajaxResponse({ post: { id: 1, name: "Rails is omakase" } }); - - return run(() => store.findRecord('post', 1).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "GET"); - assert.deepEqual(passedHash.data, {}); +test('findRecord - basic payload (with legacy singular name)', function(assert) { + ajaxResponse({ post: { id: 1, name: 'Rails is omakase' } }); - assert.equal(post.get('id'), "1"); - assert.equal(post.get('name'), "Rails is omakase"); - })); + return run(() => + store.findRecord('post', 1).then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'GET'); + assert.deepEqual(passedHash.data, {}); + + assert.equal(post.get('id'), '1'); + assert.equal(post.get('name'), 'Rails is omakase'); + }) + ); }); -test("findRecord - payload with sideloaded records of the same type", function(assert) { +test('findRecord - payload with sideloaded records of the same type', function(assert) { ajaxResponse({ - posts: [ - { id: 1, name: "Rails is omakase" }, - { id: 2, name: "The Parley Letter" } - ] + posts: [{ id: 1, name: 'Rails is omakase' }, { id: 2, name: 'The Parley Letter' }], }); - return run(() => store.findRecord('post', 1).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "GET"); - assert.deepEqual(passedHash.data, {}); - - assert.equal(post.get('id'), "1"); - assert.equal(post.get('name'), "Rails is omakase"); - - let post2 = store.peekRecord('post', 2); - assert.equal(post2.get('id'), "2"); - assert.equal(post2.get('name'), "The Parley Letter"); - })); + return run(() => + store.findRecord('post', 1).then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'GET'); + assert.deepEqual(passedHash.data, {}); + + assert.equal(post.get('id'), '1'); + assert.equal(post.get('name'), 'Rails is omakase'); + + let post2 = store.peekRecord('post', 2); + assert.equal(post2.get('id'), '2'); + assert.equal(post2.get('name'), 'The Parley Letter'); + }) + ); }); -test("findRecord - payload with sideloaded records of a different type", function(assert) { +test('findRecord - payload with sideloaded records of a different type', function(assert) { ajaxResponse({ - posts: [{ id: 1, name: "Rails is omakase" }], - comments: [{ id: 1, name: "FIRST" }] + posts: [{ id: 1, name: 'Rails is omakase' }], + comments: [{ id: 1, name: 'FIRST' }], }); - return run(() => store.findRecord('post', 1).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "GET"); - assert.deepEqual(passedHash.data, {}); + return run(() => + store.findRecord('post', 1).then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'GET'); + assert.deepEqual(passedHash.data, {}); - assert.equal(post.get('id'), "1"); - assert.equal(post.get('name'), "Rails is omakase"); + assert.equal(post.get('id'), '1'); + assert.equal(post.get('name'), 'Rails is omakase'); - let comment = store.peekRecord('comment', 1); - assert.equal(comment.get('id'), "1"); - assert.equal(comment.get('name'), "FIRST"); - })); + let comment = store.peekRecord('comment', 1); + assert.equal(comment.get('id'), '1'); + assert.equal(comment.get('name'), 'FIRST'); + }) + ); }); +test('findRecord - payload with an serializer-specified primary key', function(assert) { + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + primaryKey: '_ID_', + }) + ); -test("findRecord - payload with an serializer-specified primary key", function(assert) { - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - primaryKey: '_ID_' - })); - - ajaxResponse({ posts: [{ "_ID_": 1, name: "Rails is omakase" }] }); - - return run(() => store.findRecord('post', 1).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "GET"); - assert.deepEqual(passedHash.data, {}); + ajaxResponse({ posts: [{ _ID_: 1, name: 'Rails is omakase' }] }); - assert.equal(post.get('id'), "1"); - assert.equal(post.get('name'), "Rails is omakase"); - })); + return run(() => + store.findRecord('post', 1).then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'GET'); + assert.deepEqual(passedHash.data, {}); + + assert.equal(post.get('id'), '1'); + assert.equal(post.get('name'), 'Rails is omakase'); + }) + ); }); -test("findRecord - payload with a serializer-specified attribute mapping", function(assert) { - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - attrs: { - 'name': '_NAME_', - 'createdAt': { key: '_CREATED_AT_', someOtherOption: 'option' } - } - })); +test('findRecord - payload with a serializer-specified attribute mapping', function(assert) { + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + attrs: { + name: '_NAME_', + createdAt: { key: '_CREATED_AT_', someOtherOption: 'option' }, + }, + }) + ); Post.reopen({ - createdAt: DS.attr("number") + createdAt: DS.attr('number'), }); - ajaxResponse({ posts: [{ id: 1, _NAME_: "Rails is omakase", _CREATED_AT_: 2013 }] }); - - return run(() => store.findRecord('post', 1).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "GET"); - assert.deepEqual(passedHash.data, {}); + ajaxResponse({ posts: [{ id: 1, _NAME_: 'Rails is omakase', _CREATED_AT_: 2013 }] }); - assert.equal(post.get('id'), "1"); - assert.equal(post.get('name'), "Rails is omakase"); - assert.equal(post.get('createdAt'), 2013); - })); + return run(() => + store.findRecord('post', 1).then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'GET'); + assert.deepEqual(passedHash.data, {}); + + assert.equal(post.get('id'), '1'); + assert.equal(post.get('name'), 'Rails is omakase'); + assert.equal(post.get('createdAt'), 2013); + }) + ); }); -test("findRecord - passes `include` as a query parameter to ajax", function(assert) { +test('findRecord - passes `include` as a query parameter to ajax', function(assert) { ajaxResponse({ - post: { id: 1, name: 'Rails is very expensive sushi' } + post: { id: 1, name: 'Rails is very expensive sushi' }, }); - return run(() => store.findRecord('post', 1, { include: 'comments' }).then(() => { - assert.deepEqual(passedHash.data, { include: 'comments' }, '`include` parameter sent to adapter.ajax'); - })); + return run(() => + store.findRecord('post', 1, { include: 'comments' }).then(() => { + assert.deepEqual( + passedHash.data, + { include: 'comments' }, + '`include` parameter sent to adapter.ajax' + ); + }) + ); }); -test("createRecord - an empty payload is a basic success if an id was specified", function(assert) { +test('createRecord - an empty payload is a basic success if an id was specified', function(assert) { ajaxResponse(); return run(() => { - let post = store.createRecord('post', { id: "some-uuid", name: "The Parley Letter" }); + let post = store.createRecord('post', { id: 'some-uuid', name: 'The Parley Letter' }); return post.save().then(post => { - assert.equal(passedUrl, "/posts"); - assert.equal(passedVerb, "POST"); - assert.deepEqual(passedHash.data, { post: { id: "some-uuid", name: "The Parley Letter" } }); + assert.equal(passedUrl, '/posts'); + assert.equal(passedVerb, 'POST'); + assert.deepEqual(passedHash.data, { post: { id: 'some-uuid', name: 'The Parley Letter' } }); assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('name'), "The Parley Letter", "the post was updated"); + assert.equal(post.get('name'), 'The Parley Letter', 'the post was updated'); }); }); }); -test("createRecord - passes buildURL the requestType", function(assert) { +test('createRecord - passes buildURL the requestType', function(assert) { adapter.buildURL = function(type, id, snapshot, requestType) { - return "/post/" + requestType; + return '/post/' + requestType; }; ajaxResponse(); return run(() => { - let post = store.createRecord('post', { id: "some-uuid", name: "The Parley Letter" }); + let post = store.createRecord('post', { id: 'some-uuid', name: 'The Parley Letter' }); return post.save().then(post => { - assert.equal(passedUrl, "/post/createRecord"); + assert.equal(passedUrl, '/post/createRecord'); }); }); }); -test("createRecord - a payload with a new ID and data applies the updates", function(assert) { - ajaxResponse({ posts: [{ id: "1", name: "Dat Parley Letter" }] }); +test('createRecord - a payload with a new ID and data applies the updates', function(assert) { + ajaxResponse({ posts: [{ id: '1', name: 'Dat Parley Letter' }] }); return run(() => { - let post = store.createRecord('post', { name: "The Parley Letter" }); + let post = store.createRecord('post', { name: 'The Parley Letter' }); return post.save().then(post => { - assert.equal(passedUrl, "/posts"); - assert.equal(passedVerb, "POST"); - assert.deepEqual(passedHash.data, { post: { name: "The Parley Letter" } }); + assert.equal(passedUrl, '/posts'); + assert.equal(passedVerb, 'POST'); + assert.deepEqual(passedHash.data, { post: { name: 'The Parley Letter' } }); - assert.equal(post.get('id'), "1", "the post has the updated ID"); + assert.equal(post.get('id'), '1', 'the post has the updated ID'); assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('name'), "Dat Parley Letter", "the post was updated"); + assert.equal(post.get('name'), 'Dat Parley Letter', 'the post was updated'); }); }); }); -test("createRecord - a payload with a new ID and data applies the updates (with legacy singular name)", function(assert) { - ajaxResponse({ post: { id: "1", name: "Dat Parley Letter" } }); - let post = store.createRecord('post', { name: "The Parley Letter" }); +test('createRecord - a payload with a new ID and data applies the updates (with legacy singular name)', function(assert) { + ajaxResponse({ post: { id: '1', name: 'Dat Parley Letter' } }); + let post = store.createRecord('post', { name: 'The Parley Letter' }); return run(post, 'save').then(post => { - assert.equal(passedUrl, "/posts"); - assert.equal(passedVerb, "POST"); - assert.deepEqual(passedHash.data, { post: { name: "The Parley Letter" } }); + assert.equal(passedUrl, '/posts'); + assert.equal(passedVerb, 'POST'); + assert.deepEqual(passedHash.data, { post: { name: 'The Parley Letter' } }); - assert.equal(post.get('id'), "1", "the post has the updated ID"); + assert.equal(post.get('id'), '1', 'the post has the updated ID'); assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('name'), "Dat Parley Letter", "the post was updated"); + assert.equal(post.get('name'), 'Dat Parley Letter', 'the post was updated'); }); }); test("createRecord - findMany doesn't overwrite owner", function(assert) { - ajaxResponse({ comment: { id: "1", name: "Dat Parley Letter", post: 1 } }); + ajaxResponse({ comment: { id: '1', name: 'Dat Parley Letter', post: 1 } }); Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); @@ -281,168 +303,202 @@ test("createRecord - findMany doesn't overwrite owner", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { - data: [] - } - } - } + data: [], + }, + }, + }, }); }); let post = store.peekRecord('post', 1); - let comment = store.createRecord('comment', { name: "The Parley Letter" }); + let comment = store.createRecord('comment', { name: 'The Parley Letter' }); run(() => { post.get('comments').pushObject(comment); - assert.equal(comment.get('post'), post, "the post has been set correctly"); + assert.equal(comment.get('post'), post, 'the post has been set correctly'); }); return run(() => { return comment.save().then(comment => { assert.equal(comment.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(comment.get('name'), "Dat Parley Letter", "the post was updated"); - assert.equal(comment.get('post'), post, "the post is still set"); + assert.equal(comment.get('name'), 'Dat Parley Letter', 'the post was updated'); + assert.equal(comment.get('post'), post, 'the post is still set'); }); }); }); test("createRecord - a serializer's primary key and attributes are consulted when building the payload", function(assert) { - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - primaryKey: '_id_', + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + primaryKey: '_id_', - attrs: { - name: '_name_' - } - })); + attrs: { + name: '_name_', + }, + }) + ); ajaxResponse(); - let post = store.createRecord('post', { id: "some-uuid", name: "The Parley Letter" }); + let post = store.createRecord('post', { id: 'some-uuid', name: 'The Parley Letter' }); return run(() => - post.save() - .then(post => { - assert.deepEqual(passedHash.data, { post: { _id_: 'some-uuid', '_name_': "The Parley Letter" } }); - }) + post.save().then(post => { + assert.deepEqual(passedHash.data, { + post: { _id_: 'some-uuid', _name_: 'The Parley Letter' }, + }); + }) ); }); test("createRecord - a serializer's attributes are consulted when building the payload if no id is pre-defined", function(assert) { let post; - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - attrs: { - name: '_name_' - } - })); + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + attrs: { + name: '_name_', + }, + }) + ); ajaxResponse({ - post: { '_name_': "The Parley Letter", id: '1' } + post: { _name_: 'The Parley Letter', id: '1' }, }); return run(() => { - post = store.createRecord('post', { name: "The Parley Letter" }); + post = store.createRecord('post', { name: 'The Parley Letter' }); return post.save().then(post => { - assert.deepEqual(passedHash.data, { post: { '_name_': "The Parley Letter" } }); + assert.deepEqual(passedHash.data, { post: { _name_: 'The Parley Letter' } }); }); }); }); test("createRecord - a serializer's attribute mapping takes precedence over keyForAttribute when building the payload", function(assert) { - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - attrs: { - name: 'given_name' - }, + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + attrs: { + name: 'given_name', + }, - keyForAttribute(attr) { - return attr.toUpperCase(); - } - })); + keyForAttribute(attr) { + return attr.toUpperCase(); + }, + }) + ); ajaxResponse(); return run(() => { - let post = store.createRecord('post', { id: "some-uuid", name: "The Parley Letter" }); + let post = store.createRecord('post', { id: 'some-uuid', name: 'The Parley Letter' }); return post.save().then(post => { - assert.deepEqual(passedHash.data, { post: { 'given_name': "The Parley Letter", id: "some-uuid" } }); + assert.deepEqual(passedHash.data, { + post: { given_name: 'The Parley Letter', id: 'some-uuid' }, + }); }); }); }); test("createRecord - a serializer's attribute mapping takes precedence over keyForRelationship (belongsTo) when building the payload", function(assert) { - env.registry.register('serializer:comment', DS.RESTSerializer.extend({ - attrs: { - post: 'article' - }, + env.registry.register( + 'serializer:comment', + DS.RESTSerializer.extend({ + attrs: { + post: 'article', + }, - keyForRelationship(attr, kind) { - return attr.toUpperCase(); - } - })); + keyForRelationship(attr, kind) { + return attr.toUpperCase(); + }, + }) + ); ajaxResponse(); Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); return run(() => { - let post = store.createRecord('post', { id: "a-post-id", name: "The Parley Letter" }); - let comment = store.createRecord('comment', { id: "some-uuid", name: "Letters are fun", post: post }); + let post = store.createRecord('post', { id: 'a-post-id', name: 'The Parley Letter' }); + let comment = store.createRecord('comment', { + id: 'some-uuid', + name: 'Letters are fun', + post: post, + }); return comment.save().then(post => { - assert.deepEqual(passedHash.data, { comment: { article: "a-post-id", id: "some-uuid", name: "Letters are fun" } }); + assert.deepEqual(passedHash.data, { + comment: { article: 'a-post-id', id: 'some-uuid', name: 'Letters are fun' }, + }); }); }); }); test("createRecord - a serializer's attribute mapping takes precedence over keyForRelationship (hasMany) when building the payload", function(assert) { - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - attrs: { - comments: 'opinions' - }, + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + attrs: { + comments: 'opinions', + }, - keyForRelationship(attr, kind) { - return attr.toUpperCase(); - } - })); + keyForRelationship(attr, kind) { + return attr.toUpperCase(); + }, + }) + ); ajaxResponse(); Post.reopen({ comments: DS.hasMany('comment', { async: false }) }); return run(() => { - let comment = store.createRecord('comment', { id: "a-comment-id", name: "First!" }); - let post = store.createRecord('post', { id: "some-uuid", name: "The Parley Letter", comments: [comment] }); + let comment = store.createRecord('comment', { id: 'a-comment-id', name: 'First!' }); + let post = store.createRecord('post', { + id: 'some-uuid', + name: 'The Parley Letter', + comments: [comment], + }); return post.save().then(post => { - assert.deepEqual(passedHash.data, { post: { opinions: ["a-comment-id"], id: "some-uuid", name: "The Parley Letter" } }); + assert.deepEqual(passedHash.data, { + post: { opinions: ['a-comment-id'], id: 'some-uuid', name: 'The Parley Letter' }, + }); }); }); }); -test("createRecord - a record on the many side of a hasMany relationship should update relationships when data is sideloaded", function(assert) { +test('createRecord - a record on the many side of a hasMany relationship should update relationships when data is sideloaded', function(assert) { assert.expect(3); ajaxResponse({ - posts: [{ - id: "1", - name: "Rails is omakase", - comments: [1,2] - }], - comments: [{ - id: "2", - name: "Another Comment", - post: 1 - }, - { - id: "1", - name: "Dat Parley Letter", - post: 1 - }] + posts: [ + { + id: '1', + name: 'Rails is omakase', + comments: [1, 2], + }, + ], + comments: [ + { + id: '2', + name: 'Another Comment', + post: 1, + }, + { + id: '1', + name: 'Dat Parley Letter', + post: 1, + }, + ], // My API is returning a comment:{} as well as a comments:[{...},...] //, comment: { // id: "2", @@ -460,69 +516,79 @@ test("createRecord - a record on the many side of a hasMany relationship should type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { - data: [ - { type: 'comment', id: '1' } - ] - } - } - } + data: [{ type: 'comment', id: '1' }], + }, + }, + }, }); store.push({ data: { type: 'comment', id: '1', attributes: { - name: "Dat Parlay Letter" + name: 'Dat Parlay Letter', }, relationships: { post: { - data: { type: 'post', id: '1' } - } - } - } + data: { type: 'post', id: '1' }, + }, + }, + }, }); }); let post = store.peekRecord('post', 1); let commentCount = run(() => post.get('comments.length')); - assert.equal(commentCount, 1, "the post starts life with a comment"); + assert.equal(commentCount, 1, 'the post starts life with a comment'); return run(() => { - let comment = store.createRecord('comment', { name: "Another Comment", post: post }); + let comment = store.createRecord('comment', { name: 'Another Comment', post: post }); return comment.save().then(comment => { - assert.equal(comment.get('post'), post, "the comment is related to the post"); + assert.equal(comment.get('post'), post, 'the comment is related to the post'); return post.reload().then(post => { - assert.equal(post.get('comments.length'), 2, "Post comment count has been updated"); + assert.equal(post.get('comments.length'), 2, 'Post comment count has been updated'); }); }); }); }); -test("createRecord - sideloaded belongsTo relationships are both marked as loaded", function(assert) { +test('createRecord - sideloaded belongsTo relationships are both marked as loaded', function(assert) { assert.expect(4); Post.reopen({ comment: DS.belongsTo('comment', { async: false }) }); Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); - let post = store.createRecord('post', { name: "man" }); + let post = store.createRecord('post', { name: 'man' }); ajaxResponse({ - posts: [{ id: 1, comment: 1, name: "marked" }], - comments: [{ id: 1, post: 1, name: "Comcast is a bargain" }] + posts: [{ id: 1, comment: 1, name: 'marked' }], + comments: [{ id: 1, post: 1, name: 'Comcast is a bargain' }], }); return run(() => { return post.save().then(record => { - assert.equal(store.peekRecord('post', 1).get('comment.isLoaded'), true, "post's comment isLoaded (via store)"); - assert.equal(store.peekRecord('comment', 1).get('post.isLoaded'), true, "comment's post isLoaded (via store)"); + assert.equal( + store.peekRecord('post', 1).get('comment.isLoaded'), + true, + "post's comment isLoaded (via store)" + ); + assert.equal( + store.peekRecord('comment', 1).get('post.isLoaded'), + true, + "comment's post isLoaded (via store)" + ); assert.equal(record.get('comment.isLoaded'), true, "post's comment isLoaded (via record)"); - assert.equal(record.get('comment.post.isLoaded'), true, "post's comment's post isLoaded (via record)"); + assert.equal( + record.get('comment.post.isLoaded'), + true, + "post's comment's post isLoaded (via record)" + ); }); }); }); @@ -531,71 +597,92 @@ test("createRecord - response can contain relationships the client doesn't yet k assert.expect(3); // while records.length is 2, we are getting 4 assertions ajaxResponse({ - posts: [{ - id: "1", - name: "Rails is omakase", - comments: [2] - }], - comments: [{ - id: "2", - name: "Another Comment", - post: 1 - }] + posts: [ + { + id: '1', + name: 'Rails is omakase', + comments: [2], + }, + ], + comments: [ + { + id: '2', + name: 'Another Comment', + post: 1, + }, + ], }); Post.reopen({ comments: DS.hasMany('comment', { async: false }) }); Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); - let post = store.createRecord('post', { name: "Rails is omakase" }); + let post = store.createRecord('post', { name: 'Rails is omakase' }); return run(() => { return post.save().then(post => { - assert.equal(post.get('comments.firstObject.post'), post, "the comments are related to the correct post model"); - assert.equal(store._internalModelsFor('post').models.length, 1, "There should only be one post record in the store"); + assert.equal( + post.get('comments.firstObject.post'), + post, + 'the comments are related to the correct post model' + ); + assert.equal( + store._internalModelsFor('post').models.length, + 1, + 'There should only be one post record in the store' + ); let postRecords = store._internalModelsFor('post').models; for (var i = 0; i < postRecords.length; i++) { - assert.equal(post, postRecords[i].getRecord(), "The object in the identity map is the same"); + assert.equal( + post, + postRecords[i].getRecord(), + 'The object in the identity map is the same' + ); } }); }); }); -test("createRecord - relationships are not duplicated", function(assert) { +test('createRecord - relationships are not duplicated', function(assert) { Post.reopen({ comments: DS.hasMany('comment', { async: false }) }); Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); - let post = store.createRecord('post', { name: "Tomtomhuda" }); - let comment = store.createRecord('comment', { id: 2, name: "Comment title" }); + let post = store.createRecord('post', { name: 'Tomtomhuda' }); + let comment = store.createRecord('comment', { id: 2, name: 'Comment title' }); - ajaxResponse({ post: [{ id: 1, name: "Rails is omakase", comments: [] }] }); + ajaxResponse({ post: [{ id: 1, name: 'Rails is omakase', comments: [] }] }); - return run(() => post.save().then(post => { - assert.equal(post.get('comments.length'), 0, "post has 0 comments"); - post.get('comments').pushObject(comment); - assert.equal(post.get('comments.length'), 1, "post has 1 comment"); + return run(() => + post + .save() + .then(post => { + assert.equal(post.get('comments.length'), 0, 'post has 0 comments'); + post.get('comments').pushObject(comment); + assert.equal(post.get('comments.length'), 1, 'post has 1 comment'); - ajaxResponse({ - post: [{ id: 1, name: "Rails is omakase", comments: [2] }], - comments: [{ id: 2, name: "Comment title" }] - }); + ajaxResponse({ + post: [{ id: 1, name: 'Rails is omakase', comments: [2] }], + comments: [{ id: 2, name: 'Comment title' }], + }); - return post.save(); - }).then(post => { - assert.equal(post.get('comments.length'), 1, "post has 1 comment"); - })); + return post.save(); + }) + .then(post => { + assert.equal(post.get('comments.length'), 1, 'post has 1 comment'); + }) + ); }); -test("updateRecord - an empty payload is a basic success", function(assert) { +test('updateRecord - an empty payload is a basic success', function(assert) { run(() => { store.push({ data: { type: 'post', id: '1', attributes: { - name: "Rails is omakase" - } - } + name: 'Rails is omakase', + }, + }, }); }); @@ -603,21 +690,21 @@ test("updateRecord - an empty payload is a basic success", function(assert) { let post = store.peekRecord('post', 1); ajaxResponse(); - post.set('name', "The Parley Letter"); + post.set('name', 'The Parley Letter'); return post.save().then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "PUT"); - assert.deepEqual(passedHash.data, { post: { name: "The Parley Letter" } }); + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'PUT'); + assert.deepEqual(passedHash.data, { post: { name: 'The Parley Letter' } }); assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('name'), "The Parley Letter", "the post was updated"); + assert.equal(post.get('name'), 'The Parley Letter', 'the post was updated'); }); }); }); -test("updateRecord - passes the requestType to buildURL", function(assert) { +test('updateRecord - passes the requestType to buildURL', function(assert) { adapter.buildURL = function(type, id, snapshot, requestType) { - return "/posts/" + id + "/" + requestType; + return '/posts/' + id + '/' + requestType; }; adapter.shouldBackgroundReloadRecord = () => false; @@ -627,25 +714,28 @@ test("updateRecord - passes the requestType to buildURL", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" - } - } + name: 'Rails is omakase', + }, + }, }); }); return run(() => { - return store.findRecord('post', 1).then(post => { - ajaxResponse(); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse(); - post.set('name', "The Parley Letter"); - return post.save(); - }).then(post => { - assert.equal(passedUrl, "/posts/1/updateRecord"); - }); + post.set('name', 'The Parley Letter'); + return post.save(); + }) + .then(post => { + assert.equal(passedUrl, '/posts/1/updateRecord'); + }); }); }); -test("updateRecord - a payload with updates applies the updates", function(assert) { +test('updateRecord - a payload with updates applies the updates', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; run(() => { store.push({ @@ -653,28 +743,31 @@ test("updateRecord - a payload with updates applies the updates", function(asser type: 'post', id: '1', attributes: { - name: "Rails is omakase" - } - } + name: 'Rails is omakase', + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse({ posts: [{ id: 1, name: "Dat Parley Letter" }] }); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ posts: [{ id: 1, name: 'Dat Parley Letter' }] }); - post.set('name', "The Parley Letter"); - return post.save(); - }).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "PUT"); - assert.deepEqual(passedHash.data, { post: { name: "The Parley Letter" } }); + post.set('name', 'The Parley Letter'); + return post.save(); + }) + .then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'PUT'); + assert.deepEqual(passedHash.data, { post: { name: 'The Parley Letter' } }); - assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('name'), "Dat Parley Letter", "the post was updated"); - }); + assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); + assert.equal(post.get('name'), 'Dat Parley Letter', 'the post was updated'); + }); }); -test("updateRecord - a payload with updates applies the updates (with legacy singular name)", function(assert) { +test('updateRecord - a payload with updates applies the updates (with legacy singular name)', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; run(() => { store.push({ @@ -682,52 +775,55 @@ test("updateRecord - a payload with updates applies the updates (with legacy sin type: 'post', id: '1', attributes: { - name: "Rails is omakase" - } - } + name: 'Rails is omakase', + }, + }, }); }); - return store.findRecord('post', 1).then(post =>{ - ajaxResponse({ post: { id: 1, name: "Dat Parley Letter" } }); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ post: { id: 1, name: 'Dat Parley Letter' } }); - post.set('name', "The Parley Letter"); - return post.save(); - }).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "PUT"); - assert.deepEqual(passedHash.data, { post: { name: "The Parley Letter" } }); + post.set('name', 'The Parley Letter'); + return post.save(); + }) + .then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'PUT'); + assert.deepEqual(passedHash.data, { post: { name: 'The Parley Letter' } }); - assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('name'), "Dat Parley Letter", "the post was updated"); - }); + assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); + assert.equal(post.get('name'), 'Dat Parley Letter', 'the post was updated'); + }); }); -test("updateRecord - a payload with sideloaded updates pushes the updates", function(assert) { +test('updateRecord - a payload with sideloaded updates pushes the updates', function(assert) { let post; ajaxResponse({ - posts: [{ id: 1, name: "Dat Parley Letter" }], - comments: [{ id: 1, name: "FIRST" }] + posts: [{ id: 1, name: 'Dat Parley Letter' }], + comments: [{ id: 1, name: 'FIRST' }], }); return run(() => { - post = store.createRecord('post', { name: "The Parley Letter" }); + post = store.createRecord('post', { name: 'The Parley Letter' }); return post.save().then(post => { - assert.equal(passedUrl, "/posts"); - assert.equal(passedVerb, "POST"); - assert.deepEqual(passedHash.data, { post: { name: "The Parley Letter" } }); + assert.equal(passedUrl, '/posts'); + assert.equal(passedVerb, 'POST'); + assert.deepEqual(passedHash.data, { post: { name: 'The Parley Letter' } }); - assert.equal(post.get('id'), "1", "the post has the updated ID"); + assert.equal(post.get('id'), '1', 'the post has the updated ID'); assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('name'), "Dat Parley Letter", "the post was updated"); + assert.equal(post.get('name'), 'Dat Parley Letter', 'the post was updated'); let comment = store.peekRecord('comment', 1); - assert.equal(comment.get('name'), "FIRST", "The comment was sideloaded"); + assert.equal(comment.get('name'), 'FIRST', 'The comment was sideloaded'); }); }); }); -test("updateRecord - a payload with sideloaded updates pushes the updates", function(assert) { +test('updateRecord - a payload with sideloaded updates pushes the updates', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; run(() => { store.push({ @@ -735,64 +831,73 @@ test("updateRecord - a payload with sideloaded updates pushes the updates", func type: 'post', id: '1', attributes: { - name: "Rails is omakase" - } - } + name: 'Rails is omakase', + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse({ - posts: [{ id: 1, name: "Dat Parley Letter" }], - comments: [{ id: 1, name: "FIRST" }] - }); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ + posts: [{ id: 1, name: 'Dat Parley Letter' }], + comments: [{ id: 1, name: 'FIRST' }], + }); - post.set('name', "The Parley Letter"); - return post.save(); - }).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "PUT"); - assert.deepEqual(passedHash.data, { post: { name: "The Parley Letter" } }); + post.set('name', 'The Parley Letter'); + return post.save(); + }) + .then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'PUT'); + assert.deepEqual(passedHash.data, { post: { name: 'The Parley Letter' } }); - assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('name'), "Dat Parley Letter", "the post was updated"); + assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); + assert.equal(post.get('name'), 'Dat Parley Letter', 'the post was updated'); - let comment = store.peekRecord('comment', 1); - assert.equal(comment.get('name'), "FIRST", "The comment was sideloaded"); - }); + let comment = store.peekRecord('comment', 1); + assert.equal(comment.get('name'), 'FIRST', 'The comment was sideloaded'); + }); }); test("updateRecord - a serializer's primary key and attributes are consulted when building the payload", function(assert) { adapter.shouldBackgroundReloadRecord = () => false; - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - primaryKey: '_id_', + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + primaryKey: '_id_', - attrs: { - name: '_name_' - } - })); + attrs: { + name: '_name_', + }, + }) + ); run(() => { store.push({ data: { type: 'post', id: '1', - name: "Rails is omakase" - } + name: 'Rails is omakase', + }, }); }); ajaxResponse(); - return store.findRecord('post', 1).then(post => { - post.set('name', "The Parley Letter"); - return post.save(); - }).then(post => { - assert.deepEqual(passedHash.data, { post: { '_name_': "The Parley Letter" } }); - }); + return store + .findRecord('post', 1) + .then(post => { + post.set('name', 'The Parley Letter'); + return post.save(); + }) + .then(post => { + assert.deepEqual(passedHash.data, { post: { _name_: 'The Parley Letter' } }); + }); }); -test("updateRecord - hasMany relationships faithfully reflect simultaneous adds and removes", function(assert) { +test('updateRecord - hasMany relationships faithfully reflect simultaneous adds and removes', function(assert) { Post.reopen({ comments: DS.hasMany('comment', { async: false }) }); Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); adapter.shouldBackgroundReloadRecord = () => false; @@ -803,54 +908,63 @@ test("updateRecord - hasMany relationships faithfully reflect simultaneous adds type: 'post', id: '1', attributes: { - name: "Not everyone uses Rails" + name: 'Not everyone uses Rails', }, relationships: { comments: { - data: [ - { type: 'comment', id: '1' } - ] - } - } + 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." - } - }] + included: [ + { + type: 'comment', + id: '1', + attributes: { + name: 'Rails is omakase', + }, + }, + { + type: 'comment', + id: '2', + attributes: { + name: 'Yes. Yes it is.', + }, + }, + ], }); }); ajaxResponse({ - posts: { id: 1, name: "Not everyone uses Rails", comments: [2] } + posts: { id: 1, name: 'Not everyone uses Rails', comments: [2] }, }); - return store.findRecord('comment', 2).then(() => { - return store.findRecord('post', 1); - }).then(post => { - let newComment = store.peekRecord('comment', 2); - let comments = post.get('comments'); + return store + .findRecord('comment', 2) + .then(() => { + return store.findRecord('post', 1); + }) + .then(post => { + let newComment = store.peekRecord('comment', 2); + let comments = post.get('comments'); - // Replace the comment with a new one - comments.popObject(); - comments.pushObject(newComment); + // Replace the comment with a new one + comments.popObject(); + comments.pushObject(newComment); - return post.save(); - }).then(post => { - assert.equal(post.get('comments.length'), 1, "the post has the correct number of comments"); - assert.equal(post.get('comments.firstObject.name'), "Yes. Yes it is.", "the post has the correct comment"); - }); + return post.save(); + }) + .then(post => { + assert.equal(post.get('comments.length'), 1, 'the post has the correct number of comments'); + assert.equal( + post.get('comments.firstObject.name'), + 'Yes. Yes it is.', + 'the post has the correct comment' + ); + }); }); -test("deleteRecord - an empty payload is a basic success", function(assert) { +test('deleteRecord - an empty payload is a basic success', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; run(() => { store.push({ @@ -858,31 +972,34 @@ test("deleteRecord - an empty payload is a basic success", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" - } - } + name: 'Rails is omakase', + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse(); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse(); - post.deleteRecord(); - return post.save(); - }).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "DELETE"); - assert.strictEqual(passedHash, undefined); + post.deleteRecord(); + return post.save(); + }) + .then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'DELETE'); + assert.strictEqual(passedHash, undefined); - assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('isDeleted'), true, "the post is now deleted"); - }); + assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); + assert.equal(post.get('isDeleted'), true, 'the post is now deleted'); + }); }); -test("deleteRecord - passes the requestType to buildURL", function(assert) { +test('deleteRecord - passes the requestType to buildURL', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; adapter.buildURL = function(type, id, snapshot, requestType) { - return "/posts/" + id + "/" + requestType; + return '/posts/' + id + '/' + requestType; }; run(() => { @@ -891,23 +1008,26 @@ test("deleteRecord - passes the requestType to buildURL", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" - } - } + name: 'Rails is omakase', + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse(); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse(); - post.deleteRecord(); - return post.save(); - }).then(post => { - assert.equal(passedUrl, "/posts/1/deleteRecord"); - }); + post.deleteRecord(); + return post.save(); + }) + .then(post => { + assert.equal(passedUrl, '/posts/1/deleteRecord'); + }); }); -test("deleteRecord - a payload with sideloaded updates pushes the updates", function(assert) { +test('deleteRecord - a payload with sideloaded updates pushes the updates', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; run(() => { store.push({ @@ -915,31 +1035,34 @@ test("deleteRecord - a payload with sideloaded updates pushes the updates", func type: 'post', id: '1', attributes: { - name: "Rails is omakase" - } - } + name: 'Rails is omakase', + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse({ comments: [{ id: 1, name: "FIRST" }] }); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ comments: [{ id: 1, name: 'FIRST' }] }); - post.deleteRecord(); - return post.save(); - }).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "DELETE"); - assert.strictEqual(passedHash, undefined); + post.deleteRecord(); + return post.save(); + }) + .then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'DELETE'); + assert.strictEqual(passedHash, undefined); - assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); - assert.equal(post.get('isDeleted'), true, "the post is now deleted"); + assert.equal(post.get('hasDirtyAttributes'), false, "the post isn't dirty anymore"); + assert.equal(post.get('isDeleted'), true, 'the post is now deleted'); - let comment = store.peekRecord('comment', 1); - assert.equal(comment.get('name'), "FIRST", "The comment was sideloaded"); - }); + let comment = store.peekRecord('comment', 1); + assert.equal(comment.get('name'), 'FIRST', 'The comment was sideloaded'); + }); }); -test("deleteRecord - a payload with sidloaded updates pushes the updates when the original record is omitted", function(assert) { +test('deleteRecord - a payload with sidloaded updates pushes the updates when the original record is omitted', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; run(() => { store.push({ @@ -947,57 +1070,69 @@ test("deleteRecord - a payload with sidloaded updates pushes the updates when th type: 'post', id: '1', attributes: { - name: "Rails is omakase" - } - } + name: 'Rails is omakase', + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse({ posts: [{ id: 2, name: "The Parley Letter" }] }); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ posts: [{ id: 2, name: 'The Parley Letter' }] }); - post.deleteRecord(); - return post.save(); - }).then(post => { - assert.equal(passedUrl, "/posts/1"); - assert.equal(passedVerb, "DELETE"); - assert.strictEqual(passedHash, undefined); + post.deleteRecord(); + return post.save(); + }) + .then(post => { + assert.equal(passedUrl, '/posts/1'); + assert.equal(passedVerb, 'DELETE'); + assert.strictEqual(passedHash, undefined); - assert.equal(post.get('hasDirtyAttributes'), false, "the original post isn't dirty anymore"); - assert.equal(post.get('isDeleted'), true, "the original post is now deleted"); + assert.equal(post.get('hasDirtyAttributes'), false, "the original post isn't dirty anymore"); + assert.equal(post.get('isDeleted'), true, 'the original post is now deleted'); - let newPost = store.peekRecord('post', 2); - assert.equal(newPost.get('name'), "The Parley Letter", "The new post was added to the store"); - }); + let newPost = store.peekRecord('post', 2); + assert.equal(newPost.get('name'), 'The Parley Letter', 'The new post was added to the store'); + }); }); -test("deleteRecord - deleting a newly created record should not throw an error", function(assert) { +test('deleteRecord - deleting a newly created record should not throw an error', function(assert) { let post = store.createRecord('post'); return run(() => { post.deleteRecord(); return post.save().then(post => { - assert.equal(passedUrl, null, "There is no ajax call to delete a record that has never been saved."); - assert.equal(passedVerb, null, "There is no ajax call to delete a record that has never been saved."); - assert.equal(passedHash, null, "There is no ajax call to delete a record that has never been saved."); + assert.equal( + passedUrl, + null, + 'There is no ajax call to delete a record that has never been saved.' + ); + assert.equal( + passedVerb, + null, + 'There is no ajax call to delete a record that has never been saved.' + ); + assert.equal( + passedHash, + null, + 'There is no ajax call to delete a record that has never been saved.' + ); - assert.equal(post.get('isDeleted'), true, "the post is now deleted"); - assert.equal(post.get('isError'), false, "the post is not an error"); + assert.equal(post.get('isDeleted'), true, 'the post is now deleted'); + assert.equal(post.get('isError'), false, 'the post is not an error'); }); }); }); -test("findAll - returning an array populates the array", function(assert) { +test('findAll - returning an array populates the array', function(assert) { ajaxResponse({ - posts: [ - { id: 1, name: "Rails is omakase" }, - { id: 2, name: "The Parley Letter" } - ] + posts: [{ id: 1, name: 'Rails is omakase' }, { id: 2, name: 'The Parley Letter' }], }); return store.findAll('post').then(posts => { - assert.equal(passedUrl, "/posts"); - assert.equal(passedVerb, "GET"); + assert.equal(passedUrl, '/posts'); + assert.equal(passedVerb, 'GET'); assert.deepEqual(passedHash.data, {}); let post1 = store.peekRecord('post', 1); @@ -1005,83 +1140,77 @@ test("findAll - returning an array populates the array", function(assert) { assert.deepEqual( post1.getProperties('id', 'name'), - { id: "1", name: "Rails is omakase" }, - "Post 1 is loaded" + { id: '1', name: 'Rails is omakase' }, + 'Post 1 is loaded' ); assert.deepEqual( post2.getProperties('id', 'name'), - { id: "2", name: "The Parley Letter" }, - "Post 2 is loaded" + { id: '2', name: 'The Parley Letter' }, + 'Post 2 is loaded' ); - assert.equal(posts.get('length'), 2, "The posts are in the array"); - assert.equal(posts.get('isLoaded'), true, "The RecordArray is loaded"); - assert.deepEqual( - posts.toArray(), - [post1, post2], - "The correct records are in the array" - ); + assert.equal(posts.get('length'), 2, 'The posts are in the array'); + assert.equal(posts.get('isLoaded'), true, 'The RecordArray is loaded'); + assert.deepEqual(posts.toArray(), [post1, post2], 'The correct records are in the array'); }); }); - -test("findAll - passes buildURL the requestType and snapshot", function(assert) { +test('findAll - passes buildURL the requestType and snapshot', function(assert) { assert.expect(2); let adapterOptionsStub = { stub: true }; adapter.buildURL = function(type, id, snapshot, requestType) { assert.equal(snapshot.adapterOptions, adapterOptionsStub); - return "/" + requestType + "/posts"; + return '/' + requestType + '/posts'; }; ajaxResponse({ - posts: [ - { id: 1, name: "Rails is omakase" }, - { id: 2, name: "The Parley Letter" } - ] + posts: [{ id: 1, name: 'Rails is omakase' }, { id: 2, name: 'The Parley Letter' }], }); return store.findAll('post', { adapterOptions: adapterOptionsStub }).then(posts => { - assert.equal(passedUrl, "/findAll/posts"); + assert.equal(passedUrl, '/findAll/posts'); }); }); -test("findAll - passed `include` as a query parameter to ajax", function(assert) { +test('findAll - passed `include` as a query parameter to ajax', function(assert) { ajaxResponse({ - posts: [{ id: 1, name: 'Rails is very expensive sushi' }] + posts: [{ id: 1, name: 'Rails is very expensive sushi' }], }); return run(store, 'findAll', 'post', { include: 'comments' }).then(() => { - assert.deepEqual(passedHash.data, { include: 'comments' }, '`include` params sent to adapter.ajax'); + assert.deepEqual( + passedHash.data, + { include: 'comments' }, + '`include` params sent to adapter.ajax' + ); }); }); -test("findAll - returning sideloaded data loads the data", function(assert) { +test('findAll - returning sideloaded data loads the data', function(assert) { ajaxResponse({ - posts: [ - { id: 1, name: "Rails is omakase" }, - { id: 2, name: "The Parley Letter" } - ], - comments: [{ id: 1, name: "FIRST" }] }); + posts: [{ id: 1, name: 'Rails is omakase' }, { id: 2, name: 'The Parley Letter' }], + comments: [{ id: 1, name: 'FIRST' }], + }); return store.findAll('post').then(posts => { let comment = store.peekRecord('comment', 1); - assert.deepEqual(comment.getProperties('id', 'name'), { id: "1", name: "FIRST" }); + assert.deepEqual(comment.getProperties('id', 'name'), { id: '1', name: 'FIRST' }); }); }); -test("findAll - data is normalized through custom serializers", function(assert) { - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - primaryKey: '_ID_', - attrs: { name: '_NAME_' } - })); +test('findAll - data is normalized through custom serializers', function(assert) { + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + primaryKey: '_ID_', + attrs: { name: '_NAME_' }, + }) + ); ajaxResponse({ - posts: [ - { _ID_: 1, _NAME_: "Rails is omakase" }, - { _ID_: 2, _NAME_: "The Parley Letter" } - ] + posts: [{ _ID_: 1, _NAME_: 'Rails is omakase' }, { _ID_: 2, _NAME_: 'The Parley Letter' }], }); return store.findAll('post').then(posts => { @@ -1090,68 +1219,74 @@ test("findAll - data is normalized through custom serializers", function(assert) assert.deepEqual( post1.getProperties('id', 'name'), - { id: "1", name: "Rails is omakase" }, - "Post 1 is loaded" + { id: '1', name: 'Rails is omakase' }, + 'Post 1 is loaded' ); assert.deepEqual( post2.getProperties('id', 'name'), - { id: "2", name: "The Parley Letter" }, - "Post 2 is loaded" + { id: '2', name: 'The Parley Letter' }, + 'Post 2 is loaded' ); - assert.equal(posts.get('length'), 2, "The posts are in the array"); - assert.equal(posts.get('isLoaded'), true, "The RecordArray is loaded"); - assert.deepEqual( - posts.toArray(), - [post1, post2], - "The correct records are in the array" - ); + assert.equal(posts.get('length'), 2, 'The posts are in the array'); + assert.equal(posts.get('isLoaded'), true, 'The RecordArray is loaded'); + assert.deepEqual(posts.toArray(), [post1, post2], 'The correct records are in the array'); }); }); -test("query - if `sortQueryParams` option is not provided, query params are sorted alphabetically", function(assert) { +test('query - if `sortQueryParams` option is not provided, query params are sorted alphabetically', function(assert) { ajaxResponse({ - posts: [{ id: 1, name: "Rails is very expensive sushi" }] + posts: [{ id: 1, name: 'Rails is very expensive sushi' }], }); - return store.query('post', { "params": 1, "in": 2, "wrong": 3, "order": 4 }).then(() => { - assert.deepEqual(Object.keys(passedHash.data), ["in", "order", "params", "wrong"], 'query params are received in alphabetical order'); + return store.query('post', { params: 1, in: 2, wrong: 3, order: 4 }).then(() => { + assert.deepEqual( + Object.keys(passedHash.data), + ['in', 'order', 'params', 'wrong'], + 'query params are received in alphabetical order' + ); }); }); -test("query - passes buildURL the requestType", function(assert) { +test('query - passes buildURL the requestType', function(assert) { adapter.buildURL = function(type, id, snapshot, requestType) { - return "/" + requestType + "/posts"; + return '/' + requestType + '/posts'; }; ajaxResponse({ - posts: [{ id: 1, name: "Rails is very expensive sushi" }] + posts: [{ id: 1, name: 'Rails is very expensive sushi' }], }); - return store.query('post', { "params": 1, "in": 2, "wrong": 3, "order": 4 }).then(() => { + return store.query('post', { params: 1, in: 2, wrong: 3, order: 4 }).then(() => { assert.equal(passedUrl, '/query/posts'); }); }); -test("query - if `sortQueryParams` is falsey, query params are not sorted at all", function(assert) { +test('query - if `sortQueryParams` is falsey, query params are not sorted at all', function(assert) { ajaxResponse({ - posts: [{ id: 1, name: "Rails is very expensive sushi" }] + posts: [{ id: 1, name: 'Rails is very expensive sushi' }], }); adapter.sortQueryParams = null; - return store.query('post', { "params": 1, "in": 2, "wrong": 3, "order": 4 }).then(() => { - assert.deepEqual(Object.keys(passedHash.data), ["params", "in", "wrong", "order"], 'query params are received in their original order'); + return store.query('post', { params: 1, in: 2, wrong: 3, order: 4 }).then(() => { + assert.deepEqual( + Object.keys(passedHash.data), + ['params', 'in', 'wrong', 'order'], + 'query params are received in their original order' + ); }); }); -test("query - if `sortQueryParams` is a custom function, query params passed through that function", function(assert) { +test('query - if `sortQueryParams` is a custom function, query params passed through that function', function(assert) { ajaxResponse({ - posts: [{ id: 1, name: "Rails is very expensive sushi" }] + posts: [{ id: 1, name: 'Rails is very expensive sushi' }], }); adapter.sortQueryParams = function(obj) { - let sortedKeys = Object.keys(obj).sort().reverse(); + let sortedKeys = Object.keys(obj) + .sort() + .reverse(); let len = sortedKeys.length; let newQueryParams = {}; @@ -1161,22 +1296,26 @@ test("query - if `sortQueryParams` is a custom function, query params passed thr return newQueryParams; }; - return store.query('post', { "params": 1, "in": 2, "wrong": 3, "order": 4 }).then(() => { - assert.deepEqual(Object.keys(passedHash.data), ["wrong", "params", "order", "in"], 'query params are received in reverse alphabetical order'); + return store.query('post', { params: 1, in: 2, wrong: 3, order: 4 }).then(() => { + assert.deepEqual( + Object.keys(passedHash.data), + ['wrong', 'params', 'order', 'in'], + 'query params are received in reverse alphabetical order' + ); }); }); test("query - payload 'meta' is accessible on the record array", function(assert) { ajaxResponse({ meta: { offset: 5 }, - posts: [{ id: 1, name: "Rails is very expensive sushi" }] + posts: [{ id: 1, name: 'Rails is very expensive sushi' }], }); return store.query('post', { page: 2 }).then(posts => { assert.equal( posts.get('meta.offset'), 5, - "Reponse metadata can be accessed with recordArray.meta" + 'Reponse metadata can be accessed with recordArray.meta' ); }); }); @@ -1184,18 +1323,18 @@ test("query - payload 'meta' is accessible on the record array", function(assert test("query - each record array can have it's own meta object", function(assert) { ajaxResponse({ meta: { offset: 5 }, - posts: [{ id: 1, name: "Rails is very expensive sushi" }] + posts: [{ id: 1, name: 'Rails is very expensive sushi' }], }); return store.query('post', { page: 2 }).then(posts => { assert.equal( posts.get('meta.offset'), 5, - "Reponse metadata can be accessed with recordArray.meta" + 'Reponse metadata can be accessed with recordArray.meta' ); ajaxResponse({ meta: { offset: 1 }, - posts: [{ id: 1, name: "Rails is very expensive sushi" }] + posts: [{ id: 1, name: 'Rails is very expensive sushi' }], }); return store.query('post', { page: 1 }).then(newPosts => { @@ -1205,12 +1344,9 @@ test("query - each record array can have it's own meta object", function(assert) }); }); - -test("query - returning an array populates the array", function(assert) { +test('query - returning an array populates the array', function(assert) { ajaxResponse({ - posts: [ - { id: 1, name: "Rails is omakase" }, - { id: 2, name: "The Parley Letter" }] + posts: [{ id: 1, name: 'Rails is omakase' }, { id: 2, name: 'The Parley Letter' }], }); return store.query('post', { page: 1 }).then(posts => { @@ -1223,50 +1359,45 @@ test("query - returning an array populates the array", function(assert) { assert.deepEqual( post1.getProperties('id', 'name'), - { id: "1", name: "Rails is omakase" }, - "Post 1 is loaded" + { id: '1', name: 'Rails is omakase' }, + 'Post 1 is loaded' ); assert.deepEqual( post2.getProperties('id', 'name'), - { id: "2", name: "The Parley Letter" }, - "Post 2 is loaded" + { id: '2', name: 'The Parley Letter' }, + 'Post 2 is loaded' ); - assert.equal(posts.get('length'), 2, "The posts are in the array"); - assert.equal(posts.get('isLoaded'), true, "The RecordArray is loaded"); - assert.deepEqual( - posts.toArray(), - [post1, post2], - "The correct records are in the array" - ); + assert.equal(posts.get('length'), 2, 'The posts are in the array'); + assert.equal(posts.get('isLoaded'), true, 'The RecordArray is loaded'); + assert.deepEqual(posts.toArray(), [post1, post2], 'The correct records are in the array'); }); }); -test("query - returning sideloaded data loads the data", function(assert) { +test('query - returning sideloaded data loads the data', function(assert) { ajaxResponse({ - posts: [ - { id: 1, name: "Rails is omakase" }, - { id: 2, name: "The Parley Letter" } - ], - comments: [{ id: 1, name: "FIRST" }] + posts: [{ id: 1, name: 'Rails is omakase' }, { id: 2, name: 'The Parley Letter' }], + comments: [{ id: 1, name: 'FIRST' }], }); return store.query('post', { page: 1 }).then(posts => { let comment = store.peekRecord('comment', 1); - assert.deepEqual(comment.getProperties('id', 'name'), { id: "1", name: "FIRST" }); + assert.deepEqual(comment.getProperties('id', 'name'), { id: '1', name: 'FIRST' }); }); }); -test("query - data is normalized through custom serializers", function(assert) { - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - primaryKey: '_ID_', - attrs: { name: '_NAME_' } - })); +test('query - data is normalized through custom serializers', function(assert) { + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + primaryKey: '_ID_', + attrs: { name: '_NAME_' }, + }) + ); ajaxResponse({ - posts: [{ _ID_: 1, _NAME_: "Rails is omakase" }, - { _ID_: 2, _NAME_: "The Parley Letter" }] + posts: [{ _ID_: 1, _NAME_: 'Rails is omakase' }, { _ID_: 2, _NAME_: 'The Parley Letter' }], }); return store.query('post', { page: 1 }).then(posts => { @@ -1275,27 +1406,23 @@ test("query - data is normalized through custom serializers", function(assert) { assert.deepEqual( post1.getProperties('id', 'name'), - { id: "1", name: "Rails is omakase" }, - "Post 1 is loaded" + { id: '1', name: 'Rails is omakase' }, + 'Post 1 is loaded' ); assert.deepEqual( post2.getProperties('id', 'name'), - { id: "2", name: "The Parley Letter" }, - "Post 2 is loaded" + { id: '2', name: 'The Parley Letter' }, + 'Post 2 is loaded' ); - assert.equal(posts.get('length'), 2, "The posts are in the array"); - assert.equal(posts.get('isLoaded'), true, "The RecordArray is loaded"); - assert.deepEqual( - posts.toArray(), - [post1, post2], - "The correct records are in the array" - ); + assert.equal(posts.get('length'), 2, 'The posts are in the array'); + assert.equal(posts.get('isLoaded'), true, 'The RecordArray is loaded'); + assert.deepEqual(posts.toArray(), [post1, post2], 'The correct records are in the array'); }); }); -test("queryRecord - empty response", function(assert) { +test('queryRecord - empty response', function(assert) { ajaxResponse({}); return store.queryRecord('post', { slug: 'ember-js-rocks' }).then(post => { @@ -1303,9 +1430,9 @@ test("queryRecord - empty response", function(assert) { }); }); -test("queryRecord - primary data being null", function(assert) { +test('queryRecord - primary data being null', function(assert) { ajaxResponse({ - post: null + post: null, }); return store.queryRecord('post', { slug: 'ember-js-rocks' }).then(post => { @@ -1313,65 +1440,74 @@ test("queryRecord - primary data being null", function(assert) { }); }); -test("queryRecord - primary data being a single object", function(assert) { +test('queryRecord - primary data being a single object', function(assert) { ajaxResponse({ post: { id: '1', - name: 'Ember.js rocks' - } + name: 'Ember.js rocks', + }, }); return store.queryRecord('post', { slug: 'ember-js-rocks' }).then(post => { - assert.deepEqual(post.get('name'), "Ember.js rocks"); + assert.deepEqual(post.get('name'), 'Ember.js rocks'); }); }); -test("queryRecord - returning sideloaded data loads the data", function(assert) { +test('queryRecord - returning sideloaded data loads the data', function(assert) { ajaxResponse({ - post: { id: 1, name: "Rails is omakase" }, - comments: [{ id: 1, name: "FIRST" }] + post: { id: 1, name: 'Rails is omakase' }, + comments: [{ id: 1, name: 'FIRST' }], }); return store.queryRecord('post', { slug: 'rails-is-omakaze' }).then(post => { let comment = store.peekRecord('comment', 1); - assert.deepEqual(comment.getProperties('id', 'name'), { id: "1", name: "FIRST" }); + assert.deepEqual(comment.getProperties('id', 'name'), { id: '1', name: 'FIRST' }); }); }); -testInDebug("queryRecord - returning an array picks the first one but saves all records to the store", function(assert) { - ajaxResponse({ - post: [{ id: 1, name: "Rails is omakase" }, { id: 2, name: "Ember is js" }] - }); +testInDebug( + 'queryRecord - returning an array picks the first one but saves all records to the store', + function(assert) { + ajaxResponse({ + post: [{ id: 1, name: 'Rails is omakase' }, { id: 2, name: 'Ember is js' }], + }); - assert.expectDeprecation( - () => - run(() => { - return store.queryRecord('post', { slug: 'rails-is-omakaze' }).then(post => { - let post2 = store.peekRecord('post', 2); + assert.expectDeprecation( + () => + run(() => { + return store.queryRecord('post', { slug: 'rails-is-omakaze' }).then(post => { + let post2 = store.peekRecord('post', 2); - assert.deepEqual(post.getProperties('id', 'name'), { id: "1", name: "Rails is omakase" }); - assert.deepEqual(post2.getProperties('id', 'name'), { id: "2", name: "Ember is js" }); - }); - }), + assert.deepEqual(post.getProperties('id', 'name'), { + id: '1', + name: 'Rails is omakase', + }); + assert.deepEqual(post2.getProperties('id', 'name'), { id: '2', name: 'Ember is js' }); + }); + }), - /The adapter returned an array for the primary data of a `queryRecord` response. This is deprecated as `queryRecord` should return a single record./); -}); + /The adapter returned an array for the primary data of a `queryRecord` response. This is deprecated as `queryRecord` should return a single record./ + ); + } +); -testInDebug("queryRecord - returning an array is deprecated", function(assert) { +testInDebug('queryRecord - returning an array is deprecated', function(assert) { ajaxResponse({ - post: [{ id: 1, name: "Rails is omakase" }, { id: 2, name: "Ember is js" }] + post: [{ id: 1, name: 'Rails is omakase' }, { id: 2, name: 'Ember is js' }], }); assert.expectDeprecation( - () => - run(() => store.queryRecord('post', { slug: 'rails-is-omakaze' })), - 'The adapter returned an array for the primary data of a `queryRecord` response. This is deprecated as `queryRecord` should return a single record.'); + () => run(() => store.queryRecord('post', { slug: 'rails-is-omakaze' })), + 'The adapter returned an array for the primary data of a `queryRecord` response. This is deprecated as `queryRecord` should return a single record.' + ); }); -testInDebug("queryRecord - returning an single object doesn't throw a deprecation", function(assert) { +testInDebug("queryRecord - returning an single object doesn't throw a deprecation", function( + assert +) { ajaxResponse({ - post: { id: 1, name: "Rails is omakase" } + post: { id: 1, name: 'Rails is omakase' }, }); assert.expectNoDeprecation(); @@ -1379,26 +1515,29 @@ testInDebug("queryRecord - returning an single object doesn't throw a deprecatio return run(() => store.queryRecord('post', { slug: 'rails-is-omakaze' })); }); -test("queryRecord - data is normalized through custom serializers", function(assert) { - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - primaryKey: '_ID_', - attrs: { name: '_NAME_' } - })); +test('queryRecord - data is normalized through custom serializers', function(assert) { + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + primaryKey: '_ID_', + attrs: { name: '_NAME_' }, + }) + ); ajaxResponse({ - post: { _ID_: 1, _NAME_: "Rails is omakase" } + post: { _ID_: 1, _NAME_: 'Rails is omakase' }, }); return store.queryRecord('post', { slug: 'rails-is-omakaze' }).then(post => { assert.deepEqual( post.getProperties('id', 'name'), - { id: "1", name: "Rails is omakase" }, - "Post 1 is loaded with correct data" + { id: '1', name: 'Rails is omakase' }, + 'Post 1 is loaded with correct data' ); }); }); -test("findMany - findMany uses a correct URL to access the records", function(assert) { +test('findMany - findMany uses a correct URL to access the records', function(assert) { Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); adapter.coalesceFindRequests = true; @@ -1408,39 +1547,41 @@ test("findMany - findMany uses a correct URL to access the records", function(as type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { data: [ { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + { type: 'comment', id: '3' }, + ], + }, + }, + }, }); }); let post = store.peekRecord('post', 1); ajaxResponse({ comments: [ - { id: 1, name: "FIRST" }, - { id: 2, name: "Rails is unagi" }, - { id: 3, name: "What is omakase?" } - ] + { id: 1, name: 'FIRST' }, + { id: 2, name: 'Rails is unagi' }, + { id: 3, name: 'What is omakase?' }, + ], }); - return run(() => post.get('comments').then(comments => { - assert.equal(passedUrl, "/comments"); - assert.deepEqual(passedHash, { data: { ids: ["1", "2", "3"] } }); - })); + return run(() => + post.get('comments').then(comments => { + assert.equal(passedUrl, '/comments'); + assert.deepEqual(passedHash, { data: { ids: ['1', '2', '3'] } }); + }) + ); }); -test("findMany - passes buildURL the requestType", function(assert) { +test('findMany - passes buildURL the requestType', function(assert) { adapter.buildURL = function(type, id, snapshot, requestType) { - return "/" + requestType + "/" + type; + return '/' + requestType + '/' + type; }; Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); @@ -1452,36 +1593,36 @@ test("findMany - passes buildURL the requestType", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { data: [ { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + { type: 'comment', id: '3' }, + ], + }, + }, + }, }); }); let post = store.peekRecord('post', 1); ajaxResponse({ comments: [ - { id: 1, name: "FIRST" }, - { id: 2, name: "Rails is unagi" }, - { id: 3, name: "What is omakase?" } - ] + { id: 1, name: 'FIRST' }, + { id: 2, name: 'Rails is unagi' }, + { id: 3, name: 'What is omakase?' }, + ], }); return run(post, 'get', 'comments').then(comments => { - assert.equal(passedUrl, "/findMany/comment"); + assert.equal(passedUrl, '/findMany/comment'); }); }); -test("findMany - findMany does not coalesce by default", function(assert) { +test('findMany - findMany does not coalesce by default', function(assert) { Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); run(() => { @@ -1490,18 +1631,18 @@ test("findMany - findMany does not coalesce by default", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { data: [ { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + { type: 'comment', id: '3' }, + ], + }, + }, + }, }); }); @@ -1509,19 +1650,21 @@ test("findMany - findMany does not coalesce by default", function(assert) { //It's still ok to return this even without coalescing because RESTSerializer supports sideloading ajaxResponse({ comments: [ - { id: 1, name: "FIRST" }, - { id: 2, name: "Rails is unagi" }, - { id: 3, name: "What is omakase?" } - ] + { id: 1, name: 'FIRST' }, + { id: 2, name: 'Rails is unagi' }, + { id: 3, name: 'What is omakase?' }, + ], }); - return run(() => post.get('comments').then(comments => { - assert.equal(passedUrl, "/comments/3"); - assert.deepEqual(passedHash.data, {}); - })); + return run(() => + post.get('comments').then(comments => { + assert.equal(passedUrl, '/comments/3'); + assert.deepEqual(passedHash.data, {}); + }) + ); }); -test("findMany - returning an array populates the array", function(assert) { +test('findMany - returning an array populates the array', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); adapter.coalesceFindRequests = true; @@ -1532,49 +1675,52 @@ test("findMany - returning an array populates the array", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { data: [ { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + { type: 'comment', id: '3' }, + ], + }, + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse({ - comments: [ - { id: 1, name: "FIRST" }, - { id: 2, name: "Rails is unagi" }, - { id: 3, name: "What is omakase?" } - ] - }); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ + comments: [ + { id: 1, name: 'FIRST' }, + { id: 2, name: 'Rails is unagi' }, + { id: 3, name: 'What is omakase?' }, + ], + }); - return post.get('comments'); - }).then(comments => { - let comment1 = store.peekRecord('comment', 1); - let comment2 = store.peekRecord('comment', 2); - let comment3 = store.peekRecord('comment', 3); + return post.get('comments'); + }) + .then(comments => { + let comment1 = store.peekRecord('comment', 1); + let comment2 = store.peekRecord('comment', 2); + let comment3 = store.peekRecord('comment', 3); - assert.deepEqual(comment1.getProperties('id', 'name'), { id: "1", name: "FIRST" }); - assert.deepEqual(comment2.getProperties('id', 'name'), { id: "2", name: "Rails is unagi" }); - assert.deepEqual(comment3.getProperties('id', 'name'), { id: "3", name: "What is omakase?" }); + assert.deepEqual(comment1.getProperties('id', 'name'), { id: '1', name: 'FIRST' }); + assert.deepEqual(comment2.getProperties('id', 'name'), { id: '2', name: 'Rails is unagi' }); + assert.deepEqual(comment3.getProperties('id', 'name'), { id: '3', name: 'What is omakase?' }); - assert.deepEqual( - comments.toArray(), - [comment1, comment2, comment3], - "The correct records are in the array" - ); - }); + assert.deepEqual( + comments.toArray(), + [comment1, comment2, comment3], + 'The correct records are in the array' + ); + }); }); -test("findMany - returning sideloaded data loads the data", function(assert) { +test('findMany - returning sideloaded data loads the data', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); adapter.coalesceFindRequests = true; @@ -1585,62 +1731,74 @@ test("findMany - returning sideloaded data loads the data", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { data: [ { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + { type: 'comment', id: '3' }, + ], + }, + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse({ - comments: [ - { id: 1, name: "FIRST" }, - { id: 2, name: "Rails is unagi" }, - { id: 3, name: "What is omakase?" }, - { id: 4, name: "Unrelated comment" } - ], - posts: [{ id: 2, name: "The Parley Letter" }] - }); - - return post.get('comments'); - }).then(comments => { - let comment1 = store.peekRecord('comment', 1); - let comment2 = store.peekRecord('comment', 2); - let comment3 = store.peekRecord('comment', 3); - let comment4 = store.peekRecord('comment', 4); - let post2 = store.peekRecord('post', 2); - - assert.deepEqual( - comments.toArray(), - [comment1, comment2, comment3], - "The correct records are in the array" - ); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ + comments: [ + { id: 1, name: 'FIRST' }, + { id: 2, name: 'Rails is unagi' }, + { id: 3, name: 'What is omakase?' }, + { id: 4, name: 'Unrelated comment' }, + ], + posts: [{ id: 2, name: 'The Parley Letter' }], + }); - assert.deepEqual(comment4.getProperties('id', 'name'), { id: "4", name: "Unrelated comment" }); - assert.deepEqual(post2.getProperties('id', 'name'), { id: "2", name: "The Parley Letter" }); - }); + return post.get('comments'); + }) + .then(comments => { + let comment1 = store.peekRecord('comment', 1); + let comment2 = store.peekRecord('comment', 2); + let comment3 = store.peekRecord('comment', 3); + let comment4 = store.peekRecord('comment', 4); + let post2 = store.peekRecord('post', 2); + + assert.deepEqual( + comments.toArray(), + [comment1, comment2, comment3], + 'The correct records are in the array' + ); + + assert.deepEqual(comment4.getProperties('id', 'name'), { + id: '4', + name: 'Unrelated comment', + }); + assert.deepEqual(post2.getProperties('id', 'name'), { id: '2', name: 'The Parley Letter' }); + }); }); -test("findMany - a custom serializer is used if present", function(assert) { +test('findMany - a custom serializer is used if present', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - primaryKey: '_ID_', - attrs: { name: '_NAME_' } - })); + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + primaryKey: '_ID_', + attrs: { name: '_NAME_' }, + }) + ); - env.registry.register('serializer:comment', DS.RESTSerializer.extend({ - primaryKey: '_ID_', - attrs: { name: '_NAME_' } - })); + env.registry.register( + 'serializer:comment', + DS.RESTSerializer.extend({ + primaryKey: '_ID_', + attrs: { name: '_NAME_' }, + }) + ); adapter.coalesceFindRequests = true; Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); @@ -1651,44 +1809,52 @@ test("findMany - a custom serializer is used if present", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { data: [ { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + { type: 'comment', id: '3' }, + ], + }, + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse({ - comments: [ - { _ID_: 1, _NAME_: "FIRST" }, - { _ID_: 2, _NAME_: "Rails is unagi" }, - { _ID_: 3, _NAME_: "What is omakase?" }] - }); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ + comments: [ + { _ID_: 1, _NAME_: 'FIRST' }, + { _ID_: 2, _NAME_: 'Rails is unagi' }, + { _ID_: 3, _NAME_: 'What is omakase?' }, + ], + }); - return post.get('comments'); - }).then(comments => { - let comment1 = store.peekRecord('comment', 1); - let comment2 = store.peekRecord('comment', 2); - let comment3 = store.peekRecord('comment', 3); + return post.get('comments'); + }) + .then(comments => { + let comment1 = store.peekRecord('comment', 1); + let comment2 = store.peekRecord('comment', 2); + let comment3 = store.peekRecord('comment', 3); - assert.deepEqual(comment1.getProperties('id', 'name'), { id: "1", name: "FIRST" }); - assert.deepEqual(comment2.getProperties('id', 'name'), { id: "2", name: "Rails is unagi" }); - assert.deepEqual(comment3.getProperties('id', 'name'), { id: "3", name: "What is omakase?" }); + assert.deepEqual(comment1.getProperties('id', 'name'), { id: '1', name: 'FIRST' }); + assert.deepEqual(comment2.getProperties('id', 'name'), { id: '2', name: 'Rails is unagi' }); + assert.deepEqual(comment3.getProperties('id', 'name'), { id: '3', name: 'What is omakase?' }); - assert.deepEqual(comments.toArray(), [comment1, comment2, comment3], "The correct records are in the array"); - }); + assert.deepEqual( + comments.toArray(), + [comment1, comment2, comment3], + 'The correct records are in the array' + ); + }); }); -test("findHasMany - returning an array populates the array", function(assert) { +test('findHasMany - returning an array populates the array', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); @@ -1698,47 +1864,59 @@ test("findHasMany - returning an array populates the array", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { links: { - related: '/posts/1/comments' - } - } - } - } + related: '/posts/1/comments', + }, + }, + }, + }, }); }); - return run(() => store.findRecord('post', '1').then(post => { - ajaxResponse({ - comments: [ - { id: 1, name: "FIRST" }, - { id: 2, name: "Rails is unagi" }, - { id: 3, name: "What is omakase?" } - ] - }); - - return post.get('comments'); - }).then(comments => { - assert.equal(passedUrl, '/posts/1/comments'); - assert.equal(passedVerb, 'GET'); - assert.strictEqual(passedHash, undefined); - - let comment1 = store.peekRecord('comment', 1); - let comment2 = store.peekRecord('comment', 2); - let comment3 = store.peekRecord('comment', 3); + return run(() => + store + .findRecord('post', '1') + .then(post => { + ajaxResponse({ + comments: [ + { id: 1, name: 'FIRST' }, + { id: 2, name: 'Rails is unagi' }, + { id: 3, name: 'What is omakase?' }, + ], + }); - assert.deepEqual(comment1.getProperties('id', 'name'), { id: "1", name: "FIRST" }); - assert.deepEqual(comment2.getProperties('id', 'name'), { id: "2", name: "Rails is unagi" }); - assert.deepEqual(comment3.getProperties('id', 'name'), { id: "3", name: "What is omakase?" }); + return post.get('comments'); + }) + .then(comments => { + assert.equal(passedUrl, '/posts/1/comments'); + assert.equal(passedVerb, 'GET'); + assert.strictEqual(passedHash, undefined); + + let comment1 = store.peekRecord('comment', 1); + let comment2 = store.peekRecord('comment', 2); + let comment3 = store.peekRecord('comment', 3); + + assert.deepEqual(comment1.getProperties('id', 'name'), { id: '1', name: 'FIRST' }); + assert.deepEqual(comment2.getProperties('id', 'name'), { id: '2', name: 'Rails is unagi' }); + assert.deepEqual(comment3.getProperties('id', 'name'), { + id: '3', + name: 'What is omakase?', + }); - assert.deepEqual(comments.toArray(), [comment1, comment2, comment3], "The correct records are in the array"); - })); + assert.deepEqual( + comments.toArray(), + [comment1, comment2, comment3], + 'The correct records are in the array' + ); + }) + ); }); -test("findHasMany - passes buildURL the requestType", function(assert) { +test('findHasMany - passes buildURL the requestType', function(assert) { assert.expect(2); adapter.shouldBackgroundReloadRecord = () => false; adapter.buildURL = function(type, id, snapshot, requestType) { @@ -1754,33 +1932,35 @@ test("findHasMany - passes buildURL the requestType", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { links: { - related: '/posts/1/comments' - } - } - } - } + related: '/posts/1/comments', + }, + }, + }, + }, }); }); - return run(() => store.findRecord('post', '1').then(post => { - ajaxResponse({ - comments: [ - { id: 1, name: "FIRST" }, - { id: 2, name: "Rails is unagi" }, - { id: 3, name: "What is omakase?" } - ] - }); + return run(() => + store.findRecord('post', '1').then(post => { + ajaxResponse({ + comments: [ + { id: 1, name: 'FIRST' }, + { id: 2, name: 'Rails is unagi' }, + { id: 3, name: 'What is omakase?' }, + ], + }); - return post.get('comments'); - })); + return post.get('comments'); + }) + ); }); -test("findMany - returning sideloaded data loads the data (with JSONApi Links)", function(assert) { +test('findMany - returning sideloaded data loads the data (with JSONApi Links)', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); adapter.coalesceFindRequests = true; @@ -1791,53 +1971,66 @@ test("findMany - returning sideloaded data loads the data (with JSONApi Links)", type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { links: { - related: '/posts/1/comments' - } - } - } - } + related: '/posts/1/comments', + }, + }, + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse({ - comments: [ - { id: 1, name: "FIRST" }, - { id: 2, name: "Rails is unagi" }, - { id: 3, name: "What is omakase?" } - ], - posts: [{ id: 2, name: "The Parley Letter" }] - }); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ + comments: [ + { id: 1, name: 'FIRST' }, + { id: 2, name: 'Rails is unagi' }, + { id: 3, name: 'What is omakase?' }, + ], + posts: [{ id: 2, name: 'The Parley Letter' }], + }); - return post.get('comments'); - }).then(comments => { - let comment1 = store.peekRecord('comment', 1); - let comment2 = store.peekRecord('comment', 2); - let comment3 = store.peekRecord('comment', 3); - let post2 = store.peekRecord('post', 2); + return post.get('comments'); + }) + .then(comments => { + let comment1 = store.peekRecord('comment', 1); + let comment2 = store.peekRecord('comment', 2); + let comment3 = store.peekRecord('comment', 3); + let post2 = store.peekRecord('post', 2); - assert.deepEqual(comments.toArray(), [comment1, comment2, comment3], "The correct records are in the array"); + assert.deepEqual( + comments.toArray(), + [comment1, comment2, comment3], + 'The correct records are in the array' + ); - assert.deepEqual(post2.getProperties('id', 'name'), { id: "2", name: "The Parley Letter" }); - }); + assert.deepEqual(post2.getProperties('id', 'name'), { id: '2', name: 'The Parley Letter' }); + }); }); -test("findMany - a custom serializer is used if present", function(assert) { +test('findMany - a custom serializer is used if present', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - primaryKey: '_ID_', - attrs: { name: '_NAME_' } - })); + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + primaryKey: '_ID_', + attrs: { name: '_NAME_' }, + }) + ); - env.registry.register('serializer:comment', DS.RESTSerializer.extend({ - primaryKey: '_ID_', - attrs: { name: '_NAME_' } - })); + env.registry.register( + 'serializer:comment', + DS.RESTSerializer.extend({ + primaryKey: '_ID_', + attrs: { name: '_NAME_' }, + }) + ); Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); @@ -1847,39 +2040,46 @@ test("findMany - a custom serializer is used if present", function(assert) { type: 'post', id: '1', attributes: { - name: "Rails is omakase" + name: 'Rails is omakase', }, relationships: { comments: { links: { - related: '/posts/1/comments' - } - } - } - } + related: '/posts/1/comments', + }, + }, + }, + }, }); }); - return store.findRecord('post', 1).then(post => { - ajaxResponse({ - comments: [ - { _ID_: 1, _NAME_: "FIRST" }, - { _ID_: 2, _NAME_: "Rails is unagi" }, - { _ID_: 3, _NAME_: "What is omakase?" } - ] - }); - return post.get('comments'); - }).then(comments => { - let comment1 = store.peekRecord('comment', 1); - let comment2 = store.peekRecord('comment', 2); - let comment3 = store.peekRecord('comment', 3); + return store + .findRecord('post', 1) + .then(post => { + ajaxResponse({ + comments: [ + { _ID_: 1, _NAME_: 'FIRST' }, + { _ID_: 2, _NAME_: 'Rails is unagi' }, + { _ID_: 3, _NAME_: 'What is omakase?' }, + ], + }); + return post.get('comments'); + }) + .then(comments => { + let comment1 = store.peekRecord('comment', 1); + let comment2 = store.peekRecord('comment', 2); + let comment3 = store.peekRecord('comment', 3); - assert.deepEqual(comment1.getProperties('id', 'name'), { id: "1", name: "FIRST" }); - assert.deepEqual(comment2.getProperties('id', 'name'), { id: "2", name: "Rails is unagi" }); - assert.deepEqual(comment3.getProperties('id', 'name'), { id: "3", name: "What is omakase?" }); + assert.deepEqual(comment1.getProperties('id', 'name'), { id: '1', name: 'FIRST' }); + assert.deepEqual(comment2.getProperties('id', 'name'), { id: '2', name: 'Rails is unagi' }); + assert.deepEqual(comment3.getProperties('id', 'name'), { id: '3', name: 'What is omakase?' }); - assert.deepEqual(comments.toArray(), [comment1, comment2, comment3], "The correct records are in the array"); - }); + assert.deepEqual( + comments.toArray(), + [comment1, comment2, comment3], + 'The correct records are in the array' + ); + }); }); test('findBelongsTo - passes buildURL the requestType', function(assert) { @@ -1898,69 +2098,70 @@ test('findBelongsTo - passes buildURL the requestType', function(assert) { type: 'comment', id: '1', attributes: { - name: "FIRST" + name: 'FIRST', }, relationships: { post: { links: { - related: '/posts/1' - } - } - } - } + related: '/posts/1', + }, + }, + }, + }, }); }); - return run(() => store.findRecord('comment', '1').then(comment => { - ajaxResponse({ post: { id: 1, name: 'Rails is omakase' } }); - return comment.get('post'); - })); + return run(() => + store.findRecord('comment', '1').then(comment => { + ajaxResponse({ post: { id: 1, name: 'Rails is omakase' } }); + return comment.get('post'); + }) + ); }); -testInDebug('coalesceFindRequests assert.warns if the expected records are not returned in the coalesced request', function(assert) { - assert.expect(2); - Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); - Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); +testInDebug( + 'coalesceFindRequests assert.warns if the expected records are not returned in the coalesced request', + function(assert) { + assert.expect(2); + Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); + Post.reopen({ comments: DS.hasMany('comment', { async: true }) }); - adapter.coalesceFindRequests = true; + adapter.coalesceFindRequests = true; - ajaxResponse({ - comments: [ - { id: '1', type: 'comment' } - ] - }); - - let post = run(() => store.push({ - data: { - type: 'post', - id: '2', - relationships: { - comments: { - data: [ - { type: 'comment', id: '1'}, - { type: 'comment', id: '2'}, - { type: 'comment', id: '3'} - ] - } - } - } - })); + ajaxResponse({ + comments: [{ id: '1', type: 'comment' }], + }); + + let post = run(() => + store.push({ + data: { + type: 'post', + id: '2', + relationships: { + comments: { + data: [ + { type: 'comment', id: '1' }, + { type: 'comment', id: '2' }, + { type: 'comment', id: '3' }, + ], + }, + }, + }, + }) + ); - assert.expectWarning( - () => { + assert.expectWarning(() => { return run(() => { - return post.get('comments') - .catch(e => { - assert.equal( - e.message, - `Expected: '' to be present in the adapter provided payload, but it was not found.` - ); - }); + return post.get('comments').catch(e => { + assert.equal( + e.message, + `Expected: '' to be present in the adapter provided payload, but it was not found.` + ); + }); }); - }, - /expected to find records with the following ids in the adapter response but they were missing: \[ "2", "3" \]/ - ); -}); + }, /expected to find records with the following ids in the adapter response but they were missing: \[ "2", "3" \]/); + } +); test('groupRecordsForFindMany groups records based on their url', function(assert) { Comment.reopen({ post: DS.belongsTo('post', { async: false }) }); @@ -1996,11 +2197,11 @@ test('groupRecordsForFindMany groups records based on their url', function(asser data: [ { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + { type: 'comment', id: '3' }, + ], + }, + }, + }, }); post = store.peekRecord('post', 2); }); @@ -2042,11 +2243,11 @@ test('groupRecordsForFindMany groups records correctly when singular URLs are en data: [ { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + { type: 'comment', id: '3' }, + ], + }, + }, + }, }); post = store.peekRecord('post', 2); }); @@ -2055,69 +2256,87 @@ test('groupRecordsForFindMany groups records correctly when singular URLs are en }); test('normalizeKey - to set up _ids and _id', function(assert) { - env.registry.register('serializer:application', DS.RESTSerializer.extend({ - keyForAttribute(attr) { - return underscore(attr); - }, + env.registry.register( + 'serializer:application', + DS.RESTSerializer.extend({ + keyForAttribute(attr) { + return underscore(attr); + }, - keyForBelongsTo(belongsTo) { - }, + keyForBelongsTo(belongsTo) {}, - keyForRelationship(rel, kind) { - if (kind === 'belongsTo') { - let underscored = underscore(rel); - return underscored + '_id'; - } else { - let singular = singularize(rel); - return underscore(singular) + '_ids'; - } - } - })); + keyForRelationship(rel, kind) { + if (kind === 'belongsTo') { + let underscored = underscore(rel); + return underscored + '_id'; + } else { + let singular = singularize(rel); + return underscore(singular) + '_ids'; + } + }, + }) + ); - env.registry.register('model:post', DS.Model.extend({ - name: DS.attr(), - authorName: DS.attr(), - author: DS.belongsTo('user', { async: false }), - comments: DS.hasMany('comment', { async: false }) - })); + env.registry.register( + 'model:post', + DS.Model.extend({ + name: DS.attr(), + authorName: DS.attr(), + author: DS.belongsTo('user', { async: false }), + comments: DS.hasMany('comment', { async: false }), + }) + ); - env.registry.register('model:user', DS.Model.extend({ - createdAt: DS.attr(), - name: DS.attr() - })); + env.registry.register( + 'model:user', + DS.Model.extend({ + createdAt: DS.attr(), + name: DS.attr(), + }) + ); - env.registry.register('model:comment', DS.Model.extend({ - body: DS.attr() - })); + env.registry.register( + 'model:comment', + DS.Model.extend({ + body: DS.attr(), + }) + ); ajaxResponse({ - posts: [{ - id: "1", - name: "Rails is omakase", - author_name: "@d2h", - author_id: "1", - comment_ids: ["1", "2"] - }], - - users: [{ - id: "1", - name: "D2H" - }], - - comments: [{ - id: "1", - body: "Rails is unagi" - }, { - id: "2", - body: "What is omakase?" - }] + posts: [ + { + id: '1', + name: 'Rails is omakase', + author_name: '@d2h', + author_id: '1', + comment_ids: ['1', '2'], + }, + ], + + users: [ + { + id: '1', + name: 'D2H', + }, + ], + + comments: [ + { + id: '1', + body: 'Rails is unagi', + }, + { + id: '2', + body: 'What is omakase?', + }, + ], }); return run(() => { return store.findRecord('post', 1).then(post => { - assert.equal(post.get('authorName'), "@d2h"); - assert.equal(post.get('author.name'), "D2H"); - assert.deepEqual(post.get('comments').mapBy('body'), ["Rails is unagi", "What is omakase?"]); + assert.equal(post.get('authorName'), '@d2h'); + assert.equal(post.get('author.name'), 'D2H'); + assert.deepEqual(post.get('comments').mapBy('body'), ['Rails is unagi', 'What is omakase?']); }); }); }); @@ -2129,7 +2348,7 @@ test('groupRecordsForFindMany splits up calls for large ids', function(assert) { assert.expect(2); function repeatChar(character, n) { - return new Array(n+1).join(character); + return new Array(n + 1).join(character); } let a2000 = repeatChar('a', 2000); @@ -2143,13 +2362,10 @@ test('groupRecordsForFindMany splits up calls for large ids', function(assert) { id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: a2000 }, - { type: 'comment', id: b2000 } - ] - } - } - } + data: [{ type: 'comment', id: a2000 }, { type: 'comment', id: b2000 }], + }, + }, + }, }); post = store.peekRecord('post', 1); }); @@ -2158,14 +2374,17 @@ test('groupRecordsForFindMany splits up calls for large ids', function(assert) { adapter.findRecord = function(store, type, id, snapshot) { if (id === a2000 || id === b2000) { - assert.ok(true, "Found " + id); + assert.ok(true, 'Found ' + id); } return resolve({ comments: { id: id } }); }; adapter.findMany = function(store, type, ids, snapshots) { - assert.ok(false, "findMany should not be called - we expect 2 calls to find for a2000 and b2000"); + assert.ok( + false, + 'findMany should not be called - we expect 2 calls to find for a2000 and b2000' + ); return reject(); }; @@ -2179,7 +2398,7 @@ test('groupRecordsForFindMany groups calls for small ids', function(assert) { assert.expect(1); function repeatChar(character, n) { - return new Array(n+1).join(character); + return new Array(n + 1).join(character); } let a100 = repeatChar('a', 100); @@ -2193,13 +2412,10 @@ test('groupRecordsForFindMany groups calls for small ids', function(assert) { id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: a100 }, - { type: 'comment', id: b100 } - ] - } - } - } + data: [{ type: 'comment', id: a100 }, { type: 'comment', id: b100 }], + }, + }, + }, }); post = store.peekRecord('post', 1); }); @@ -2207,7 +2423,10 @@ test('groupRecordsForFindMany groups calls for small ids', function(assert) { adapter.coalesceFindRequests = true; adapter.findRecord = function(store, type, id, snapshot) { - assert.ok(false, "findRecord should not be called - we expect 1 call to findMany for a100 and b100"); + assert.ok( + false, + 'findRecord should not be called - we expect 1 call to findMany for a100 and b100' + ); return reject(); }; @@ -2219,19 +2438,18 @@ test('groupRecordsForFindMany groups calls for small ids', function(assert) { run(() => post.get('comments')); }); - -test("calls adapter.handleResponse with the jqXHR and json", function(assert) { +test('calls adapter.handleResponse with the jqXHR and json', function(assert) { assert.expect(2); let data = { post: { - id: "1", - name: "Docker is amazing" - } + id: '1', + name: 'Docker is amazing', + }, }; server.get('/posts/1', function() { - return [200, { "Content-Type": "application/json" }, JSON.stringify(data)]; + return [200, { 'Content-Type': 'application/json' }, JSON.stringify(data)]; }); adapter.handleResponse = function(status, headers, json) { @@ -2249,8 +2467,8 @@ test('calls handleResponse with jqXHR, jqXHR.responseText, and requestData', fun let responseText = 'Nope lol'; let expectedRequestData = { - method: "GET", - url: "/posts/1" + method: 'GET', + url: '/posts/1', }; server.get('/posts/1', function() { @@ -2269,15 +2487,15 @@ test('calls handleResponse with jqXHR, jqXHR.responseText, and requestData', fun }); }); -test("rejects promise if DS.AdapterError is returned from adapter.handleResponse", function(assert) { +test('rejects promise if DS.AdapterError is returned from adapter.handleResponse', function(assert) { assert.expect(3); let data = { - something: 'is invalid' + something: 'is invalid', }; server.get('/posts/1', function() { - return [200, { "Content-Type": "application/json" }, JSON.stringify(data)]; + return [200, { 'Content-Type': 'application/json' }, JSON.stringify(data)]; }); adapter.handleResponse = function(status, headers, json) { @@ -2288,16 +2506,19 @@ test("rejects promise if DS.AdapterError is returned from adapter.handleResponse return run(() => { return store.findRecord('post', '1').catch(reason => { assert.ok(true, 'promise should be rejected'); - assert.ok(reason instanceof DS.AdapterError, 'reason should be an instance of DS.AdapterError'); + assert.ok( + reason instanceof DS.AdapterError, + 'reason should be an instance of DS.AdapterError' + ); }); }); }); -test("gracefully handles exceptions in handleResponse", function(assert) { +test('gracefully handles exceptions in handleResponse', function(assert) { assert.expect(1); server.post('/posts/1', function() { - return [200, { "Content-Type": "application/json" }, "ok"]; + return [200, { 'Content-Type': 'application/json' }, 'ok']; }); adapter.handleResponse = function(status, headers, json) { @@ -2311,11 +2532,11 @@ test("gracefully handles exceptions in handleResponse", function(assert) { }); }); -test("gracefully handles exceptions in handleResponse where the ajax request errors", function(assert) { +test('gracefully handles exceptions in handleResponse where the ajax request errors', function(assert) { assert.expect(1); server.get('/posts/1', function() { - return [500, { "Content-Type": "application/json" }, "Internal Server Error"]; + return [500, { 'Content-Type': 'application/json' }, 'Internal Server Error']; }); adapter.handleResponse = function(status, headers, json) { @@ -2333,7 +2554,12 @@ test('treats status code 0 as an abort', function(assert) { assert.expect(1); adapter._ajaxRequest = function(hash) { - hash.error({ status: 0, getAllResponseHeaders() { return ''; } }); + hash.error({ + status: 0, + getAllResponseHeaders() { + return ''; + }, + }); }; adapter.handleResponse = function(status, headers, payload) { assert.ok(false); @@ -2351,7 +2577,9 @@ test('on error appends errorThrown for sanity', function(assert) { let jqXHR = { responseText: 'Nope lol', - getAllResponseHeaders() { return ''; } + getAllResponseHeaders() { + return ''; + }, }; let errorThrown = new Error('nope!'); @@ -2372,7 +2600,7 @@ test('on error appends errorThrown for sanity', function(assert) { }); }); -test("rejects promise with a specialized subclass of DS.AdapterError if ajax responds with http error codes", function(assert) { +test('rejects promise with a specialized subclass of DS.AdapterError if ajax responds with http error codes', function(assert) { assert.expect(10); ajaxError('error', 401); @@ -2380,7 +2608,10 @@ test("rejects promise with a specialized subclass of DS.AdapterError if ajax res run(() => { store.find('post', '1').catch(reason => { assert.ok(true, 'promise should be rejected'); - assert.ok(reason instanceof DS.UnauthorizedError, 'reason should be an instance of DS.UnauthorizedError'); + assert.ok( + reason instanceof DS.UnauthorizedError, + 'reason should be an instance of DS.UnauthorizedError' + ); }); }); @@ -2389,7 +2620,10 @@ test("rejects promise with a specialized subclass of DS.AdapterError if ajax res run(() => { store.find('post', '1').catch(reason => { assert.ok(true, 'promise should be rejected'); - assert.ok(reason instanceof DS.ForbiddenError, 'reason should be an instance of DS.ForbiddenError'); + assert.ok( + reason instanceof DS.ForbiddenError, + 'reason should be an instance of DS.ForbiddenError' + ); }); }); @@ -2398,7 +2632,10 @@ test("rejects promise with a specialized subclass of DS.AdapterError if ajax res run(() => { store.find('post', '1').catch(reason => { assert.ok(true, 'promise should be rejected'); - assert.ok(reason instanceof DS.NotFoundError, 'reason should be an instance of DS.NotFoundError'); + assert.ok( + reason instanceof DS.NotFoundError, + 'reason should be an instance of DS.NotFoundError' + ); }); }); @@ -2407,7 +2644,10 @@ test("rejects promise with a specialized subclass of DS.AdapterError if ajax res run(() => { store.find('post', '1').catch(reason => { assert.ok(true, 'promise should be rejected'); - assert.ok(reason instanceof DS.ConflictError, 'reason should be an instance of DS.ConflictError'); + assert.ok( + reason instanceof DS.ConflictError, + 'reason should be an instance of DS.ConflictError' + ); }); }); @@ -2418,7 +2658,6 @@ test("rejects promise with a specialized subclass of DS.AdapterError if ajax res assert.ok(true, 'promise should be rejected'); assert.ok(reason instanceof DS.ServerError, 'reason should be an instance of DS.ServerError'); }); - }); }); @@ -2427,7 +2666,9 @@ test('on error wraps the error string in an DS.AdapterError object', function(as let jqXHR = { responseText: '', - getAllResponseHeaders() { return ''; } + getAllResponseHeaders() { + return ''; + }, }; let errorThrown = 'nope!'; @@ -2444,78 +2685,91 @@ test('on error wraps the error string in an DS.AdapterError object', function(as }); }); -test('error handling includes a detailed message from the server', (assert) => { +test('error handling includes a detailed message from the server', assert => { assert.expect(2); - ajaxError('An error message, perhaps generated from a backend server!', 500, 'Content-Type: text/plain'); + ajaxError( + 'An error message, perhaps generated from a backend server!', + 500, + 'Content-Type: text/plain' + ); run(() => { store.findRecord('post', '1').catch(err => { - assert.equal(err.message, "Ember Data Request GET /posts/1 returned a 500\nPayload (text/plain)\nAn error message, perhaps generated from a backend server!"); + assert.equal( + err.message, + 'Ember Data Request GET /posts/1 returned a 500\nPayload (text/plain)\nAn error message, perhaps generated from a backend server!' + ); assert.ok(err, 'promise rejected'); }); }); }); -test('error handling with a very long HTML-formatted payload truncates the friendly message', (assert) => { +test('error handling with a very long HTML-formatted payload truncates the friendly message', assert => { assert.expect(2); - ajaxError(new Array(100).join(""), 500, 'Content-Type: text/html'); + ajaxError(new Array(100).join(''), 500, 'Content-Type: text/html'); run(() => { store.findRecord('post', '1').catch(err => { - assert.equal(err.message, "Ember Data Request GET /posts/1 returned a 500\nPayload (text/html)\n[Omitted Lengthy HTML]"); + assert.equal( + err.message, + 'Ember Data Request GET /posts/1 returned a 500\nPayload (text/html)\n[Omitted Lengthy HTML]' + ); assert.ok(err, 'promise rejected'); }); }); }); -test('findAll resolves with a collection of DS.Models, not DS.InternalModels', (assert) => { +test('findAll resolves with a collection of DS.Models, not DS.InternalModels', assert => { assert.expect(4); ajaxResponse({ posts: [ { id: 1, - name: 'dhh lol' + name: 'dhh lol', }, { id: 2, - name: 'james mickens is rad' + name: 'james mickens is rad', }, { id: 3, - name: 'in the name of love' - } - ] + name: 'in the name of love', + }, + ], }); return run(() => { return store.findAll('post').then(posts => { assert.equal(get(posts, 'length'), 3); - posts.forEach((post) => assert.ok(post instanceof DS.Model)); + posts.forEach(post => assert.ok(post instanceof DS.Model)); }); }); }); -test("createRecord - sideloaded records are pushed to the store", function(assert) { +test('createRecord - sideloaded records are pushed to the store', function(assert) { Post.reopen({ - comments: DS.hasMany('comment') + comments: DS.hasMany('comment'), }); ajaxResponse({ post: { id: 1, name: 'The Parley Letter', - comments: [2, 3] + comments: [2, 3], }, - comments: [{ - id: 2, - name: 'First comment' - }, { - id: 3, - name: 'Second comment' - }] + comments: [ + { + id: 2, + name: 'First comment', + }, + { + id: 3, + name: 'Second comment', + }, + ], }); let post; @@ -2526,22 +2780,36 @@ test("createRecord - sideloaded records are pushed to the store", function(asser let comments = store.peekAll('comment'); assert.equal(get(comments, 'length'), 2, 'comments.length is correct'); - assert.equal(get(comments, 'firstObject.name'), 'First comment', 'comments.firstObject.name is correct'); - assert.equal(get(comments, 'lastObject.name'), 'Second comment', 'comments.lastObject.name is correct'); + assert.equal( + get(comments, 'firstObject.name'), + 'First comment', + 'comments.firstObject.name is correct' + ); + assert.equal( + get(comments, 'lastObject.name'), + 'Second comment', + 'comments.lastObject.name is correct' + ); }); }); }); -testInDebug("warns when an empty response is returned, though a valid stringified JSON is expected", function(assert) { - server.post('/posts', function() { - return [201, { "Content-Type": "application/json" }, ""]; - }); +testInDebug( + 'warns when an empty response is returned, though a valid stringified JSON is expected', + function(assert) { + server.post('/posts', function() { + return [201, { 'Content-Type': 'application/json' }, '']; + }); - return run(() => { - return store.createRecord('post').save(); - }).then(() => { - assert.equal(true, false, 'should not have fulfilled'); - }, reason => { - assert.ok(/JSON/.test(reason.message)); - }); -}); + return run(() => { + return store.createRecord('post').save(); + }).then( + () => { + assert.equal(true, false, 'should not have fulfilled'); + }, + reason => { + assert.ok(/JSON/.test(reason.message)); + } + ); + } +); diff --git a/tests/integration/adapter/serialize-test.js b/tests/integration/adapter/serialize-test.js index f0b1686b9b3..f5ced5ec0b6 100644 --- a/tests/integration/adapter/serialize-test.js +++ b/tests/integration/adapter/serialize-test.js @@ -7,10 +7,10 @@ import DS from 'ember-data'; let env, store, adapter, serializer; -module("integration/adapter/serialize - DS.Adapter integration test", { +module('integration/adapter/serialize - DS.Adapter integration test', { beforeEach() { const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); env = setupStore({ person: Person }); @@ -21,10 +21,10 @@ module("integration/adapter/serialize - DS.Adapter integration test", { afterEach() { run(env.container, 'destroy'); - } + }, }); -test("serialize() is delegated to the serializer", function(assert) { +test('serialize() is delegated to the serializer', function(assert) { assert.expect(1); serializer.serialize = function(snapshot, options) { diff --git a/tests/integration/adapter/store-adapter-test.js b/tests/integration/adapter/store-adapter-test.js index 2adefff5a95..655f5df7d45 100644 --- a/tests/integration/adapter/store-adapter-test.js +++ b/tests/integration/adapter/store-adapter-test.js @@ -1,9 +1,4 @@ -import { - resolve, - hash, - Promise as EmberPromise, - reject -} from 'rsvp'; +import { resolve, hash, Promise as EmberPromise, reject } from 'rsvp'; import { set, get } from '@ember/object'; import { run } from '@ember/runloop'; import setupStore from 'dummy/tests/helpers/store'; @@ -24,24 +19,24 @@ function moveRecordOutOfInFlight(record) { }); } -module("integration/adapter/store-adapter - DS.Store and DS.Adapter integration test", { +module('integration/adapter/store-adapter - DS.Store and DS.Adapter integration test', { beforeEach() { Person = DS.Model.extend({ updatedAt: DS.attr('string'), name: DS.attr('string'), firstName: DS.attr('string'), - lastName: DS.attr('string') + lastName: DS.attr('string'), }); Dog = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); env = setupStore({ serializer: DS.JSONAPISerializer, adapter: DS.JSONAPIAdapter, person: Person, - dog: Dog + dog: Dog, }); store = env.store; adapter = env.adapter; @@ -49,81 +44,87 @@ module("integration/adapter/store-adapter - DS.Store and DS.Adapter integration afterEach() { run(env.container, 'destroy'); - } + }, }); -test("Records loaded multiple times and retrieved in recordArray are ready to send state events", function(assert) { +test('Records loaded multiple times and retrieved in recordArray are ready to send state events', function(assert) { adapter.query = function(store, type, query, recordArray) { return resolve({ data: [ { id: 1, - type: "person", + type: 'person', attributes: { - name: "Mickael Ramírez" - } - }, { + name: 'Mickael Ramírez', + }, + }, + { id: 2, - type: "person", + type: 'person', attributes: { - name: "Johny Fontana" - } - } - ] + name: 'Johny Fontana', + }, + }, + ], }); }; - return run(() => store.query('person', { q: 'bla' }).then(people => { - let people2 = store.query('person', { q: 'bla2' }); - - return hash({ people: people, people2: people2 }); - }).then(results => { - assert.equal(results.people2.get('length'), 2, 'return the elements'); - assert.ok(results.people2.get('isLoaded'), 'array is loaded'); - - var person = results.people.objectAt(0); - assert.ok(person.get('isLoaded'), 'record is loaded'); - - // delete record will not throw exception - person.deleteRecord(); - })); + return run(() => + store + .query('person', { q: 'bla' }) + .then(people => { + let people2 = store.query('person', { q: 'bla2' }); + + return hash({ people: people, people2: people2 }); + }) + .then(results => { + assert.equal(results.people2.get('length'), 2, 'return the elements'); + assert.ok(results.people2.get('isLoaded'), 'array is loaded'); + + var person = results.people.objectAt(0); + assert.ok(person.get('isLoaded'), 'record is loaded'); + + // delete record will not throw exception + person.deleteRecord(); + }) + ); }); -test("by default, createRecords calls createRecord once per record", function(assert) { +test('by default, createRecords calls createRecord once per record', function(assert) { let count = 1; adapter.shouldBackgroundReloadRecord = () => false; adapter.createRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); + assert.equal(type, Person, 'the type is correct'); if (count === 1) { - assert.equal(snapshot.attr('name'), "Tom Dale"); + assert.equal(snapshot.attr('name'), 'Tom Dale'); } else if (count === 2) { - assert.equal(snapshot.attr('name'), "Yehuda Katz"); + assert.equal(snapshot.attr('name'), 'Yehuda Katz'); } else { - assert.ok(false, "should not have invoked more than 2 times"); + assert.ok(false, 'should not have invoked more than 2 times'); } let hash = snapshot.attributes(); let recordId = count; - hash['updated-at'] = "now"; + hash['updated-at'] = 'now'; count++; return resolve({ data: { id: recordId, - type: "person", - attributes: hash - } + type: 'person', + attributes: hash, + }, }); }; - let tom = store.createRecord('person', { name: "Tom Dale" }); - let yehuda = store.createRecord('person', { name: "Yehuda Katz" }); + let tom = store.createRecord('person', { name: 'Tom Dale' }); + let yehuda = store.createRecord('person', { name: 'Yehuda Katz' }); let promise = run(() => { return hash({ tom: tom.save(), - yehuda: yehuda.save() + yehuda: yehuda.save(), }); }); @@ -131,162 +132,184 @@ test("by default, createRecords calls createRecord once per record", function(as tom = records.tom; yehuda = records.yehuda; - assert.asyncEqual(tom, store.findRecord('person', 1), "Once an ID is in, findRecord returns the same object"); - assert.asyncEqual(yehuda, store.findRecord('person', 2), "Once an ID is in, findRecord returns the same object"); - assert.equal(get(tom, 'updatedAt'), "now", "The new information is received"); - assert.equal(get(yehuda, 'updatedAt'), "now", "The new information is received"); + assert.asyncEqual( + tom, + store.findRecord('person', 1), + 'Once an ID is in, findRecord returns the same object' + ); + assert.asyncEqual( + yehuda, + store.findRecord('person', 2), + 'Once an ID is in, findRecord returns the same object' + ); + assert.equal(get(tom, 'updatedAt'), 'now', 'The new information is received'); + assert.equal(get(yehuda, 'updatedAt'), 'now', 'The new information is received'); }); }); -test("by default, updateRecords calls updateRecord once per record", function(assert) { +test('by default, updateRecords calls updateRecord once per record', function(assert) { let count = 0; adapter.shouldBackgroundReloadRecord = () => false; adapter.updateRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); + assert.equal(type, Person, 'the type is correct'); if (count === 0) { - assert.equal(snapshot.attr('name'), "Tom Dale"); + assert.equal(snapshot.attr('name'), 'Tom Dale'); } else if (count === 1) { - assert.equal(snapshot.attr('name'), "Yehuda Katz"); + assert.equal(snapshot.attr('name'), 'Yehuda Katz'); } else { - assert.ok(false, "should not get here"); + assert.ok(false, 'should not get here'); } count++; - assert.equal(snapshot.record.get('isSaving'), true, "record is saving"); + assert.equal(snapshot.record.get('isSaving'), true, 'record is saving'); return resolve(); }; run(() => { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Braaaahm Dale' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Brohuda Katz' - } - }] + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale', + }, + }, + { + type: 'person', + id: '2', + attributes: { + name: 'Brohuda Katz', + }, + }, + ], }); }); let promise = run(() => { return hash({ tom: store.findRecord('person', 1), - yehuda: store.findRecord('person', 2) + yehuda: store.findRecord('person', 2), }); }); - return promise.then(records => { - let tom = records.tom; - let yehuda = records.yehuda; + return promise + .then(records => { + let tom = records.tom; + let yehuda = records.yehuda; - set(tom, "name", "Tom Dale"); - set(yehuda, "name", "Yehuda Katz"); + set(tom, 'name', 'Tom Dale'); + set(yehuda, 'name', 'Yehuda Katz'); - return hash({ - tom: tom.save(), - yehuda: yehuda.save() - }); - }).then(records => { - let tom = records.tom; - let yehuda = records.yehuda; + return hash({ + tom: tom.save(), + yehuda: yehuda.save(), + }); + }) + .then(records => { + let tom = records.tom; + let yehuda = records.yehuda; - assert.equal(tom.get('isSaving'), false, "record is no longer saving"); - assert.equal(tom.get('isLoaded'), true, "record is loaded"); + assert.equal(tom.get('isSaving'), false, 'record is no longer saving'); + assert.equal(tom.get('isLoaded'), true, 'record is loaded'); - assert.equal(yehuda.get('isSaving'), false, "record is no longer saving"); - assert.equal(yehuda.get('isLoaded'), true, "record is loaded"); - }); + assert.equal(yehuda.get('isSaving'), false, 'record is no longer saving'); + assert.equal(yehuda.get('isLoaded'), true, 'record is loaded'); + }); }); -test("calling store.didSaveRecord can provide an optional hash", function(assert) { +test('calling store.didSaveRecord can provide an optional hash', function(assert) { let count = 0; adapter.shouldBackgroundReloadRecord = () => false; adapter.updateRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); + assert.equal(type, Person, 'the type is correct'); count++; if (count === 1) { - assert.equal(snapshot.attr('name'), "Tom Dale"); - return resolve({ data: { id: 1, type: "person", attributes: { name: "Tom Dale", "updated-at": "now" } } }); + assert.equal(snapshot.attr('name'), 'Tom Dale'); + return resolve({ + data: { id: 1, type: 'person', attributes: { name: 'Tom Dale', 'updated-at': 'now' } }, + }); } else if (count === 2) { - assert.equal(snapshot.attr('name'), "Yehuda Katz"); - return resolve({ data: { id: 2, type: "person", attributes: { name: "Yehuda Katz", "updated-at": "now!" } } }); + assert.equal(snapshot.attr('name'), 'Yehuda Katz'); + return resolve({ + data: { id: 2, type: 'person', attributes: { name: 'Yehuda Katz', 'updated-at': 'now!' } }, + }); } else { - assert.ok(false, "should not get here"); + assert.ok(false, 'should not get here'); } }; run(() => { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Braaaahm Dale' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Brohuda Katz' - } - }] + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Braaaahm Dale', + }, + }, + { + type: 'person', + id: '2', + attributes: { + name: 'Brohuda Katz', + }, + }, + ], }); }); let promise = run(() => { return hash({ tom: store.findRecord('person', 1), - yehuda: store.findRecord('person', 2) + yehuda: store.findRecord('person', 2), }); }); - return promise.then(records => { - let tom = records.tom; - let yehuda = records.yehuda; + return promise + .then(records => { + let tom = records.tom; + let yehuda = records.yehuda; - set(tom, "name", "Tom Dale"); - set(yehuda, "name", "Yehuda Katz"); + set(tom, 'name', 'Tom Dale'); + set(yehuda, 'name', 'Yehuda Katz'); - return hash({ - tom: tom.save(), - yehuda: yehuda.save() - }); - }).then(records => { - let tom = records.tom; - let yehuda = records.yehuda; + return hash({ + tom: tom.save(), + yehuda: yehuda.save(), + }); + }) + .then(records => { + let tom = records.tom; + let yehuda = records.yehuda; - assert.equal(get(tom, 'hasDirtyAttributes'), false, "the record should not be dirty"); - assert.equal(get(tom, 'updatedAt'), "now", "the hash was updated"); + assert.equal(get(tom, 'hasDirtyAttributes'), false, 'the record should not be dirty'); + assert.equal(get(tom, 'updatedAt'), 'now', 'the hash was updated'); - assert.equal(get(yehuda, 'hasDirtyAttributes'), false, "the record should not be dirty"); - assert.equal(get(yehuda, 'updatedAt'), "now!", "the hash was updated"); - }); + assert.equal(get(yehuda, 'hasDirtyAttributes'), false, 'the record should not be dirty'); + assert.equal(get(yehuda, 'updatedAt'), 'now!', 'the hash was updated'); + }); }); -test("by default, deleteRecord calls deleteRecord once per record", function(assert) { +test('by default, deleteRecord calls deleteRecord once per record', function(assert) { assert.expect(4); let count = 0; adapter.shouldBackgroundReloadRecord = () => false; adapter.deleteRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); + assert.equal(type, Person, 'the type is correct'); if (count === 0) { - assert.equal(snapshot.attr('name'), "Tom Dale"); + assert.equal(snapshot.attr('name'), 'Tom Dale'); } else if (count === 1) { - assert.equal(snapshot.attr('name'), "Yehuda Katz"); + assert.equal(snapshot.attr('name'), 'Yehuda Katz'); } else { - assert.ok(false, "should not get here"); + assert.ok(false, 'should not get here'); } count++; @@ -296,26 +319,29 @@ test("by default, deleteRecord calls deleteRecord once per record", function(ass run(() => { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Yehuda Katz' - } - }] + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + }, + { + type: 'person', + id: '2', + attributes: { + name: 'Yehuda Katz', + }, + }, + ], }); }); let promise = run(() => { return hash({ tom: store.findRecord('person', 1), - yehuda: store.findRecord('person', 2) + yehuda: store.findRecord('person', 2), }); }); @@ -326,28 +352,25 @@ test("by default, deleteRecord calls deleteRecord once per record", function(ass tom.deleteRecord(); yehuda.deleteRecord(); - return EmberPromise.all([ - tom.save(), - yehuda.save() - ]); + return EmberPromise.all([tom.save(), yehuda.save()]); }); }); -test("by default, destroyRecord calls deleteRecord once per record without requiring .save", function(assert) { +test('by default, destroyRecord calls deleteRecord once per record without requiring .save', function(assert) { assert.expect(4); let count = 0; adapter.shouldBackgroundReloadRecord = () => false; adapter.deleteRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); + assert.equal(type, Person, 'the type is correct'); if (count === 0) { - assert.equal(snapshot.attr('name'), "Tom Dale"); + assert.equal(snapshot.attr('name'), 'Tom Dale'); } else if (count === 1) { - assert.equal(snapshot.attr('name'), "Yehuda Katz"); + assert.equal(snapshot.attr('name'), 'Yehuda Katz'); } else { - assert.ok(false, "should not get here"); + assert.ok(false, 'should not get here'); } count++; @@ -357,26 +380,29 @@ test("by default, destroyRecord calls deleteRecord once per record without requi run(() => { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Yehuda Katz' - } - }] + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + }, + { + type: 'person', + id: '2', + attributes: { + name: 'Yehuda Katz', + }, + }, + ], }); }); let promise = run(() => { return hash({ tom: store.findRecord('person', 1), - yehuda: store.findRecord('person', 2) + yehuda: store.findRecord('person', 2), }); }); @@ -384,28 +410,25 @@ test("by default, destroyRecord calls deleteRecord once per record without requi let tom = records.tom; let yehuda = records.yehuda; - return EmberPromise.all([ - tom.destroyRecord(), - yehuda.destroyRecord() - ]); + return EmberPromise.all([tom.destroyRecord(), yehuda.destroyRecord()]); }); }); -test("if an existing model is edited then deleted, deleteRecord is called on the adapter", function(assert) { +test('if an existing model is edited then deleted, deleteRecord is called on the adapter', function(assert) { assert.expect(5); let count = 0; adapter.shouldBackgroundReloadRecord = () => false; adapter.deleteRecord = function(store, type, snapshot) { count++; - assert.equal(snapshot.id, 'deleted-record', "should pass correct record to deleteRecord"); - assert.equal(count, 1, "should only call deleteRecord method of adapter once"); + assert.equal(snapshot.id, 'deleted-record', 'should pass correct record to deleteRecord'); + assert.equal(count, 1, 'should only call deleteRecord method of adapter once'); return resolve(); }; adapter.updateRecord = function() { - assert.ok(false, "should not have called updateRecord method of adapter"); + assert.ok(false, 'should not have called updateRecord method of adapter'); }; // Load data for a record into the store. @@ -415,27 +438,36 @@ test("if an existing model is edited then deleted, deleteRecord is called on the type: 'person', id: 'deleted-record', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); }); // Retrieve that loaded record and edit it so it becomes dirty - return run(() => store.findRecord('person', 'deleted-record').then(tom => { - tom.set('name', "Tom Mothereffin' Dale"); - - assert.equal(get(tom, 'hasDirtyAttributes'), true, "precond - record should be dirty after editing"); - - tom.deleteRecord(); - return tom.save(); - }).then(tom => { - assert.equal(get(tom, 'hasDirtyAttributes'), false, "record should not be dirty"); - assert.equal(get(tom, 'isDeleted'), true, "record should be considered deleted"); - })); + return run(() => + store + .findRecord('person', 'deleted-record') + .then(tom => { + tom.set('name', "Tom Mothereffin' Dale"); + + assert.equal( + get(tom, 'hasDirtyAttributes'), + true, + 'precond - record should be dirty after editing' + ); + + tom.deleteRecord(); + return tom.save(); + }) + .then(tom => { + assert.equal(get(tom, 'hasDirtyAttributes'), false, 'record should not be dirty'); + assert.equal(get(tom, 'isDeleted'), true, 'record should be considered deleted'); + }) + ); }); -test("if a deleted record errors, it enters the error state", function(assert) { +test('if a deleted record errors, it enters the error state', function(assert) { let count = 0; let error = new DS.AdapterError(); @@ -454,179 +486,215 @@ test("if a deleted record errors, it enters the error state", function(assert) { type: 'person', id: 'deleted-record', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); }); return run(() => { let tom; - store.findRecord('person', 'deleted-record').then(person => { - tom = person; - person.deleteRecord(); - return person.save(); - }).catch(() => { - assert.equal(tom.get('isError'), true, "Tom is now errored"); - assert.equal(tom.get('adapterError'), error, "error object is exposed"); - - // this time it succeeds - return tom.save(); - }).then(() => { - assert.equal(tom.get('isError'), false, "Tom is not errored anymore"); - assert.equal(tom.get('adapterError'), null, "error object is discarded"); - }); + store + .findRecord('person', 'deleted-record') + .then(person => { + tom = person; + person.deleteRecord(); + return person.save(); + }) + .catch(() => { + assert.equal(tom.get('isError'), true, 'Tom is now errored'); + assert.equal(tom.get('adapterError'), error, 'error object is exposed'); + + // this time it succeeds + return tom.save(); + }) + .then(() => { + assert.equal(tom.get('isError'), false, 'Tom is not errored anymore'); + assert.equal(tom.get('adapterError'), null, 'error object is discarded'); + }); }); }); -test("if a created record is marked as invalid by the server, it enters an error state", function(assert) { +test('if a created record is marked as invalid by the server, it enters an error state', function(assert) { adapter.createRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); + assert.equal(type, Person, 'the type is correct'); if (snapshot.attr('name').indexOf('Bro') === -1) { - return reject(new DS.InvalidError([ - { - title: 'Invalid Attribute', - detail: 'common... name requires a "bro"', - source: { - pointer: '/data/attributes/name' - } - } - ])); + return reject( + new DS.InvalidError([ + { + title: 'Invalid Attribute', + detail: 'common... name requires a "bro"', + source: { + pointer: '/data/attributes/name', + }, + }, + ]) + ); } else { return resolve(); } }; - let yehuda = store.createRecord('person', { id: 1, name: "Yehuda Katz" }); + let yehuda = store.createRecord('person', { id: 1, name: 'Yehuda Katz' }); // Wrap this in an Ember.run so that all chained async behavior is set up // before flushing any scheduled behavior. return run(function() { - return yehuda.save().catch(error => { - assert.equal(get(yehuda, 'isValid'), false, "the record is invalid"); - assert.ok(get(yehuda, 'errors.name'), "The errors.name property exists"); + return yehuda + .save() + .catch(error => { + assert.equal(get(yehuda, 'isValid'), false, 'the record is invalid'); + assert.ok(get(yehuda, 'errors.name'), 'The errors.name property exists'); - set(yehuda, 'updatedAt', true); - assert.equal(get(yehuda, 'isValid'), false, "the record is still invalid"); + set(yehuda, 'updatedAt', true); + assert.equal(get(yehuda, 'isValid'), false, 'the record is still invalid'); - set(yehuda, 'name', "Brohuda Brokatz"); + set(yehuda, 'name', 'Brohuda Brokatz'); - assert.equal(get(yehuda, 'isValid'), true, "the record is no longer invalid after changing"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record has outstanding changes"); + assert.equal( + get(yehuda, 'isValid'), + true, + 'the record is no longer invalid after changing' + ); + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record has outstanding changes'); - assert.equal(get(yehuda, 'isNew'), true, "precond - record is still new"); + assert.equal(get(yehuda, 'isNew'), true, 'precond - record is still new'); - return yehuda.save(); - }).then(person => { - assert.strictEqual(person, yehuda, "The promise resolves with the saved record"); + return yehuda.save(); + }) + .then(person => { + assert.strictEqual(person, yehuda, 'The promise resolves with the saved record'); - assert.equal(get(yehuda, 'isValid'), true, "record remains valid after committing"); - assert.equal(get(yehuda, 'isNew'), false, "record is no longer new"); - }); + assert.equal(get(yehuda, 'isValid'), true, 'record remains valid after committing'); + assert.equal(get(yehuda, 'isNew'), false, 'record is no longer new'); + }); }); }); -test("allows errors on arbitrary properties on create", function(assert) { +test('allows errors on arbitrary properties on create', function(assert) { adapter.createRecord = function(store, type, snapshot) { if (snapshot.attr('name').indexOf('Bro') === -1) { - return reject(new DS.InvalidError([ - { - title: "Invalid Attribute", - detail: "is a generally unsavoury character", - source: { - pointer: "/data/attributes/base" - } - } - ])); + return reject( + new DS.InvalidError([ + { + title: 'Invalid Attribute', + detail: 'is a generally unsavoury character', + source: { + pointer: '/data/attributes/base', + }, + }, + ]) + ); } else { return resolve(); } }; - let yehuda = store.createRecord('person', { id: 1, name: "Yehuda Katz" }); + let yehuda = store.createRecord('person', { id: 1, name: 'Yehuda Katz' }); // Wrap this in an Ember.run so that all chained async behavior is set up // before flushing any scheduled behavior. return run(() => { - return yehuda.save().catch(error => { - assert.equal(get(yehuda, 'isValid'), false, "the record is invalid"); - assert.ok(get(yehuda, 'errors.base'), "The errors.base property exists"); - assert.deepEqual(get(yehuda, 'errors').errorsFor('base'), [{ attribute: 'base', message: "is a generally unsavoury character" }]); - - set(yehuda, 'updatedAt', true); - assert.equal(get(yehuda, 'isValid'), false, "the record is still invalid"); - - set(yehuda, 'name', "Brohuda Brokatz"); - - assert.equal(get(yehuda, 'isValid'), false, "the record is still invalid as far as we know"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record has outstanding changes"); - - assert.equal(get(yehuda, 'isNew'), true, "precond - record is still new"); - - return yehuda.save(); - }).then(person => { - assert.strictEqual(person, yehuda, "The promise resolves with the saved record"); - assert.ok(!get(yehuda, 'errors.base'), "The errors.base property does not exist"); - assert.deepEqual(get(yehuda, 'errors').errorsFor('base'), []); - assert.equal(get(yehuda, 'isValid'), true, "record remains valid after committing"); - assert.equal(get(yehuda, 'isNew'), false, "record is no longer new"); - }); + return yehuda + .save() + .catch(error => { + assert.equal(get(yehuda, 'isValid'), false, 'the record is invalid'); + assert.ok(get(yehuda, 'errors.base'), 'The errors.base property exists'); + assert.deepEqual(get(yehuda, 'errors').errorsFor('base'), [ + { attribute: 'base', message: 'is a generally unsavoury character' }, + ]); + + set(yehuda, 'updatedAt', true); + assert.equal(get(yehuda, 'isValid'), false, 'the record is still invalid'); + + set(yehuda, 'name', 'Brohuda Brokatz'); + + assert.equal( + get(yehuda, 'isValid'), + false, + 'the record is still invalid as far as we know' + ); + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record has outstanding changes'); + + assert.equal(get(yehuda, 'isNew'), true, 'precond - record is still new'); + + return yehuda.save(); + }) + .then(person => { + assert.strictEqual(person, yehuda, 'The promise resolves with the saved record'); + assert.ok(!get(yehuda, 'errors.base'), 'The errors.base property does not exist'); + assert.deepEqual(get(yehuda, 'errors').errorsFor('base'), []); + assert.equal(get(yehuda, 'isValid'), true, 'record remains valid after committing'); + assert.equal(get(yehuda, 'isNew'), false, 'record is no longer new'); + }); }); }); -test("if a created record is marked as invalid by the server, you can attempt the save again", function(assert) { +test('if a created record is marked as invalid by the server, you can attempt the save again', function(assert) { let saveCount = 0; adapter.createRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); + assert.equal(type, Person, 'the type is correct'); saveCount++; if (snapshot.attr('name').indexOf('Bro') === -1) { - return reject(new DS.InvalidError([ - { - title: 'Invalid Attribute', - detail: 'common... name requires a "bro"', - source: { - pointer: '/data/attributes/name' - } - } - ])); + return reject( + new DS.InvalidError([ + { + title: 'Invalid Attribute', + detail: 'common... name requires a "bro"', + source: { + pointer: '/data/attributes/name', + }, + }, + ]) + ); } else { return resolve(); } }; - let yehuda = store.createRecord('person', { id: 1, name: "Yehuda Katz" }); + let yehuda = store.createRecord('person', { id: 1, name: 'Yehuda Katz' }); // Wrap this in an Ember.run so that all chained async behavior is set up // before flushing any scheduled behavior. return run(() => { - return yehuda.save().catch(reason => { - assert.equal(saveCount, 1, "The record has been saved once"); - assert.ok(reason.message.match("The adapter rejected the commit because it was invalid"), "It should fail due to being invalid"); - assert.equal(get(yehuda, 'isValid'), false, "the record is invalid"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record has outstanding changes"); - assert.ok(get(yehuda, 'errors.name'), "The errors.name property exists"); - assert.equal(get(yehuda, 'isNew'), true, "precond - record is still new"); - return yehuda.save(); - }).catch(reason => { - assert.equal(saveCount, 2, "The record has been saved twice"); - assert.ok(reason.message.match("The adapter rejected the commit because it was invalid"), "It should fail due to being invalid"); - assert.equal(get(yehuda, 'isValid'), false, "the record is still invalid"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record has outstanding changes"); - assert.ok(get(yehuda, 'errors.name'), "The errors.name property exists"); - assert.equal(get(yehuda, 'isNew'), true, "precond - record is still new"); - set(yehuda, 'name', 'Brohuda Brokatz'); - return yehuda.save(); - }).then(person => { - assert.equal(saveCount, 3, "The record has been saved thrice"); - assert.equal(get(yehuda, 'isValid'), true, "record is valid"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), false, "record is not dirty"); - assert.equal(get(yehuda, 'errors.isEmpty'), true, "record has no errors"); - }); + return yehuda + .save() + .catch(reason => { + assert.equal(saveCount, 1, 'The record has been saved once'); + assert.ok( + reason.message.match('The adapter rejected the commit because it was invalid'), + 'It should fail due to being invalid' + ); + assert.equal(get(yehuda, 'isValid'), false, 'the record is invalid'); + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record has outstanding changes'); + assert.ok(get(yehuda, 'errors.name'), 'The errors.name property exists'); + assert.equal(get(yehuda, 'isNew'), true, 'precond - record is still new'); + return yehuda.save(); + }) + .catch(reason => { + assert.equal(saveCount, 2, 'The record has been saved twice'); + assert.ok( + reason.message.match('The adapter rejected the commit because it was invalid'), + 'It should fail due to being invalid' + ); + assert.equal(get(yehuda, 'isValid'), false, 'the record is still invalid'); + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record has outstanding changes'); + assert.ok(get(yehuda, 'errors.name'), 'The errors.name property exists'); + assert.equal(get(yehuda, 'isNew'), true, 'precond - record is still new'); + set(yehuda, 'name', 'Brohuda Brokatz'); + return yehuda.save(); + }) + .then(person => { + assert.equal(saveCount, 3, 'The record has been saved thrice'); + assert.equal(get(yehuda, 'isValid'), true, 'record is valid'); + assert.equal(get(yehuda, 'hasDirtyAttributes'), false, 'record is not dirty'); + assert.equal(get(yehuda, 'errors.isEmpty'), true, 'record has no errors'); + }); }); }); -test("if a created record is marked as erred by the server, it enters an error state", function(assert) { +test('if a created record is marked as erred by the server, it enters an error state', function(assert) { let error = new DS.AdapterError(); adapter.createRecord = function(store, type, snapshot) { @@ -634,30 +702,32 @@ test("if a created record is marked as erred by the server, it enters an error s }; return run(() => { - let person = store.createRecord('person', { id: 1, name: "John Doe" }); + let person = store.createRecord('person', { id: 1, name: 'John Doe' }); return person.save().catch(() => { - assert.ok(get(person, 'isError'), "the record is in the error state"); - assert.equal(get(person, 'adapterError'), error, "error object is exposed"); + assert.ok(get(person, 'isError'), 'the record is in the error state'); + assert.equal(get(person, 'adapterError'), error, 'error object is exposed'); }); }); }); -test("if an updated record is marked as invalid by the server, it enters an error state", function(assert) { +test('if an updated record is marked as invalid by the server, it enters an error state', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; adapter.updateRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); + assert.equal(type, Person, 'the type is correct'); if (snapshot.attr('name').indexOf('Bro') === -1) { - return reject(new DS.InvalidError([ - { - title: 'Invalid Attribute', - detail: 'common... name requires a "bro"', - source: { - pointer: '/data/attributes/name' - } - } - ])); + return reject( + new DS.InvalidError([ + { + title: 'Invalid Attribute', + detail: 'common... name requires a "bro"', + source: { + pointer: '/data/attributes/name', + }, + }, + ]) + ); } else { return resolve(); } @@ -669,57 +739,71 @@ test("if an updated record is marked as invalid by the server, it enters an erro type: 'person', id: '1', attributes: { - name: 'Brohuda Brokatz' - } - } + name: 'Brohuda Brokatz', + }, + }, }); return store.peekRecord('person', 1); }); return run(() => { - return store.findRecord('person', 1).then(person => { - assert.equal(person, yehuda, "The same object is passed through"); - - assert.equal(get(yehuda, 'isValid'), true, "precond - the record is valid"); - set(yehuda, 'name', "Yehuda Katz"); - assert.equal(get(yehuda, 'isValid'), true, "precond - the record is still valid as far as we know"); - - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record is dirty"); - - return yehuda.save(); - }).catch(reason => { - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record is still dirty"); - assert.equal(get(yehuda, 'isValid'), false, "the record is invalid"); - - set(yehuda, 'updatedAt', true); - assert.equal(get(yehuda, 'isValid'), false, "the record is still invalid"); - - set(yehuda, 'name', "Brohuda Brokatz"); - assert.equal(get(yehuda, 'isValid'), true, "the record is no longer invalid after changing"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record has outstanding changes"); - - return yehuda.save(); - }).then(yehuda => { - assert.equal(get(yehuda, 'isValid'), true, "record remains valid after committing"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), false, "record is no longer new"); - }); + return store + .findRecord('person', 1) + .then(person => { + assert.equal(person, yehuda, 'The same object is passed through'); + + assert.equal(get(yehuda, 'isValid'), true, 'precond - the record is valid'); + set(yehuda, 'name', 'Yehuda Katz'); + assert.equal( + get(yehuda, 'isValid'), + true, + 'precond - the record is still valid as far as we know' + ); + + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record is dirty'); + + return yehuda.save(); + }) + .catch(reason => { + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record is still dirty'); + assert.equal(get(yehuda, 'isValid'), false, 'the record is invalid'); + + set(yehuda, 'updatedAt', true); + assert.equal(get(yehuda, 'isValid'), false, 'the record is still invalid'); + + set(yehuda, 'name', 'Brohuda Brokatz'); + assert.equal( + get(yehuda, 'isValid'), + true, + 'the record is no longer invalid after changing' + ); + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record has outstanding changes'); + + return yehuda.save(); + }) + .then(yehuda => { + assert.equal(get(yehuda, 'isValid'), true, 'record remains valid after committing'); + assert.equal(get(yehuda, 'hasDirtyAttributes'), false, 'record is no longer new'); + }); }); }); -test("records can have errors on arbitrary properties after update", function(assert) { +test('records can have errors on arbitrary properties after update', function(assert) { adapter.shouldBackgroundReloadRecord = () => false; adapter.updateRecord = function(store, type, snapshot) { if (snapshot.attr('name').indexOf('Bro') === -1) { - return reject(new DS.InvalidError([ - { - title: "Invalid Attribute", - detail: "is a generally unsavoury character", - source: { - pointer: "/data/attributes/base" - } - } - ])); + return reject( + new DS.InvalidError([ + { + title: 'Invalid Attribute', + detail: 'is a generally unsavoury character', + source: { + pointer: '/data/attributes/base', + }, + }, + ]) + ); } else { return resolve(); } @@ -731,63 +815,79 @@ test("records can have errors on arbitrary properties after update", function(as type: 'person', id: '1', attributes: { - name: 'Brohuda Brokatz' - } - } + name: 'Brohuda Brokatz', + }, + }, }); return store.peekRecord('person', 1); }); return run(() => { - return store.findRecord('person', 1).then(person => { - assert.equal(person, yehuda, "The same object is passed through"); - - assert.equal(get(yehuda, 'isValid'), true, "precond - the record is valid"); - set(yehuda, 'name', "Yehuda Katz"); - assert.equal(get(yehuda, 'isValid'), true, "precond - the record is still valid as far as we know"); - - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record is dirty"); - - return yehuda.save(); - }).catch(reason => { - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record is still dirty"); - assert.equal(get(yehuda, 'isValid'), false, "the record is invalid"); - assert.ok(get(yehuda, 'errors.base'), "The errors.base property exists"); - assert.deepEqual(get(yehuda, 'errors').errorsFor('base'), [{ attribute: 'base', message: "is a generally unsavoury character" }]); - - set(yehuda, 'updatedAt', true); - assert.equal(get(yehuda, 'isValid'), false, "the record is still invalid"); - - set(yehuda, 'name', "Brohuda Brokatz"); - assert.equal(get(yehuda, 'isValid'), false, "the record is still invalid after changing (only server can know if it's now valid)"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record has outstanding changes"); - - return yehuda.save(); - }).then(yehuda => { - assert.equal(get(yehuda, 'isValid'), true, "record remains valid after committing"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), false, "record is no longer new"); - assert.ok(!get(yehuda, 'errors.base'), "The errors.base property does not exist"); - assert.deepEqual(get(yehuda, 'errors').errorsFor('base'), []); - }); + return store + .findRecord('person', 1) + .then(person => { + assert.equal(person, yehuda, 'The same object is passed through'); + + assert.equal(get(yehuda, 'isValid'), true, 'precond - the record is valid'); + set(yehuda, 'name', 'Yehuda Katz'); + assert.equal( + get(yehuda, 'isValid'), + true, + 'precond - the record is still valid as far as we know' + ); + + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record is dirty'); + + return yehuda.save(); + }) + .catch(reason => { + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record is still dirty'); + assert.equal(get(yehuda, 'isValid'), false, 'the record is invalid'); + assert.ok(get(yehuda, 'errors.base'), 'The errors.base property exists'); + assert.deepEqual(get(yehuda, 'errors').errorsFor('base'), [ + { attribute: 'base', message: 'is a generally unsavoury character' }, + ]); + + set(yehuda, 'updatedAt', true); + assert.equal(get(yehuda, 'isValid'), false, 'the record is still invalid'); + + set(yehuda, 'name', 'Brohuda Brokatz'); + assert.equal( + get(yehuda, 'isValid'), + false, + "the record is still invalid after changing (only server can know if it's now valid)" + ); + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record has outstanding changes'); + + return yehuda.save(); + }) + .then(yehuda => { + assert.equal(get(yehuda, 'isValid'), true, 'record remains valid after committing'); + assert.equal(get(yehuda, 'hasDirtyAttributes'), false, 'record is no longer new'); + assert.ok(!get(yehuda, 'errors.base'), 'The errors.base property does not exist'); + assert.deepEqual(get(yehuda, 'errors').errorsFor('base'), []); + }); }); }); -test("if an updated record is marked as invalid by the server, you can attempt the save again", function(assert) { +test('if an updated record is marked as invalid by the server, you can attempt the save again', function(assert) { let saveCount = 0; adapter.shouldBackgroundReloadRecord = () => false; adapter.updateRecord = function(store, type, snapshot) { - assert.equal(type, Person, "the type is correct"); + assert.equal(type, Person, 'the type is correct'); saveCount++; if (snapshot.attr('name').indexOf('Bro') === -1) { - return reject(new DS.InvalidError([ - { - title: 'Invalid Attribute', - detail: 'common... name requires a "bro"', - source: { - pointer: '/data/attributes/name' - } - } - ])); + return reject( + new DS.InvalidError([ + { + title: 'Invalid Attribute', + detail: 'common... name requires a "bro"', + source: { + pointer: '/data/attributes/name', + }, + }, + ]) + ); } else { return resolve(); } @@ -799,47 +899,62 @@ test("if an updated record is marked as invalid by the server, you can attempt t type: 'person', id: '1', attributes: { - name: 'Brohuda Brokatz' - } - } + name: 'Brohuda Brokatz', + }, + }, }); return store.peekRecord('person', 1); }); return run(() => { - return store.findRecord('person', 1).then(person => { - assert.equal(person, yehuda, "The same object is passed through"); - - assert.equal(get(yehuda, 'isValid'), true, "precond - the record is valid"); - set(yehuda, 'name', "Yehuda Katz"); - assert.equal(get(yehuda, 'isValid'), true, "precond - the record is still valid as far as we know"); - - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record is dirty"); - - return yehuda.save(); - }).catch(reason => { - assert.equal(saveCount, 1, "The record has been saved once"); - assert.ok(reason.message.match("The adapter rejected the commit because it was invalid"), "It should fail due to being invalid"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "the record is still dirty"); - assert.equal(get(yehuda, 'isValid'), false, "the record is invalid"); - return yehuda.save(); - }).catch(reason => { - assert.equal(saveCount, 2, "The record has been saved twice"); - assert.ok(reason.message.match("The adapter rejected the commit because it was invalid"), "It should fail due to being invalid"); - assert.equal(get(yehuda, 'isValid'), false, "record is still invalid"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), true, "record is still dirty"); - set(yehuda, 'name', 'Brohuda Brokatz'); - return yehuda.save(); - }).then(person => { - assert.equal(saveCount, 3, "The record has been saved thrice"); - assert.equal(get(yehuda, 'isValid'), true, "record is valid"); - assert.equal(get(yehuda, 'hasDirtyAttributes'), false, "record is not dirty"); - assert.equal(get(yehuda, 'errors.isEmpty'), true, "record has no errors"); - }); + return store + .findRecord('person', 1) + .then(person => { + assert.equal(person, yehuda, 'The same object is passed through'); + + assert.equal(get(yehuda, 'isValid'), true, 'precond - the record is valid'); + set(yehuda, 'name', 'Yehuda Katz'); + assert.equal( + get(yehuda, 'isValid'), + true, + 'precond - the record is still valid as far as we know' + ); + + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record is dirty'); + + return yehuda.save(); + }) + .catch(reason => { + assert.equal(saveCount, 1, 'The record has been saved once'); + assert.ok( + reason.message.match('The adapter rejected the commit because it was invalid'), + 'It should fail due to being invalid' + ); + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'the record is still dirty'); + assert.equal(get(yehuda, 'isValid'), false, 'the record is invalid'); + return yehuda.save(); + }) + .catch(reason => { + assert.equal(saveCount, 2, 'The record has been saved twice'); + assert.ok( + reason.message.match('The adapter rejected the commit because it was invalid'), + 'It should fail due to being invalid' + ); + assert.equal(get(yehuda, 'isValid'), false, 'record is still invalid'); + assert.equal(get(yehuda, 'hasDirtyAttributes'), true, 'record is still dirty'); + set(yehuda, 'name', 'Brohuda Brokatz'); + return yehuda.save(); + }) + .then(person => { + assert.equal(saveCount, 3, 'The record has been saved thrice'); + assert.equal(get(yehuda, 'isValid'), true, 'record is valid'); + assert.equal(get(yehuda, 'hasDirtyAttributes'), false, 'record is not dirty'); + assert.equal(get(yehuda, 'errors.isEmpty'), true, 'record has no errors'); + }); }); }); -test("if a updated record is marked as erred by the server, it enters an error state", function(assert) { +test('if a updated record is marked as erred by the server, it enters an error state', function(assert) { let error = new DS.AdapterError(); adapter.shouldBackgroundReloadRecord = () => false; @@ -853,37 +968,42 @@ test("if a updated record is marked as erred by the server, it enters an error s type: 'person', id: '1', attributes: { - name: 'John Doe' - } - } + name: 'John Doe', + }, + }, }); return store.peekRecord('person', 1); }); - return run(() => store.findRecord('person', 1).then(record => { - assert.equal(record, person, "The person was resolved"); - person.set('name', "Jonathan Doe"); - return person.save(); - }).catch(reason => { - assert.ok(get(person, 'isError'), "the record is in the error state"); - assert.equal(get(person, 'adapterError'), error, "error object is exposed"); - })); + return run(() => + store + .findRecord('person', 1) + .then(record => { + assert.equal(record, person, 'The person was resolved'); + person.set('name', 'Jonathan Doe'); + return person.save(); + }) + .catch(reason => { + assert.ok(get(person, 'isError'), 'the record is in the error state'); + assert.equal(get(person, 'adapterError'), error, 'error object is exposed'); + }) + ); }); -test("can be created after the DS.Store", function(assert) { +test('can be created after the DS.Store', function(assert) { assert.expect(1); adapter.findRecord = function(store, type, id, snapshot) { - assert.equal(type, Person, "the type is correct"); - return resolve({ data: { id: 1, type: "person" } }); + assert.equal(type, Person, 'the type is correct'); + return resolve({ data: { id: 1, type: 'person' } }); }; run(() => store.findRecord('person', 1)); }); -test("relationships returned via `commit` do not trigger additional findManys", function(assert) { +test('relationships returned via `commit` do not trigger additional findManys', function(assert) { Person.reopen({ - dogs: DS.hasMany('dog', { async: false }) + dogs: DS.hasMany('dog', { async: false }), }); run(() => { @@ -892,9 +1012,9 @@ test("relationships returned via `commit` do not trigger additional findManys", type: 'dog', id: '1', attributes: { - name: 'Scruffy' - } - } + name: 'Scruffy', + }, + }, }); }); @@ -902,14 +1022,14 @@ test("relationships returned via `commit` do not trigger additional findManys", return resolve({ data: { id: 1, - type: "person", - attributes: { name: "Tom Dale" }, + type: 'person', + attributes: { name: 'Tom Dale' }, relationships: { dogs: { - data: [{ id: 1, type: "dog" }] - } - } - } + data: [{ id: 1, type: 'dog' }], + }, + }, + }, }); }; @@ -920,58 +1040,61 @@ test("relationships returned via `commit` do not trigger additional findManys", type: 'person', id: '1', attributes: { - name: 'Tom Dale' + name: 'Tom Dale', }, relationships: { dogs: { - data: [ - { type: 'dog', id: '1' }, - { type: 'dog', id: '2' } - ] - } - } + data: [{ type: 'dog', id: '1' }, { type: 'dog', id: '2' }], + }, + }, }, - included: [{ - type: 'dog', - id: '2', - attributes: { - name: 'Scruffles' - } - }] + included: [ + { + type: 'dog', + id: '2', + attributes: { + name: 'Scruffles', + }, + }, + ], }); - resolve({ data: { id: 1, type: "dog", attributes: { name: "Scruffy" } } }); + resolve({ data: { id: 1, type: 'dog', attributes: { name: 'Scruffy' } } }); }); }; adapter.findMany = function(store, type, ids, snapshots) { - assert.ok(false, "Should not get here"); + assert.ok(false, 'Should not get here'); }; return run(() => { - store.findRecord('person', 1).then(person => { - return hash({ tom: person, dog: store.findRecord('dog', 1) }); - }).then(records => { - records.tom.get('dogs'); - return records.dog.save(); - }).then(tom => { - assert.ok(true, "Tom was saved"); - }); + store + .findRecord('person', 1) + .then(person => { + return hash({ tom: person, dog: store.findRecord('dog', 1) }); + }) + .then(records => { + records.tom.get('dogs'); + return records.dog.save(); + }) + .then(tom => { + assert.ok(true, 'Tom was saved'); + }); }); }); test("relationships don't get reset if the links is the same", function(assert) { adapter.shouldBackgroundReloadRecord = () => false; Person.reopen({ - dogs: DS.hasMany({ async: true }) + dogs: DS.hasMany({ async: true }), }); let count = 0; adapter.findHasMany = function(store, snapshot, link, relationship) { - assert.ok(count++ === 0, "findHasMany is only called once"); + assert.ok(count++ === 0, 'findHasMany is only called once'); - return resolve({ data: [{ id: 1, type: "dog", attributes: { name: "Scruffy" } }] }); + return resolve({ data: [{ id: 1, type: 'dog', attributes: { name: 'Scruffy' } }] }); }; run(() => { @@ -980,101 +1103,107 @@ test("relationships don't get reset if the links is the same", function(assert) type: 'person', id: '1', attributes: { - name: 'Tom Dale' + name: 'Tom Dale', }, relationships: { dogs: { links: { - related: '/dogs' - } - } - } - } + related: '/dogs', + }, + }, + }, + }, }); }); let tom, dogs; - return run(() => store.findRecord('person', 1).then(person => { - tom = person; - dogs = tom.get('dogs'); - return dogs; - }).then(dogs => { - assert.equal(dogs.get('length'), 1, "The dogs are loaded"); - store.push({ - data: { - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' - }, - relationships: { - dogs: { - links: { - related: '/dogs' - } - } - } - } - }); - assert.ok(tom.get('dogs') instanceof DS.PromiseArray, 'dogs is a promise'); - return tom.get('dogs'); - }).then(dogs => { - assert.equal(dogs.get('length'), 1, "The same dogs are loaded"); - })); + return run(() => + store + .findRecord('person', 1) + .then(person => { + tom = person; + dogs = tom.get('dogs'); + return dogs; + }) + .then(dogs => { + assert.equal(dogs.get('length'), 1, 'The dogs are loaded'); + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + dogs: { + links: { + related: '/dogs', + }, + }, + }, + }, + }); + assert.ok(tom.get('dogs') instanceof DS.PromiseArray, 'dogs is a promise'); + return tom.get('dogs'); + }) + .then(dogs => { + assert.equal(dogs.get('length'), 1, 'The same dogs are loaded'); + }) + ); }); -test("async hasMany always returns a promise", function(assert) { +test('async hasMany always returns a promise', function(assert) { Person.reopen({ - dogs: DS.hasMany({ async: true }) + dogs: DS.hasMany({ async: true }), }); adapter.createRecord = function(store, type, snapshot) { return resolve({ data: { id: 1, - type: "person", + type: 'person', attributes: { - name: "Tom Dale" + name: 'Tom Dale', }, relationships: { - dogs: [] - } - } + dogs: [], + }, + }, }); }; - let tom = store.createRecord('person', { name: "Tom Dale" }); + let tom = store.createRecord('person', { name: 'Tom Dale' }); run(() => { - assert.ok(tom.get('dogs') instanceof DS.PromiseArray, "dogs is a promise before save"); + assert.ok(tom.get('dogs') instanceof DS.PromiseArray, 'dogs is a promise before save'); }); return run(() => { return tom.save().then(() => { - assert.ok(tom.get('dogs') instanceof DS.PromiseArray, "dogs is a promise after save"); + assert.ok(tom.get('dogs') instanceof DS.PromiseArray, 'dogs is a promise after save'); }); }); }); -test("createRecord receives a snapshot", function(assert) { +test('createRecord receives a snapshot', function(assert) { assert.expect(1); adapter.createRecord = function(store, type, snapshot) { - assert.ok(snapshot instanceof DS.Snapshot, "snapshot is an instance of DS.Snapshot"); + assert.ok(snapshot instanceof DS.Snapshot, 'snapshot is an instance of DS.Snapshot'); return resolve(); }; - let record = store.createRecord('person', { name: "Tom Dale", id: 1 }); + let record = store.createRecord('person', { name: 'Tom Dale', id: 1 }); run(() => record.save()); }); -test("updateRecord receives a snapshot", function(assert) { +test('updateRecord receives a snapshot', function(assert) { assert.expect(1); adapter.updateRecord = function(store, type, snapshot) { - assert.ok(snapshot instanceof DS.Snapshot, "snapshot is an instance of DS.Snapshot"); + assert.ok(snapshot instanceof DS.Snapshot, 'snapshot is an instance of DS.Snapshot'); return resolve(); }; @@ -1086,24 +1215,24 @@ test("updateRecord receives a snapshot", function(assert) { type: 'person', id: '1', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); person = store.peekRecord('person', 1); }); run(() => { - set(person, "name", "Tomster"); + set(person, 'name', 'Tomster'); person.save(); }); }); -test("deleteRecord receives a snapshot", function(assert) { +test('deleteRecord receives a snapshot', function(assert) { assert.expect(1); adapter.deleteRecord = function(store, type, snapshot) { - assert.ok(snapshot instanceof DS.Snapshot, "snapshot is an instance of DS.Snapshot"); + assert.ok(snapshot instanceof DS.Snapshot, 'snapshot is an instance of DS.Snapshot'); return resolve(); }; @@ -1115,9 +1244,9 @@ test("deleteRecord receives a snapshot", function(assert) { type: 'person', id: '1', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); person = store.peekRecord('person', 1); }); @@ -1128,29 +1257,29 @@ test("deleteRecord receives a snapshot", function(assert) { }); }); -test("findRecord receives a snapshot", function(assert) { +test('findRecord receives a snapshot', function(assert) { assert.expect(1); adapter.findRecord = function(store, type, id, snapshot) { - assert.ok(snapshot instanceof DS.Snapshot, "snapshot is an instance of DS.Snapshot"); - return resolve({ data: { id: 1, type: "person" } }); + assert.ok(snapshot instanceof DS.Snapshot, 'snapshot is an instance of DS.Snapshot'); + return resolve({ data: { id: 1, type: 'person' } }); }; return run(() => store.findRecord('person', 1)); }); -test("findMany receives an array of snapshots", function(assert) { +test('findMany receives an array of snapshots', function(assert) { assert.expect(2); Person.reopen({ - dogs: DS.hasMany({ async: true }) + dogs: DS.hasMany({ async: true }), }); adapter.coalesceFindRequests = true; adapter.findMany = function(store, type, ids, snapshots) { - assert.ok(snapshots[0] instanceof DS.Snapshot, "snapshots[0] is an instance of DS.Snapshot"); - assert.ok(snapshots[1] instanceof DS.Snapshot, "snapshots[1] is an instance of DS.Snapshot"); - return resolve({ data: [{ id: 2, type: "dog" }, { id: 3, type: "dog" }] }); + assert.ok(snapshots[0] instanceof DS.Snapshot, 'snapshots[0] is an instance of DS.Snapshot'); + assert.ok(snapshots[1] instanceof DS.Snapshot, 'snapshots[1] is an instance of DS.Snapshot'); + return resolve({ data: [{ id: 2, type: 'dog' }, { id: 3, type: 'dog' }] }); }; let person; @@ -1162,13 +1291,10 @@ test("findMany receives an array of snapshots", function(assert) { id: '1', relationships: { dogs: { - data: [ - { type: 'dog', id: '2' }, - { type: 'dog', id: '3' } - ] - } - } - } + data: [{ type: 'dog', id: '2' }, { type: 'dog', id: '3' }], + }, + }, + }, }); person = store.peekRecord('person', 1); }); @@ -1176,16 +1302,16 @@ test("findMany receives an array of snapshots", function(assert) { run(() => person.get('dogs')); }); -test("findHasMany receives a snapshot", function(assert) { +test('findHasMany receives a snapshot', function(assert) { assert.expect(1); Person.reopen({ - dogs: DS.hasMany({ async: true }) + dogs: DS.hasMany({ async: true }), }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - assert.ok(snapshot instanceof DS.Snapshot, "snapshot is an instance of DS.Snapshot"); - return resolve({ data: [{ id: 2, type: "dog" }, { id: 3, type: "dog" }] }); + assert.ok(snapshot instanceof DS.Snapshot, 'snapshot is an instance of DS.Snapshot'); + return resolve({ data: [{ id: 2, type: 'dog' }, { id: 3, type: 'dog' }] }); }; let person; @@ -1198,11 +1324,11 @@ test("findHasMany receives a snapshot", function(assert) { relationships: { dogs: { links: { - related: 'dogs' - } - } - } - } + related: 'dogs', + }, + }, + }, + }, }); person = store.peekRecord('person', 1); }); @@ -1210,16 +1336,16 @@ test("findHasMany receives a snapshot", function(assert) { return run(() => person.get('dogs')); }); -test("findBelongsTo receives a snapshot", function(assert) { +test('findBelongsTo receives a snapshot', function(assert) { assert.expect(1); Person.reopen({ - dog: DS.belongsTo({ async: true }) + dog: DS.belongsTo({ async: true }), }); env.adapter.findBelongsTo = function(store, snapshot, link, relationship) { - assert.ok(snapshot instanceof DS.Snapshot, "snapshot is an instance of DS.Snapshot"); - return resolve({ data: { id: 2, type: "dog" } }); + assert.ok(snapshot instanceof DS.Snapshot, 'snapshot is an instance of DS.Snapshot'); + return resolve({ data: { id: 2, type: 'dog' } }); }; let person; @@ -1232,11 +1358,11 @@ test("findBelongsTo receives a snapshot", function(assert) { relationships: { dog: { links: { - related: 'dog' - } - } - } - } + related: 'dog', + }, + }, + }, + }, }); person = store.peekRecord('person', 1); }); @@ -1244,12 +1370,12 @@ test("findBelongsTo receives a snapshot", function(assert) { return run(() => person.get('dog')); }); -test("record.save should pass adapterOptions to the updateRecord method", function(assert) { +test('record.save should pass adapterOptions to the updateRecord method', function(assert) { assert.expect(1); env.adapter.updateRecord = function(store, type, snapshot) { assert.deepEqual(snapshot.adapterOptions, { subscribe: true }); - return resolve({ data: { id: 1, type: "person" } }); + return resolve({ data: { id: 1, type: 'person' } }); }; return run(() => { @@ -1258,35 +1384,34 @@ test("record.save should pass adapterOptions to the updateRecord method", functi type: 'person', id: '1', attributes: { - name: 'Tom' - } - } + name: 'Tom', + }, + }, }); let person = store.peekRecord('person', 1); return person.save({ adapterOptions: { subscribe: true } }); }); }); -test("record.save should pass adapterOptions to the createRecord method", function(assert) { +test('record.save should pass adapterOptions to the createRecord method', function(assert) { assert.expect(1); env.adapter.createRecord = function(store, type, snapshot) { assert.deepEqual(snapshot.adapterOptions, { subscribe: true }); - return resolve({ data: { id: 1, type: "person" } }); + return resolve({ data: { id: 1, type: 'person' } }); }; return run(() => { - store.createRecord('person', { name: 'Tom' }) - .save({ adapterOptions: { subscribe: true } }); + store.createRecord('person', { name: 'Tom' }).save({ adapterOptions: { subscribe: true } }); }); }); -test("record.save should pass adapterOptions to the deleteRecord method", function(assert) { +test('record.save should pass adapterOptions to the deleteRecord method', function(assert) { assert.expect(1); env.adapter.deleteRecord = function(store, type, snapshot) { assert.deepEqual(snapshot.adapterOptions, { subscribe: true }); - return resolve({ data: { id: 1, type: "person" } }); + return resolve({ data: { id: 1, type: 'person' } }); }; run(() => { @@ -1295,21 +1420,21 @@ test("record.save should pass adapterOptions to the deleteRecord method", functi type: 'person', id: '1', attributes: { - name: 'Tom' - } - } + name: 'Tom', + }, + }, }); let person = store.peekRecord('person', 1); person.destroyRecord({ adapterOptions: { subscribe: true } }); }); }); -test("store.findRecord should pass adapterOptions to adapter.findRecord", function(assert) { +test('store.findRecord should pass adapterOptions to adapter.findRecord', function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, id, snapshot) { assert.deepEqual(snapshot.adapterOptions, { query: { embed: true } }); - return resolve({ data: { id: 1, type: "person" } }); + return resolve({ data: { id: 1, type: 'person' } }); }; return run(() => { @@ -1317,7 +1442,7 @@ test("store.findRecord should pass adapterOptions to adapter.findRecord", functi }); }); -test("store.query should pass adapterOptions to adapter.query ", function(assert) { +test('store.query should pass adapterOptions to adapter.query ', function(assert) { assert.expect(2); env.adapter.query = function(store, type, query, array, options) { @@ -1331,7 +1456,7 @@ test("store.query should pass adapterOptions to adapter.query ", function(assert }); }); -test("store.queryRecord should pass adapterOptions to adapter.queryRecord", function(assert) { +test('store.queryRecord should pass adapterOptions to adapter.queryRecord', function(assert) { assert.expect(2); env.adapter.queryRecord = function(store, type, query, snapshot) { @@ -1349,20 +1474,20 @@ test("store.findRecord should pass 'include' to adapter.findRecord", function(as assert.expect(1); env.adapter.findRecord = (store, type, id, snapshot) => { - assert.equal(snapshot.include, 'books', 'include passed to adapter.findRecord'); - return resolve({ data: { id: 1, type: "person" } }); + assert.equal(snapshot.include, 'books', 'include passed to adapter.findRecord'); + return resolve({ data: { id: 1, type: 'person' } }); }; run(() => store.findRecord('person', 1, { include: 'books' })); }); -test("store.findAll should pass adapterOptions to the adapter.findAll method", function(assert) { +test('store.findAll should pass adapterOptions to the adapter.findAll method', function(assert) { assert.expect(1); env.adapter.findAll = function(store, type, sinceToken, arraySnapshot) { let adapterOptions = arraySnapshot.adapterOptions; assert.deepEqual(adapterOptions, { query: { embed: true } }); - return resolve({ data: [{ id: 1, type: "person" }] }); + return resolve({ data: [{ id: 1, type: 'person' }] }); }; return run(() => { @@ -1375,20 +1500,20 @@ test("store.findAll should pass 'include' to adapter.findAll", function(assert) env.adapter.findAll = function(store, type, sinceToken, arraySnapshot) { assert.equal(arraySnapshot.include, 'books', 'include passed to adapter.findAll'); - return resolve({ data: [{ id: 1, type: "person" }] }); + return resolve({ data: [{ id: 1, type: 'person' }] }); }; run(() => store.findAll('person', { include: 'books' })); }); -test("An async hasMany relationship with links should not trigger shouldBackgroundReloadRecord", function(assert) { +test('An async hasMany relationship with links should not trigger shouldBackgroundReloadRecord', function(assert) { const Post = DS.Model.extend({ - name: DS.attr("string"), - comments: DS.hasMany('comment', { async: true }) + name: DS.attr('string'), + comments: DS.hasMany('comment', { async: true }), }); const Comment = DS.Model.extend({ - name: DS.attr("string") + name: DS.attr('string'), }); env = setupStore({ @@ -1399,69 +1524,83 @@ test("An async hasMany relationship with links should not trigger shouldBackgrou return { posts: { id: 1, - name: "Rails is omakase", - links: { comments: '/posts/1/comments' } - } + name: 'Rails is omakase', + links: { comments: '/posts/1/comments' }, + }, }; }, findHasMany() { return resolve({ comments: [ - { id: 1, name: "FIRST" }, - { id: 2, name: "Rails is unagi" }, - { id: 3, name: "What is omakase?" } - ] + { id: 1, name: 'FIRST' }, + { id: 2, name: 'Rails is unagi' }, + { id: 3, name: 'What is omakase?' }, + ], }); }, shouldBackgroundReloadRecord() { assert.ok(false, 'shouldBackgroundReloadRecord should not be called'); - } - }) + }, + }), }); store = env.store; - return run(() => store.findRecord('post', '1').then(post => { - return post.get('comments'); - }).then(comments => { - assert.equal(comments.get('length'), 3); - })); + return run(() => + store + .findRecord('post', '1') + .then(post => { + return post.get('comments'); + }) + .then(comments => { + assert.equal(comments.get('length'), 3); + }) + ); }); -testInDebug("There should be a friendly error for if the adapter does not implement createRecord", function(assert) { - adapter.createRecord = null; +testInDebug( + 'There should be a friendly error for if the adapter does not implement createRecord', + function(assert) { + adapter.createRecord = null; - let tom = run(() => store.createRecord('person', { name: "Tom Dale" })); + let tom = run(() => store.createRecord('person', { name: 'Tom Dale' })); - assert.expectAssertion(() => { - run(() => tom.save()); - }, /does not implement 'createRecord'/); + assert.expectAssertion(() => { + run(() => tom.save()); + }, /does not implement 'createRecord'/); - moveRecordOutOfInFlight(tom); -}); + moveRecordOutOfInFlight(tom); + } +); -testInDebug("There should be a friendly error for if the adapter does not implement updateRecord", function(assert) { - adapter.updateRecord = null; +testInDebug( + 'There should be a friendly error for if the adapter does not implement updateRecord', + function(assert) { + adapter.updateRecord = null; - let tom = run(() => store.push({ data: { type: 'person', id: 1 } })); - assert.expectAssertion(() => { - run(() => tom.save()); - }, /does not implement 'updateRecord'/); + let tom = run(() => store.push({ data: { type: 'person', id: 1 } })); + assert.expectAssertion(() => { + run(() => tom.save()); + }, /does not implement 'updateRecord'/); - moveRecordOutOfInFlight(tom); -}); + moveRecordOutOfInFlight(tom); + } +); -testInDebug("There should be a friendly error for if the adapter does not implement deleteRecord", function(assert) { - adapter.deleteRecord = null; +testInDebug( + 'There should be a friendly error for if the adapter does not implement deleteRecord', + function(assert) { + adapter.deleteRecord = null; - let tom = run(() => store.push({ data: { type: 'person', id: 1 } })); + let tom = run(() => store.push({ data: { type: 'person', id: 1 } })); - assert.expectAssertion(() => { - run(() => { - tom.deleteRecord(); - return tom.save(); - }); - }, /does not implement 'deleteRecord'/); + assert.expectAssertion(() => { + run(() => { + tom.deleteRecord(); + return tom.save(); + }); + }, /does not implement 'deleteRecord'/); - moveRecordOutOfInFlight(tom); -}); + moveRecordOutOfInFlight(tom); + } +); diff --git a/tests/integration/application-test.js b/tests/integration/application-test.js index d09499705c7..fdbcc0ed0d3 100644 --- a/tests/integration/application-test.js +++ b/tests/integration/application-test.js @@ -26,7 +26,7 @@ function lookup(thing) { return run(container, 'lookup', thing); } -module("integration/application - Injecting a Custom Store", { +module('integration/application - Injecting a Custom Store', { beforeEach() { run(() => { app = Application.create({ @@ -34,7 +34,7 @@ module("integration/application - Injecting a Custom Store", { FooController: Controller.extend(), BazController: {}, ApplicationController: Controller.extend(), - rootElement: '#qunit-fixture' + rootElement: '#qunit-fixture', }); }); @@ -44,22 +44,22 @@ module("integration/application - Injecting a Custom Store", { afterEach() { run(app, app.destroy); Ember.BOOTED = false; - } + }, }); -test("If a Store property exists on an Ember.Application, it should be instantiated.", function(assert) { +test('If a Store property exists on an Ember.Application, it should be instantiated.', function(assert) { run(() => { - assert.ok(getStore().get('isCustom'), "the custom store was instantiated"); + assert.ok(getStore().get('isCustom'), 'the custom store was instantiated'); }); }); -test("If a store is instantiated, it should be made available to each controller.", function(assert) { +test('If a store is instantiated, it should be made available to each controller.', function(assert) { let fooController = lookup('controller:foo'); let isCustom = run(fooController, 'get', 'store.isCustom'); - assert.ok(isCustom, "the custom store was injected"); + assert.ok(isCustom, 'the custom store was injected'); }); -test("The JSONAPIAdapter is the default adapter when no custom adapter is provided", function(assert) { +test('The JSONAPIAdapter is the default adapter when no custom adapter is provided', function(assert) { run(() => { let store = getStore(); let adapter = store.adapterFor('application'); @@ -68,13 +68,13 @@ test("The JSONAPIAdapter is the default adapter when no custom adapter is provid }); }); -module("integration/application - Injecting the Default Store", { +module('integration/application - Injecting the Default Store', { beforeEach() { run(() => { app = Application.create({ FooController: Controller.extend(), BazController: {}, - ApplicationController: Controller.extend() + ApplicationController: Controller.extend(), }); }); @@ -84,32 +84,32 @@ module("integration/application - Injecting the Default Store", { afterEach() { run(app, 'destroy'); Ember.BOOTED = false; - } + }, }); -test("If a Store property exists on an Ember.Application, it should be instantiated.", function(assert) { - assert.ok(getStore() instanceof DS.Store, "the store was instantiated"); +test('If a Store property exists on an Ember.Application, it should be instantiated.', function(assert) { + assert.ok(getStore() instanceof DS.Store, 'the store was instantiated'); }); -test("If a store is instantiated, it should be made available to each controller.", function(assert) { +test('If a store is instantiated, it should be made available to each controller.', function(assert) { run(() => { let fooController = lookup('controller:foo'); - assert.ok(fooController.get('store') instanceof DS.Store, "the store was injected"); + assert.ok(fooController.get('store') instanceof DS.Store, 'the store was injected'); }); }); -test("the DS namespace should be accessible", function(assert) { +test('the DS namespace should be accessible', function(assert) { run(() => { - assert.ok(Namespace.byName('DS') instanceof Namespace, "the DS namespace is accessible"); + assert.ok(Namespace.byName('DS') instanceof Namespace, 'the DS namespace is accessible'); }); }); if (Ember.inject && service) { - module("integration/application - Using the store as a service", { + module('integration/application - Using the store as a service', { beforeEach() { run(() => { app = Application.create({ - DoodleService: Service.extend({ store: service() }) + DoodleService: Service.extend({ store: service() }), }); }); @@ -119,18 +119,18 @@ if (Ember.inject && service) { afterEach() { run(app, 'destroy'); Ember.BOOTED = false; - } + }, }); - test("The store can be injected as a service", function(assert) { + test('The store can be injected as a service', function(assert) { run(() => { let doodleService = lookup('service:doodle'); - assert.ok(doodleService.get('store') instanceof Store, "the store can be used as a service"); + assert.ok(doodleService.get('store') instanceof Store, 'the store can be used as a service'); }); }); } -module("integration/application - Attaching initializer", { +module('integration/application - Attaching initializer', { beforeEach() { App = Application.extend(); }, @@ -140,15 +140,17 @@ module("integration/application - Attaching initializer", { run(app, app.destroy); } Ember.BOOTED = false; - } + }, }); -test("ember-data initializer is run", function(assert) { +test('ember-data initializer is run', function(assert) { let ran = false; App.initializer({ - name: "after-ember-data", - after: "ember-data", - initialize() { ran = true; } + name: 'after-ember-data', + after: 'ember-data', + initialize() { + ran = true; + }, }); run(() => { @@ -158,18 +160,17 @@ test("ember-data initializer is run", function(assert) { assert.ok(ran, 'ember-data initializer was found'); }); -test("ember-data initializer does not register the store service when it was already registered", function(assert) { - +test('ember-data initializer does not register the store service when it was already registered', function(assert) { let AppStore = Store.extend({ - isCustomStore: true + isCustomStore: true, }); App.initializer({ - name: "after-ember-data", - before: "ember-data", + name: 'after-ember-data', + before: 'ember-data', initialize(registry) { registry.register('service:store', AppStore); - } + }, }); run(() => { @@ -178,6 +179,8 @@ test("ember-data initializer does not register the store service when it was alr }); let store = getStore(); - assert.ok(store && store.get('isCustomStore'), 'ember-data initializer does not overwrite the previous registered service store'); - + assert.ok( + store && store.get('isCustomStore'), + 'ember-data initializer does not overwrite the previous registered service store' + ); }); diff --git a/tests/integration/backwards-compat/non-dasherized-lookups-test.js b/tests/integration/backwards-compat/non-dasherized-lookups-test.js index 807a1657966..bfbb18379a2 100644 --- a/tests/integration/backwards-compat/non-dasherized-lookups-test.js +++ b/tests/integration/backwards-compat/non-dasherized-lookups-test.js @@ -6,40 +6,37 @@ import { module, test } from 'qunit'; import DS from 'ember-data'; -const { - JSONAPIAdapter, - Model, - attr, - belongsTo, - hasMany -} = DS; +const { JSONAPIAdapter, Model, attr, belongsTo, hasMany } = DS; let store; -module('integration/backwards-compat/non-dasherized-lookups - non dasherized lookups in application code finders', { - beforeEach() { - const PostNote = Model.extend({ - name: attr('string') - }); - - const ApplicationAdapter = JSONAPIAdapter.extend({ - shouldBackgroundReloadRecord() { - return false; - } - }); +module( + 'integration/backwards-compat/non-dasherized-lookups - non dasherized lookups in application code finders', + { + beforeEach() { + const PostNote = Model.extend({ + name: attr('string'), + }); + + const ApplicationAdapter = JSONAPIAdapter.extend({ + shouldBackgroundReloadRecord() { + return false; + }, + }); - const env = setupStore({ - postNote: PostNote, - adapter: ApplicationAdapter - }); + const env = setupStore({ + postNote: PostNote, + adapter: ApplicationAdapter, + }); - store = env.store; - }, + store = env.store; + }, - afterEach() { - run(store, 'destroy'); + afterEach() { + run(store, 'destroy'); + }, } -}); +); test('can lookup records using camelCase strings', function(assert) { assert.expect(1); @@ -50,14 +47,14 @@ test('can lookup records using camelCase strings', function(assert) { type: 'post-notes', id: '1', attributes: { - name: 'Ember Data' - } - } + name: 'Ember Data', + }, + }, }); }); run(() => { - store.findRecord('postNote', 1).then((postNote) => { + store.findRecord('postNote', 1).then(postNote => { assert.equal(get(postNote, 'name'), 'Ember Data', 'record found'); }); }); @@ -72,55 +69,58 @@ test('can lookup records using under_scored strings', function(assert) { type: 'post-notes', id: '1', attributes: { - name: 'Ember Data' - } - } + name: 'Ember Data', + }, + }, }); }); run(() => { - store.findRecord('post_note', 1).then((postNote) => { + store.findRecord('post_note', 1).then(postNote => { assert.equal(get(postNote, 'name'), 'Ember Data', 'record found'); }); }); }); -module('integration/backwards-compat/non-dasherized-lookups - non dasherized lookups in application code relationship macros', { - beforeEach() { - const PostNote = Model.extend({ - notePost: belongsTo('note-post', { async: false }), +module( + 'integration/backwards-compat/non-dasherized-lookups - non dasherized lookups in application code relationship macros', + { + beforeEach() { + const PostNote = Model.extend({ + notePost: belongsTo('note-post', { async: false }), - name: attr('string') - }); + name: attr('string'), + }); - const NotePost = Model.extend({ - name: attr('string') - }); + const NotePost = Model.extend({ + name: attr('string'), + }); - const LongModelName = Model.extend({ - postNotes: hasMany('post_note') - }); + const LongModelName = Model.extend({ + postNotes: hasMany('post_note'), + }); - const ApplicationAdapter = JSONAPIAdapter.extend({ - shouldBackgroundReloadRecord() { - return false; - } - }); + const ApplicationAdapter = JSONAPIAdapter.extend({ + shouldBackgroundReloadRecord() { + return false; + }, + }); - const env = setupStore({ - longModelName: LongModelName, - notePost: NotePost, - postNote: PostNote, - adapter: ApplicationAdapter - }); + const env = setupStore({ + longModelName: LongModelName, + notePost: NotePost, + postNote: PostNote, + adapter: ApplicationAdapter, + }); - store = env.store; - }, + store = env.store; + }, - afterEach() { - run(store, 'destroy'); + afterEach() { + run(store, 'destroy'); + }, } -}); +); test('looks up belongsTo using camelCase strings', function(assert) { assert.expect(1); @@ -131,28 +131,28 @@ test('looks up belongsTo using camelCase strings', function(assert) { type: 'post-notes', id: '1', attributes: { - name: 'Ember Data' + name: 'Ember Data', }, relationships: { 'note-post': { - data: { type: 'note-post', id: '1' } - } - } - } + data: { type: 'note-post', id: '1' }, + }, + }, + }, }); store.pushPayload('notePost', { data: { type: 'note-posts', id: '1', attributes: { - name: 'Inverse' - } - } + name: 'Inverse', + }, + }, }); }); run(() => { - store.findRecord('post-note', 1).then((postNote) => { + store.findRecord('post-note', 1).then(postNote => { assert.equal(get(postNote, 'notePost.name'), 'Inverse', 'inverse record found'); }); }); @@ -166,14 +166,13 @@ test('looks up belongsTo using under_scored strings', function(assert) { data: { type: 'long-model-names', id: '1', - attributes: { - }, + attributes: {}, relationships: { 'post-notes': { - data: [{ type: 'post-note', id: '1' }] - } - } - } + data: [{ type: 'post-note', id: '1' }], + }, + }, + }, }); store.pushPayload('post-note', { @@ -181,18 +180,17 @@ test('looks up belongsTo using under_scored strings', function(assert) { type: 'post-notes', id: '1', attributes: { - name: 'Ember Data' - } - } + name: 'Ember Data', + }, + }, }); }); run(() => { - store.findRecord('long_model_name', 1).then((longModelName) => { + store.findRecord('long_model_name', 1).then(longModelName => { const postNotes = get(longModelName, 'postNotes').toArray(); - assert.deepEqual(postNotes, [store.peekRecord('postNote', 1)], - 'inverse records found'); + assert.deepEqual(postNotes, [store.peekRecord('postNote', 1)], 'inverse records found'); }); }); }); diff --git a/tests/integration/client-id-generation-test.js b/tests/integration/client-id-generation-test.js index e7a0561fabe..f9929264304 100644 --- a/tests/integration/client-id-generation-test.js +++ b/tests/integration/client-id-generation-test.js @@ -9,41 +9,41 @@ import DS from 'ember-data'; let Post, Comment, Misc, env; -module("integration/client_id_generation - Client-side ID Generation", { +module('integration/client_id_generation - Client-side ID Generation', { beforeEach() { Comment = DS.Model.extend({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); Post = DS.Model.extend({ - comments: DS.hasMany('comment', { async: false }) + comments: DS.hasMany('comment', { async: false }), }); Misc = DS.Model.extend({ - foo: DS.attr('string') + foo: DS.attr('string'), }); env = setupStore({ post: Post, comment: Comment, - misc: Misc + misc: Misc, }); }, afterEach() { run(env.container, 'destroy'); - } + }, }); -test("If an adapter implements the `generateIdForRecord` method, the store should be able to assign IDs without saving to the persistence layer.", function(assert) { +test('If an adapter implements the `generateIdForRecord` method, the store should be able to assign IDs without saving to the persistence layer.', function(assert) { assert.expect(6); let idCount = 1; env.adapter.generateIdForRecord = function(passedStore, record) { - assert.equal(env.store, passedStore, "store is the first parameter"); + assert.equal(env.store, passedStore, 'store is the first parameter'); - return "id-" + idCount++; + return 'id-' + idCount++; }; env.adapter.createRecord = function(store, type, snapshot) { @@ -70,13 +70,13 @@ test("If an adapter implements the `generateIdForRecord` method, the store shoul }); }); -test("empty string and undefined ids should coerce to null", function(assert) { +test('empty string and undefined ids should coerce to null', function(assert) { assert.expect(6); let idCount = 0; let id = 1; let ids = [undefined, '']; env.adapter.generateIdForRecord = function(passedStore, record) { - assert.equal(env.store, passedStore, "store is the first parameter"); + assert.equal(env.store, passedStore, 'store is the first parameter'); return ids[idCount++]; }; diff --git a/tests/integration/debug-adapter-test.js b/tests/integration/debug-adapter-test.js index 0d0d0759697..13a7e11a7dc 100644 --- a/tests/integration/debug-adapter-test.js +++ b/tests/integration/debug-adapter-test.js @@ -13,24 +13,25 @@ module('DS.DebugAdapter', { beforeEach() { run(function() { App = Application.extend({ - toString() { return 'debug-app'; } + toString() { + return 'debug-app'; + }, }).create(); App.StoreService = DS.Store.extend({}); App.ApplicationAdapter = DS.Adapter.extend({ - shouldBackgroundReloadRecord: () => false + shouldBackgroundReloadRecord: () => false, }); App.Post = DS.Model.extend({ - title: DS.attr('string') + title: DS.attr('string'), }); // TODO: Remove this when Ember is upgraded to >= 1.13 App.Post.reopenClass({ - _debugContainerKey: 'model:post' + _debugContainerKey: 'model:post', }); - }); store = App.__container__.lookup('service:store'); @@ -47,13 +48,13 @@ module('DS.DebugAdapter', { debugAdapter.reopen({ getModelTypes() { return A([{ klass, name: 'post' }]); - } + }, }); }, afterEach() { run(App, App.destroy); App = store = null; - } + }, }); test('Watching Model Types', function(assert) { @@ -78,14 +79,14 @@ test('Watching Model Types', function(assert) { type: 'post', id: '1', attributes: { - title: 'Post Title' - } - } + title: 'Post Title', + }, + }, }); }); }); -test("Watching Records", function(assert) { +test('Watching Records', function(assert) { var post, record, addedRecords, updatedRecords, removedIndex, removedCount; run(function() { @@ -94,16 +95,16 @@ test("Watching Records", function(assert) { type: 'post', id: '1', attributes: { - title: 'Clean Post' - } - } + title: 'Clean Post', + }, + }, }); }); var recordsAdded = function(wrappedRecords) { addedRecords = wrappedRecords; }; - var recordsUpdated = function(wrappedRecords) { + var recordsUpdated = function(wrappedRecords) { updatedRecords = wrappedRecords; }; var recordsRemoved = function(index, count) { diff --git a/tests/integration/injection-test.js b/tests/integration/injection-test.js index 9b7e72315c9..4e5d80c7cbf 100644 --- a/tests/integration/injection-test.js +++ b/tests/integration/injection-test.js @@ -1,6 +1,6 @@ import { setup as setupModelFactoryInjections, - reset as resetModelFactoryInjections + reset as resetModelFactoryInjections, } from 'dummy/tests/helpers/model-factory-injection'; import EmberObject from '@ember/object'; import { getOwner } from '@ember/application'; @@ -13,10 +13,10 @@ let env, hasFactoryFor, originalLookupFactory, originalOwnerLookupFactory, origi const model = { isModel: true, - _create() { } + _create() {}, }; const factory = { - class: model + class: model, }; module('integration/injection factoryFor enabled', { @@ -63,13 +63,17 @@ module('integration/injection factoryFor enabled', { } run(env.store, 'destroy'); - } + }, }); test('modelFactoryFor', function(assert) { const modelFactory = env.store._modelFactoryFor('super-villain'); - assert.equal(modelFactory, hasFactoryFor ? factory : model, 'expected the factory itself to be returned'); + assert.equal( + modelFactory, + hasFactoryFor ? factory : model, + 'expected the factory itself to be returned' + ); }); test('modelFor', function(assert) { @@ -78,7 +82,11 @@ test('modelFor', function(assert) { assert.equal(modelFactory, model, 'expected the factory itself to be returned'); // TODO: we should deprecate this next line. Resolved state on the class is fraught with peril - assert.equal(modelFactory.modelName, 'super-villain', 'expected the factory itself to be returned'); + assert.equal( + modelFactory.modelName, + 'super-villain', + 'expected the factory itself to be returned' + ); }); module('integration/injection eager injections', { @@ -87,7 +95,7 @@ module('integration/injection eager injections', { env = setupStore(); env.registry.injection('model:foo', 'apple', 'service:apple'); - env.registry.register('model:foo', DS.Model); + env.registry.register('model:foo', DS.Model); env.registry.register('service:apple', EmberObject.extend({ isService: true })); // container injection }, @@ -97,7 +105,7 @@ module('integration/injection eager injections', { resetModelFactoryInjections(); run(env.store, 'destroy'); - } + }, }); test('did inject', function(assert) { diff --git a/tests/integration/inverse-test.js b/tests/integration/inverse-test.js index 25c57d81dd7..870f6139bab 100644 --- a/tests/integration/inverse-test.js +++ b/tests/integration/inverse-test.js @@ -11,7 +11,9 @@ let env, store, User, Job, ReflexiveModel; const { attr, belongsTo } = DS; function stringify(string) { - return function() { return string; }; + return function() { + return string; + }; } module('integration/inverse_test - inverseFor', { @@ -19,20 +21,20 @@ module('integration/inverse_test - inverseFor', { User = DS.Model.extend({ name: attr('string'), bestFriend: belongsTo('user', { async: true, inverse: null }), - job: belongsTo('job', { async: false }) + job: belongsTo('job', { async: false }), }); User.toString = stringify('user'); Job = DS.Model.extend({ isGood: attr(), - user: belongsTo('user', { async: false }) + user: belongsTo('user', { async: false }), }); Job.toString = stringify('job'); ReflexiveModel = DS.Model.extend({ - reflexiveProp: belongsTo('reflexive-model', { async: false }) + reflexiveProp: belongsTo('reflexive-model', { async: false }), }); ReflexiveModel.toString = stringify('reflexiveModel'); @@ -40,7 +42,7 @@ module('integration/inverse_test - inverseFor', { env = setupStore({ user: User, job: Job, - reflexiveModel: ReflexiveModel + reflexiveModel: ReflexiveModel, }); store = env.store; @@ -52,71 +54,83 @@ module('integration/inverse_test - inverseFor', { afterEach() { run(env.container, 'destroy'); - } + }, }); -test("Finds the inverse when there is only one possible available", function(assert) { +test('Finds the inverse when there is only one possible available', function(assert) { let inverseDefinition = Job.inverseFor('user', store); - assert.deepEqual(inverseDefinition, { - type: User, - name: 'job', - kind: 'belongsTo', - options: { - async: false - } - }, 'Gets correct type, name and kind'); + assert.deepEqual( + inverseDefinition, + { + type: User, + name: 'job', + kind: 'belongsTo', + options: { + async: false, + }, + }, + 'Gets correct type, name and kind' + ); }); -test("Finds the inverse when only one side has defined it manually", function(assert) { +test('Finds the inverse when only one side has defined it manually', function(assert) { Job.reopen({ - owner: belongsTo('user', { inverse: 'previousJob', async: false }) + owner: belongsTo('user', { inverse: 'previousJob', async: false }), }); User.reopen({ - previousJob: belongsTo('job', { async: false }) + previousJob: belongsTo('job', { async: false }), }); - assert.deepEqual(Job.inverseFor('owner', store), { - type: User, //the model's type - name: 'previousJob', //the models relationship key - kind: 'belongsTo', - options: { - async: false - } - }, 'Gets correct type, name and kind'); - - assert.deepEqual(User.inverseFor('previousJob', store), { - type: Job, //the model's type - name: 'owner', //the models relationship key - kind: 'belongsTo', - options: { - inverse: 'previousJob', - async: false - } - }, 'Gets correct type, name and kind'); + assert.deepEqual( + Job.inverseFor('owner', store), + { + type: User, //the model's type + name: 'previousJob', //the models relationship key + kind: 'belongsTo', + options: { + async: false, + }, + }, + 'Gets correct type, name and kind' + ); + + assert.deepEqual( + User.inverseFor('previousJob', store), + { + type: Job, //the model's type + name: 'owner', //the models relationship key + kind: 'belongsTo', + options: { + inverse: 'previousJob', + async: false, + }, + }, + 'Gets correct type, name and kind' + ); }); -test("Returns null if inverse relationship it is manually set with a different relationship key", function(assert) { +test('Returns null if inverse relationship it is manually set with a different relationship key', function(assert) { Job.reopen({ - user: belongsTo('user', { inverse: 'previousJob', async: false }) + user: belongsTo('user', { inverse: 'previousJob', async: false }), }); User.reopen({ - job: belongsTo('job', { async: false }) + job: belongsTo('job', { async: false }), }); assert.equal(User.inverseFor('job', store), null, 'There is no inverse'); }); -testInDebug("Errors out if you define 2 inverses to the same model", function(assert) { +testInDebug('Errors out if you define 2 inverses to the same model', function(assert) { Job.reopen({ user: belongsTo('user', { inverse: 'job', async: false }), - owner: belongsTo('user', { inverse: 'job', async: false }) + owner: belongsTo('user', { inverse: 'job', async: false }), }); User.reopen({ - job: belongsTo('job', { async: false }) + job: belongsTo('job', { async: false }), }); assert.expectAssertion(() => { @@ -124,8 +138,7 @@ testInDebug("Errors out if you define 2 inverses to the same model", function(as }, /You defined the 'job' relationship on user, but you defined the inverse relationships of type job multiple times/i); }); - -test("Caches findInverseFor return value", function(assert) { +test('Caches findInverseFor return value', function(assert) { assert.expect(1); var inverseForUser = Job.inverseFor('user', store); @@ -136,8 +149,9 @@ test("Caches findInverseFor return value", function(assert) { assert.equal(inverseForUser, Job.inverseFor('user', store), 'Inverse cached succesfully'); }); -testInDebug("Errors out if you do not define an inverse for a reflexive relationship", function(assert) { - +testInDebug('Errors out if you do not define an inverse for a reflexive relationship', function( + assert +) { //Maybe store is evaluated lazily, so we need this :( assert.expectWarning(() => { var reflexiveModel; @@ -145,8 +159,8 @@ testInDebug("Errors out if you do not define an inverse for a reflexive relation store.push({ data: { type: 'reflexive-model', - id: '1' - } + id: '1', + }, }); reflexiveModel = store.peekRecord('reflexive-model', 1); reflexiveModel.get('reflexiveProp'); diff --git a/tests/integration/lifecycle-hooks-test.js b/tests/integration/lifecycle-hooks-test.js index 9e6de92c52e..aaf85583e20 100644 --- a/tests/integration/lifecycle-hooks-test.js +++ b/tests/integration/lifecycle-hooks-test.js @@ -9,55 +9,55 @@ import DS from 'ember-data'; let Person, env; const { attr } = DS; -module("integration/lifecycle_hooks - Lifecycle Hooks", { +module('integration/lifecycle_hooks - Lifecycle Hooks', { beforeEach() { Person = DS.Model.extend({ - name: attr('string') + name: attr('string'), }); env = setupStore({ - person: Person + person: Person, }); }, afterEach() { run(env.container, 'destroy'); - } + }, }); -test("When the adapter acknowledges that a record has been created, a `didCreate` event is triggered.", function(assert) { +test('When the adapter acknowledges that a record has been created, a `didCreate` event is triggered.', function(assert) { let done = assert.async(); assert.expect(3); env.adapter.createRecord = function(store, type, snapshot) { - return resolve({ data: { id: 99, type: "person", attributes: { name: "Yehuda Katz" } } }); + return resolve({ data: { id: 99, type: 'person', attributes: { name: 'Yehuda Katz' } } }); }; - let person = env.store.createRecord('person', { name: "Yehuda Katz" }); + let person = env.store.createRecord('person', { name: 'Yehuda Katz' }); person.on('didCreate', function() { - assert.equal(this, person, "this is bound to the record"); - assert.equal(this.get('id'), "99", "the ID has been assigned"); - assert.equal(this.get('name'), "Yehuda Katz", "the attribute has been assigned"); + assert.equal(this, person, 'this is bound to the record'); + assert.equal(this.get('id'), '99', 'the ID has been assigned'); + assert.equal(this.get('name'), 'Yehuda Katz', 'the attribute has been assigned'); done(); }); run(person, 'save'); }); -test("When the adapter acknowledges that a record has been created without a new data payload, a `didCreate` event is triggered.", function(assert) { +test('When the adapter acknowledges that a record has been created without a new data payload, a `didCreate` event is triggered.', function(assert) { assert.expect(3); env.adapter.createRecord = function(store, type, snapshot) { return resolve(); }; - let person = env.store.createRecord('person', { id: 99, name: "Yehuda Katz" }); + let person = env.store.createRecord('person', { id: 99, name: 'Yehuda Katz' }); person.on('didCreate', function() { - assert.equal(this, person, "this is bound to the record"); - assert.equal(this.get('id'), "99", "the ID has been assigned"); - assert.equal(this.get('name'), "Yehuda Katz", "the attribute has been assigned"); + assert.equal(this, person, 'this is bound to the record'); + assert.equal(this.get('id'), '99', 'the ID has been assigned'); + assert.equal(this.get('name'), 'Yehuda Katz', 'the attribute has been assigned'); }); run(person, 'save'); diff --git a/tests/integration/multiple-stores-test.js b/tests/integration/multiple-stores-test.js index b632c75562a..2081e0d6743 100644 --- a/tests/integration/multiple-stores-test.js +++ b/tests/integration/multiple-stores-test.js @@ -8,27 +8,27 @@ import DS from 'ember-data'; let env; let SuperVillain, HomePlanet, EvilMinion; -module("integration/multiple_stores - Multiple Stores Tests", { +module('integration/multiple_stores - Multiple Stores Tests', { beforeEach() { SuperVillain = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - homePlanet: DS.belongsTo('home-planet', { inverse: 'villains', async: false }), - evilMinions: DS.hasMany('evil-minion', { async: false }) + firstName: DS.attr('string'), + lastName: DS.attr('string'), + homePlanet: DS.belongsTo('home-planet', { inverse: 'villains', async: false }), + evilMinions: DS.hasMany('evil-minion', { async: false }), }); HomePlanet = DS.Model.extend({ - name: DS.attr('string'), - villains: DS.hasMany('super-villain', { inverse: 'homePlanet', async: false }) + name: DS.attr('string'), + villains: DS.hasMany('super-villain', { inverse: 'homePlanet', async: false }), }); EvilMinion = DS.Model.extend({ - superVillain: DS.belongsTo('super-villain', { async: false }), - name: DS.attr('string') + superVillain: DS.belongsTo('super-villain', { async: false }), + name: DS.attr('string'), }); env = setupStore({ - superVillain: SuperVillain, - homePlanet: HomePlanet, - evilMinion: EvilMinion + superVillain: SuperVillain, + homePlanet: HomePlanet, + evilMinion: EvilMinion, }); env.registry.register('adapter:application', DS.RESTAdapter); @@ -43,13 +43,16 @@ module("integration/multiple_stores - Multiple Stores Tests", { afterEach() { run(env.store, 'destroy'); - } + }, }); -test("should be able to push into multiple stores", function(assert) { - env.registry.register('adapter:home-planet', DS.RESTAdapter.extend({ - shouldBackgroundReloadRecord: () => false - })); +test('should be able to push into multiple stores', function(assert) { + env.registry.register( + 'adapter:home-planet', + DS.RESTAdapter.extend({ + shouldBackgroundReloadRecord: () => false, + }) + ); let home_planet_main = { id: '1', name: 'Earth' }; let home_planet_a = { id: '1', name: 'Mars' }; @@ -61,24 +64,31 @@ test("should be able to push into multiple stores", function(assert) { env.store_b.push(env.store_b.normalize('home-planet', home_planet_b)); }); - return env.store.findRecord('home-planet', 1).then(homePlanet => { - assert.equal(homePlanet.get('name'), 'Earth'); - - return env.store_a.findRecord('homePlanet', 1); - }).then(homePlanet => { - assert.equal(homePlanet.get('name'), 'Mars'); - return env.store_b.findRecord('homePlanet', 1); - }).then(homePlanet => { - assert.equal(homePlanet.get('name'), 'Saturn'); - }); + return env.store + .findRecord('home-planet', 1) + .then(homePlanet => { + assert.equal(homePlanet.get('name'), 'Earth'); + + return env.store_a.findRecord('homePlanet', 1); + }) + .then(homePlanet => { + assert.equal(homePlanet.get('name'), 'Mars'); + return env.store_b.findRecord('homePlanet', 1); + }) + .then(homePlanet => { + assert.equal(homePlanet.get('name'), 'Saturn'); + }); }); -test("embedded records should be created in multiple stores", function(assert) { - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' } - } - })); +test('embedded records should be created in multiple stores', function(assert) { + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + }, + }) + ); let serializer_main = env.store.serializerFor('home-planet'); let serializer_a = env.store_a.serializerFor('home-planet'); @@ -86,72 +96,118 @@ test("embedded records should be created in multiple stores", function(assert) { let json_hash_main = { homePlanet: { - id: "1", - name: "Earth", - villains: [{ - id: "1", - firstName: "Tom", - lastName: "Dale" - }] - } + id: '1', + name: 'Earth', + villains: [ + { + id: '1', + firstName: 'Tom', + lastName: 'Dale', + }, + ], + }, }; let json_hash_a = { homePlanet: { - id: "1", - name: "Mars", - villains: [{ - id: "1", - firstName: "James", - lastName: "Murphy" - }] - } + id: '1', + name: 'Mars', + villains: [ + { + id: '1', + firstName: 'James', + lastName: 'Murphy', + }, + ], + }, }; let json_hash_b = { homePlanet: { - id: "1", - name: "Saturn", - villains: [{ - id: "1", - firstName: "Jade", - lastName: "John" - }] - } + id: '1', + name: 'Saturn', + villains: [ + { + id: '1', + firstName: 'Jade', + lastName: 'John', + }, + ], + }, }; let json_main, json_a, json_b; run(() => { - json_main = serializer_main.normalizeResponse(env.store, env.store.modelFor('home-planet'), json_hash_main, 1, 'findRecord'); + json_main = serializer_main.normalizeResponse( + env.store, + env.store.modelFor('home-planet'), + json_hash_main, + 1, + 'findRecord' + ); env.store.push(json_main); - assert.equal(env.store.hasRecordForId('super-villain', "1"), true, "superVillain should exist in service:store"); + assert.equal( + env.store.hasRecordForId('super-villain', '1'), + true, + 'superVillain should exist in service:store' + ); }); run(() => { - json_a = serializer_a.normalizeResponse(env.store_a, env.store_a.modelFor('home-planet'), json_hash_a, 1, 'findRecord'); + json_a = serializer_a.normalizeResponse( + env.store_a, + env.store_a.modelFor('home-planet'), + json_hash_a, + 1, + 'findRecord' + ); env.store_a.push(json_a); - assert.equal(env.store_a.hasRecordForId("super-villain", "1"), true, "superVillain should exist in store:store-a"); + assert.equal( + env.store_a.hasRecordForId('super-villain', '1'), + true, + 'superVillain should exist in store:store-a' + ); }); run(() => { - json_b = serializer_b.normalizeResponse(env.store_b, env.store_a.modelFor('home-planet'), json_hash_b, 1, 'findRecord'); + json_b = serializer_b.normalizeResponse( + env.store_b, + env.store_a.modelFor('home-planet'), + json_hash_b, + 1, + 'findRecord' + ); env.store_b.push(json_b); - assert.equal(env.store_b.hasRecordForId("super-villain", "1"), true, "superVillain should exist in store:store-b"); + assert.equal( + env.store_b.hasRecordForId('super-villain', '1'), + true, + 'superVillain should exist in store:store-b' + ); }); }); - -test("each store should have a unique instance of the serializers", function(assert) { +test('each store should have a unique instance of the serializers', function(assert) { env.registry.register('serializer:home-planet', DS.RESTSerializer.extend({})); let serializer_a = env.store_a.serializerFor('home-planet'); let serializer_b = env.store_b.serializerFor('home-planet'); - assert.equal(get(serializer_a, 'store'), env.store_a, 'serializer_a\'s store prop should be sotre_a'); - assert.equal(get(serializer_b, 'store'), env.store_b, 'serializer_b\'s store prop should be sotre_b'); - assert.notEqual(serializer_a, serializer_b, 'serialier_a and serialier_b should be unique instances'); + assert.equal( + get(serializer_a, 'store'), + env.store_a, + "serializer_a's store prop should be sotre_a" + ); + assert.equal( + get(serializer_b, 'store'), + env.store_b, + "serializer_b's store prop should be sotre_b" + ); + assert.notEqual( + serializer_a, + serializer_b, + 'serialier_a and serialier_b should be unique instances' + ); }); - -test("each store should have a unique instance of the adapters", function(assert) { +test('each store should have a unique instance of the adapters', function(assert) { env.registry.register('adapter:home-planet', DS.Adapter.extend({})); let adapter_a = env.store_a.adapterFor('home-planet'); diff --git a/tests/integration/peek-all-test.js b/tests/integration/peek-all-test.js index c023ee7ee96..28560111ac6 100644 --- a/tests/integration/peek-all-test.js +++ b/tests/integration/peek-all-test.js @@ -8,31 +8,36 @@ import DS from 'ember-data'; let Person, store, array, moreArray; -module("integration/peek-all - DS.Store#peekAll()", { +module('integration/peek-all - DS.Store#peekAll()', { beforeEach() { array = { - data: [{ - type: 'person', - id: '1', - attributes: { - name: "Scumbag Dale" - } - }, { - type: 'person', - id: '2', - attributes: { - name: "Scumbag Katz" - } - }] + 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" - } - }] + data: [ + { + type: 'person', + id: '3', + attributes: { + name: 'Scumbag Bryn', + }, + }, + ], }; Person = DS.Model.extend({ name: DS.attr('string') }); @@ -43,7 +48,7 @@ module("integration/peek-all - DS.Store#peekAll()", { run(store, 'destroy'); Person = null; array = null; - } + }, }); test("store.peekAll('person') should return all records and should update with new ones", function(assert) { @@ -61,31 +66,31 @@ test("store.peekAll('person') should return all records and should update with n assert.equal(get(all, 'length'), 3); }); -test("Calling store.peekAll() multiple times should update immediately inside the runloop", function(assert) { +test('Calling store.peekAll() multiple times should update immediately inside the runloop', function(assert) { assert.expect(3); run(() => { assert.equal(get(store.peekAll('person'), 'length'), 0, 'should initially be empty'); - store.createRecord('person', { name: "Tomster" }); + store.createRecord('person', { name: 'Tomster' }); assert.equal(get(store.peekAll('person'), 'length'), 1, 'should contain one person'); store.push({ data: { type: 'person', id: '1', attributes: { - name: "Tomster's friend" - } - } + name: "Tomster's friend", + }, + }, }); assert.equal(get(store.peekAll('person'), 'length'), 2, 'should contain two people'); }); }); -test("Calling store.peekAll() after creating a record should return correct data", function(assert) { +test('Calling store.peekAll() after creating a record should return correct data', function(assert) { assert.expect(1); run(() => { - store.createRecord('person', { name: "Tomster" }); + store.createRecord('person', { name: 'Tomster' }); assert.equal(get(store.peekAll('person'), 'length'), 1, 'should contain one person'); }); }); diff --git a/tests/integration/polymorphic-belongs-to-test.js b/tests/integration/polymorphic-belongs-to-test.js index a6272b795a9..558f0419be2 100644 --- a/tests/integration/polymorphic-belongs-to-test.js +++ b/tests/integration/polymorphic-belongs-to-test.js @@ -11,15 +11,15 @@ let store; const Book = DS.Model.extend({ title: attr(), - author: belongsTo('person', { polymorphic: true, async: false }) + author: belongsTo('person', { polymorphic: true, async: false }), }); const Author = DS.Model.extend({ - name: attr() + name: attr(), }); const AsyncBook = DS.Model.extend({ - author: belongsTo('person', { polymorphic: true }) + author: belongsTo('person', { polymorphic: true }), }); module('integration/polymorphic-belongs-to - Polymorphic BelongsTo', { @@ -28,18 +28,17 @@ module('integration/polymorphic-belongs-to - Polymorphic BelongsTo', { book: Book, author: Author, 'async-book': AsyncBook, - person: DS.Model.extend() + person: DS.Model.extend(), }); store = env.store; }, afterEach() { run(store, 'destroy'); - } + }, }); - -test('using store.push with a null value for a payload in relationships sets the Models relationship to null - sync relationship', (assert) => { +test('using store.push with a null value for a payload in relationships sets the Models relationship to null - sync relationship', assert => { let payload = { data: { type: 'book', @@ -49,18 +48,18 @@ test('using store.push with a null value for a payload in relationships sets the author: { data: { type: 'author', - id: 1 - } - } - } + id: 1, + }, + }, + }, }, included: [ { id: 1, name: 'Amy Poehler', - type: 'author' - } - ] + type: 'author', + }, + ], }; let book = run(() => { @@ -77,17 +76,17 @@ test('using store.push with a null value for a payload in relationships sets the title: 'Yes, Please', relationships: { author: { - data: null - } - } - } + data: null, + }, + }, + }, }; run(() => store.push(payloadThatResetsBelongToRelationship)); assert.strictEqual(book.get('author'), null); }); -test('using store.push with a null value for a payload in relationships sets the Models relationship to null - async relationship', (assert) => { +test('using store.push with a null value for a payload in relationships sets the Models relationship to null - async relationship', assert => { let payload = { data: { type: 'async-book', @@ -97,18 +96,18 @@ test('using store.push with a null value for a payload in relationships sets the author: { data: { type: 'author', - id: 1 - } - } - } + id: 1, + }, + }, + }, }, included: [ { id: 1, name: 'Amy Poehler', - type: 'author' - } - ] + type: 'author', + }, + ], }; let book = run(() => { @@ -123,17 +122,20 @@ test('using store.push with a null value for a payload in relationships sets the title: 'Yes, Please', relationships: { author: { - data: null - } - } - } + data: null, + }, + }, + }, }; - return book.get('author').then(author => { - assert.equal(author.get('id'), 1); - run(() => store.push(payloadThatResetsBelongToRelationship)); - return book.get('author'); - }).then(author => { - assert.strictEqual(author, null); - }); + return book + .get('author') + .then(author => { + assert.equal(author.get('id'), 1); + run(() => store.push(payloadThatResetsBelongToRelationship)); + return book.get('author'); + }) + .then(author => { + assert.strictEqual(author, null); + }); }); diff --git a/tests/integration/record-array-manager-test.js b/tests/integration/record-array-manager-test.js index d46e0ea72a2..ba276658cfd 100644 --- a/tests/integration/record-array-manager-test.js +++ b/tests/integration/record-array-manager-test.js @@ -11,19 +11,19 @@ let store, env, manager; const Person = DS.Model.extend({ name: DS.attr('string'), - cars: DS.hasMany('car', { async: false }) + cars: DS.hasMany('car', { async: false }), }); const Car = DS.Model.extend({ make: DS.attr('string'), model: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); module('integration/record_array_manager', { beforeEach() { env = setupStore({ - adapter: DS.RESTAdapter.extend() + adapter: DS.RESTAdapter.extend(), }); store = env.store; @@ -31,7 +31,7 @@ module('integration/record_array_manager', { env.registry.register('model:car', Car); env.registry.register('model:person', Person); - } + }, }); function tap(obj, methodName, callback) { @@ -52,7 +52,7 @@ function tap(obj, methodName, callback) { } test('destroying the store correctly cleans everything up', function(assert) { - let query = { }; + let query = {}; let person; run(() => { @@ -62,14 +62,14 @@ test('destroying the store correctly cleans everything up', function(assert) { id: '1', attributes: { make: 'BMC', - model: 'Mini Cooper' + model: 'Mini Cooper', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } - } + data: { type: 'person', id: '1' }, + }, + }, + }, }); }); @@ -79,16 +79,14 @@ test('destroying the store correctly cleans everything up', function(assert) { type: 'person', id: '1', attributes: { - name: 'Tom Dale' + name: 'Tom Dale', }, relationships: { cars: { - data: [ - { type: 'car', id: '1' } - ] - } - } - } + data: [{ type: 'car', id: '1' }], + }, + }, + }, }); person = store.peekRecord('person', 1); }); @@ -101,18 +99,30 @@ test('destroying the store correctly cleans everything up', function(assert) { assert.equal(allSummary.called.length, 0); assert.equal(adapterPopulatedSummary.called.length, 0); - assert.equal(internalPersonModel._recordArrays.size, 1, 'expected the person to be a member of 1 recordArrays'); + assert.equal( + internalPersonModel._recordArrays.size, + 1, + 'expected the person to be a member of 1 recordArrays' + ); assert.equal('person' in manager._liveRecordArrays, true); run(all, all.destroy); - assert.equal(internalPersonModel._recordArrays.size, 0, 'expected the person to be a member of 1 recordArrays'); + assert.equal( + internalPersonModel._recordArrays.size, + 0, + 'expected the person to be a member of 1 recordArrays' + ); assert.equal(allSummary.called.length, 1); assert.equal('person' in manager._liveRecordArrays, false); run(manager, manager.destroy); - assert.equal(internalPersonModel._recordArrays.size, 0, 'expected the person to be a member of no recordArrays'); + assert.equal( + internalPersonModel._recordArrays.size, + 0, + 'expected the person to be a member of no recordArrays' + ); assert.equal(allSummary.called.length, 1); assert.equal(adapterPopulatedSummary.called.length, 1); }); @@ -139,27 +149,24 @@ test('batch liveRecordArray changes', function(assert) { id: '1', attributes: { make: 'BMC', - model: 'Mini Cooper' - } + model: 'Mini Cooper', + }, }, { type: 'car', id: '2', attributes: { make: 'Jeep', - model: 'Wrangler' - } - } - ] + model: 'Wrangler', + }, + }, + ], }); }); assert.equal(arrayContentWillChangeCount, 1, 'expected ONE array change event'); - assert.deepEqual(cars.toArray(), [ - store.peekRecord('car', 1), - store.peekRecord('car', 2) - ]); + assert.deepEqual(cars.toArray(), [store.peekRecord('car', 1), store.peekRecord('car', 2)]); run(() => store.peekRecord('car', 1).set('model', 'Mini')); @@ -182,10 +189,10 @@ test('batch liveRecordArray changes', function(assert) { id: 2, // this ID is already present, array wont need to change attributes: { make: 'Tesla', - model: 'S' - } - } - ] + model: 'S', + }, + }, + ], }); }); @@ -199,10 +206,10 @@ test('batch liveRecordArray changes', function(assert) { id: 3, attributes: { make: 'Tesla', - model: 'S' - } - } - ] + model: 'S', + }, + }, + ], }); }); @@ -217,9 +224,9 @@ test('#GH-4041 store#query AdapterPopulatedRecordArrays are removed from their m id: '1', attributes: { make: 'Honda', - model: 'fit' - } - } + model: 'fit', + }, + }, }); }); @@ -242,13 +249,13 @@ test('createRecordArray', function(assert) { assert.deepEqual(recordArray.toArray(), []); }); -test('createRecordArray \w optional content', function(assert) { +test('createRecordArray with optional content', function(assert) { let record = {}; let internalModel = { _recordArrays: new OrderedSet(), getRecord() { return record; - } + }, }; let content = A([internalModel]); let recordArray = manager.createRecordArray('foo', content); @@ -263,7 +270,7 @@ test('createRecordArray \w optional content', function(assert) { }); test('liveRecordArrayFor always return the same array for a given type', function(assert) { - assert.equal(manager.liveRecordArrayFor('foo'), manager.liveRecordArrayFor('foo')) + assert.equal(manager.liveRecordArrayFor('foo'), manager.liveRecordArrayFor('foo')); }); test('liveRecordArrayFor create with content', function(assert) { @@ -287,9 +294,9 @@ test('liveRecordArrayFor create with content', function(assert) { id: '1', attributes: { make: 'BMC', - model: 'Mini Cooper' - } - } + model: 'Mini Cooper', + }, + }, }); }); @@ -327,26 +334,28 @@ test('[DEPRECATED FILTER SUPPORT until 3.5]', function(assert) { assert.equal(updatesWithoutLiveArrayChangeCount, 0, 'expected NO silent updates yet'); assert.equal(updatesSignaledCount, 0, 'expected NO signals yet'); - let [car1, car2] = run(() => store.push({ - data: [ - { - type: 'car', - id: '1', - attributes: { - make: 'BMC', - model: 'Mini Cooper' - } - }, - { - type: 'car', - id: '2', - attributes: { - make: 'Jeep', - model: 'Wrangler' - } - } - ] - })); + let [car1, car2] = run(() => + store.push({ + data: [ + { + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini Cooper', + }, + }, + { + type: 'car', + id: '2', + attributes: { + make: 'Jeep', + model: 'Wrangler', + }, + }, + ], + }) + ); assert.equal(arrayContentWillChangeCount, 1, 'expected ONE array change event'); assert.equal(updatesWithoutLiveArrayChangeCount, 0, 'expected NO silent updates yet'); @@ -367,16 +376,18 @@ test('[DEPRECATED FILTER SUPPORT until 3.5]', function(assert) { updatesWithoutLiveArrayChangeCount = 0; updatesSignaledCount = 0; - run(() => store.push({ - data: { - type: 'car', - id: '2', // this ID is already present, array wont need to change - attributes: { - make: 'Tesla', - model: 'S' - } - } - })); + run(() => + store.push({ + data: { + type: 'car', + id: '2', // this ID is already present, array wont need to change + attributes: { + make: 'Tesla', + model: 'S', + }, + }, + }) + ); assert.equal(arrayContentWillChangeCount, 0, 'expected NO array change events'); assert.equal(updatesWithoutLiveArrayChangeCount, 1, 'expected ONE silent update'); @@ -386,16 +397,18 @@ test('[DEPRECATED FILTER SUPPORT until 3.5]', function(assert) { updatesWithoutLiveArrayChangeCount = 0; updatesSignaledCount = 0; - run(() => store.push({ - data: { - type: 'car', - id: '3', - attributes: { - make: 'Tesla', - model: 'S' - } - } - })); + run(() => + store.push({ + data: { + type: 'car', + id: '3', + attributes: { + make: 'Tesla', + model: 'S', + }, + }, + }) + ); assert.equal(arrayContentWillChangeCount, 1, 'expected ONE array change event'); assert.equal(updatesWithoutLiveArrayChangeCount, 0, 'expected ONE silent update'); diff --git a/tests/integration/record-array-test.js b/tests/integration/record-array-test.js index 02b73cc5aba..cb2bd5c2963 100644 --- a/tests/integration/record-array-test.js +++ b/tests/integration/record-array-test.js @@ -12,15 +12,15 @@ let results; const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); const Tag = DS.Model.extend({ - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); const Tool = DS.Model.extend({ - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); module('unit/record_array - DS.RecordArray', { @@ -29,10 +29,10 @@ module('unit/record_array - DS.RecordArray', { data: [ { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } }, - { id: '3', type: 'person', attributes: { name: 'Scumbag Bryn' } } - ] + { id: '3', type: 'person', attributes: { name: 'Scumbag Bryn' } }, + ], }; - } + }, }); test('a record array is backed by records', function(assert) { @@ -43,8 +43,8 @@ test('a record array is backed by records', function(assert) { adapter: DS.Adapter.extend({ shouldBackgroundReloadRecord() { return false; - } - }) + }, + }), }); run(() => { @@ -54,31 +54,39 @@ test('a record array is backed by records', function(assert) { type: 'person', id: '1', attributes: { - name: 'Scumbag Dale' - } + name: 'Scumbag Dale', + }, }, { type: 'person', id: '2', attributes: { - name: 'Scumbag Katz' - } + name: 'Scumbag Katz', + }, }, { type: 'person', id: '3', attributes: { - name: 'Scumbag Bryn' - } - }] + name: 'Scumbag Bryn', + }, + }, + ], }); }); return run(() => { - return store.findByIds('person', [1,2,3]).then(records => { - for (let i=0, l = get(results, 'data.length'); i { + for (let i = 0, l = get(results, 'data.length'); i < l; i++) { + let { + id, + attributes: { name }, + } = results.data[i]; + assert.deepEqual( + records[i].getProperties('id', 'name'), + { id, name }, + 'a record array materializes objects on demand' + ); } }); }); @@ -86,7 +94,7 @@ test('a record array is backed by records', function(assert) { test('acts as a live query', function(assert) { let store = createStore({ - person: Person + person: Person, }); let recordArray = store.peekAll('person'); @@ -97,9 +105,9 @@ test('acts as a live query', function(assert) { type: 'person', id: '1', attributes: { - name: 'wycats' - } - } + name: 'wycats', + }, + }, }); }); @@ -111,18 +119,18 @@ test('acts as a live query', function(assert) { type: 'person', id: '2', attributes: { - name: 'brohuda' - } - } + name: 'brohuda', + }, + }, }); }); assert.equal(get(recordArray, 'lastObject.name'), 'brohuda'); }); -test('acts as a live query (normalized names)', function (assert) { +test('acts as a live query (normalized names)', function(assert) { let store = createStore({ person: Person, - Person: Person + Person: Person, }); let recordArray = store.peekAll('Person'); @@ -133,9 +141,9 @@ test('acts as a live query (normalized names)', function (assert) { type: 'Person', id: '1', attributes: { - name: 'John Churchill' - } - } + name: 'John Churchill', + }, + }, }); }); @@ -147,9 +155,9 @@ test('acts as a live query (normalized names)', function (assert) { type: 'Person', id: '2', attributes: { - name: 'Winston Churchill' - } - } + name: 'Winston Churchill', + }, + }, }); }); assert.deepEqual(recordArray.mapBy('name'), ['John Churchill', 'Winston Churchill']); @@ -159,7 +167,7 @@ test('stops updating when destroyed', function(assert) { assert.expect(3); let store = createStore({ - person: Person + person: Person, }); let recordArray = store.peekAll('person'); @@ -169,9 +177,9 @@ test('stops updating when destroyed', function(assert) { type: 'person', id: '1', attributes: { - name: 'wycats' - } - } + name: 'wycats', + }, + }, }); }); @@ -184,9 +192,9 @@ test('stops updating when destroyed', function(assert) { type: 'person', id: '2', attributes: { - name: 'brohuda' - } - } + name: 'brohuda', + }, + }, }); }); @@ -206,43 +214,48 @@ test('a loaded record is removed from a record array when it is deleted', functi }, shouldBackgroundReloadRecord() { return false; - } - }) + }, + }), }); let store = env.store; run(() => { 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' - }] + 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', + }, + ], }); }); return run(() => { return hash({ scumbag: store.findRecord('person', 1), - tag: store.findRecord('tag', 1) + tag: store.findRecord('tag', 1), }).then(records => { let scumbag = records.scumbag; let tag = records.tag; @@ -254,28 +267,40 @@ test('a loaded record is removed from a record array when it is deleted', functi let recordArray = tag.get('people'); assert.equal(get(recordArray, 'length'), 1, 'precond - record array has one item'); - assert.equal(get(recordArray.objectAt(0), 'name'), 'Scumbag Dale', "item at index 0 is record with id 1"); + assert.equal( + get(recordArray.objectAt(0), 'name'), + 'Scumbag Dale', + 'item at index 0 is record with id 1' + ); scumbag.deleteRecord(); - assert.equal(get(recordArray, 'length'), 1, 'record is still in the record array until it is saved'); + assert.equal( + get(recordArray, 'length'), + 1, + 'record is still in the record array until it is saved' + ); run(scumbag, 'save'); - assert.equal(get(recordArray, 'length'), 0, 'record is removed from the array when it is saved'); + assert.equal( + get(recordArray, 'length'), + 0, + 'record is removed from the array when it is saved' + ); }); }); }); -test('a loaded record is not removed from a record array when it is deleted even if the belongsTo side isn\'t defined', function(assert) { +test("a loaded record is not removed from a record array when it is deleted even if the belongsTo side isn't defined", function(assert) { let env = setupStore({ tag: Tag, - person: Person.reopen({tags: null }), + person: Person.reopen({ tags: null }), adapter: DS.Adapter.extend({ deleteRecord() { return Promise.resolve(); - } - }) + }, + }), }); let store = env.store; @@ -283,23 +308,24 @@ test('a loaded record is not removed from a record array when it is deleted even run(() => { store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Scumbag Tom' - } - }, { - type: 'tag', - id: '1', - relationships: { - people: { - data: [ - { type: 'person', id: '1' } - ] - } - } - }] + 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); @@ -321,8 +347,8 @@ test("a loaded record is not removed from both the record array and from the bel adapter: DS.Adapter.extend({ deleteRecord() { return Promise.resolve(); - } - }) + }, + }), }); let store = env.store; @@ -330,31 +356,33 @@ test("a loaded record is not removed from both the record array and from the bel run(() => { 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' } - } - } - }] + 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); @@ -376,14 +404,18 @@ test("a loaded record is not removed from both the record array and from the bel test('a newly created record is removed from a record array when it is deleted', function(assert) { let store = createStore({ person: Person, - tag: Tag + tag: Tag, }); let recordArray = store.peekAll('person'); let scumbag = store.createRecord('person', { - name: 'Scumbag Dale' + name: 'Scumbag Dale', }); - assert.equal(get(recordArray, 'length'), 1, 'precond - record array already has the first created item'); + assert.equal( + get(recordArray, 'length'), + 1, + 'precond - record array already has the first created item' + ); store.createRecord('person', { name: 'p1' }); store.createRecord('person', { name: 'p2' }); @@ -399,73 +431,85 @@ test('a newly created record is removed from a record array when it is deleted', test("a record array returns undefined when asking for a member outside of its content Array's range", function(assert) { let store = createStore({ - person: Person + person: Person, }); run(() => { 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' - } - }] + 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', + }, + }, + ], }); }); let recordArray = store.peekAll('person'); - assert.strictEqual(recordArray.objectAt(20), undefined, "objects outside of the range just return undefined"); + assert.strictEqual( + recordArray.objectAt(20), + undefined, + 'objects outside of the range just return undefined' + ); }); // This tests for a bug in the recordCache, where the records were being cached in the incorrect order. test('a record array should be able to be enumerated in any order', function(assert) { let store = createStore({ - person: Person + person: Person, }); run(() => { 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' - } - }] + 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', + }, + }, + ], }); }); let recordArray = store.peekAll('person'); - assert.equal(get(recordArray.objectAt(2), 'id'), 3, "should retrieve correct record at index 2"); - assert.equal(get(recordArray.objectAt(1), 'id'), 2, "should retrieve correct record at index 1"); - assert.equal(get(recordArray.objectAt(0), 'id'), 1, "should retrieve correct record at index 0"); + assert.equal(get(recordArray.objectAt(2), 'id'), 3, 'should retrieve correct record at index 2'); + assert.equal(get(recordArray.objectAt(1), 'id'), 2, 'should retrieve correct record at index 1'); + assert.equal(get(recordArray.objectAt(0), 'id'), 1, 'should retrieve correct record at index 0'); }); test("an AdapterPopulatedRecordArray knows if it's loaded or not", function(assert) { @@ -480,7 +524,7 @@ test("an AdapterPopulatedRecordArray knows if it's loaded or not", function(asse return run(() => { return store.query('person', { page: 1 }).then(people => { - assert.equal(get(people, 'isLoaded'), true, "The array is now loaded"); + assert.equal(get(people, 'isLoaded'), true, 'The array is now loaded'); }); }); }); diff --git a/tests/integration/record-arrays/adapter-populated-record-array-test.js b/tests/integration/record-arrays/adapter-populated-record-array-test.js index 809c3e92ed7..6d376136442 100644 --- a/tests/integration/record-arrays/adapter-populated-record-array-test.js +++ b/tests/integration/record-arrays/adapter-populated-record-array-test.js @@ -12,28 +12,29 @@ const Person = DS.Model.extend({ name: DS.attr('string'), toString() { return ``; - } + }, }); - const adapter = DS.Adapter.extend({ deleteRecord() { return Promise.resolve(); - } + }, }); -module('integration/record-arrays/adapter_populated_record_array - DS.AdapterPopulatedRecordArray', { - beforeEach() { - store = createStore({ - adapter: adapter, - person: Person - }); +module( + 'integration/record-arrays/adapter_populated_record_array - DS.AdapterPopulatedRecordArray', + { + beforeEach() { + store = createStore({ + adapter: adapter, + person: Person, + }); + }, } -}); +); test('when a record is deleted in an adapter populated record array, it should be removed', function(assert) { - let recordArray = store.recordArrayManager - .createAdapterPopulatedRecordArray('person', null); + let recordArray = store.recordArrayManager.createAdapterPopulatedRecordArray('person', null); let payload = { data: [ @@ -41,40 +42,39 @@ test('when a record is deleted in an adapter populated record array, it should b type: 'person', id: '1', attributes: { - name: 'Scumbag Dale' - } + name: 'Scumbag Dale', + }, }, { type: 'person', id: '2', attributes: { - name: 'Scumbag Katz' - } + name: 'Scumbag Katz', + }, }, { type: 'person', id: '3', attributes: { - name: 'Scumbag Bryn' - } - } - ] + name: 'Scumbag Bryn', + }, + }, + ], }; run(() => { recordArray._setInternalModels(store._push(payload), payload); }); - assert.equal(recordArray.get('length'), 3, "expected recordArray to contain exactly 3 records"); + assert.equal(recordArray.get('length'), 3, 'expected recordArray to contain exactly 3 records'); run(() => recordArray.get('firstObject').destroyRecord()); - assert.equal(recordArray.get('length'), 2, "expected recordArray to contain exactly 2 records"); + assert.equal(recordArray.get('length'), 2, 'expected recordArray to contain exactly 2 records'); }); test('stores the metadata off the payload', function(assert) { - let recordArray = store.recordArrayManager - .createAdapterPopulatedRecordArray('person', null); + let recordArray = store.recordArrayManager.createAdapterPopulatedRecordArray('person', null); let payload = { data: [ @@ -82,27 +82,27 @@ test('stores the metadata off the payload', function(assert) { type: 'person', id: '1', attributes: { - name: 'Scumbag Dale' - } + name: 'Scumbag Dale', + }, }, { type: 'person', id: '2', attributes: { - name: 'Scumbag Katz' - } + name: 'Scumbag Katz', + }, }, { type: 'person', id: '3', attributes: { - name: 'Scumbag Bryn' - } - } + name: 'Scumbag Bryn', + }, + }, ], meta: { - foo: 'bar' - } + foo: 'bar', + }, }; run(() => { @@ -113,8 +113,7 @@ test('stores the metadata off the payload', function(assert) { }); test('stores the links off the payload', function(assert) { - let recordArray = store.recordArrayManager - .createAdapterPopulatedRecordArray('person', null); + let recordArray = store.recordArrayManager.createAdapterPopulatedRecordArray('person', null); let payload = { data: [ @@ -122,43 +121,50 @@ test('stores the links off the payload', function(assert) { type: 'person', id: '1', attributes: { - name: 'Scumbag Dale' - } + name: 'Scumbag Dale', + }, }, { type: 'person', id: '2', attributes: { - name: 'Scumbag Katz' - } + name: 'Scumbag Katz', + }, }, { type: 'person', id: '3', attributes: { - name: 'Scumbag Bryn' - } - } + name: 'Scumbag Bryn', + }, + }, ], links: { - first: '/foo?page=1' - } + first: '/foo?page=1', + }, }; run(() => { recordArray._setInternalModels(store._push(payload), payload); }); - assert.equal(recordArray.get('links.first'), '/foo?page=1', 'expected links.first to be "/foo?page=1" from payload'); + assert.equal( + recordArray.get('links.first'), + '/foo?page=1', + 'expected links.first to be "/foo?page=1" from payload' + ); }); test('recordArray.replace() throws error', function(assert) { - let recordArray = store.recordArrayManager - .createAdapterPopulatedRecordArray('person', null); - - assert.throws(() => { - recordArray.replace(); - }, Error('The result of a server query (on person) is immutable.'), 'throws error'); + let recordArray = store.recordArrayManager.createAdapterPopulatedRecordArray('person', null); + + assert.throws( + () => { + recordArray.replace(); + }, + Error('The result of a server query (on person) is immutable.'), + 'throws error' + ); }); test('pass record array to adapter.query based on arity', function(assert) { @@ -168,8 +174,8 @@ test('pass record array to adapter.query based on arity', function(assert) { let payload = { data: [ { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, - { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } } - ] + { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } }, + ], }; env.adapter.query = function(store, type, query) { @@ -177,12 +183,12 @@ test('pass record array to adapter.query based on arity', function(assert) { return payload; }; - return store.query('person', { }).then(recordArray => { + return store.query('person', {}).then(recordArray => { env.adapter.query = function(store, type, query, _recordArray) { assert.equal(arguments.length, 5); return payload; }; - return store.query('person', { }); + return store.query('person', {}); }); }); @@ -193,13 +199,14 @@ test('pass record array to adapter.query based on arity', function(assert) { let payload = { data: [ { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, - { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } } - ] + { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } }, + ], }; - let actualQuery = { }; + let actualQuery = {}; - let superCreateAdapterPopulatedRecordArray = store.recordArrayManager.createAdapterPopulatedRecordArray; + let superCreateAdapterPopulatedRecordArray = + store.recordArrayManager.createAdapterPopulatedRecordArray; store.recordArrayManager.createStore = function(modelName, query, internalModels, _payload) { assert.equal(arguments.length === 4); @@ -241,29 +248,36 @@ test('loadRecord re-syncs internalModels recordArrays', function(assert) { let payload = { data: [ { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, - { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } } - ] + { id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } }, + ], }; env.adapter.query = function(store, type, query, recordArray) { return payload; }; - return store.query('person', { }).then(recordArray => { - return recordArray.update().then(recordArray => { - assert.deepEqual(recordArray.getEach('name'), ['Scumbag Dale', 'Scumbag Katz'], 'expected query to contain specific records'); - - payload = { - data: [ - { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, - { id: '3', type: 'person', attributes: { name: 'Scumbag Penner' } } - ] - }; - - return recordArray.update(); - }).then(recordArray => { - assert.deepEqual(recordArray.getEach('name'), ['Scumbag Dale', 'Scumbag Penner']); - }); + return store.query('person', {}).then(recordArray => { + return recordArray + .update() + .then(recordArray => { + assert.deepEqual( + recordArray.getEach('name'), + ['Scumbag Dale', 'Scumbag Katz'], + 'expected query to contain specific records' + ); + + payload = { + data: [ + { id: '1', type: 'person', attributes: { name: 'Scumbag Dale' } }, + { id: '3', type: 'person', attributes: { name: 'Scumbag Penner' } }, + ], + }; + + return recordArray.update(); + }) + .then(recordArray => { + assert.deepEqual(recordArray.getEach('name'), ['Scumbag Dale', 'Scumbag Penner']); + }); }); }); @@ -291,14 +305,14 @@ test('when an adapter populated record gets updated the array contents are also findPromise = store.findAll('person'); // initialize adapter populated record array and assert initial state - queryPromise.then((_queryArr) => { + queryPromise.then(_queryArr => { queryArr = _queryArr; assert.equal(queryArr.get('length'), 0, 'No records for this query'); assert.equal(queryArr.get('isUpdating'), false, 'Record array isUpdating state updated'); }); // initialize a record collection array and assert initial state - findPromise.then((_findArr) => { + findPromise.then(_findArr => { findArray = _findArr; assert.equal(findArray.get('length'), 1, 'All records are included in collection array'); }); @@ -308,7 +322,11 @@ test('when an adapter populated record gets updated the array contents are also run(() => { array.push({ id: '2', type: 'person', attributes: { name: 'Scumbag Katz' } }); queryArr.update().then(() => { - assert.equal(queryArr.get('length'), 1, 'The new record is returned and added in adapter populated array'); + assert.equal( + queryArr.get('length'), + 1, + 'The new record is returned and added in adapter populated array' + ); assert.equal(queryArr.get('isUpdating'), false, 'Record array isUpdating state updated'); assert.equal(findArray.get('length'), 2); }); diff --git a/tests/integration/record-arrays/peeked-records-test.js b/tests/integration/record-arrays/peeked-records-test.js index f8aa2431791..9ea46a67b98 100644 --- a/tests/integration/record-arrays/peeked-records-test.js +++ b/tests/integration/record-arrays/peeked-records-test.js @@ -11,39 +11,41 @@ const Person = DS.Model.extend({ name: DS.attr('string'), toString() { return ``; - } + }, }); module('integration/peeked-records', { beforeEach() { store = createStore({ - person: Person + person: Person, }); - } + }, }); test('repeated calls to peekAll in separate run-loops works as expected', function(assert) { let peekedRecordArray = run(() => store.peekAll('person')); let watcher = watchProperties(peekedRecordArray, ['length', '[]']); - run(() => store.push({ - data: [ - { - type: 'person', - id: '1', - attributes: { - name: 'John' - } - }, - { - type: 'person', - id: '2', - attributes: { - name: 'Joe' - } - } - ] - })); + run(() => + store.push({ + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'John', + }, + }, + { + type: 'person', + id: '2', + attributes: { + name: 'Joe', + }, + }, + ], + }) + ); assert.watchedPropertyCounts( watcher, @@ -71,17 +73,17 @@ test('peekAll in the same run-loop as push works as expected', function(assert) type: 'person', id: '1', attributes: { - name: 'John' - } + name: 'John', + }, }, { type: 'person', id: '2', attributes: { - name: 'Joe' - } - } - ] + name: 'Joe', + }, + }, + ], }); store.peekAll('person'); }); @@ -105,7 +107,7 @@ test('newly created records notify the array as expected', function(assert) { let peekedRecordArray = run(() => store.peekAll('person')); let watcher = watchProperties(peekedRecordArray, ['length', '[]']); let aNewlyCreatedRecord = store.createRecord('person', { - name: 'James' + name: 'James', }); assert.watchedPropertyCounts( @@ -129,7 +131,7 @@ test('immediately peeking newly created records works as expected', function(ass let peekedRecordArray = run(() => store.peekAll('person')); let watcher = watchProperties(peekedRecordArray, ['length', '[]']); let aNewlyCreatedRecord = store.createRecord('person', { - name: 'James' + name: 'James', }); assert.watchedPropertyCounts( @@ -154,7 +156,7 @@ test('unloading newly created records notify the array as expected', function(as let peekedRecordArray = run(() => store.peekAll('person')); let watcher = watchProperties(peekedRecordArray, ['length', '[]']); let aNewlyCreatedRecord = store.createRecord('person', { - name: 'James' + name: 'James', }); assert.watchedPropertyCounts( @@ -178,7 +180,7 @@ test('immediately peeking after unloading newly created records works as expecte let peekedRecordArray = run(() => store.peekAll('person')); let watcher = watchProperties(peekedRecordArray, ['length', '[]']); let aNewlyCreatedRecord = store.createRecord('person', { - name: 'James' + name: 'James', }); assert.watchedPropertyCounts( @@ -210,17 +212,17 @@ test('unloadAll followed by peekAll in the same run-loop works as expected', fun type: 'person', id: '1', attributes: { - name: 'John' - } + name: 'John', + }, }, { type: 'person', id: '2', attributes: { - name: 'Joe' - } - } - ] + name: 'Joe', + }, + }, + ], }); }); @@ -241,7 +243,11 @@ test('unloadAll followed by peekAll in the same run-loop works as expected', fun 'RecordArray state after unloadAll has not changed yet' ); - assert.equal(get(peekedRecordArray, 'length'), 2, 'Array length is unchanged before the next peek'); + assert.equal( + get(peekedRecordArray, 'length'), + 2, + 'Array length is unchanged before the next peek' + ); store.peekAll('person'); @@ -270,17 +276,17 @@ test('push+materialize => unloadAll => push+materialize works as expected', func type: 'person', id: '1', attributes: { - name: 'John' - } + name: 'John', + }, }, { type: 'person', id: '2', attributes: { - name: 'Joe' - } - } - ] + name: 'Joe', + }, + }, + ], }); }); } @@ -327,17 +333,17 @@ test('push-without-materialize => unloadAll => push-without-materialize works as type: 'person', id: '1', attributes: { - name: 'John' - } + name: 'John', + }, }, { type: 'person', id: '2', attributes: { - name: 'Joe' - } - } - ] + name: 'Joe', + }, + }, + ], }); }); } @@ -374,4 +380,3 @@ test('push-without-materialize => unloadAll => push-without-materialize works as 'RecordArray state now has records again' ); }); - diff --git a/tests/integration/records/collection-save-test.js b/tests/integration/records/collection-save-test.js index cd715aa1083..c4f7b3bc900 100644 --- a/tests/integration/records/collection-save-test.js +++ b/tests/integration/records/collection-save-test.js @@ -8,10 +8,10 @@ import DS from 'ember-data'; let Post, env; -module("integration/records/collection_save - Save Collection of Records", { +module('integration/records/collection_save - Save Collection of Records', { beforeEach() { Post = DS.Model.extend({ - title: DS.attr('string') + title: DS.attr('string'), }); env = setupStore({ post: Post }); @@ -19,10 +19,10 @@ module("integration/records/collection_save - Save Collection of Records", { afterEach() { run(env.container, 'destroy'); - } + }, }); -test("Collection will resolve save on success", function(assert) { +test('Collection will resolve save on success', function(assert) { assert.expect(1); let id = 1; @@ -32,7 +32,7 @@ test("Collection will resolve save on success", function(assert) { let posts = env.store.peekAll('post'); env.adapter.createRecord = function(store, type, snapshot) { - return resolve({ data: { id: id++ , type: 'post' } }); + return resolve({ data: { id: id++, type: 'post' } }); }; return run(() => { @@ -42,7 +42,7 @@ test("Collection will resolve save on success", function(assert) { }); }); -test("Collection will reject save on error", function(assert) { +test('Collection will reject save on error', function(assert) { env.store.createRecord('post', { title: 'Hello' }); env.store.createRecord('post', { title: 'World' }); @@ -59,7 +59,7 @@ test("Collection will reject save on error", function(assert) { }); }); -test("Retry is allowed in a failure handler", function(assert) { +test('Retry is allowed in a failure handler', function(assert) { env.store.createRecord('post', { title: 'Hello' }); env.store.createRecord('post', { title: 'World' }); @@ -81,17 +81,18 @@ test("Retry is allowed in a failure handler", function(assert) { }; return run(() => { - return posts.save() + return posts + .save() .catch(() => posts.save()) .then(post => { // the ID here is '2' because the second post saves on the first attempt, // while the first post saves on the second attempt - assert.equal(posts.get('firstObject.id'), '2', "The post ID made it through"); + assert.equal(posts.get('firstObject.id'), '2', 'The post ID made it through'); }); }); }); -test("Collection will reject save on invalid", function(assert) { +test('Collection will reject save on invalid', function(assert) { assert.expect(1); env.store.createRecord('post', { title: 'Hello' }); diff --git a/tests/integration/records/delete-record-test.js b/tests/integration/records/delete-record-test.js index 44e2fcd8462..116b533e824 100644 --- a/tests/integration/records/delete-record-test.js +++ b/tests/integration/records/delete-record-test.js @@ -14,15 +14,17 @@ import DS from 'ember-data'; var attr = DS.attr; var Person, env; -module("integration/deletedRecord - Deleting Records", { +module('integration/deletedRecord - Deleting Records', { beforeEach() { Person = DS.Model.extend({ - name: attr('string') + name: attr('string'), }); - Person.toString = () => { return 'Person'; }; + Person.toString = () => { + return 'Person'; + }; env = setupStore({ - person: Person + person: Person, }); }, @@ -30,10 +32,10 @@ module("integration/deletedRecord - Deleting Records", { run(function() { env.container.destroy(); }); - } + }, }); -test("records should not be removed from record arrays just after deleting, but only after committing them", function(assert) { +test('records should not be removed from record arrays just after deleting, but only after committing them', function(assert) { var adam, dave; env.adapter.deleteRecord = function() { @@ -43,26 +45,28 @@ test("records should not be removed from record arrays just after deleting, but var all; run(function() { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Adam Sunderland' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Dave Sunderland' - } - }] + 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'); + all = env.store.peekAll('person'); }); - // pre-condition assert.equal(all.get('length'), 2, 'pre-condition: 2 records in array'); @@ -79,9 +83,11 @@ test('deleting a record that is part of a hasMany removes it from the hasMany re let group; let person; const Group = DS.Model.extend({ - people: DS.hasMany('person', { inverse: null, async: false }) + people: DS.hasMany('person', { inverse: null, async: false }), }); - Group.toString = () => { return 'Group'; } + Group.toString = () => { + return 'Group'; + }; env.adapter.deleteRecord = function() { return EmberPromise.resolve(); @@ -96,29 +102,26 @@ test('deleting a record that is part of a hasMany removes it from the hasMany re id: '1', relationships: { people: { - data: [ - { type: 'person', id: '1' }, - { type: 'person', id: '2' } - ] - } - } + data: [{ type: 'person', id: '1' }, { type: 'person', id: '2' }], + }, + }, }, included: [ { type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' - } + name: 'Adam Sunderland', + }, }, { type: 'person', id: '2', attributes: { - name: 'Dave Sunderland' - } - } - ] + name: 'Dave Sunderland', + }, + }, + ], }); group = env.store.peekRecord('group', '1'); @@ -136,7 +139,7 @@ test('deleting a record that is part of a hasMany removes it from the hasMany re assert.equal(group.get('people.length'), 1, 'expected 1 related records after delete'); }); -test("records can be deleted during record array enumeration", function(assert) { +test('records can be deleted during record array enumeration', function(assert) { var adam, dave; env.adapter.deleteRecord = function() { @@ -145,19 +148,22 @@ test("records can be deleted during record array enumeration", function(assert) run(function() { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Adam Sunderland' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Dave Sunderland' - } - }] + 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); @@ -177,20 +183,22 @@ test("records can be deleted during record array enumeration", function(assert) assert.equal(all.objectAt(0), null, "can't get any records"); }); -test("Deleting an invalid newly created record should remove it from the store", function(assert) { +test('Deleting an invalid newly created record should remove it from the store', function(assert) { var record; var store = env.store; env.adapter.createRecord = function() { - return EmberPromise.reject(new DS.InvalidError([ - { - title: 'Invalid Attribute', - detail: 'name is invalid', - source: { - pointer: '/data/attributes/name' - } - } - ])); + return EmberPromise.reject( + new DS.InvalidError([ + { + title: 'Invalid Attribute', + detail: 'name is invalid', + source: { + pointer: '/data/attributes/name', + }, + }, + ]) + ); }; run(function() { @@ -200,8 +208,11 @@ test("Deleting an invalid newly created record should remove it from the store", }); // Preconditions - assert.equal(get(record, 'currentState.stateName'), 'root.loaded.created.invalid', - 'records should start in the created.invalid state'); + assert.equal( + get(record, 'currentState.stateName'), + 'root.loaded.created.invalid', + 'records should start in the created.invalid state' + ); assert.equal(get(store.peekAll('person'), 'length'), 1, 'The new person should be in the store'); run(function() { @@ -209,28 +220,35 @@ test("Deleting an invalid newly created record should remove it from the store", }); assert.equal(get(record, 'currentState.stateName'), 'root.deleted.saved'); - assert.equal(get(store.peekAll('person'), 'length'), 0, 'The new person should be removed from the store'); + assert.equal( + get(store.peekAll('person'), 'length'), + 0, + 'The new person should be removed from the store' + ); }); - -test("Destroying an invalid newly created record should remove it from the store", function(assert) { +test('Destroying an invalid newly created record should remove it from the store', function(assert) { var record; var store = env.store; env.adapter.deleteRecord = function() { - assert.fail('The adapter\'s deletedRecord method should not be called when the record was created locally.'); + assert.fail( + "The adapter's deletedRecord method should not be called when the record was created locally." + ); }; env.adapter.createRecord = function() { - return EmberPromise.reject(new DS.InvalidError([ - { - title: 'Invalid Attribute', - detail: 'name is invalid', - source: { - pointer: '/data/attributes/name' - } - } - ])); + return EmberPromise.reject( + new DS.InvalidError([ + { + title: 'Invalid Attribute', + detail: 'name is invalid', + source: { + pointer: '/data/attributes/name', + }, + }, + ]) + ); }; run(function() { @@ -240,8 +258,11 @@ test("Destroying an invalid newly created record should remove it from the store }); // Preconditions - assert.equal(get(record, 'currentState.stateName'), 'root.loaded.created.invalid', - 'records should start in the created.invalid state'); + assert.equal( + get(record, 'currentState.stateName'), + 'root.loaded.created.invalid', + 'records should start in the created.invalid state' + ); assert.equal(get(store.peekAll('person'), 'length'), 1, 'The new person should be in the store'); run(function() { @@ -249,10 +270,14 @@ test("Destroying an invalid newly created record should remove it from the store }); assert.equal(get(record, 'currentState.stateName'), 'root.deleted.saved'); - assert.equal(get(store.peekAll('person'), 'length'), 0, 'The new person should be removed from the store'); + assert.equal( + get(store.peekAll('person'), 'length'), + 0, + 'The new person should be removed from the store' + ); }); -test("Will resolve destroy and save in same loop", function(assert) { +test('Will resolve destroy and save in same loop', function(assert) { let adam, dave; let promises; @@ -263,8 +288,8 @@ test("Will resolve destroy and save in same loop", function(assert) { return EmberPromise.resolve({ data: { id: 123, - type: 'person' - } + type: 'person', + }, }); }; @@ -272,10 +297,7 @@ test("Will resolve destroy and save in same loop", function(assert) { dave = env.store.createRecord('person', { name: 'Dave Sunderland' }); run(function() { - promises = [ - adam.destroyRecord(), - dave.save() - ]; + promises = [adam.destroyRecord(), dave.save()]; }); return all(promises); diff --git a/tests/integration/records/error-test.js b/tests/integration/records/error-test.js index 10ea3ba7289..851950316fc 100644 --- a/tests/integration/records/error-test.js +++ b/tests/integration/records/error-test.js @@ -18,11 +18,11 @@ module('integration/records/error', { beforeEach: function() { Person = DS.Model.extend({ firstName: attr('string'), - lastName: attr('string') + lastName: attr('string'), }); env = setupStore({ - person: Person + person: Person, }); store = env.store; @@ -32,7 +32,7 @@ module('integration/records/error', { run(function() { env.container.destroy(); }); - } + }, }); testInDebug('adding errors during root.loaded.created.invalid works', function(assert) { @@ -45,9 +45,9 @@ testInDebug('adding errors during root.loaded.created.invalid works', function(a id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' - } - } + lastName: 'Katz', + }, + }, }); return store.peekRecord('person', 'wat'); }); @@ -59,7 +59,7 @@ testInDebug('adding errors during root.loaded.created.invalid works', function(a assert.equal(person._internalModel.currentState.stateName, 'root.loaded.updated.uncommitted'); - updateErrors(() => person.get('errors').add('firstName', 'is invalid') , assert); + updateErrors(() => person.get('errors').add('firstName', 'is invalid'), assert); assert.equal(person._internalModel.currentState.stateName, 'root.loaded.updated.invalid'); @@ -67,18 +67,17 @@ testInDebug('adding errors during root.loaded.created.invalid works', function(a assert.deepEqual(person.get('errors').toArray(), [ { attribute: 'firstName', message: 'is invalid' }, - { attribute: 'lastName', message: 'is invalid' } + { attribute: 'lastName', message: 'is invalid' }, ]); }); - testInDebug('adding errors root.loaded.created.invalid works', function(assert) { assert.expect(5); let person = store.createRecord('person', { id: 'wat', firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }); run(() => { @@ -96,7 +95,7 @@ testInDebug('adding errors root.loaded.created.invalid works', function(assert) assert.deepEqual(person.get('errors').toArray(), [ { attribute: 'firstName', message: 'is invalid' }, - { attribute: 'lastName', message: 'is invalid' } + { attribute: 'lastName', message: 'is invalid' }, ]); }); @@ -105,7 +104,7 @@ testInDebug('adding errors root.loaded.created.invalid works add + remove + add' let person = store.createRecord('person', { id: 'wat', - firstName: 'Yehuda' + firstName: 'Yehuda', }); run(() => { @@ -125,16 +124,18 @@ testInDebug('adding errors root.loaded.created.invalid works add + remove + add' updateErrors(() => person.get('errors').add('firstName', 'is invalid'), assert); assert.deepEqual(person.get('errors').toArray(), [ - { attribute: 'firstName', message: 'is invalid' } + { attribute: 'firstName', message: 'is invalid' }, ]); }); -testInDebug('adding errors root.loaded.created.invalid works add + (remove, add)', function(assert) { +testInDebug('adding errors root.loaded.created.invalid works add + (remove, add)', function( + assert +) { assert.expect(6); let person = store.createRecord('person', { id: 'wat', - firstName: 'Yehuda' + firstName: 'Yehuda', }); run(() => { @@ -154,28 +155,29 @@ testInDebug('adding errors root.loaded.created.invalid works add + (remove, add) person.get('errors').add('firstName', 'is invalid'); }, assert); - assert.equal(person._internalModel.currentState.stateName, 'root.loaded.created.invalid'); assert.deepEqual(person.get('errors').toArray(), [ - { attribute: 'firstName', message: 'is invalid' } + { attribute: 'firstName', message: 'is invalid' }, ]); }); test('using setProperties to clear errors', function(assert) { env.adapter.reopen({ createRecord() { - return RSVP.reject(new DS.InvalidError([ - { - detail: 'Must be unique', - source: { pointer: '/data/attributes/first-name' } - }, - { - detail: 'Must not be blank', - source: { pointer: '/data/attributes/last-name'} - } - ])); - } + return RSVP.reject( + new DS.InvalidError([ + { + detail: 'Must be unique', + source: { pointer: '/data/attributes/first-name' }, + }, + { + detail: 'Must not be blank', + source: { pointer: '/data/attributes/last-name' }, + }, + ]) + ); + }, }); return run(() => { @@ -189,8 +191,8 @@ test('using setProperties to clear errors', function(assert) { assert.ok(errors.has('lastName')); person.setProperties({ - firstName: "updated", - lastName: "updated" + firstName: 'updated', + lastName: 'updated', }); assert.equal(errors.get('length'), 0); diff --git a/tests/integration/records/load-test.js b/tests/integration/records/load-test.js index 605e92115c4..f7836cc2d33 100644 --- a/tests/integration/records/load-test.js +++ b/tests/integration/records/load-test.js @@ -10,10 +10,10 @@ const { hasMany } = DS; let Post, Comment, env; -module("integration/load - Loading Records", { +module('integration/load - Loading Records', { beforeEach() { Post = DS.Model.extend({ - comments: hasMany({ async: true }) + comments: hasMany({ async: true }), }); Comment = DS.Model.extend(); @@ -23,10 +23,10 @@ module("integration/load - Loading Records", { afterEach() { run(env.container, 'destroy'); - } + }, }); -test("When loading a record fails, the record is not left behind", function(assert) { +test('When loading a record fails, the record is not left behind', function(assert) { env.adapter.findRecord = function(store, type, id, snapshot) { return reject(); }; diff --git a/tests/integration/records/property-changes-test.js b/tests/integration/records/property-changes-test.js index 059434d14c8..c1a2ffbe1d6 100644 --- a/tests/integration/records/property-changes-test.js +++ b/tests/integration/records/property-changes-test.js @@ -13,11 +13,11 @@ module('integration/records/property-changes - Property changes', { beforeEach() { Person = DS.Model.extend({ firstName: attr('string'), - lastName: attr('string') + lastName: attr('string'), }); env = setupStore({ - person: Person + person: Person, }); store = env.store; }, @@ -26,7 +26,7 @@ module('integration/records/property-changes - Property changes', { run(function() { env.container.destroy(); }); - } + }, }); test('Calling push with partial records trigger observers for just those attributes that changed', function(assert) { @@ -40,9 +40,9 @@ test('Calling push with partial records trigger observers for just those attribu id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' - } - } + lastName: 'Katz', + }, + }, }); person = store.peekRecord('person', 'wat'); }); @@ -62,9 +62,9 @@ test('Calling push with partial records trigger observers for just those attribu id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz!' - } - } + lastName: 'Katz!', + }, + }, }); }); }); @@ -80,9 +80,9 @@ test('Calling push does not trigger observers for locally changed attributes wit id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' - } - } + lastName: 'Katz', + }, + }, }); person = store.peekRecord('person', 'wat'); person.set('lastName', 'Katz!'); @@ -103,9 +103,9 @@ test('Calling push does not trigger observers for locally changed attributes wit id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz!' - } - } + lastName: 'Katz!', + }, + }, }); }); }); @@ -125,9 +125,9 @@ test('Saving a record trigger observers for locally changed attributes with the id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' - } - } + lastName: 'Katz', + }, + }, }); person = store.peekRecord('person', 'wat'); person.set('lastName', 'Katz!'); @@ -157,9 +157,9 @@ test('store.push should not override a modified attribute', function(assert) { id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' - } - } + lastName: 'Katz', + }, + }, }); person = store.peekRecord('person', 'wat'); person.set('lastName', 'Katz!'); @@ -180,9 +180,9 @@ test('store.push should not override a modified attribute', function(assert) { id: 'wat', attributes: { firstName: 'Tom', - lastName: 'Dale' - } - } + lastName: 'Dale', + }, + }, }); }); }); diff --git a/tests/integration/records/relationship-changes-test.js b/tests/integration/records/relationship-changes-test.js index 8385abd3a81..b7c1d38d764 100644 --- a/tests/integration/records/relationship-changes-test.js +++ b/tests/integration/records/relationship-changes-test.js @@ -11,17 +11,17 @@ const { attr, belongsTo, hasMany, Model } = DS; let env, store; const Author = Model.extend({ - name: attr('string') + name: attr('string'), }); const Post = Model.extend({ - author: belongsTo() + author: belongsTo(), }); const Person = DS.Model.extend({ firstName: attr('string'), lastName: attr('string'), - siblings: hasMany('person') + siblings: hasMany('person'), }); const sibling1 = { @@ -29,13 +29,13 @@ const sibling1 = { id: '1', attributes: { firstName: 'Dogzn', - lastName: 'Katz' - } + lastName: 'Katz', + }, }; const sibling1Ref = { type: 'person', - id: '1' + id: '1', }; const sibling2 = { @@ -43,13 +43,13 @@ const sibling2 = { id: '2', attributes: { firstName: 'Katzn', - lastName: 'Dogz' - } + lastName: 'Dogz', + }, }; const sibling2Ref = { type: 'person', - id: '2' + id: '2', }; const sibling3 = { @@ -57,13 +57,13 @@ const sibling3 = { id: '3', attributes: { firstName: 'Snakezn', - lastName: 'Ladderz' - } + lastName: 'Ladderz', + }, }; const sibling3Ref = { type: 'person', - id: '3' + id: '3', }; const sibling4 = { @@ -71,13 +71,13 @@ const sibling4 = { id: '4', attributes: { firstName: 'Hamsterzn', - lastName: 'Gerbilz' - } + lastName: 'Gerbilz', + }, }; const sibling4Ref = { type: 'person', - id: '4' + id: '4', }; const sibling5 = { @@ -85,13 +85,13 @@ const sibling5 = { id: '5', attributes: { firstName: 'Donkeyzn', - lastName: 'Llamaz' - } + lastName: 'Llamaz', + }, }; const sibling5Ref = { type: 'person', - id: '5' + id: '5', }; module('integration/records/relationship-changes - Relationship changes', { @@ -99,7 +99,7 @@ module('integration/records/relationship-changes - Relationship changes', { env = setupStore({ person: Person, author: Author, - post: Post + post: Post, }); store = env.store; }, @@ -108,7 +108,7 @@ module('integration/records/relationship-changes - Relationship changes', { run(() => { env.container.destroy(); }); - } + }, }); test('Calling push with relationship triggers observers once if the relationship was empty and is added to', function(assert) { @@ -123,14 +123,14 @@ test('Calling push with relationship triggers observers once if the relationship id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [] - } - } - } + data: [], + }, + }, + }, }); person = store.peekRecord('person', 'wat'); }); @@ -148,17 +148,14 @@ test('Calling push with relationship triggers observers once if the relationship data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref] - } - } + data: [sibling1Ref], + }, + }, }, - included: [ - sibling1 - ] + included: [sibling1], }); }); @@ -172,7 +169,7 @@ test('Calling push with relationship recalculates computed alias property if the let Obj = EmberObject.extend({ person: null, - siblings: alias('person.siblings') + siblings: alias('person.siblings'), }); const obj = Obj.create(); @@ -184,14 +181,14 @@ test('Calling push with relationship recalculates computed alias property if the id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [] - } - } - } + data: [], + }, + }, + }, }); set(obj, 'person', store.peekRecord('person', 'wat')); }); @@ -201,17 +198,14 @@ test('Calling push with relationship recalculates computed alias property if the data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref] - } - } + data: [sibling1Ref], + }, + }, }, - included: [ - sibling1 - ] + included: [sibling1], }); }); @@ -227,7 +221,7 @@ test('Calling push with relationship recalculates computed alias property to fir let Obj = EmberObject.extend({ person: null, - firstSibling: alias('person.siblings.firstObject') + firstSibling: alias('person.siblings.firstObject'), }); const obj = Obj.create(); @@ -239,14 +233,14 @@ test('Calling push with relationship recalculates computed alias property to fir id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [] - } - } - } + data: [], + }, + }, + }, }); set(obj, 'person', store.peekRecord('person', 'wat')); }); @@ -256,17 +250,14 @@ test('Calling push with relationship recalculates computed alias property to fir data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref] - } - } + data: [sibling1Ref], + }, + }, }, - included: [ - sibling1 - ] + included: [sibling1], }); }); @@ -289,17 +280,15 @@ test('Calling push with relationship triggers observers once if the relationship id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [sibling1Ref] - } - } + data: [sibling1Ref], + }, + }, }, - included: [ - sibling1 - ] + included: [sibling1], }); person = store.peekRecord('person', 'wat'); }); @@ -317,17 +306,14 @@ test('Calling push with relationship triggers observers once if the relationship data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref, sibling2Ref] - } - } + data: [sibling1Ref, sibling2Ref], + }, + }, }, - included: [ - sibling2 - ] + included: [sibling2], }); }); @@ -348,17 +334,15 @@ test('Calling push with relationship triggers observers once if the relationship id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [sibling1Ref] - } - } + data: [sibling1Ref], + }, + }, }, - included: [ - sibling1 - ] + included: [sibling1], }); person = store.peekRecord('person', 'wat'); }); @@ -371,21 +355,19 @@ test('Calling push with relationship triggers observers once if the relationship person.get('siblings'); }); - run(() => { store.push({ data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [] - } - } + data: [], + }, + }, }, - included: [] + included: [], }); }); @@ -406,19 +388,15 @@ test('Calling push with relationship triggers observers once if the relationship id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [sibling1Ref, sibling2Ref] - } - } + data: [sibling1Ref, sibling2Ref], + }, + }, }, - included: [ - sibling1, - sibling2 - ] - + included: [sibling1, sibling2], }); person = store.peekRecord('person', 'wat'); }); @@ -431,21 +409,19 @@ test('Calling push with relationship triggers observers once if the relationship person.get('siblings'); }); - run(() => { store.push({ data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling2Ref, sibling1Ref] - } - } + data: [sibling2Ref, sibling1Ref], + }, + }, }, - included: [] + included: [], }); }); @@ -466,18 +442,15 @@ test('Calling push with relationship does not trigger observers if the relations id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [sibling1Ref] - } - } + data: [sibling1Ref], + }, + }, }, - included: [ - sibling1 - ] - + included: [sibling1], }); person = store.peekRecord('person', 'wat'); }); @@ -490,21 +463,19 @@ test('Calling push with relationship does not trigger observers if the relations }); }); - run(() => { store.push({ data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref] - } - } + data: [sibling1Ref], + }, + }, }, - included: [] + included: [], }); }); @@ -530,7 +501,7 @@ test('Calling push with relationship triggers willChange and didChange with deta assert.equal(start, 1, 'didChange.start'); assert.equal(removed, 0, 'didChange.removed'); assert.equal(added, 1, 'didChange.added'); - } + }, }; run(() => { @@ -540,22 +511,18 @@ test('Calling push with relationship triggers willChange and didChange with deta id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [sibling1Ref] - } - } + data: [sibling1Ref], + }, + }, }, - included: [ - sibling1 - ] - + included: [sibling1], }); }); - let person = store.peekRecord('person', 'wat'); let siblings = run(() => person.get('siblings')); @@ -566,17 +533,14 @@ test('Calling push with relationship triggers willChange and didChange with deta data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref, sibling2Ref] - } - } + data: [sibling1Ref, sibling2Ref], + }, + }, }, - included: [ - sibling2 - ] + included: [sibling2], }); }); @@ -597,17 +561,15 @@ test('Calling push with relationship triggers willChange and didChange with deta id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [sibling1Ref, sibling2Ref] - } - } + data: [sibling1Ref, sibling2Ref], + }, + }, }, - included: [ - sibling1, sibling2 - ] + included: [sibling1, sibling2], }); }); @@ -627,7 +589,7 @@ test('Calling push with relationship triggers willChange and didChange with deta assert.equal(start, 1); assert.equal(removed, 1); assert.equal(added, 0); - } + }, }; siblings.addArrayObserver(observer); @@ -637,15 +599,14 @@ test('Calling push with relationship triggers willChange and didChange with deta data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref] - } - } + data: [sibling1Ref], + }, + }, }, - included: [] + included: [], }); }); @@ -666,17 +627,15 @@ test('Calling push with relationship triggers willChange and didChange with deta id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [sibling2Ref] - } - } + data: [sibling2Ref], + }, + }, }, - included: [ - sibling2 - ] + included: [sibling2], }); }); let person = store.peekRecord('person', 'wat'); @@ -694,7 +653,7 @@ test('Calling push with relationship triggers willChange and didChange with deta assert.equal(start, 0); assert.equal(removed, 0); assert.equal(added, 1); - } + }, }; let siblings = run(() => person.get('siblings')); @@ -705,17 +664,14 @@ test('Calling push with relationship triggers willChange and didChange with deta data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref, sibling2Ref] - } - } + data: [sibling1Ref, sibling2Ref], + }, + }, }, - included: [ - sibling2 - ] + included: [sibling2], }); }); @@ -736,19 +692,15 @@ test('Calling push with relationship triggers willChange and didChange with deta id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [sibling1Ref, sibling3Ref] - } - } + data: [sibling1Ref, sibling3Ref], + }, + }, }, - included: [ - sibling1, - sibling3 - ] - + included: [sibling1, sibling3], }); }); let person = store.peekRecord('person', 'wat'); @@ -764,7 +716,7 @@ test('Calling push with relationship triggers willChange and didChange with deta assert.equal(start, 1); assert.equal(removed, 0); assert.equal(added, 1); - } + }, }; let siblings = run(() => person.get('siblings')); @@ -775,17 +727,14 @@ test('Calling push with relationship triggers willChange and didChange with deta data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref, sibling2Ref, sibling3Ref] - } - } + data: [sibling1Ref, sibling2Ref, sibling3Ref], + }, + }, }, - included: [ - sibling2 - ] + included: [sibling2], }); }); @@ -806,19 +755,15 @@ test('Calling push with relationship triggers willChange and didChange with deta id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }, relationships: { siblings: { - data: [sibling1Ref, sibling2Ref, sibling3Ref] - } - } + data: [sibling1Ref, sibling2Ref, sibling3Ref], + }, + }, }, - included: [ - sibling1, - sibling2, - sibling3 - ] + included: [sibling1, sibling2, sibling3], }); }); @@ -836,10 +781,10 @@ test('Calling push with relationship triggers willChange and didChange with deta assert.equal(start, 1); assert.equal(removed, 1); assert.equal(added, 2); - } + }, }; - let siblings = run(() => person.get('siblings')); + let siblings = run(() => person.get('siblings')); siblings.addArrayObserver(observer); run(() => { @@ -847,18 +792,14 @@ test('Calling push with relationship triggers willChange and didChange with deta data: { type: 'person', id: 'wat', - attributes: { - }, + attributes: {}, relationships: { siblings: { - data: [sibling1Ref, sibling4Ref, sibling5Ref, sibling3Ref] - } - } + data: [sibling1Ref, sibling4Ref, sibling5Ref, sibling3Ref], + }, + }, }, - included: [ - sibling4, - sibling5 - ] + included: [sibling4, sibling5], }); }); @@ -880,14 +821,16 @@ test('Calling push with updated belongsTo relationship trigger observer', functi id: '1', relationships: { author: { - data: { type: 'author', id: '2' } - } - } + data: { type: 'author', id: '2' }, + }, + }, }, - included: [{ - id: 2, - type: 'author' - }] + included: [ + { + id: 2, + type: 'author', + }, + ], }); post.get('author'); @@ -902,10 +845,10 @@ test('Calling push with updated belongsTo relationship trigger observer', functi id: '1', relationships: { author: { - data: { type: 'author', id: '3' } - } - } - } + data: { type: 'author', id: '3' }, + }, + }, + }, }); }); @@ -924,10 +867,10 @@ test('Calling push with same belongsTo relationship does not trigger observer', id: '1', relationships: { author: { - data: { type: 'author', id: '2' } - } - } - } + data: { type: 'author', id: '2' }, + }, + }, + }, }); post.addObserver('author', function() { @@ -940,10 +883,10 @@ test('Calling push with same belongsTo relationship does not trigger observer', id: '1', relationships: { author: { - data: { type: 'author', id: '2' } - } - } - } + data: { type: 'author', id: '2' }, + }, + }, + }, }); }); diff --git a/tests/integration/records/reload-test.js b/tests/integration/records/reload-test.js index 694d801ecb5..e764cd4cb56 100644 --- a/tests/integration/records/reload-test.js +++ b/tests/integration/records/reload-test.js @@ -10,13 +10,13 @@ import DS from 'ember-data'; var attr = DS.attr; var Person, env; -module("integration/reload - Reloading Records", { +module('integration/reload - Reloading Records', { beforeEach() { Person = DS.Model.extend({ updatedAt: attr('string'), name: attr('string'), firstName: attr('string'), - lastName: attr('string') + lastName: attr('string'), }); env = setupStore({ person: Person }); @@ -24,7 +24,7 @@ module("integration/reload - Reloading Records", { afterEach() { run(env.container, 'destroy'); - } + }, }); test("When a single record is requested, the adapter's find method should be called unless it's loaded.", function(assert) { @@ -33,26 +33,33 @@ test("When a single record is requested, the adapter's find method should be cal env.adapter.findRecord = function(store, type, id, snapshot) { if (count === 0) { count++; - return resolve({ data: { id: id, type: 'person', attributes: { name: "Tom Dale" } } }); + return resolve({ data: { id: id, type: 'person', attributes: { name: 'Tom Dale' } } }); } else if (count === 1) { count++; - return resolve({ data: { id: id, type: 'person', attributes: { name: "Braaaahm Dale" } } }); + return resolve({ data: { id: id, type: 'person', attributes: { name: 'Braaaahm Dale' } } }); } else { - assert.ok(false, "Should not get here"); + assert.ok(false, 'Should not get here'); } }; run(function() { - env.store.findRecord('person', 1).then(function(person) { - assert.equal(get(person, 'name'), "Tom Dale", "The person is loaded with the right name"); - assert.equal(get(person, 'isLoaded'), true, "The person is now loaded"); - var promise = person.reload(); - assert.equal(get(person, 'isReloading'), true, "The person is now reloading"); - return promise; - }).then(function(person) { - assert.equal(get(person, 'isReloading'), false, "The person is no longer reloading"); - assert.equal(get(person, 'name'), "Braaaahm Dale", "The person is now updated with the right name"); - }); + env.store + .findRecord('person', 1) + .then(function(person) { + assert.equal(get(person, 'name'), 'Tom Dale', 'The person is loaded with the right name'); + assert.equal(get(person, 'isLoaded'), true, 'The person is now loaded'); + var promise = person.reload(); + assert.equal(get(person, 'isReloading'), true, 'The person is now reloading'); + return promise; + }) + .then(function(person) { + assert.equal(get(person, 'isReloading'), false, 'The person is no longer reloading'); + assert.equal( + get(person, 'name'), + 'Braaaahm Dale', + 'The person is now updated with the right name' + ); + }); }); }); @@ -60,41 +67,52 @@ test("When a single record is requested, the adapter's find method should be cal let count = 0; let reloadOptions = { adapterOptions: { - makeSnazzy: true - } + makeSnazzy: true, + }, }; env.adapter.findRecord = function(store, type, id, snapshot) { if (count === 0) { count++; - return resolve({ data: { id: id, type: 'person', attributes: { name: "Tom Dale" } } }); + return resolve({ data: { id: id, type: 'person', attributes: { name: 'Tom Dale' } } }); } else if (count === 1) { - assert.equal(snapshot.adapterOptions, reloadOptions.adapterOptions, 'We passed adapterOptions via reload'); + assert.equal( + snapshot.adapterOptions, + reloadOptions.adapterOptions, + 'We passed adapterOptions via reload' + ); count++; - return resolve({ data: { id: id, type: 'person', attributes: { name: "Braaaahm Dale" } } }); + return resolve({ data: { id: id, type: 'person', attributes: { name: 'Braaaahm Dale' } } }); } else { - assert.ok(false, "Should not get here"); + assert.ok(false, 'Should not get here'); } }; run(function() { - env.store.findRecord('person', 1).then(function(person) { - assert.equal(get(person, 'name'), "Tom Dale", "The person is loaded with the right name"); - assert.equal(get(person, 'isLoaded'), true, "The person is now loaded"); - - let promise = person.reload(reloadOptions); - - assert.equal(get(person, 'isReloading'), true, "The person is now reloading"); - - return promise; - }).then(function(person) { - assert.equal(get(person, 'isReloading'), false, "The person is no longer reloading"); - assert.equal(get(person, 'name'), "Braaaahm Dale", "The person is now updated with the right name"); - }); + env.store + .findRecord('person', 1) + .then(function(person) { + assert.equal(get(person, 'name'), 'Tom Dale', 'The person is loaded with the right name'); + assert.equal(get(person, 'isLoaded'), true, 'The person is now loaded'); + + let promise = person.reload(reloadOptions); + + assert.equal(get(person, 'isReloading'), true, 'The person is now reloading'); + + return promise; + }) + .then(function(person) { + assert.equal(get(person, 'isReloading'), false, 'The person is no longer reloading'); + assert.equal( + get(person, 'name'), + 'Braaaahm Dale', + 'The person is now updated with the right name' + ); + }); }); }); -test("When a record is reloaded and fails, it can try again", function(assert) { +test('When a record is reloaded and fails, it can try again', function(assert) { var tom; run(function() { env.store.push({ @@ -102,46 +120,49 @@ test("When a record is reloaded and fails, it can try again", function(assert) { type: 'person', id: '1', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); tom = env.store.peekRecord('person', 1); }); var count = 0; env.adapter.findRecord = function(store, type, id, snapshot) { - assert.equal(tom.get('isReloading'), true, "Tom is reloading"); + assert.equal(tom.get('isReloading'), true, 'Tom is reloading'); if (count++ === 0) { return reject(); } else { - return resolve({ data: { id: 1, type: 'person', attributes: { name: "Thomas Dale" } } }); + return resolve({ data: { id: 1, type: 'person', attributes: { name: 'Thomas Dale' } } }); } }; run(function() { - tom.reload().then(null, function() { - assert.equal(tom.get('isError'), true, "Tom is now errored"); - assert.equal(tom.get('isReloading'), false, "Tom is no longer reloading"); - return tom.reload(); - }).then(function(person) { - assert.equal(person, tom, "The resolved value is the record"); - assert.equal(tom.get('isError'), false, "Tom is no longer errored"); - assert.equal(tom.get('isReloading'), false, "Tom is no longer reloading"); - assert.equal(tom.get('name'), "Thomas Dale", "the updates apply"); - }); + tom + .reload() + .then(null, function() { + assert.equal(tom.get('isError'), true, 'Tom is now errored'); + assert.equal(tom.get('isReloading'), false, 'Tom is no longer reloading'); + return tom.reload(); + }) + .then(function(person) { + assert.equal(person, tom, 'The resolved value is the record'); + assert.equal(tom.get('isError'), false, 'Tom is no longer errored'); + assert.equal(tom.get('isReloading'), false, 'Tom is no longer reloading'); + assert.equal(tom.get('name'), 'Thomas Dale', 'the updates apply'); + }); }); }); -test("When a record is loaded a second time, isLoaded stays true", function(assert) { +test('When a record is loaded a second time, isLoaded stays true', function(assert) { let record = { data: { type: 'person', id: '1', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }; env.adapter.findRecord = function(store, type, id, snapshot) { return record; @@ -152,13 +173,13 @@ test("When a record is loaded a second time, isLoaded stays true", function(asse run(function() { env.store.findRecord('person', 1).then(function(person) { - assert.equal(get(person, 'isLoaded'), true, "The person is loaded"); + assert.equal(get(person, 'isLoaded'), true, 'The person is loaded'); person.addObserver('isLoaded', isLoadedDidChange); // Reload the record env.store.push(record); - assert.equal(get(person, 'isLoaded'), true, "The person is still loaded after load"); + assert.equal(get(person, 'isLoaded'), true, 'The person is still loaded after load'); person.removeObserver('isLoaded', isLoadedDidChange); }); @@ -166,21 +187,27 @@ test("When a record is loaded a second time, isLoaded stays true", function(asse function isLoadedDidChange() { // This shouldn't be hit - assert.equal(get(this, 'isLoaded'), true, "The person is still loaded after change"); + assert.equal(get(this, 'isLoaded'), true, 'The person is still loaded after change'); } }); -test("When a record is reloaded, its async hasMany relationships still work", function(assert) { - env.registry.register('model:person', DS.Model.extend({ - name: DS.attr(), - tags: DS.hasMany('tag', { async: true }) - })); +test('When a record is reloaded, its async hasMany relationships still work', function(assert) { + env.registry.register( + 'model:person', + DS.Model.extend({ + name: DS.attr(), + tags: DS.hasMany('tag', { async: true }), + }) + ); - env.registry.register('model:tag', DS.Model.extend({ - name: DS.attr() - })); + env.registry.register( + 'model:tag', + DS.Model.extend({ + name: DS.attr(), + }) + ); - var tags = { 1: "hipster", 2: "hair" }; + var tags = { 1: 'hipster', 2: 'hair' }; env.adapter.findRecord = function(store, type, id, snapshot) { switch (type.modelName) { @@ -189,16 +216,13 @@ test("When a record is reloaded, its async hasMany relationships still work", fu data: { id: 1, type: 'person', - attributes: { name: "Tom" }, + attributes: { name: 'Tom' }, relationships: { tags: { - data: [ - { id: 1, type: 'tag' }, - { id: 2, type: 'tag' } - ] - } - } - } + data: [{ id: 1, type: 'tag' }, { id: 2, type: 'tag' }], + }, + }, + }, }); case 'tag': return resolve({ data: { id: id, type: 'tag', attributes: { name: tags[id] } } }); @@ -208,21 +232,26 @@ test("When a record is reloaded, its async hasMany relationships still work", fu var tom; run(function() { - env.store.findRecord('person', 1).then(function(person) { - tom = person; - assert.equal(person.get('name'), "Tom", "precond"); - - return person.get('tags'); - }).then(function(tags) { - assert.deepEqual(tags.mapBy('name'), ['hipster', 'hair']); - - return tom.reload(); - }).then(function(person) { - assert.equal(person.get('name'), "Tom", "precond"); - - return person.get('tags'); - }).then(function(tags) { - assert.deepEqual(tags.mapBy('name'), ['hipster', 'hair'], "The tags are still there"); - }); + env.store + .findRecord('person', 1) + .then(function(person) { + tom = person; + assert.equal(person.get('name'), 'Tom', 'precond'); + + return person.get('tags'); + }) + .then(function(tags) { + assert.deepEqual(tags.mapBy('name'), ['hipster', 'hair']); + + return tom.reload(); + }) + .then(function(person) { + assert.equal(person.get('name'), 'Tom', 'precond'); + + return person.get('tags'); + }) + .then(function(tags) { + assert.deepEqual(tags.mapBy('name'), ['hipster', 'hair'], 'The tags are still there'); + }); }); }); diff --git a/tests/integration/records/rematerialize-test.js b/tests/integration/records/rematerialize-test.js index 6375ab15f3e..c55e59c4c94 100644 --- a/tests/integration/records/rematerialize-test.js +++ b/tests/integration/records/rematerialize-test.js @@ -13,36 +13,50 @@ let env; let Person = Model.extend({ name: attr('string'), cars: hasMany('car', { async: false }), - boats: hasMany('boat', { async: true }) + boats: hasMany('boat', { async: true }), +}); +Person.reopenClass({ + toString() { + return 'Person'; + }, }); -Person.reopenClass({ toString() { return 'Person'; } }); let Group = Model.extend({ - people: hasMany('person', { async: false }) + people: hasMany('person', { async: false }), +}); +Group.reopenClass({ + toString() { + return 'Group'; + }, }); -Group.reopenClass({ toString() { return 'Group'; } }); let Car = Model.extend({ make: attr('string'), model: attr('string'), - person: belongsTo('person', { async: false }) + person: belongsTo('person', { async: false }), +}); +Car.reopenClass({ + toString() { + return 'Car'; + }, }); -Car.reopenClass({ toString() { return 'Car'; } }); let Boat = Model.extend({ name: attr('string'), - person: belongsTo('person', { async: false }) + person: belongsTo('person', { async: false }), }); -Boat.toString = function() { return 'Boat'; }; +Boat.toString = function() { + return 'Boat'; +}; -module("integration/unload - Rematerializing Unloaded Records", { +module('integration/unload - Rematerializing Unloaded Records', { beforeEach() { env = setupStore({ adapter: DS.JSONAPIAdapter, person: Person, car: Car, group: Group, - boat: Boat + boat: Boat, }); }, @@ -50,10 +64,10 @@ module("integration/unload - Rematerializing Unloaded Records", { run(function() { env.container.destroy(); }); - } + }, }); -test("a sync belongs to relationship to an unloaded record can restore that record", function(assert) { +test('a sync belongs to relationship to an unloaded record can restore that record', function(assert) { // disable background reloading so we do not re-create the relationship. env.adapter.shouldBackgroundReloadRecord = () => false; @@ -63,16 +77,14 @@ test("a sync belongs to relationship to an unloaded record can restore that reco type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' + name: 'Adam Sunderland', }, relationships: { cars: { - data: [ - { type: 'car', id: '1' } - ] - } - } - } + data: [{ type: 'car', id: '1' }], + }, + }, + }, }); return env.store.peekRecord('person', 1); @@ -84,15 +96,15 @@ test("a sync belongs to relationship to an unloaded record can restore that reco type: 'car', id: '1', attributes: { - make: "Lotus", - model: "Exige" + make: 'Lotus', + model: 'Exige', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } - } + data: { type: 'person', id: '1' }, + }, + }, + }, }); return env.store.peekRecord('car', 1); @@ -102,12 +114,20 @@ test("a sync belongs to relationship to an unloaded record can restore that reco assert.equal(person.get('cars.length'), 1, 'The inital length of cars is correct'); assert.equal(env.store.hasRecordForId('person', 1), true, 'The person is in the store'); - assert.equal(env.store._internalModelsFor('person').has(1), true, 'The person internalModel is loaded'); + assert.equal( + env.store._internalModelsFor('person').has(1), + true, + 'The person internalModel is loaded' + ); run(() => person.unloadRecord()); assert.equal(env.store.hasRecordForId('person', 1), false, 'The person is unloaded'); - assert.equal(env.store._internalModelsFor('person').has(1), false, 'The person internalModel is freed'); + assert.equal( + env.store._internalModelsFor('person').has(1), + false, + 'The person internalModel is freed' + ); run(() => { env.store.push({ @@ -115,16 +135,14 @@ test("a sync belongs to relationship to an unloaded record can restore that reco type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' + name: 'Adam Sunderland', }, relationships: { cars: { - data: [ - { type: 'car', id: '1' } - ] - } - } - } + data: [{ type: 'car', id: '1' }], + }, + }, + }, }); }); @@ -135,7 +153,7 @@ test("a sync belongs to relationship to an unloaded record can restore that reco assert.notEqual(rematerializedPerson, adam, 'the person is rematerialized, not recycled'); }); -test("an async has many relationship to an unloaded record can restore that record", function(assert) { +test('an async has many relationship to an unloaded record can restore that record', function(assert) { assert.expect(16); // disable background reloading so we do not re-create the relationship. @@ -145,26 +163,26 @@ test("an async has many relationship to an unloaded record can restore that reco type: 'boat', id: '1', attributes: { - name: "Boaty McBoatface" + name: 'Boaty McBoatface', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } + data: { type: 'person', id: '1' }, + }, + }, }; const BOAT_TWO = { type: 'boat', id: '2', attributes: { - name: 'Some other boat' + name: 'Some other boat', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } + data: { type: 'person', id: '1' }, + }, + }, }; let adapterCalls = 0; @@ -181,7 +199,7 @@ test("an async has many relationship to an unloaded record can restore that reco } return { - data + data, }; }; @@ -191,26 +209,20 @@ test("an async has many relationship to an unloaded record can restore that reco type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' + name: 'Adam Sunderland', }, relationships: { boats: { - data: [ - { type: 'boat', id: '2' }, - { type: 'boat', id: '1' } - ] - } - } - } + data: [{ type: 'boat', id: '2' }, { type: 'boat', id: '1' }], + }, + }, + }, }); }); run(() => { env.store.push({ - data: [ - deepCopy(BOAT_ONE), - deepCopy(BOAT_TWO) - ] + data: [deepCopy(BOAT_ONE), deepCopy(BOAT_TWO)], }); }); @@ -219,9 +231,17 @@ test("an async has many relationship to an unloaded record can restore that reco // assert our initial cache state assert.equal(env.store.hasRecordForId('person', '1'), true, 'The person is in the store'); - assert.equal(env.store._internalModelsFor('person').has('1'), true, 'The person internalModel is loaded'); + assert.equal( + env.store._internalModelsFor('person').has('1'), + true, + 'The person internalModel is loaded' + ); assert.equal(env.store.hasRecordForId('boat', '1'), true, 'The boat is in the store'); - assert.equal(env.store._internalModelsFor('boat').has('1'), true, 'The boat internalModel is loaded'); + assert.equal( + env.store._internalModelsFor('boat').has('1'), + true, + 'The boat internalModel is loaded' + ); let boats = run(() => adam.get('boats')); assert.equal(boats.get('length'), 2, 'Before unloading boats.length is correct'); @@ -231,7 +251,11 @@ test("an async has many relationship to an unloaded record can restore that reco // assert our new cache state assert.equal(env.store.hasRecordForId('boat', '1'), false, 'The boat is unloaded'); - assert.equal(env.store._internalModelsFor('boat').has('1'), true, 'The boat internalModel is retained'); + assert.equal( + env.store._internalModelsFor('boat').has('1'), + true, + 'The boat internalModel is retained' + ); // cause a rematerialization, this should also cause us to fetch boat '1' again boats = run(() => adam.get('boats')); @@ -240,9 +264,17 @@ test("an async has many relationship to an unloaded record can restore that reco assert.ok(!!rematerializedBoaty, 'We have a boat!'); assert.equal(adam.get('boats.length'), 2, 'boats.length correct after rematerialization'); assert.equal(rematerializedBoaty.get('id'), '1', 'Rematerialized boat has the right id'); - assert.equal(rematerializedBoaty.get('name'), 'Boaty McBoatface', 'Rematerialized boat has the right name'); + assert.equal( + rematerializedBoaty.get('name'), + 'Boaty McBoatface', + 'Rematerialized boat has the right name' + ); assert.ok(rematerializedBoaty !== boaty, 'the boat is rematerialized, not recycled'); assert.equal(env.store.hasRecordForId('boat', '1'), true, 'The boat is loaded'); - assert.equal(env.store._internalModelsFor('boat').has('1'), true, 'The boat internalModel is retained'); + assert.equal( + env.store._internalModelsFor('boat').has('1'), + true, + 'The boat internalModel is retained' + ); }); diff --git a/tests/integration/records/save-test.js b/tests/integration/records/save-test.js index 018d3fd2066..86abd1f34fa 100644 --- a/tests/integration/records/save-test.js +++ b/tests/integration/records/save-test.js @@ -8,10 +8,10 @@ import DS from 'ember-data'; var Post, env; -module("integration/records/save - Save Record", { +module('integration/records/save - Save Record', { beforeEach() { Post = DS.Model.extend({ - title: DS.attr('string') + title: DS.attr('string'), }); env = setupStore({ post: Post }); @@ -19,10 +19,10 @@ module("integration/records/save - Save Record", { afterEach() { run(env.container, 'destroy'); - } + }, }); -test("Will resolve save on success", function(assert) { +test('Will resolve save on success', function(assert) { assert.expect(4); let post = env.store.createRecord('post', { title: 'toto' }); @@ -41,12 +41,12 @@ test("Will resolve save on success", function(assert) { saved.then(function(model) { assert.ok(true, 'save operation was resolved'); assert.equal(saved.get('id'), 123); - assert.equal(model, post, "resolves with the model"); + assert.equal(model, post, 'resolves with the model'); }); }); }); -test("Will reject save on error", function(assert) { +test('Will reject save on error', function(assert) { let post = env.store.createRecord('post', { title: 'toto' }); env.adapter.createRecord = function(store, type, snapshot) { @@ -56,13 +56,16 @@ test("Will reject save on error", function(assert) { }; run(function() { - post.save().then(function() {}, function() { - assert.ok(true, 'save operation was rejected'); - }); + post.save().then( + function() {}, + function() { + assert.ok(true, 'save operation was rejected'); + } + ); }); }); -test("Retry is allowed in a failure handler", function(assert) { +test('Retry is allowed in a failure handler', function(assert) { let post = env.store.createRecord('post', { title: 'toto' }); var count = 0; @@ -78,15 +81,21 @@ test("Retry is allowed in a failure handler", function(assert) { }; run(function() { - post.save().then(function() {}, function() { - return post.save(); - }).then(function(post) { - assert.equal(post.get('id'), '123', "The post ID made it through"); - }); + post + .save() + .then( + function() {}, + function() { + return post.save(); + } + ) + .then(function(post) { + assert.equal(post.get('id'), '123', 'The post ID made it through'); + }); }); }); -test("Repeated failed saves keeps the record in uncommited state", function(assert) { +test('Repeated failed saves keeps the record in uncommited state', function(assert) { assert.expect(4); let post = env.store.createRecord('post', { title: 'toto' }); @@ -107,7 +116,7 @@ test("Repeated failed saves keeps the record in uncommited state", function(asse }); }); -test("Repeated failed saves with invalid error marks the record as invalid", function(assert) { +test('Repeated failed saves with invalid error marks the record as invalid', function(assert) { assert.expect(2); let post = env.store.createRecord('post', { title: 'toto' }); @@ -115,8 +124,8 @@ test("Repeated failed saves with invalid error marks the record as invalid", fun var error = new DS.InvalidError([ { detail: 'is invalid', - source: { pointer: 'data/attributes/title' } - } + source: { pointer: 'data/attributes/title' }, + }, ]); return reject(error); @@ -133,7 +142,7 @@ test("Repeated failed saves with invalid error marks the record as invalid", fun }); }); -test("Repeated failed saves with invalid error without payload marks the record as invalid", function(assert) { +test('Repeated failed saves with invalid error without payload marks the record as invalid', function(assert) { assert.expect(2); let post = env.store.createRecord('post', { title: 'toto' }); @@ -154,7 +163,7 @@ test("Repeated failed saves with invalid error without payload marks the record }); }); -test("Will reject save on invalid", function(assert) { +test('Will reject save on invalid', function(assert) { assert.expect(1); let post = env.store.createRecord('post', { title: 'toto' }); @@ -165,8 +174,11 @@ test("Will reject save on invalid", function(assert) { }; run(function() { - post.save().then(function() {}, function() { - assert.ok(true, 'save operation was rejected'); - }); + post.save().then( + function() {}, + function() { + assert.ok(true, 'save operation was rejected'); + } + ); }); }); diff --git a/tests/integration/records/unload-test.js b/tests/integration/records/unload-test.js index 0b91dddd2d1..6caa286b03d 100644 --- a/tests/integration/records/unload-test.js +++ b/tests/integration/records/unload-test.js @@ -12,12 +12,7 @@ function idsFromOrderedSet(set) { return set.list.map(i => i.id); } -const { - attr, - belongsTo, - hasMany, - Model -} = DS; +const { attr, belongsTo, hasMany, Model } = DS; let env; @@ -46,57 +41,87 @@ let Person = Model.extend({ // many sync : many async favoriteFriends: hasMany('people', { async: true, inverse: 'favoriteAsyncFriends' }), // many async : many sync - favoriteAsyncFriends: hasMany('people', { async: false, inverse: 'favoriteFriends' }) + favoriteAsyncFriends: hasMany('people', { async: false, inverse: 'favoriteFriends' }), +}); +Person.reopenClass({ + toString() { + return 'Person'; + }, }); -Person.reopenClass({ toString() { return 'Person'; } }); let House = Model.extend({ - person: belongsTo('person', { async: false }) + person: belongsTo('person', { async: false }), +}); +House.reopenClass({ + toString() { + return 'House'; + }, }); -House.reopenClass({ toString() { return 'House'; } }); let Mortgage = Model.extend({ - person: belongsTo('person', { async: true }) + person: belongsTo('person', { async: true }), +}); +Mortgage.reopenClass({ + toString() { + return 'Mortgage'; + }, }); -Mortgage.reopenClass({ toString() { return 'Mortgage'; } }); let Group = Model.extend({ - people: hasMany('person', { async: false }) + people: hasMany('person', { async: false }), +}); +Group.reopenClass({ + toString() { + return 'Group'; + }, }); -Group.reopenClass({ toString() { return 'Group'; } }); let Car = Model.extend({ make: attr('string'), model: attr('string'), - person: belongsTo('person', { async: false }) + person: belongsTo('person', { async: false }), +}); +Car.reopenClass({ + toString() { + return 'Car'; + }, }); -Car.reopenClass({ toString() { return 'Car'; } }); let Boat = Model.extend({ name: attr('string'), - person: belongsTo('person', { async: true }) + person: belongsTo('person', { async: true }), }); -Boat.toString = function() { return 'Boat'; }; +Boat.toString = function() { + return 'Boat'; +}; let Bike = Model.extend({ - name: DS.attr() + name: DS.attr(), }); -Bike.toString = function() { return 'Bike'; }; +Bike.toString = function() { + return 'Bike'; +}; let Book = Model.extend({ - person: belongsTo('person', { async: true }) + person: belongsTo('person', { async: true }), }); -Book.toString = function() { return 'Book'; }; +Book.toString = function() { + return 'Book'; +}; let Spoon = Model.extend({ - person: belongsTo('person', { async: true }) + person: belongsTo('person', { async: true }), }); -Spoon.toString = function() { return 'Spoon'; }; +Spoon.toString = function() { + return 'Spoon'; +}; let Show = Model.extend({ - person: belongsTo('person', { async: false }) + person: belongsTo('person', { async: false }), }); -Show.toString = function() { return 'Show'; }; +Show.toString = function() { + return 'Show'; +}; module('integration/unload - Unloading Records', { beforeEach() { @@ -111,7 +136,7 @@ module('integration/unload - Unloading Records', { bike: Bike, book: Book, spoon: Spoon, - show: Show + show: Show, }); }, @@ -119,7 +144,7 @@ module('integration/unload - Unloading Records', { run(function() { env.container.destroy(); }); - } + }, }); test('can unload a single record', function(assert) { @@ -130,23 +155,27 @@ test('can unload a single record', function(assert) { type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' + name: 'Adam Sunderland', }, relationships: { cars: { - data: [{ - id: 1, - type: 'car' - }] + data: [ + { + id: 1, + type: 'car', + }, + ], }, boats: { - data: [{ - id: 2, - type: 'boat' - }] - } - } - } + data: [ + { + id: 2, + type: 'boat', + }, + ], + }, + }, + }, }); adam = env.store.peekRecord('person', 1); }); @@ -168,19 +197,22 @@ test('can unload all records for a given type', function(assert) { let adam, bob, dudu, car; run(function() { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Adam Sunderland' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Bob Bobson' - } - }] + 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); @@ -191,20 +223,24 @@ test('can unload all records for a given type', function(assert) { id: '1', attributes: { make: 'VW', - model: 'Beetle' + model: 'Beetle', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } - } + data: { type: 'person', id: '1' }, + }, + }, + }, }); dudu = bob = env.store.peekRecord('car', 1); }); assert.equal(env.store.peekAll('person').get('length'), 2, 'two person records loaded'); - assert.equal(env.store._internalModelsFor('person').length, 2, 'two person internalModels loaded'); + assert.equal( + env.store._internalModelsFor('person').length, + 2, + 'two person internalModels loaded' + ); assert.equal(env.store.peekAll('car').get('length'), 1, 'one car record loaded'); assert.equal(env.store._internalModelsFor('car').length, 1, 'one car internalModel loaded'); @@ -215,7 +251,11 @@ test('can unload all records for a given type', function(assert) { assert.equal(env.store.peekAll('person').get('length'), 0); assert.equal(env.store.peekAll('car').get('length'), 1); - assert.equal(env.store._internalModelsFor('person').length, 0, 'zero person internalModels loaded'); + assert.equal( + env.store._internalModelsFor('person').length, + 0, + 'zero person internalModels loaded' + ); assert.equal(env.store._internalModelsFor('car').length, 1, 'one car internalModel loaded'); run(function() { @@ -224,9 +264,9 @@ test('can unload all records for a given type', function(assert) { id: 1, type: 'person', attributes: { - name: 'Richard II' - } - } + name: 'Richard II', + }, + }, }); }); @@ -258,19 +298,22 @@ test('can unload all records', function(assert) { let adam, bob, dudu; run(function() { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Adam Sunderland' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Bob Bobson' - } - }] + 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); @@ -281,20 +324,24 @@ test('can unload all records', function(assert) { id: '1', attributes: { make: 'VW', - model: 'Beetle' + model: 'Beetle', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } - } + data: { type: 'person', id: '1' }, + }, + }, + }, }); dudu = bob = env.store.peekRecord('car', 1); }); assert.equal(env.store.peekAll('person').get('length'), 2, 'two person records loaded'); - assert.equal(env.store._internalModelsFor('person').length, 2, 'two person internalModels loaded'); + assert.equal( + env.store._internalModelsFor('person').length, + 2, + 'two person internalModels loaded' + ); assert.equal(env.store.peekAll('car').get('length'), 1, 'one car record loaded'); assert.equal(env.store._internalModelsFor('car').length, 1, 'one car internalModel loaded'); @@ -304,7 +351,11 @@ test('can unload all records', function(assert) { assert.equal(env.store.peekAll('person').get('length'), 0); assert.equal(env.store.peekAll('car').get('length'), 0); - assert.equal(env.store._internalModelsFor('person').length, 0, 'zero person internalModels loaded'); + assert.equal( + env.store._internalModelsFor('person').length, + 0, + 'zero person internalModels loaded' + ); assert.equal(env.store._internalModelsFor('car').length, 0, 'zero car internalModels loaded'); }); @@ -314,26 +365,33 @@ test('removes findAllCache after unloading all records', function(assert) { let adam, bob; run(function() { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Adam Sunderland' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Bob Bobson' - } - }] + 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); }); assert.equal(env.store.peekAll('person').get('length'), 2, 'two person records loaded'); - assert.equal(env.store._internalModelsFor('person').length, 2, 'two person internalModels loaded'); + assert.equal( + env.store._internalModelsFor('person').length, + 2, + 'two person internalModels loaded' + ); run(function() { env.store.peekAll('person'); @@ -341,26 +399,33 @@ test('removes findAllCache after unloading all records', function(assert) { }); assert.equal(env.store.peekAll('person').get('length'), 0, 'zero person records loaded'); - assert.equal(env.store._internalModelsFor('person').length, 0, 'zero person internalModels loaded'); + assert.equal( + env.store._internalModelsFor('person').length, + 0, + 'zero person internalModels loaded' + ); }); test('unloading all records also updates record array from peekAll()', function(assert) { let adam, bob; run(function() { env.store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Adam Sunderland' - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Bob Bobson' - } - }] + 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); @@ -369,7 +434,6 @@ test('unloading all records also updates record array from peekAll()', function( assert.equal(all.get('length'), 2); - run(function() { env.store.unloadAll('person'); }); @@ -381,13 +445,13 @@ function makeBoatOneForPersonOne() { type: 'boat', id: '1', attributes: { - name: 'Boaty McBoatface' + name: 'Boaty McBoatface', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } + data: { type: 'person', id: '1' }, + }, + }, }; } @@ -396,25 +460,23 @@ test('unloadAll(type) does not leave stranded internalModels in relationships (r let { store } = env; - let person = run(() => store.push({ - data: { - type: 'person', - id: '1', - attributes: { - name: 'Could be Anybody' + let person = run(() => + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Could be Anybody', + }, + relationships: { + boats: { + data: [{ type: 'boat', id: '1' }], + }, + }, }, - relationships: { - boats: { - data: [ - { type: 'boat', id: '1' } - ] - } - } - }, - included: [ - makeBoatOneForPersonOne() - ] - })); + included: [makeBoatOneForPersonOne()], + }) + ); let boat = store.peekRecord('boat', '1'); let initialBoatInternalModel = boat._internalModel; @@ -438,23 +500,34 @@ test('unloadAll(type) does not leave stranded internalModels in relationships (r assert.ok(peopleBoats.objectAt(0) === boat, 'Our person has the right boat'); assert.ok(boatPerson === person, 'Our boat has the right person'); - run(() => { store.unloadAll('boat') }); + run(() => { + store.unloadAll('boat'); + }); // ensure that our new state is correct assert.equal(knownPeople.models.length, 1, 'one person record is loaded'); assert.equal(knownBoats.models.length, 0, 'no boat records are loaded'); - assert.equal(relationshipState.canonicalMembers.size, 1, 'canonical member size should still be 1'); + assert.equal( + relationshipState.canonicalMembers.size, + 1, + 'canonical member size should still be 1' + ); assert.equal(relationshipState.members.size, 1, 'members size should still be 1'); assert.ok(get(peopleBoats, 'length') === 0, 'Our person thinks they have no boats'); - run(() => store.push({ - data: makeBoatOneForPersonOne() - })); + run(() => + store.push({ + data: makeBoatOneForPersonOne(), + }) + ); let reloadedBoat = store.peekRecord('boat', '1'); let reloadedBoatInternalModel = reloadedBoat._internalModel; - assert.ok(reloadedBoatInternalModel === initialBoatInternalModel, 'after an unloadAll, subsequent fetch results in the same InternalModel'); + assert.ok( + reloadedBoatInternalModel === initialBoatInternalModel, + 'after an unloadAll, subsequent fetch results in the same InternalModel' + ); }); test('unloadAll(type) does not leave stranded internalModels in relationships (rediscover via relationship reload)', function(assert) { @@ -466,29 +539,27 @@ test('unloadAll(type) does not leave stranded internalModels in relationships (r assert.ok(type.modelName === 'boat', 'We refetch the boat'); assert.ok(id === '1', 'We refetch the right boat'); return resolve({ - data: makeBoatOneForPersonOne() + data: makeBoatOneForPersonOne(), }); }; - let person = run(() => store.push({ - data: { - type: 'person', - id: '1', - attributes: { - name: 'Could be Anybody' + let person = run(() => + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Could be Anybody', + }, + relationships: { + boats: { + data: [{ type: 'boat', id: '1' }], + }, + }, }, - relationships: { - boats: { - data: [ - { type: 'boat', id: '1' } - ] - } - } - }, - included: [ - makeBoatOneForPersonOne() - ] - })); + included: [makeBoatOneForPersonOne()], + }) + ); let boat = store.peekRecord('boat', '1'); let initialBoatInternalModel = boat._internalModel; @@ -512,12 +583,18 @@ test('unloadAll(type) does not leave stranded internalModels in relationships (r assert.ok(peopleBoats.objectAt(0) === boat, 'Our person has the right boat'); assert.ok(boatPerson === person, 'Our boat has the right person'); - run(() => { store.unloadAll('boat') }); + run(() => { + store.unloadAll('boat'); + }); // ensure that our new state is correct assert.equal(knownPeople.models.length, 1, 'one person record is loaded'); assert.equal(knownBoats.models.length, 0, 'no boat records are loaded'); - assert.equal(relationshipState.canonicalMembers.size, 1, 'canonical member size should still be 1'); + assert.equal( + relationshipState.canonicalMembers.size, + 1, + 'canonical member size should still be 1' + ); assert.equal(relationshipState.members.size, 1, 'members size should still be 1'); assert.ok(get(peopleBoats, 'length') === 0, 'Our person thinks they have no boats'); @@ -526,31 +603,32 @@ test('unloadAll(type) does not leave stranded internalModels in relationships (r let reloadedBoat = store.peekRecord('boat', '1'); let reloadedBoatInternalModel = reloadedBoat._internalModel; - assert.ok(reloadedBoatInternalModel === initialBoatInternalModel, 'after an unloadAll, subsequent fetch results in the same InternalModel'); + assert.ok( + reloadedBoatInternalModel === initialBoatInternalModel, + 'after an unloadAll, subsequent fetch results in the same InternalModel' + ); }); test('(regression) unloadRecord followed by push in the same run-loop', function(assert) { let { store } = env; - let person = run(() => store.push({ - data: { - type: 'person', - id: '1', - attributes: { - name: 'Could be Anybody' + let person = run(() => + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Could be Anybody', + }, + relationships: { + boats: { + data: [{ type: 'boat', id: '1' }], + }, + }, }, - relationships: { - boats: { - data: [ - { type: 'boat', id: '1' } - ] - } - } - }, - included: [ - makeBoatOneForPersonOne() - ] - })); + included: [makeBoatOneForPersonOne()], + }) + ); let boat = store.peekRecord('boat', '1'); let initialBoatInternalModel = boat._internalModel; @@ -568,7 +646,11 @@ test('(regression) unloadRecord followed by push in the same run-loop', function let peopleBoats = run(() => person.get('boats.content')); let boatPerson = run(() => boat.get('person.content')); - assert.deepEqual(idsFromOrderedSet(relationshipState.canonicalMembers), ['1'], 'canonical member size should be 1'); + assert.deepEqual( + idsFromOrderedSet(relationshipState.canonicalMembers), + ['1'], + 'canonical member size should be 1' + ); assert.deepEqual(idsFromOrderedSet(relationshipState.members), ['1'], 'members size should be 1'); assert.ok(get(peopleBoats, 'length') === 1, 'Our person has a boat'); assert.ok(peopleBoats.objectAt(0) === boat, 'Our person has the right boat'); @@ -581,20 +663,37 @@ test('(regression) unloadRecord followed by push in the same run-loop', function assert.deepEqual(knownBoats.models.map(m => m.id), ['1'], 'one boat record is known'); assert.ok(knownBoats.models[0] === initialBoatInternalModel, 'We still have our boat'); assert.equal(initialBoatInternalModel.isEmpty(), true, 'Model is in the empty state'); - assert.deepEqual(idsFromOrderedSet(relationshipState.canonicalMembers), ['1'], 'canonical member size should still be 1'); - assert.deepEqual(idsFromOrderedSet(relationshipState.members), ['1'], 'members size should still be 1'); + assert.deepEqual( + idsFromOrderedSet(relationshipState.canonicalMembers), + ['1'], + 'canonical member size should still be 1' + ); + assert.deepEqual( + idsFromOrderedSet(relationshipState.members), + ['1'], + 'members size should still be 1' + ); assert.ok(get(peopleBoats, 'length') === 0, 'Our person thinks they have no boats'); - run(() => store.push({ - data: makeBoatOneForPersonOne() - })); + run(() => + store.push({ + data: makeBoatOneForPersonOne(), + }) + ); let reloadedBoat = store.peekRecord('boat', '1'); let reloadedBoatInternalModel = reloadedBoat._internalModel; - assert.deepEqual(idsFromOrderedSet(relationshipState.canonicalMembers), ['1'], 'canonical member size should be 1'); + assert.deepEqual( + idsFromOrderedSet(relationshipState.canonicalMembers), + ['1'], + 'canonical member size should be 1' + ); assert.deepEqual(idsFromOrderedSet(relationshipState.members), ['1'], 'members size should be 1'); - assert.ok(reloadedBoatInternalModel === initialBoatInternalModel, 'after an unloadRecord, subsequent fetch results in the same InternalModel'); + assert.ok( + reloadedBoatInternalModel === initialBoatInternalModel, + 'after an unloadRecord, subsequent fetch results in the same InternalModel' + ); // and now the kicker, run-loop fun! // here, we will dematerialize the record, but push it back into the store @@ -603,19 +702,28 @@ test('(regression) unloadRecord followed by push in the same run-loop', function run(() => { reloadedBoat.unloadRecord(); store.push({ - data: makeBoatOneForPersonOne() + data: makeBoatOneForPersonOne(), }); }); let yaBoat = store.peekRecord('boat', '1'); let yaBoatInternalModel = yaBoat._internalModel; - assert.deepEqual(idsFromOrderedSet(relationshipState.canonicalMembers), ['1'], 'canonical member size should be 1'); + assert.deepEqual( + idsFromOrderedSet(relationshipState.canonicalMembers), + ['1'], + 'canonical member size should be 1' + ); assert.deepEqual(idsFromOrderedSet(relationshipState.members), ['1'], 'members size should be 1'); - assert.ok(yaBoatInternalModel === initialBoatInternalModel, 'after an unloadRecord, subsequent same-loop push results in the same InternalModel'); + assert.ok( + yaBoatInternalModel === initialBoatInternalModel, + 'after an unloadRecord, subsequent same-loop push results in the same InternalModel' + ); }); -testRecordData('unloading a disconnected subgraph clears the relevant internal models', function(assert) { +testRecordData('unloading a disconnected subgraph clears the relevant internal models', function( + assert +) { env.adapter.shouldBackgroundReloadRecord = () => false; run(() => { @@ -624,17 +732,14 @@ testRecordData('unloading a disconnected subgraph clears the relevant internal m type: 'person', id: '1', attributes: { - name: 'Could be Anybody' + name: 'Could be Anybody', }, relationships: { boats: { - data: [ - { type: 'boat', id: '1' }, - { type: 'boat', id: '2' } - ] - } - } - } + data: [{ type: 'boat', id: '1' }, { type: 'boat', id: '2' }], + }, + }, + }, }); }); @@ -644,14 +749,14 @@ testRecordData('unloading a disconnected subgraph clears the relevant internal m type: 'boat', id: '1', attributes: { - name: 'Boaty McBoatface' + name: 'Boaty McBoatface', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } - } + data: { type: 'person', id: '1' }, + }, + }, + }, }); }); @@ -661,14 +766,14 @@ testRecordData('unloading a disconnected subgraph clears the relevant internal m type: 'boat', id: '2', attributes: { - name: 'The jackson' + name: 'The jackson', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } - } + data: { type: 'person', id: '1' }, + }, + }, + }, }); }); @@ -696,12 +801,12 @@ testRecordData('unloading a disconnected subgraph clears the relevant internal m let modelData = internalModel._modelData; let origCleanup = modelData._cleanupOrphanedModelDatas; - internalModel._checkForOrphanedInternalModels = function () { + internalModel._checkForOrphanedInternalModels = function() { ++checkOrphanCalls; return origCheck.apply(record._internalModel, arguments); }; - modelData._cleanupOrphanedModelDatas = function () { + modelData._cleanupOrphanedModelDatas = function() { ++cleanupOrphanCalls; return origCleanup.apply(modelData, arguments); }; @@ -711,22 +816,27 @@ testRecordData('unloading a disconnected subgraph clears the relevant internal m countOrphanCalls(env.store.peekRecord('boat', 2)); // make sure relationships are initialized - return env.store.peekRecord('person', 1).get('boats').then(() => { - run(() => { - env.store.peekRecord('person', 1).unloadRecord(); - env.store.peekRecord('boat', 1).unloadRecord(); - env.store.peekRecord('boat', 2).unloadRecord(); - }); + return env.store + .peekRecord('person', 1) + .get('boats') + .then(() => { + run(() => { + env.store.peekRecord('person', 1).unloadRecord(); + env.store.peekRecord('boat', 1).unloadRecord(); + env.store.peekRecord('boat', 2).unloadRecord(); + }); - assert.equal(env.store._internalModelsFor('person').models.length, 0); - assert.equal(env.store._internalModelsFor('boat').models.length, 0); + assert.equal(env.store._internalModelsFor('person').models.length, 0); + assert.equal(env.store._internalModelsFor('boat').models.length, 0); - assert.equal(checkOrphanCalls, 3, 'each internalModel checks for cleanup'); - assert.equal(cleanupOrphanCalls, 3, 'each model data tries to cleanup'); - }); + assert.equal(checkOrphanCalls, 3, 'each internalModel checks for cleanup'); + assert.equal(cleanupOrphanCalls, 3, 'each model data tries to cleanup'); + }); }); -skipRecordData('unloading a disconnected subgraph clears the relevant internal models', function(assert) { +skipRecordData('unloading a disconnected subgraph clears the relevant internal models', function( + assert +) { env.adapter.shouldBackgroundReloadRecord = () => false; run(() => { @@ -735,17 +845,14 @@ skipRecordData('unloading a disconnected subgraph clears the relevant internal m type: 'person', id: '1', attributes: { - name: 'Could be Anybody' + name: 'Could be Anybody', }, relationships: { boats: { - data: [ - { type: 'boat', id: '1' }, - { type: 'boat', id: '2' } - ] - } - } - } + data: [{ type: 'boat', id: '1' }, { type: 'boat', id: '2' }], + }, + }, + }, }); }); @@ -755,14 +862,14 @@ skipRecordData('unloading a disconnected subgraph clears the relevant internal m type: 'boat', id: '1', attributes: { - name: 'Boaty McBoatface' + name: 'Boaty McBoatface', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } - } + data: { type: 'person', id: '1' }, + }, + }, + }, }); }); @@ -772,14 +879,14 @@ skipRecordData('unloading a disconnected subgraph clears the relevant internal m type: 'boat', id: '2', attributes: { - name: 'The jackson' + name: 'The jackson', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } - } + data: { type: 'person', id: '1' }, + }, + }, + }, }); }); @@ -805,12 +912,12 @@ skipRecordData('unloading a disconnected subgraph clears the relevant internal m let origCheck = internalModel._checkForOrphanedInternalModels; let origCleanup = internalModel._cleanupOrphanedInternalModels; - internalModel._checkForOrphanedInternalModels = function () { + internalModel._checkForOrphanedInternalModels = function() { ++checkOrphanCalls; return origCheck.apply(record._internalModel, arguments); }; - internalModel._cleanupOrphanedInternalModels = function () { + internalModel._cleanupOrphanedInternalModels = function() { ++cleanupOrphanCalls; return origCleanup.apply(internalModel, arguments); }; @@ -820,19 +927,22 @@ skipRecordData('unloading a disconnected subgraph clears the relevant internal m countOrphanCalls(env.store.peekRecord('boat', 2)); // make sure relationships are initialized - return env.store.peekRecord('person', 1).get('boats').then(() => { - run(() => { - env.store.peekRecord('person', 1).unloadRecord(); - env.store.peekRecord('boat', 1).unloadRecord(); - env.store.peekRecord('boat', 2).unloadRecord(); - }); + return env.store + .peekRecord('person', 1) + .get('boats') + .then(() => { + run(() => { + env.store.peekRecord('person', 1).unloadRecord(); + env.store.peekRecord('boat', 1).unloadRecord(); + env.store.peekRecord('boat', 2).unloadRecord(); + }); - assert.equal(env.store._internalModelsFor('person').models.length, 0); - assert.equal(env.store._internalModelsFor('boat').models.length, 0); + assert.equal(env.store._internalModelsFor('person').models.length, 0); + assert.equal(env.store._internalModelsFor('boat').models.length, 0); - assert.equal(checkOrphanCalls, 3, 'each internalModel checks for cleanup'); - assert.equal(cleanupOrphanCalls, 1, 'each model data tries to cleanup'); - }); + assert.equal(checkOrphanCalls, 3, 'each internalModel checks for cleanup'); + assert.equal(cleanupOrphanCalls, 1, 'each model data tries to cleanup'); + }); }); test('Unloading a record twice only schedules destroy once', function(assert) { @@ -846,9 +956,9 @@ test('Unloading a record twice only schedules destroy once', function(assert) { type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' - } - } + name: 'Adam Sunderland', + }, + }, }); }); @@ -874,14 +984,18 @@ test('Cancelling destroy leaves the record in the empty state', function(assert) type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' - } - } + name: 'Adam Sunderland', + }, + }, }); }); const internalModel = record._internalModel; - assert.equal(internalModel.currentState.stateName, 'root.loaded.saved', 'We are loaded initially'); + assert.equal( + internalModel.currentState.stateName, + 'root.loaded.saved', + 'We are loaded initially' + ); run(function() { store.unloadRecord(record); @@ -889,12 +1003,24 @@ test('Cancelling destroy leaves the record in the empty state', function(assert) assert.equal(internalModel.isDestroyed, false, 'the internal model is not destroyed'); assert.equal(internalModel._isDematerializing, true, 'the internal model is dematerializing'); internalModel.cancelDestroy(); - assert.equal(internalModel.currentState.stateName, 'root.empty', 'We are unloaded after unloadRecord'); + assert.equal( + internalModel.currentState.stateName, + 'root.empty', + 'We are unloaded after unloadRecord' + ); }); assert.equal(internalModel.isDestroyed, false, 'the internal model was not destroyed'); - assert.equal(internalModel._isDematerializing, false, 'the internal model is no longer dematerializing'); - assert.equal(internalModel.currentState.stateName, 'root.empty', 'We are still unloaded after unloadRecord'); + assert.equal( + internalModel._isDematerializing, + false, + 'the internal model is no longer dematerializing' + ); + assert.equal( + internalModel.currentState.stateName, + 'root.empty', + 'We are still unloaded after unloadRecord' + ); }); test('after unloading a record, the record can be fetched again immediately', function(assert) { @@ -907,9 +1033,9 @@ test('after unloading a record, the record can be fetched again immediately', fu type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' - } - } + name: 'Adam Sunderland', + }, + }, }; }; @@ -920,18 +1046,18 @@ test('after unloading a record, the record can be fetched again immediately', fu type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' + name: 'Adam Sunderland', }, relationships: { cars: { data: [ { id: 1, - type: 'car' - } - ] - } - } + type: 'car', + }, + ], + }, + }, }, included: [ { @@ -939,24 +1065,36 @@ test('after unloading a record, the record can be fetched again immediately', fu id: 1, attributes: { make: 'jeep', - model: 'wrangler' - } - } - ] + model: 'wrangler', + }, + }, + ], }); }); const internalModel = record._internalModel; - assert.equal(internalModel.currentState.stateName, 'root.loaded.saved', 'We are loaded initially'); + assert.equal( + internalModel.currentState.stateName, + 'root.loaded.saved', + 'We are loaded initially' + ); // we test that we can sync call unloadRecord followed by findRecord return run(() => { store.unloadRecord(record); assert.equal(record.isDestroying, true, 'the record is destroying'); - assert.equal(internalModel.currentState.stateName, 'root.empty', 'We are unloaded after unloadRecord'); + assert.equal( + internalModel.currentState.stateName, + 'root.empty', + 'We are unloaded after unloadRecord' + ); return store.findRecord('person', '1').then(newRecord => { assert.ok(internalModel === newRecord._internalModel, 'the old internalModel is reused'); - assert.equal(newRecord._internalModel.currentState.stateName, 'root.loaded.saved', 'We are loaded after findRecord'); + assert.equal( + newRecord._internalModel.currentState.stateName, + 'root.loaded.saved', + 'We are loaded after findRecord' + ); }); }); }); @@ -971,14 +1109,14 @@ test('after unloading a record, the record can be fetched again immediately (pur type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' + name: 'Adam Sunderland', }, relationships: { cars: { - data: [] - } - } - } + data: [], + }, + }, + }, }; }; @@ -989,18 +1127,18 @@ test('after unloading a record, the record can be fetched again immediately (pur type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' + name: 'Adam Sunderland', }, relationships: { cars: { data: [ { id: '1', - type: 'car' - } - ] - } - } + type: 'car', + }, + ], + }, + }, }, included: [ { @@ -1008,27 +1146,43 @@ test('after unloading a record, the record can be fetched again immediately (pur id: '1', attributes: { make: 'jeep', - model: 'wrangler' - } - } - ] + model: 'wrangler', + }, + }, + ], }); }); const internalModel = record._internalModel; - assert.equal(internalModel.currentState.stateName, 'root.loaded.saved', 'We are loaded initially'); + assert.equal( + internalModel.currentState.stateName, + 'root.loaded.saved', + 'We are loaded initially' + ); // we test that we can sync call unloadRecord followed by findRecord return run(() => { assert.equal(record.get('cars.firstObject.make'), 'jeep'); store.unloadRecord(record); assert.equal(record.isDestroying, true, 'the record is destroying'); - assert.equal(internalModel.currentState.stateName, 'root.empty', 'Expected the previous internal model tobe unloaded'); + assert.equal( + internalModel.currentState.stateName, + 'root.empty', + 'Expected the previous internal model tobe unloaded' + ); return store.findRecord('person', '1').then(record => { - assert.equal(record.get('cars.length'), 0, 'Expected relationship to be cleared by the new push'); + assert.equal( + record.get('cars.length'), + 0, + 'Expected relationship to be cleared by the new push' + ); assert.ok(internalModel === record._internalModel, 'the old internalModel is reused'); - assert.equal(record._internalModel.currentState.stateName, 'root.loaded.saved', 'Expected the NEW internal model to be loaded'); + assert.equal( + record._internalModel.currentState.stateName, + 'root.loaded.saved', + 'Expected the NEW internal model to be loaded' + ); }); }); }); @@ -1042,9 +1196,9 @@ test('after unloading a record, the record can be fetched again immediately (wit type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' - } - } + name: 'Adam Sunderland', + }, + }, }; }; @@ -1056,9 +1210,9 @@ test('after unloading a record, the record can be fetched again immediately (wit id: '1', relationships: { bike: { - data: { type: 'bike', id: '1' } - } - } + data: { type: 'bike', id: '1' }, + }, + }, }, included: [ @@ -1066,16 +1220,20 @@ test('after unloading a record, the record can be fetched again immediately (wit id: '1', type: 'bike', attributes: { - name: 'mr bike' - } - } - ] + name: 'mr bike', + }, + }, + ], }); }); const internalModel = record._internalModel; const bike = store.peekRecord('bike', '1'); - assert.equal(internalModel.currentState.stateName, 'root.loaded.saved', 'We are loaded initially'); + assert.equal( + internalModel.currentState.stateName, + 'root.loaded.saved', + 'We are loaded initially' + ); assert.equal(record.get('bike.name'), 'mr bike'); @@ -1084,11 +1242,18 @@ test('after unloading a record, the record can be fetched again immediately (wit store.unloadRecord(record); assert.equal(record.isDestroying, true, 'the record is destroying'); assert.equal(record.isDestroyed, false, 'the record is NOT YET destroyed'); - assert.equal(internalModel.currentState.stateName, 'root.empty', 'We are unloaded after unloadRecord'); + assert.equal( + internalModel.currentState.stateName, + 'root.empty', + 'We are unloaded after unloadRecord' + ); let wait = store.findRecord('person', '1').then(newRecord => { assert.equal(record.isDestroyed, false, 'the record is NOT YET destroyed'); - assert.ok(newRecord.get('bike') === bike, 'the newRecord should retain knowledge of the bike'); + assert.ok( + newRecord.get('bike') === bike, + 'the newRecord should retain knowledge of the bike' + ); }); assert.equal(record.isDestroyed, false, 'the record is NOT YET destroyed'); @@ -1110,9 +1275,9 @@ test('after unloading a record, the record can be fetched again soon there after type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' - } - } + name: 'Adam Sunderland', + }, + }, }); }; @@ -1123,19 +1288,27 @@ test('after unloading a record, the record can be fetched again soon there after type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' - } - } + name: 'Adam Sunderland', + }, + }, }); }); let internalModel = record._internalModel; - assert.equal(internalModel.currentState.stateName, 'root.loaded.saved', 'We are loaded initially'); + assert.equal( + internalModel.currentState.stateName, + 'root.loaded.saved', + 'We are loaded initially' + ); run(function() { store.unloadRecord(record); assert.equal(record.isDestroying, true, 'the record is destroying'); - assert.equal(internalModel.currentState.stateName, 'root.empty', 'We are unloaded after unloadRecord'); + assert.equal( + internalModel.currentState.stateName, + 'root.empty', + 'We are unloaded after unloadRecord' + ); }); run(function() { @@ -1145,10 +1318,14 @@ test('after unloading a record, the record can be fetched again soon there after record = store.peekRecord('person', '1'); internalModel = record._internalModel; - assert.equal(internalModel.currentState.stateName, 'root.loaded.saved', 'We are loaded after findRecord'); + assert.equal( + internalModel.currentState.stateName, + 'root.loaded.saved', + 'We are loaded after findRecord' + ); }); -test('after unloading a record, the record can be saved again immediately', function (assert) { +test('after unloading a record, the record can be saved again immediately', function(assert) { assert.expect(0); const store = env.store; @@ -1157,9 +1334,9 @@ test('after unloading a record, the record can be saved again immediately', func type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' - } - } + name: 'Adam Sunderland', + }, + }, }; env.adapter.createRecord = () => EmberPromise.resolve(data); @@ -1176,16 +1353,16 @@ test('after unloading a record, the record can be saved again immediately', func }); }); -test('after unloading a record, pushing a new copy will setup relationships', function (assert) { +test('after unloading a record, pushing a new copy will setup relationships', function(assert) { const store = env.store; const personData = { data: { type: 'person', id: '1', attributes: { - name: 'Adam Sunderland' - } - } + name: 'Adam Sunderland', + }, + }, }; function pushCar() { @@ -1195,18 +1372,20 @@ test('after unloading a record, pushing a new copy will setup relationships', fu id: '10', attributes: { make: 'VW', - model: 'Beetle' + model: 'Beetle', }, relationships: { person: { - data: { type: 'person', id: '1' } - } - } - } + data: { type: 'person', id: '1' }, + }, + }, + }, }); } - run(() => { store.push(personData) }); + run(() => { + store.push(personData); + }); let adam = env.store.peekRecord('person', 1); assert.equal(adam.get('cars.length'), 0, 'cars hasMany starts off empty'); @@ -1221,7 +1400,7 @@ test('after unloading a record, pushing a new copy will setup relationships', fu assert.equal(adam.get('cars.length'), 1, 'pushing car again setups inverse relationship'); }); -test('1:1 sync unload', function (assert) { +test('1:1 sync unload', function(assert) { run(() => env.store.push({ data: { @@ -1231,15 +1410,17 @@ test('1:1 sync unload', function (assert) { house: { data: { id: 2, - type: 'house' - } - } - } + type: 'house', + }, + }, + }, }, - included: [{ - id: 2, - type: 'house' - }] + included: [ + { + id: 2, + type: 'house', + }, + ], }) ); @@ -1251,7 +1432,6 @@ test('1:1 sync unload', function (assert) { run(() => house.unloadRecord()); - assert.equal(person.get('house'), null, 'unloading acts as a delete for sync relationships'); assert.equal(env.store.hasRecordForId('house', 2), false, 'unloaded record gone from store'); @@ -1259,14 +1439,22 @@ test('1:1 sync unload', function (assert) { env.store.push({ data: { id: 2, - type: 'house' - } + type: 'house', + }, }) ); assert.equal(env.store.hasRecordForId('house', 2), true, 'unloaded record can be restored'); - assert.equal(person.get('house'), null, 'restoring unloaded record does not restore relationship'); - assert.equal(house.get('person'), null, 'restoring unloaded record does not restore relationship'); + assert.equal( + person.get('house'), + null, + 'restoring unloaded record does not restore relationship' + ); + assert.equal( + house.get('person'), + null, + 'restoring unloaded record does not restore relationship' + ); run(() => env.store.push({ @@ -1277,11 +1465,11 @@ test('1:1 sync unload', function (assert) { person: { data: { id: 1, - type: 'person' - } - } - } - } + type: 'person', + }, + }, + }, + }, }) ); @@ -1289,7 +1477,7 @@ test('1:1 sync unload', function (assert) { assert.equal(house.get('person.id'), 1, 'after unloading, relationship can be restored'); }); -test('1:many sync unload 1 side', function (assert) { +test('1:many sync unload 1 side', function(assert) { run(() => env.store.push({ data: { @@ -1297,23 +1485,29 @@ test('1:many sync unload 1 side', function (assert) { type: 'person', relationships: { cars: { - data: [{ - id: 2, - type: 'car' - }, { - id: 3, - type: 'car' - }] - } - } + data: [ + { + id: 2, + type: 'car', + }, + { + id: 3, + type: 'car', + }, + ], + }, + }, }, - included: [{ - id: 2, - type: 'car' - }, { - id: 3, - type: 'car' - }] + included: [ + { + id: 2, + type: 'car', + }, + { + id: 3, + type: 'car', + }, + ], }) ); @@ -1323,7 +1517,11 @@ test('1:many sync unload 1 side', function (assert) { let cars = person.get('cars'); assert.equal(cars.isDestroyed, false, 'ManyArray not destroyed'); - assert.deepEqual(person.get('cars').mapBy('id'), ['2', '3'], 'initialy relationship established lhs'); + assert.deepEqual( + person.get('cars').mapBy('id'), + ['2', '3'], + 'initialy relationship established lhs' + ); assert.equal(car2.get('person.id'), 1, 'initially relationship established rhs'); assert.equal(car3.get('person.id'), 1, 'initially relationship established rhs'); @@ -1339,13 +1537,17 @@ test('1:many sync unload 1 side', function (assert) { env.store.push({ data: { id: 1, - type: 'person' - } + type: 'person', + }, }) ); assert.equal(env.store.hasRecordForId('person', 1), true, 'unloaded record can be restored'); - assert.deepEqual(person.get('cars').mapBy('id'), [], 'restoring unloaded record does not restore relationship'); + assert.deepEqual( + person.get('cars').mapBy('id'), + [], + 'restoring unloaded record does not restore relationship' + ); assert.equal(car2.get('person'), null, 'restoring unloaded record does not restore relationship'); assert.equal(car3.get('person'), null, 'restoring unloaded record does not restore relationship'); @@ -1356,25 +1558,32 @@ test('1:many sync unload 1 side', function (assert) { type: 'person', relationships: { cars: { - data: [{ - id: 2, - type: 'car' - }, { - id: 3, - type: 'car' - }] - } - } - } + data: [ + { + id: 2, + type: 'car', + }, + { + id: 3, + type: 'car', + }, + ], + }, + }, + }, }) ); assert.equal(car2.get('person.id'), '1', 'after unloading, relationship can be restored'); assert.equal(car3.get('person.id'), '1', 'after unloading, relationship can be restored'); - assert.deepEqual(person.get('cars').mapBy('id'), ['2', '3'], 'after unloading, relationship can be restored'); + assert.deepEqual( + person.get('cars').mapBy('id'), + ['2', '3'], + 'after unloading, relationship can be restored' + ); }); -test('1:many sync unload many side', function (assert) { +test('1:many sync unload many side', function(assert) { run(() => env.store.push({ data: { @@ -1382,23 +1591,29 @@ test('1:many sync unload many side', function (assert) { type: 'person', relationships: { cars: { - data: [{ - id: 2, - type: 'car' - }, { - id: 3, - type: 'car' - }] - } - } + data: [ + { + id: 2, + type: 'car', + }, + { + id: 3, + type: 'car', + }, + ], + }, + }, }, - included: [{ - id: 2, - type: 'car' - }, { - id: 3, - type: 'car' - }] + included: [ + { + id: 2, + type: 'car', + }, + { + id: 3, + type: 'car', + }, + ], }) ); @@ -1408,7 +1623,11 @@ test('1:many sync unload many side', function (assert) { let cars = person.get('cars'); assert.equal(cars.isDestroyed, false, 'ManyArray not destroyed'); - assert.deepEqual(person.get('cars').mapBy('id'), ['2', '3'], 'initialy relationship established lhs'); + assert.deepEqual( + person.get('cars').mapBy('id'), + ['2', '3'], + 'initialy relationship established lhs' + ); assert.equal(car2.get('person.id'), 1, 'initially relationship established rhs'); assert.equal(car3.get('person.id'), 1, 'initially relationship established rhs'); @@ -1417,20 +1636,32 @@ test('1:many sync unload many side', function (assert) { assert.equal(env.store.hasRecordForId('car', 2), false, 'unloaded record gone from store'); assert.equal(cars.isDestroyed, false, 'ManyArray not destroyed'); - assert.deepEqual(person.get('cars').mapBy('id'), ['3'], 'unload sync relationship acts as delete'); - assert.equal(car3.get('person.id'), '1', 'unloading one of a sync hasMany does not affect the rest'); + assert.deepEqual( + person.get('cars').mapBy('id'), + ['3'], + 'unload sync relationship acts as delete' + ); + assert.equal( + car3.get('person.id'), + '1', + 'unloading one of a sync hasMany does not affect the rest' + ); car2 = run(() => env.store.push({ data: { id: 2, - type: 'car' - } + type: 'car', + }, }) ); assert.equal(env.store.hasRecordForId('car', 2), true, 'unloaded record can be restored'); - assert.deepEqual(person.get('cars').mapBy('id'), ['3'], 'restoring unloaded record does not restore relationship'); + assert.deepEqual( + person.get('cars').mapBy('id'), + ['3'], + 'restoring unloaded record does not restore relationship' + ); assert.equal(car2.get('person'), null, 'restoring unloaded record does not restore relationship'); run(() => @@ -1440,62 +1671,81 @@ test('1:many sync unload many side', function (assert) { type: 'person', relationships: { cars: { - data: [{ - id: 2, - type: 'car' - }, { - id: 3, - type: 'car' - }] - } - } - } + data: [ + { + id: 2, + type: 'car', + }, + { + id: 3, + type: 'car', + }, + ], + }, + }, + }, }) ); assert.equal(car2.get('person.id'), '1', 'after unloading, relationship can be restored'); - assert.deepEqual(person.get('cars').mapBy('id'), ['2', '3'], 'after unloading, relationship can be restored'); + assert.deepEqual( + person.get('cars').mapBy('id'), + ['2', '3'], + 'after unloading, relationship can be restored' + ); }); -test('many:many sync unload', function (assert) { +test('many:many sync unload', function(assert) { run(() => env.store.push({ - data: [{ - id: 1, - type: 'person', - relationships: { - groups: { - data: [{ - id: 3, - type: 'group' - }, { - id: 4, - type: 'group' - }] - } - } - }, { - id: 2, - type: 'person', - relationships: { - groups: { - data: [{ - id: 3, - type: 'group' - }, { - id: 4, - type: 'group' - }] - } - } - }], - included: [{ - id: 3, - type: 'group' - }, { - id: 4, - type: 'group' - }] + data: [ + { + id: 1, + type: 'person', + relationships: { + groups: { + data: [ + { + id: 3, + type: 'group', + }, + { + id: 4, + type: 'group', + }, + ], + }, + }, + }, + { + id: 2, + type: 'person', + relationships: { + groups: { + data: [ + { + id: 3, + type: 'group', + }, + { + id: 4, + type: 'group', + }, + ], + }, + }, + }, + ], + included: [ + { + id: 3, + type: 'group', + }, + { + id: 4, + type: 'group', + }, + ], }) ); @@ -1506,10 +1756,26 @@ test('many:many sync unload', function (assert) { let p2groups = person2.get('groups'); let g3people = group3.get('people'); - assert.deepEqual(person1.get('groups').mapBy('id'), ['3', '4'], 'initially established relationship lhs'); - assert.deepEqual(person2.get('groups').mapBy('id'), ['3', '4'], 'initially established relationship lhs'); - assert.deepEqual(group3.get('people').mapBy('id'), ['1', '2'], 'initially established relationship lhs'); - assert.deepEqual(group4.get('people').mapBy('id'), ['1', '2'], 'initially established relationship lhs'); + assert.deepEqual( + person1.get('groups').mapBy('id'), + ['3', '4'], + 'initially established relationship lhs' + ); + assert.deepEqual( + person2.get('groups').mapBy('id'), + ['3', '4'], + 'initially established relationship lhs' + ); + assert.deepEqual( + group3.get('people').mapBy('id'), + ['1', '2'], + 'initially established relationship lhs' + ); + assert.deepEqual( + group4.get('people').mapBy('id'), + ['1', '2'], + 'initially established relationship lhs' + ); assert.equal(p2groups.isDestroyed, false, 'groups is not destroyed'); assert.equal(g3people.isDestroyed, false, 'people is not destroyed'); @@ -1519,9 +1785,21 @@ test('many:many sync unload', function (assert) { assert.equal(p2groups.isDestroyed, true, 'groups (unloaded side) is destroyed'); assert.equal(g3people.isDestroyed, false, 'people (inverse) is not destroyed'); - assert.deepEqual(person1.get('groups').mapBy('id'), ['3', '4'], 'unloaded record in many:many does not affect inverse of inverse'); - assert.deepEqual(group3.get('people').mapBy('id'), ['1'], 'unloading acts as delete for sync relationships'); - assert.deepEqual(group4.get('people').mapBy('id'), ['1'], 'unloading acts as delete for sync relationships'); + assert.deepEqual( + person1.get('groups').mapBy('id'), + ['3', '4'], + 'unloaded record in many:many does not affect inverse of inverse' + ); + assert.deepEqual( + group3.get('people').mapBy('id'), + ['1'], + 'unloading acts as delete for sync relationships' + ); + assert.deepEqual( + group4.get('people').mapBy('id'), + ['1'], + 'unloading acts as delete for sync relationships' + ); assert.equal(env.store.hasRecordForId('person', 2), false, 'unloading removes record from store'); @@ -1529,15 +1807,27 @@ test('many:many sync unload', function (assert) { env.store.push({ data: { id: 2, - type: 'person' - } + type: 'person', + }, }) ); assert.equal(env.store.hasRecordForId('person', 2), true, 'unloaded record can be restored'); - assert.deepEqual(person2.get('groups').mapBy('id'), [], 'restoring unloaded record does not restore relationship'); - assert.deepEqual(group3.get('people').mapBy('id'), ['1'], 'restoring unloaded record does not restore relationship'); - assert.deepEqual(group4.get('people').mapBy('id'), ['1'], 'restoring unloaded record does not restore relationship'); + assert.deepEqual( + person2.get('groups').mapBy('id'), + [], + 'restoring unloaded record does not restore relationship' + ); + assert.deepEqual( + group3.get('people').mapBy('id'), + ['1'], + 'restoring unloaded record does not restore relationship' + ); + assert.deepEqual( + group4.get('people').mapBy('id'), + ['1'], + 'restoring unloaded record does not restore relationship' + ); run(() => env.store.push({ @@ -1546,25 +1836,40 @@ test('many:many sync unload', function (assert) { type: 'person', relationships: { groups: { - data: [{ - id: 3, - type: 'group' - }, { - id: 4, - type: 'group' - }] - } - } - } + data: [ + { + id: 3, + type: 'group', + }, + { + id: 4, + type: 'group', + }, + ], + }, + }, + }, }) ); - assert.deepEqual(person2.get('groups').mapBy('id'), ['3', '4'], 'after unloading, relationship can be restored'); - assert.deepEqual(group3.get('people').mapBy('id'), ['1', '2'], 'after unloading, relationship can be restored'); - assert.deepEqual(group4.get('people').mapBy('id'), ['1', '2'], 'after unloading, relationship can be restored'); + assert.deepEqual( + person2.get('groups').mapBy('id'), + ['3', '4'], + 'after unloading, relationship can be restored' + ); + assert.deepEqual( + group3.get('people').mapBy('id'), + ['1', '2'], + 'after unloading, relationship can be restored' + ); + assert.deepEqual( + group4.get('people').mapBy('id'), + ['1', '2'], + 'after unloading, relationship can be restored' + ); }); -test('1:1 async unload', function (assert) { +test('1:1 async unload', function(assert) { let findRecordCalls = 0; env.adapter.findRecord = (store, type, id) => { @@ -1575,8 +1880,8 @@ test('1:1 async unload', function (assert) { return { data: { id: 2, - type: 'mortgage' - } + type: 'mortgage', + }, }; }; @@ -1589,39 +1894,63 @@ test('1:1 async unload', function (assert) { mortgage: { data: { id: 2, - type: 'mortgage' - } - } - } - } + type: 'mortgage', + }, + }, + }, + }, }) ); let mortgage; return run(() => - person.get('mortgage').then((asyncRecord) => { - mortgage = asyncRecord; - return mortgage.get('person'); - }).then(() => { - assert.equal(mortgage.belongsTo('person').id(), '1', 'initially relationship established lhs'); - assert.equal(person.belongsTo('mortgage').id(), '2', 'initially relationship established rhs'); - - run(() => mortgage.unloadRecord()); - - assert.equal(person.belongsTo('mortgage').id(), '2', 'unload async is not treated as delete'); - - return person.get('mortgage'); - }).then((refetchedMortgage) => { - assert.notEqual(mortgage, refetchedMortgage, 'the previously loaded record is not reused'); - - assert.equal(person.belongsTo('mortgage').id(), '2', 'unload async is not treated as delete'); - assert.equal(refetchedMortgage.belongsTo('person').id(), '1', 'unload async is not treated as delete'); - assert.equal(findRecordCalls, 2); - }) + person + .get('mortgage') + .then(asyncRecord => { + mortgage = asyncRecord; + return mortgage.get('person'); + }) + .then(() => { + assert.equal( + mortgage.belongsTo('person').id(), + '1', + 'initially relationship established lhs' + ); + assert.equal( + person.belongsTo('mortgage').id(), + '2', + 'initially relationship established rhs' + ); + + run(() => mortgage.unloadRecord()); + + assert.equal( + person.belongsTo('mortgage').id(), + '2', + 'unload async is not treated as delete' + ); + + return person.get('mortgage'); + }) + .then(refetchedMortgage => { + assert.notEqual(mortgage, refetchedMortgage, 'the previously loaded record is not reused'); + + assert.equal( + person.belongsTo('mortgage').id(), + '2', + 'unload async is not treated as delete' + ); + assert.equal( + refetchedMortgage.belongsTo('person').id(), + '1', + 'unload async is not treated as delete' + ); + assert.equal(findRecordCalls, 2); + }) ); }); -test('1:many async unload 1 side', function (assert) { +test('1:many async unload 1 side', function(assert) { let findRecordCalls = 0; let findManyCalls = 0; @@ -1635,24 +1964,27 @@ test('1:many async unload 1 side', function (assert) { return { data: { id: 1, - type: 'person' - } + type: 'person', + }, }; }; env.adapter.findMany = (store, type, ids) => { - assert.equal(type+'', Boat+'', 'findMany(_, type) is correct'); + assert.equal(type + '', Boat + '', 'findMany(_, type) is correct'); assert.deepEqual(ids, ['2', '3'], 'findMany(_, _, ids) is correct'); ++findManyCalls; return { - data: [{ - id: 2, - type: 'boat' - }, { - id: 3, - type: 'boat' - }] + data: [ + { + id: 2, + type: 'boat', + }, + { + id: 3, + type: 'boat', + }, + ], }; }; @@ -1663,70 +1995,92 @@ test('1:many async unload 1 side', function (assert) { type: 'person', relationships: { boats: { - data: [{ - id: 2, - type: 'boat' - }, { - id: 3, - type: 'boat' - }] - } - } - } + data: [ + { + id: 2, + type: 'boat', + }, + { + id: 3, + type: 'boat', + }, + ], + }, + }, + }, }) ); let boats, boat2, boat3; return run(() => - person.get('boats').then((asyncRecords) => { - boats = asyncRecords; - [boat2, boat3] = boats.toArray(); - return EmberPromise.all([boat2, boat3].map(b => b.get('person'))); - }).then(() => { - assert.deepEqual(person.hasMany('boats').ids(), ['2', '3'], 'initially relationship established lhs'); - assert.equal(boat2.belongsTo('person').id(), '1', 'initially relationship established rhs'); - assert.equal(boat3.belongsTo('person').id(), '1', 'initially relationship established rhs'); - - assert.equal(boats.isDestroyed, false, 'ManyArray is not destroyed'); - - run(() => person.unloadRecord()); - - assert.equal(boats.isDestroyed, false, 'ManyArray is not destroyed when 1 side is unloaded'); - assert.equal(boat2.belongsTo('person').id(), '1', 'unload async is not treated as delete'); - assert.equal(boat3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); - - return boat2.get('person'); - }).then((refetchedPerson) => { - assert.notEqual(person, refetchedPerson, 'the previously loaded record is not reused'); - - assert.deepEqual(person.hasMany('boats').ids(), ['2', '3'], 'unload async is not treated as delete'); - assert.equal(boat2.belongsTo('person').id(), '1', 'unload async is not treated as delete'); - assert.equal(boat3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); - - assert.equal(findManyCalls, 1, 'findMany called as expected'); - assert.equal(findRecordCalls, 1, 'findRecord called as expected'); - }) + person + .get('boats') + .then(asyncRecords => { + boats = asyncRecords; + [boat2, boat3] = boats.toArray(); + return EmberPromise.all([boat2, boat3].map(b => b.get('person'))); + }) + .then(() => { + assert.deepEqual( + person.hasMany('boats').ids(), + ['2', '3'], + 'initially relationship established lhs' + ); + assert.equal(boat2.belongsTo('person').id(), '1', 'initially relationship established rhs'); + assert.equal(boat3.belongsTo('person').id(), '1', 'initially relationship established rhs'); + + assert.equal(boats.isDestroyed, false, 'ManyArray is not destroyed'); + + run(() => person.unloadRecord()); + + assert.equal( + boats.isDestroyed, + false, + 'ManyArray is not destroyed when 1 side is unloaded' + ); + assert.equal(boat2.belongsTo('person').id(), '1', 'unload async is not treated as delete'); + assert.equal(boat3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); + + return boat2.get('person'); + }) + .then(refetchedPerson => { + assert.notEqual(person, refetchedPerson, 'the previously loaded record is not reused'); + + assert.deepEqual( + person.hasMany('boats').ids(), + ['2', '3'], + 'unload async is not treated as delete' + ); + assert.equal(boat2.belongsTo('person').id(), '1', 'unload async is not treated as delete'); + assert.equal(boat3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); + + assert.equal(findManyCalls, 1, 'findMany called as expected'); + assert.equal(findRecordCalls, 1, 'findRecord called as expected'); + }) ); }); -test('1:many async unload many side', function (assert) { +test('1:many async unload many side', function(assert) { let findManyCalls = 0; env.adapter.coalesceFindRequests = true; env.adapter.findMany = (store, type, ids) => { - assert.equal(type+'', Boat+'', 'findMany(_, type) is correct'); + assert.equal(type + '', Boat + '', 'findMany(_, type) is correct'); assert.deepEqual(ids, ['2', '3'], 'findMany(_, _, ids) is correct'); ++findManyCalls; return { - data: [{ - id: 2, - type: 'boat' - }, { - id: 3, - type: 'boat' - }] + data: [ + { + id: 2, + type: 'boat', + }, + { + id: 3, + type: 'boat', + }, + ], }; }; @@ -1737,155 +2091,247 @@ test('1:many async unload many side', function (assert) { type: 'person', relationships: { boats: { - data: [{ - id: 2, - type: 'boat' - }, { - id: 3, - type: 'boat' - }] - } - } - } + data: [ + { + id: 2, + type: 'boat', + }, + { + id: 3, + type: 'boat', + }, + ], + }, + }, + }, }) ); let boats, boat2, boat3; return run(() => - person.get('boats').then((asyncRecords) => { - boats = asyncRecords; - [boat2, boat3] = boats.toArray(); - return EmberPromise.all([boat2, boat3].map(b => b.get('person'))); - }).then(() => { - assert.deepEqual(person.hasMany('boats').ids(), ['2', '3'], 'initially relationship established lhs'); - assert.equal(boat2.belongsTo('person').id(), '1', 'initially relationship established rhs'); - assert.equal(boat3.belongsTo('person').id(), '1', 'initially relationship established rhs'); - - assert.deepEqual(boats.mapBy('id'), ['2', '3'], 'many array is initially set up correctly'); - run(() => boat2.unloadRecord()); - assert.deepEqual(boats.mapBy('id'), ['3'], 'unload async removes from previous many array'); - assert.equal(boats.isDestroyed, false, 'previous ManyArray not destroyed'); - - run(() => boat3.unloadRecord()); - assert.deepEqual(boats.mapBy('id'), [], 'unload async removes from previous many array'); - assert.equal(boats.isDestroyed, false, 'previous ManyArray not destroyed'); - - assert.deepEqual(person.hasMany('boats').ids(), ['2', '3'], 'unload async is not treated as delete'); - assert.equal(boat3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); - - return person.get('boats'); - }).then((refetchedBoats) => { - assert.equal(boats.isDestroyed, false, 'previous ManyArray is not immediately destroyed after refetch'); - assert.equal(boats.isDestroying, true, 'previous ManyArray is being destroyed immediately after refetch'); - assert.deepEqual(refetchedBoats.mapBy('id'), ['2', '3'], 'boats refetched'); - assert.deepEqual(person.hasMany('boats').ids(), ['2', '3'], 'unload async is not treated as delete'); - assert.equal(boat3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); - - assert.equal(findManyCalls, 2, 'findMany called as expected'); - }) + person + .get('boats') + .then(asyncRecords => { + boats = asyncRecords; + [boat2, boat3] = boats.toArray(); + return EmberPromise.all([boat2, boat3].map(b => b.get('person'))); + }) + .then(() => { + assert.deepEqual( + person.hasMany('boats').ids(), + ['2', '3'], + 'initially relationship established lhs' + ); + assert.equal(boat2.belongsTo('person').id(), '1', 'initially relationship established rhs'); + assert.equal(boat3.belongsTo('person').id(), '1', 'initially relationship established rhs'); + + assert.deepEqual(boats.mapBy('id'), ['2', '3'], 'many array is initially set up correctly'); + run(() => boat2.unloadRecord()); + assert.deepEqual(boats.mapBy('id'), ['3'], 'unload async removes from previous many array'); + assert.equal(boats.isDestroyed, false, 'previous ManyArray not destroyed'); + + run(() => boat3.unloadRecord()); + assert.deepEqual(boats.mapBy('id'), [], 'unload async removes from previous many array'); + assert.equal(boats.isDestroyed, false, 'previous ManyArray not destroyed'); + + assert.deepEqual( + person.hasMany('boats').ids(), + ['2', '3'], + 'unload async is not treated as delete' + ); + assert.equal(boat3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); + + return person.get('boats'); + }) + .then(refetchedBoats => { + assert.equal( + boats.isDestroyed, + false, + 'previous ManyArray is not immediately destroyed after refetch' + ); + assert.equal( + boats.isDestroying, + true, + 'previous ManyArray is being destroyed immediately after refetch' + ); + assert.deepEqual(refetchedBoats.mapBy('id'), ['2', '3'], 'boats refetched'); + assert.deepEqual( + person.hasMany('boats').ids(), + ['2', '3'], + 'unload async is not treated as delete' + ); + assert.equal(boat3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); + + assert.equal(findManyCalls, 2, 'findMany called as expected'); + }) ).then(() => { - assert.equal(boats.isDestroyed, true, 'previous ManyArray is destroyed in the runloop after refetching'); + assert.equal( + boats.isDestroyed, + true, + 'previous ManyArray is destroyed in the runloop after refetching' + ); }); }); -test('many:many async unload', function (assert) { +test('many:many async unload', function(assert) { let findManyCalls = 0; env.adapter.coalesceFindRequests = true; env.adapter.findMany = (store, type, ids) => { - assert.equal(type+'', Person+'', 'findMany(_, type) is correct'); + assert.equal(type + '', Person + '', 'findMany(_, type) is correct'); assert.deepEqual(ids, ['3', '4'], 'findMany(_, _, ids) is correct'); ++findManyCalls; return { - data: [{ - id: 3, - type: 'person' - }, { - id: 4, - type: 'person' - }] + data: [ + { + id: 3, + type: 'person', + }, + { + id: 4, + type: 'person', + }, + ], }; }; let [person1, person2] = run(() => env.store.push({ - data: [{ - id: 1, - type: 'person', - relationships: { - friends: { - data: [{ - id: 3, - type: 'person' - }, { - id: 4, - type: 'person' - }] - } - } - }, { - id: 2, - type: 'person', - relationships: { - friends: { - data: [{ - id: 3, - type: 'person' - }, { - id: 4, - type: 'person' - }] - } - } - }] + data: [ + { + id: 1, + type: 'person', + relationships: { + friends: { + data: [ + { + id: 3, + type: 'person', + }, + { + id: 4, + type: 'person', + }, + ], + }, + }, + }, + { + id: 2, + type: 'person', + relationships: { + friends: { + data: [ + { + id: 3, + type: 'person', + }, + { + id: 4, + type: 'person', + }, + ], + }, + }, + }, + ], }) ); let person1Friends, person3, person4; return run(() => - person1.get('friends').then((asyncRecords) => { - person1Friends = asyncRecords; - [person3, person4] = person1Friends.toArray(); - return EmberPromise.all([person2, person3, person4].map(b => b.get('friends'))); - }).then(() => { - assert.deepEqual(person1.hasMany('friends').ids(), ['3', '4'], 'initially relationship established lhs'); - assert.deepEqual(person2.hasMany('friends').ids(), ['3', '4'], 'initially relationship established lhs'); - assert.deepEqual(person3.hasMany('friends').ids(), ['1', '2'], 'initially relationship established rhs'); - assert.deepEqual(person4.hasMany('friends').ids(), ['1', '2'], 'initially relationship established rhs'); - - run(() => person3.unloadRecord()); - assert.deepEqual(person1Friends.mapBy('id'), ['4'], 'unload async removes from previous many array'); - assert.equal(person1Friends.isDestroyed, false, 'previous ManyArray not destroyed'); - - run(() => person4.unloadRecord()); - assert.deepEqual(person1Friends.mapBy('id'), [], 'unload async removes from previous many array'); - assert.equal(person1Friends.isDestroyed, false, 'previous ManyArray not destroyed'); - - assert.deepEqual(person1.hasMany('friends').ids(), ['3', '4'], 'unload async is not treated as delete'); - - return person1.get('friends'); - }).then((refetchedFriends) => { - assert.equal(person1Friends.isDestroyed, false, 'previous ManyArray is not immediately destroyed after refetch'); - assert.equal(person1Friends.isDestroying, true, 'previous ManyArray is being destroyed immediately after refetch'); - assert.deepEqual(refetchedFriends.mapBy('id'), ['3', '4'], 'friends refetched'); - assert.deepEqual(person1.hasMany('friends').ids(), ['3', '4'], 'unload async is not treated as delete'); - - assert.deepEqual(refetchedFriends.map(p => p.hasMany('friends').ids()), [ - ['1', '2'], - ['1', '2'] - ], 'unload async is not treated as delete'); - - assert.equal(findManyCalls, 2, 'findMany called as expected'); - }) + person1 + .get('friends') + .then(asyncRecords => { + person1Friends = asyncRecords; + [person3, person4] = person1Friends.toArray(); + return EmberPromise.all([person2, person3, person4].map(b => b.get('friends'))); + }) + .then(() => { + assert.deepEqual( + person1.hasMany('friends').ids(), + ['3', '4'], + 'initially relationship established lhs' + ); + assert.deepEqual( + person2.hasMany('friends').ids(), + ['3', '4'], + 'initially relationship established lhs' + ); + assert.deepEqual( + person3.hasMany('friends').ids(), + ['1', '2'], + 'initially relationship established rhs' + ); + assert.deepEqual( + person4.hasMany('friends').ids(), + ['1', '2'], + 'initially relationship established rhs' + ); + + run(() => person3.unloadRecord()); + assert.deepEqual( + person1Friends.mapBy('id'), + ['4'], + 'unload async removes from previous many array' + ); + assert.equal(person1Friends.isDestroyed, false, 'previous ManyArray not destroyed'); + + run(() => person4.unloadRecord()); + assert.deepEqual( + person1Friends.mapBy('id'), + [], + 'unload async removes from previous many array' + ); + assert.equal(person1Friends.isDestroyed, false, 'previous ManyArray not destroyed'); + + assert.deepEqual( + person1.hasMany('friends').ids(), + ['3', '4'], + 'unload async is not treated as delete' + ); + + return person1.get('friends'); + }) + .then(refetchedFriends => { + assert.equal( + person1Friends.isDestroyed, + false, + 'previous ManyArray is not immediately destroyed after refetch' + ); + assert.equal( + person1Friends.isDestroying, + true, + 'previous ManyArray is being destroyed immediately after refetch' + ); + assert.deepEqual(refetchedFriends.mapBy('id'), ['3', '4'], 'friends refetched'); + assert.deepEqual( + person1.hasMany('friends').ids(), + ['3', '4'], + 'unload async is not treated as delete' + ); + + assert.deepEqual( + refetchedFriends.map(p => p.hasMany('friends').ids()), + [['1', '2'], ['1', '2']], + 'unload async is not treated as delete' + ); + + assert.equal(findManyCalls, 2, 'findMany called as expected'); + }) ).then(() => { - assert.equal(person1Friends.isDestroyed, true, 'previous ManyArray is destroyed in the runloop after refetching'); + assert.equal( + person1Friends.isDestroyed, + true, + 'previous ManyArray is destroyed in the runloop after refetching' + ); }); }); -test('1 sync : 1 async unload sync side', function (assert) { +test('1 sync : 1 async unload sync side', function(assert) { run(() => env.store.push({ data: { @@ -1895,15 +2341,17 @@ test('1 sync : 1 async unload sync side', function (assert) { favoriteBook: { data: { id: 2, - type: 'book' - } - } - } + type: 'book', + }, + }, + }, }, - included: [{ - id: 2, - type: 'book' - }] + included: [ + { + id: 2, + type: 'book', + }, + ], }) ); @@ -1923,14 +2371,22 @@ test('1 sync : 1 async unload sync side', function (assert) { env.store.push({ data: { id: 2, - type: 'book' - } + type: 'book', + }, }) ); assert.equal(env.store.hasRecordForId('book', 2), true, 'unloaded record can be restored'); - assert.equal(person.get('book'), null, 'restoring unloaded record does not restore relationship'); - assert.equal(book.belongsTo('person').id(), null, 'restoring unloaded record does not restore relationship'); + assert.equal( + person.get('book'), + null, + 'restoring unloaded record does not restore relationship' + ); + assert.equal( + book.belongsTo('person').id(), + null, + 'restoring unloaded record does not restore relationship' + ); run(() => env.store.push({ @@ -1941,11 +2397,11 @@ test('1 sync : 1 async unload sync side', function (assert) { person: { data: { id: 1, - type: 'person' - } - } - } - } + type: 'person', + }, + }, + }, + }, }) ); @@ -1954,7 +2410,7 @@ test('1 sync : 1 async unload sync side', function (assert) { }); }); -test('1 sync : 1 async unload async side', function (assert) { +test('1 sync : 1 async unload async side', function(assert) { let findRecordCalls = 0; env.adapter.findRecord = (store, type, id) => { @@ -1965,8 +2421,8 @@ test('1 sync : 1 async unload async side', function (assert) { return { data: { id: 1, - type: 'person' - } + type: 'person', + }, }; }; @@ -1979,15 +2435,17 @@ test('1 sync : 1 async unload async side', function (assert) { favoriteBook: { data: { id: 2, - type: 'book' - } - } - } + type: 'book', + }, + }, + }, }, - included: [{ - id: 2, - type: 'book' - }] + included: [ + { + id: 2, + type: 'book', + }, + ], }) ); @@ -1995,26 +2453,33 @@ test('1 sync : 1 async unload async side', function (assert) { let book = env.store.peekRecord('book', 2); return run(() => - book.get('person').then(() => { - assert.equal(person.get('favoriteBook.id'), 2, 'initially relationship established lhs'); - assert.equal(book.belongsTo('person').id(), 1, 'initially relationship established rhs'); + book + .get('person') + .then(() => { + assert.equal(person.get('favoriteBook.id'), 2, 'initially relationship established lhs'); + assert.equal(book.belongsTo('person').id(), 1, 'initially relationship established rhs'); - run(() => person.unloadRecord()); + run(() => person.unloadRecord()); - assert.equal(book.belongsTo('person').id(), '1', 'unload async is not treated as delete'); + assert.equal(book.belongsTo('person').id(), '1', 'unload async is not treated as delete'); - return book.get('person'); - }).then((refetchedPerson) => { - assert.notEqual(person, refetchedPerson, 'the previously loaded record is not reused'); - - assert.equal(book.belongsTo('person').id(), '1', 'unload async is not treated as delete'); - assert.equal(refetchedPerson.get('favoriteBook.id'), '2', 'unload async is not treated as delete'); - assert.equal(findRecordCalls, 1); - }) + return book.get('person'); + }) + .then(refetchedPerson => { + assert.notEqual(person, refetchedPerson, 'the previously loaded record is not reused'); + + assert.equal(book.belongsTo('person').id(), '1', 'unload async is not treated as delete'); + assert.equal( + refetchedPerson.get('favoriteBook.id'), + '2', + 'unload async is not treated as delete' + ); + assert.equal(findRecordCalls, 1); + }) ); }); -test('1 async : many sync unload sync side', function (assert) { +test('1 async : many sync unload sync side', function(assert) { run(() => env.store.push({ data: { @@ -2022,23 +2487,29 @@ test('1 async : many sync unload sync side', function (assert) { type: 'person', relationships: { favoriteSpoons: { - data: [{ - id: 2, - type: 'spoon' - }, { - id: 3, - type: 'spoon' - }] - } - } + data: [ + { + id: 2, + type: 'spoon', + }, + { + id: 3, + type: 'spoon', + }, + ], + }, + }, }, - included: [{ - id: 2, - type: 'spoon' - }, { - id: 3, - type: 'spoon' - }] + included: [ + { + id: 2, + type: 'spoon', + }, + { + id: 3, + type: 'spoon', + }, + ], }) ); @@ -2048,7 +2519,11 @@ test('1 async : many sync unload sync side', function (assert) { let spoons = person.get('favoriteSpoons'); assert.equal(spoons.isDestroyed, false, 'ManyArray not destroyed'); - assert.deepEqual(person.get('favoriteSpoons').mapBy('id'), ['2', '3'], 'initialy relationship established lhs'); + assert.deepEqual( + person.get('favoriteSpoons').mapBy('id'), + ['2', '3'], + 'initialy relationship established lhs' + ); assert.equal(spoon2.belongsTo('person').id(), '1', 'initially relationship established rhs'); assert.equal(spoon3.belongsTo('person').id(), '1', 'initially relationship established rhs'); @@ -2057,21 +2532,37 @@ test('1 async : many sync unload sync side', function (assert) { assert.equal(env.store.hasRecordForId('spoon', 2), false, 'unloaded record gone from store'); assert.equal(spoons.isDestroyed, false, 'ManyArray not destroyed'); - assert.deepEqual(person.get('favoriteSpoons').mapBy('id'), ['3'], 'unload sync relationship acts as delete'); - assert.equal(spoon3.belongsTo('person').id(), '1', 'unloading one of a sync hasMany does not affect the rest'); + assert.deepEqual( + person.get('favoriteSpoons').mapBy('id'), + ['3'], + 'unload sync relationship acts as delete' + ); + assert.equal( + spoon3.belongsTo('person').id(), + '1', + 'unloading one of a sync hasMany does not affect the rest' + ); spoon2 = run(() => env.store.push({ data: { id: 2, - type: 'spoon' - } + type: 'spoon', + }, }) ); assert.equal(env.store.hasRecordForId('spoon', 2), true, 'unloaded record can be restored'); - assert.deepEqual(person.get('favoriteSpoons').mapBy('id'), ['3'], 'restoring unloaded record does not restore relationship'); - assert.equal(spoon2.belongsTo('person').id(), null, 'restoring unloaded record does not restore relationship'); + assert.deepEqual( + person.get('favoriteSpoons').mapBy('id'), + ['3'], + 'restoring unloaded record does not restore relationship' + ); + assert.equal( + spoon2.belongsTo('person').id(), + null, + 'restoring unloaded record does not restore relationship' + ); run(() => env.store.push({ @@ -2080,24 +2571,35 @@ test('1 async : many sync unload sync side', function (assert) { type: 'person', relationships: { favoriteSpoons: { - data: [{ - id: 2, - type: 'spoon' - }, { - id: 3, - type: 'spoon' - }] - } - } - } + data: [ + { + id: 2, + type: 'spoon', + }, + { + id: 3, + type: 'spoon', + }, + ], + }, + }, + }, }) ); - assert.equal(spoon2.belongsTo('person').id(), '1', 'after unloading, relationship can be restored'); - assert.deepEqual(person.get('favoriteSpoons').mapBy('id'), ['2', '3'], 'after unloading, relationship can be restored'); + assert.equal( + spoon2.belongsTo('person').id(), + '1', + 'after unloading, relationship can be restored' + ); + assert.deepEqual( + person.get('favoriteSpoons').mapBy('id'), + ['2', '3'], + 'after unloading, relationship can be restored' + ); }); -test('1 async : many sync unload async side', function (assert) { +test('1 async : many sync unload async side', function(assert) { let findRecordCalls = 0; env.adapter.coalesceFindRequests = true; @@ -2110,8 +2612,8 @@ test('1 async : many sync unload async side', function (assert) { return { data: { id: 1, - type: 'person' - } + type: 'person', + }, }; }; @@ -2125,26 +2627,26 @@ test('1 async : many sync unload async side', function (assert) { data: [ { id: 2, - type: 'spoon' + type: 'spoon', }, { id: 3, - type: 'spoon' - } - ] - } - } + type: 'spoon', + }, + ], + }, + }, }, included: [ { id: 2, - type: 'spoon' + type: 'spoon', }, { id: 3, - type: 'spoon' - } - ] + type: 'spoon', + }, + ], }) ); let spoon2 = env.store.peekRecord('spoon', 2); @@ -2152,7 +2654,11 @@ test('1 async : many sync unload async side', function (assert) { let spoons = person.get('favoriteSpoons'); return run(() => { - assert.deepEqual(person.get('favoriteSpoons').mapBy('id'), ['2', '3'], 'initially relationship established lhs'); + assert.deepEqual( + person.get('favoriteSpoons').mapBy('id'), + ['2', '3'], + 'initially relationship established lhs' + ); assert.equal(spoon2.belongsTo('person').id(), '1', 'initially relationship established rhs'); assert.equal(spoon3.belongsTo('person').id(), '1', 'initially relationship established rhs'); @@ -2165,10 +2671,14 @@ test('1 async : many sync unload async side', function (assert) { assert.equal(spoon3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); return spoon2.get('person'); - }).then((refetchedPerson) => { + }).then(refetchedPerson => { assert.notEqual(person, refetchedPerson, 'the previously loaded record is not reused'); - assert.deepEqual(person.get('favoriteSpoons').mapBy('id'), ['2', '3'], 'unload async is not treated as delete'); + assert.deepEqual( + person.get('favoriteSpoons').mapBy('id'), + ['2', '3'], + 'unload async is not treated as delete' + ); assert.equal(spoon2.belongsTo('person').id(), '1', 'unload async is not treated as delete'); assert.equal(spoon3.belongsTo('person').id(), '1', 'unload async is not treated as delete'); @@ -2182,18 +2692,21 @@ test('1 sync : many async unload async side', function(assert) { env.adapter.coalesceFindRequests = true; env.adapter.findMany = (store, type, ids) => { - assert.equal(type+'', Show+'', 'findMany(_, type) is correct'); + assert.equal(type + '', Show + '', 'findMany(_, type) is correct'); assert.deepEqual(ids, ['2', '3'], 'findMany(_, _, ids) is correct'); ++findManyCalls; return { - data: [{ - id: 2, - type: 'show' - }, { - id: 3, - type: 'show' - }] + data: [ + { + id: 2, + type: 'show', + }, + { + id: 3, + type: 'show', + }, + ], }; }; @@ -2207,53 +2720,80 @@ test('1 sync : many async unload async side', function(assert) { data: [ { id: 2, - type: 'show' + type: 'show', }, { id: 3, - type: 'show' - } - ] - } - } - } + type: 'show', + }, + ], + }, + }, + }, }) ); let shows, show2, show3; - return run(() => person.get('favoriteShows') - .then((asyncRecords) => { - shows = asyncRecords; - [show2, show3] = shows.toArray(); - - assert.deepEqual(person.hasMany('favoriteShows').ids(), ['2', '3'], 'initially relationship established lhs'); - assert.equal(show2.get('person.id'), '1', 'initially relationship established rhs'); - assert.equal(show3.get('person.id'), '1', 'initially relationship established rhs'); - assert.deepEqual(shows.mapBy('id'), ['2', '3'], 'many array is initially set up correctly'); - - run(() => show2.unloadRecord()); - - assert.deepEqual(shows.mapBy('id'), ['3'], 'unload async removes from previous many array'); - assert.equal(shows.isDestroyed, false, 'previous many array not destroyed'); - - run(() => show3.unloadRecord()); - - assert.deepEqual(shows.mapBy('id'), [], 'unload async removes from previous many array'); - assert.equal(shows.isDestroyed, false, 'previous many array not destroyed'); - assert.deepEqual(person.hasMany('favoriteShows').ids(), ['2', '3'], 'unload async is not treated as delete'); - - return person.get('favoriteShows'); - }).then((refetchedShows) => { - assert.equal(shows.isDestroyed, false, 'previous ManyArray is not immediately destroyed after refetch'); - assert.equal(shows.isDestroying, true, 'previous ManyArray is being destroyed immediately after refetch'); - assert.deepEqual(refetchedShows.mapBy('id'), ['2', '3'], 'shows refetched'); - assert.deepEqual(person.hasMany('favoriteShows').ids(), ['2', '3'], 'unload async is not treated as delete'); - - assert.equal(findManyCalls, 2, 'findMany called as expected'); - }) + return run(() => + person + .get('favoriteShows') + .then(asyncRecords => { + shows = asyncRecords; + [show2, show3] = shows.toArray(); + + assert.deepEqual( + person.hasMany('favoriteShows').ids(), + ['2', '3'], + 'initially relationship established lhs' + ); + assert.equal(show2.get('person.id'), '1', 'initially relationship established rhs'); + assert.equal(show3.get('person.id'), '1', 'initially relationship established rhs'); + assert.deepEqual(shows.mapBy('id'), ['2', '3'], 'many array is initially set up correctly'); + + run(() => show2.unloadRecord()); + + assert.deepEqual(shows.mapBy('id'), ['3'], 'unload async removes from previous many array'); + assert.equal(shows.isDestroyed, false, 'previous many array not destroyed'); + + run(() => show3.unloadRecord()); + + assert.deepEqual(shows.mapBy('id'), [], 'unload async removes from previous many array'); + assert.equal(shows.isDestroyed, false, 'previous many array not destroyed'); + assert.deepEqual( + person.hasMany('favoriteShows').ids(), + ['2', '3'], + 'unload async is not treated as delete' + ); + + return person.get('favoriteShows'); + }) + .then(refetchedShows => { + assert.equal( + shows.isDestroyed, + false, + 'previous ManyArray is not immediately destroyed after refetch' + ); + assert.equal( + shows.isDestroying, + true, + 'previous ManyArray is being destroyed immediately after refetch' + ); + assert.deepEqual(refetchedShows.mapBy('id'), ['2', '3'], 'shows refetched'); + assert.deepEqual( + person.hasMany('favoriteShows').ids(), + ['2', '3'], + 'unload async is not treated as delete' + ); + + assert.equal(findManyCalls, 2, 'findMany called as expected'); + }) ).then(() => { - assert.equal(shows.isDestroyed, true, 'previous ManyArray is destroyed in the runloop after refetching'); + assert.equal( + shows.isDestroyed, + true, + 'previous ManyArray is destroyed in the runloop after refetching' + ); }); }); @@ -2263,18 +2803,21 @@ test('1 sync : many async unload sync side', function(assert) { env.adapter.coalesceFindRequests = true; env.adapter.findMany = (store, type, ids) => { - assert.equal(type+'', Show+'', 'findMany(_, type) is correct'); + assert.equal(type + '', Show + '', 'findMany(_, type) is correct'); assert.deepEqual(ids, ['2', '3'], 'findMany(_, _, ids) is correct'); ++findManyCalls; return { - data: [{ - id: 2, - type: 'show' - }, { - id: 3, - type: 'show' - }] + data: [ + { + id: 2, + type: 'show', + }, + { + id: 3, + type: 'show', + }, + ], }; }; @@ -2288,85 +2831,128 @@ test('1 sync : many async unload sync side', function(assert) { data: [ { id: 2, - type: 'show' + type: 'show', }, { id: 3, - type: 'show' - } - ] - } - } - } + type: 'show', + }, + ], + }, + }, + }, }) ); let shows, show2, show3; - return run(() => person.get('favoriteShows') - .then((asyncRecords) => { - shows = asyncRecords; - [show2, show3] = shows.toArray(); - - assert.deepEqual(person.hasMany('favoriteShows').ids(), ['2', '3'], 'initially relationship established lhs'); - assert.equal(show2.get('person.id'), '1', 'initially relationship established rhs'); - assert.equal(show3.get('person.id'), '1', 'initially relationship established rhs'); - assert.deepEqual(shows.mapBy('id'), ['2', '3'], 'many array is initially set up correctly'); - - run(() => person.unloadRecord()); - - assert.equal(env.store.hasRecordForId('person', 1), false, 'unloaded record gone from store'); - - assert.equal(shows.isDestroyed, true, 'previous manyarray immediately destroyed'); - assert.equal(show2.get('person.id'), null, 'unloading acts as delete for sync relationships'); - assert.equal(show3.get('person.id'), null, 'unloading acts as delete for sync relationships'); - - person = run(() => - env.store.push({ - data: { - id: 1, - type: 'person' - } - }) - ); - - assert.equal(env.store.hasRecordForId('person', 1), true, 'unloaded record can be restored'); - assert.deepEqual(person.hasMany('favoriteShows').ids(), [], 'restoring unloaded record does not restore relationship'); - assert.equal(show2.get('person.id'), null, 'restoring unloaded record does not restore relationship'); - assert.equal(show3.get('person.id'), null, 'restoring unloaded record does not restore relationship'); - - run(() => - env.store.push({ - data: { - id: 1, - type: 'person', - relationships: { - favoriteShows: { - data: [ - { - id: 2, - type: 'show' - }, - { - id: 3, - type: 'show' - } - ] - } - } - } - }) - ); - - assert.deepEqual(person.hasMany('favoriteShows').ids(), ['2', '3'], 'relationship can be restored'); + return run(() => + person + .get('favoriteShows') + .then(asyncRecords => { + shows = asyncRecords; + [show2, show3] = shows.toArray(); + + assert.deepEqual( + person.hasMany('favoriteShows').ids(), + ['2', '3'], + 'initially relationship established lhs' + ); + assert.equal(show2.get('person.id'), '1', 'initially relationship established rhs'); + assert.equal(show3.get('person.id'), '1', 'initially relationship established rhs'); + assert.deepEqual(shows.mapBy('id'), ['2', '3'], 'many array is initially set up correctly'); + + run(() => person.unloadRecord()); + + assert.equal( + env.store.hasRecordForId('person', 1), + false, + 'unloaded record gone from store' + ); + + assert.equal(shows.isDestroyed, true, 'previous manyarray immediately destroyed'); + assert.equal( + show2.get('person.id'), + null, + 'unloading acts as delete for sync relationships' + ); + assert.equal( + show3.get('person.id'), + null, + 'unloading acts as delete for sync relationships' + ); + + person = run(() => + env.store.push({ + data: { + id: 1, + type: 'person', + }, + }) + ); + + assert.equal( + env.store.hasRecordForId('person', 1), + true, + 'unloaded record can be restored' + ); + assert.deepEqual( + person.hasMany('favoriteShows').ids(), + [], + 'restoring unloaded record does not restore relationship' + ); + assert.equal( + show2.get('person.id'), + null, + 'restoring unloaded record does not restore relationship' + ); + assert.equal( + show3.get('person.id'), + null, + 'restoring unloaded record does not restore relationship' + ); + + run(() => + env.store.push({ + data: { + id: 1, + type: 'person', + relationships: { + favoriteShows: { + data: [ + { + id: 2, + type: 'show', + }, + { + id: 3, + type: 'show', + }, + ], + }, + }, + }, + }) + ); - return person.get('favoriteShows'); - }).then((refetchedShows) => { - assert.notEqual(refetchedShows, shows, 'ManyArray not reused'); - assert.deepEqual(refetchedShows.mapBy('id'), ['2', '3'], 'unload async not treated as a delete'); + assert.deepEqual( + person.hasMany('favoriteShows').ids(), + ['2', '3'], + 'relationship can be restored' + ); - assert.equal(findManyCalls, 1, 'findMany calls as expected'); - }) + return person.get('favoriteShows'); + }) + .then(refetchedShows => { + assert.notEqual(refetchedShows, shows, 'ManyArray not reused'); + assert.deepEqual( + refetchedShows.mapBy('id'), + ['2', '3'], + 'unload async not treated as a delete' + ); + + assert.equal(findManyCalls, 1, 'findMany calls as expected'); + }) ); }); @@ -2386,29 +2972,29 @@ test('unload invalidates link promises', function(assert) { person: { data: { type: 'person', - id: 1 - } - } + id: 1, + }, + }, }; let data = [ { id: 3, type: 'boat', - relationships - } + relationships, + }, ]; if (!isUnloaded) { data.unshift({ id: 2, type: 'boat', - relationships + relationships, }); } return { - data + data, }; }; @@ -2419,35 +3005,44 @@ test('unload invalidates link promises', function(assert) { type: 'person', relationships: { boats: { - links: { related: 'boats' } - } - } - } + links: { related: 'boats' }, + }, + }, + }, }) ); let boats, boat2, boat3; return run(() => - person.get('boats').then((asyncRecords) => { - boats = asyncRecords; - [boat2, boat3] = boats.toArray(); - }).then(() => { - assert.deepEqual(person.hasMany('boats').ids(), ['2', '3'], 'initially relationship established rhs'); - assert.equal(boat2.belongsTo('person').id(), '1', 'initially relationship established rhs'); - assert.equal(boat3.belongsTo('person').id(), '1', 'initially relationship established rhs'); - - isUnloaded = true; - run(() => { - boat2.unloadRecord(); - person.get('boats'); - }); - - assert.deepEqual(boats.mapBy('id'), ['3'], 'unloaded boat is removed from ManyArray'); - }).then(() => { - return run(() => person.get('boats')); - }).then(newBoats => { - assert.equal(newBoats.length, 1, 'new ManyArray has only 1 boat after unload'); - }) + person + .get('boats') + .then(asyncRecords => { + boats = asyncRecords; + [boat2, boat3] = boats.toArray(); + }) + .then(() => { + assert.deepEqual( + person.hasMany('boats').ids(), + ['2', '3'], + 'initially relationship established rhs' + ); + assert.equal(boat2.belongsTo('person').id(), '1', 'initially relationship established rhs'); + assert.equal(boat3.belongsTo('person').id(), '1', 'initially relationship established rhs'); + + isUnloaded = true; + run(() => { + boat2.unloadRecord(); + person.get('boats'); + }); + + assert.deepEqual(boats.mapBy('id'), ['3'], 'unloaded boat is removed from ManyArray'); + }) + .then(() => { + return run(() => person.get('boats')); + }) + .then(newBoats => { + assert.equal(newBoats.length, 1, 'new ManyArray has only 1 boat after unload'); + }) ); }); @@ -2456,25 +3051,26 @@ test('fetching records cancels unloading', function(assert) { assert.equal(type, Person, 'findRecord(_, type) is correct'); assert.deepEqual(id, '1', 'findRecord(_, _, id) is correct'); - return { + return { data: { id: 1, - type: 'person' - } - } + type: 'person', + }, + }; }; run(() => env.store.push({ data: { id: 1, - type: 'person' - } + type: 'person', + }, }) ); return run(() => - env.store.findRecord('person', 1, { backgroundReload: true }) + env.store + .findRecord('person', 1, { backgroundReload: true }) .then(person => person.unloadRecord()) ); }); diff --git a/tests/integration/references/belongs-to-test.js b/tests/integration/references/belongs-to-test.js index 47b7ebffa37..cda9590dff6 100644 --- a/tests/integration/references/belongs-to-test.js +++ b/tests/integration/references/belongs-to-test.js @@ -8,25 +8,25 @@ import { module, test } from 'qunit'; var env, Family; -module("integration/references/belongs-to", { +module('integration/references/belongs-to', { beforeEach() { Family = DS.Model.extend({ persons: DS.hasMany(), - name: DS.attr() + name: DS.attr(), }); var Person = DS.Model.extend({ - family: DS.belongsTo({ async: true }) + family: DS.belongsTo({ async: true }), }); env = setupStore({ person: Person, - family: Family + family: Family, }); }, afterEach() { run(env.container, 'destroy'); - } + }, }); testInDebug("record#belongsTo asserts when specified relationship doesn't exist", function(assert) { @@ -35,37 +35,40 @@ testInDebug("record#belongsTo asserts when specified relationship doesn't exist" person = env.store.push({ data: { type: 'person', - id: 1 - } + id: 1, + }, }); }); assert.expectAssertion(function() { run(function() { - person.belongsTo("unknown-relationship"); + person.belongsTo('unknown-relationship'); }); }, "There is no belongsTo relationship named 'unknown-relationship' on a model of modelClass 'person'"); }); -testInDebug("record#belongsTo asserts when the type of the specified relationship isn't the requested one", function(assert) { - var family; - run(function() { - family = env.store.push({ - data: { - type: 'family', - id: 1 - } - }); - }); - - assert.expectAssertion(function() { +testInDebug( + "record#belongsTo asserts when the type of the specified relationship isn't the requested one", + function(assert) { + var family; run(function() { - family.belongsTo("persons"); - }); - }, "You tried to get the 'persons' relationship on a 'family' via record.belongsTo('persons'), but the relationship is of kind 'hasMany'. Use record.hasMany('persons') instead."); -}); + family = env.store.push({ + data: { + type: 'family', + id: 1, + }, + }); + }); + + assert.expectAssertion(function() { + run(function() { + family.belongsTo('persons'); + }); + }, "You tried to get the 'persons' relationship on a 'family' via record.belongsTo('persons'), but the relationship is of kind 'hasMany'. Use record.hasMany('persons') instead."); + } +); -test("record#belongsTo", function(assert) { +test('record#belongsTo', function(assert) { var person; run(function() { person = env.store.push({ @@ -74,10 +77,10 @@ test("record#belongsTo", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); }); @@ -88,7 +91,7 @@ test("record#belongsTo", function(assert) { assert.equal(familyReference.id(), 1); }); -test("record#belongsTo for a linked reference", function(assert) { +test('record#belongsTo for a linked reference', function(assert) { var person; run(function() { person = env.store.push({ @@ -97,10 +100,10 @@ test("record#belongsTo for a linked reference", function(assert) { id: 1, relationships: { family: { - links: { related: '/families/1' } - } - } - } + links: { related: '/families/1' }, + }, + }, + }, }); }); @@ -108,10 +111,10 @@ test("record#belongsTo for a linked reference", function(assert) { assert.equal(familyReference.remoteType(), 'link'); assert.equal(familyReference.type, 'family'); - assert.equal(familyReference.link(), "/families/1"); + assert.equal(familyReference.link(), '/families/1'); }); -test("BelongsToReference#parent is a reference to the parent where the relationship is defined", function(assert) { +test('BelongsToReference#parent is a reference to the parent where the relationship is defined', function(assert) { var person; run(function() { person = env.store.push({ @@ -120,10 +123,10 @@ test("BelongsToReference#parent is a reference to the parent where the relations id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); }); @@ -134,7 +137,7 @@ test("BelongsToReference#parent is a reference to the parent where the relations assert.equal(familyReference.parent, personReference); }); -test("BelongsToReference#meta() returns the most recent meta for the relationship", function(assert) { +test('BelongsToReference#meta() returns the most recent meta for the relationship', function(assert) { var person; run(function() { person = env.store.push({ @@ -144,14 +147,14 @@ test("BelongsToReference#meta() returns the most recent meta for the relationshi relationships: { family: { links: { - related: '/families/1' + related: '/families/1', }, meta: { - foo: true - } - } - } - } + foo: true, + }, + }, + }, + }, }); }); @@ -159,7 +162,7 @@ test("BelongsToReference#meta() returns the most recent meta for the relationshi assert.deepEqual(familyReference.meta(), { foo: true }); }); -test("push(object)", function(assert) { +test('push(object)', function(assert) { var done = assert.async(); var person; @@ -170,10 +173,10 @@ test("push(object)", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); }); @@ -185,21 +188,21 @@ test("push(object)", function(assert) { type: 'family', id: 1, attributes: { - name: "Coreleone" - } - } + name: 'Coreleone', + }, + }, }; familyReference.push(data).then(function(record) { - assert.ok(Family.detectInstance(record), "push resolves with the referenced record"); - assert.equal(get(record, 'name'), "Coreleone", "name is set"); + assert.ok(Family.detectInstance(record), 'push resolves with the referenced record'); + assert.equal(get(record, 'name'), 'Coreleone', 'name is set'); done(); }); }); }); -testInDebug("push(record)", function(assert) { +testInDebug('push(record)', function(assert) { var done = assert.async(); var person, family; @@ -210,19 +213,19 @@ testInDebug("push(record)", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); family = env.store.push({ data: { type: 'family', id: 1, attributes: { - name: "Coreleone" - } - } + name: 'Coreleone', + }, + }, }); }); @@ -230,8 +233,8 @@ testInDebug("push(record)", function(assert) { run(function() { familyReference.push(family).then(function(record) { - assert.ok(Family.detectInstance(record), "push resolves with the referenced record"); - assert.equal(get(record, 'name'), "Coreleone", "name is set"); + assert.ok(Family.detectInstance(record), 'push resolves with the referenced record'); + assert.equal(get(record, 'name'), 'Coreleone', 'name is set'); assert.equal(record, family); done(); @@ -239,7 +242,7 @@ testInDebug("push(record)", function(assert) { }); }); -test("push(promise)", function(assert) { +test('push(promise)', function(assert) { var done = assert.async(); var push; @@ -252,10 +255,10 @@ test("push(promise)", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); var familyReference = person.belongsTo('family'); push = familyReference.push(deferred.promise); @@ -269,23 +272,23 @@ test("push(promise)", function(assert) { type: 'family', id: 1, attributes: { - name: "Coreleone" - } - } + name: 'Coreleone', + }, + }, }); }); run(function() { push.then(function(record) { - assert.ok(Family.detectInstance(record), "push resolves with the record"); - assert.equal(get(record, 'name'), "Coreleone", "name is updated"); + assert.ok(Family.detectInstance(record), 'push resolves with the record'); + assert.equal(get(record, 'name'), 'Coreleone', 'name is updated'); done(); }); }); }); -testInDebug("push(record) asserts for invalid modelClass", function(assert) { +testInDebug('push(record) asserts for invalid modelClass', function(assert) { var person, anotherPerson; run(function() { person = env.store.push({ @@ -294,16 +297,16 @@ testInDebug("push(record) asserts for invalid modelClass", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); anotherPerson = env.store.push({ data: { type: 'person', - id: 2 - } + id: 2, + }, }); }); @@ -316,7 +319,7 @@ testInDebug("push(record) asserts for invalid modelClass", function(assert) { }, "You cannot add a record of modelClass 'person' to the 'person.family' relationship (only 'family' allowed)"); }); -testInDebug("push(record) works with polymorphic modelClass", function(assert) { +testInDebug('push(record) works with polymorphic modelClass', function(assert) { var done = assert.async(); var person, mafiaFamily; @@ -327,14 +330,14 @@ testInDebug("push(record) works with polymorphic modelClass", function(assert) { person = env.store.push({ data: { type: 'person', - id: 1 - } + id: 1, + }, }); mafiaFamily = env.store.push({ data: { type: 'mafia-family', - id: 1 - } + id: 1, + }, }); }); @@ -348,7 +351,7 @@ testInDebug("push(record) works with polymorphic modelClass", function(assert) { }); }); -test("value() is null when reference is not yet loaded", function(assert) { +test('value() is null when reference is not yet loaded', function(assert) { var person; run(function() { person = env.store.push({ @@ -357,10 +360,10 @@ test("value() is null when reference is not yet loaded", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); }); @@ -368,7 +371,7 @@ test("value() is null when reference is not yet loaded", function(assert) { assert.strictEqual(familyReference.value(), null); }); -test("value() returns the referenced record when loaded", function(assert) { +test('value() returns the referenced record when loaded', function(assert) { var person, family; run(function() { person = env.store.push({ @@ -377,16 +380,16 @@ test("value() returns the referenced record when loaded", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); family = env.store.push({ data: { type: 'family', - id: 1 - } + id: 1, + }, }); }); @@ -394,7 +397,7 @@ test("value() returns the referenced record when loaded", function(assert) { assert.equal(familyReference.value(), family); }); -test("value() returns the referenced record when loaded even if links are present", function(assert) { +test('value() returns the referenced record when loaded even if links are present', function(assert) { var person, family; run(function() { person = env.store.push({ @@ -403,10 +406,10 @@ test("value() returns the referenced record when loaded even if links are presen id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); family = env.store.push({ data: { @@ -415,11 +418,11 @@ test("value() returns the referenced record when loaded even if links are presen relationships: { persons: { links: { - related: '/this/should/not/matter' - } - } - } - } + related: '/this/should/not/matter', + }, + }, + }, + }, }); }); @@ -427,7 +430,7 @@ test("value() returns the referenced record when loaded even if links are presen assert.equal(familyReference.value(), family); }); -test("load() fetches the record", function(assert) { +test('load() fetches the record', function(assert) { var done = assert.async(); env.adapter.findRecord = function(store, type, id) { @@ -435,8 +438,8 @@ test("load() fetches the record", function(assert) { data: { id: 1, type: 'family', - attributes: { name: "Coreleone" } - } + attributes: { name: 'Coreleone' }, + }, }); }; @@ -448,10 +451,10 @@ test("load() fetches the record", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); }); @@ -459,25 +462,25 @@ test("load() fetches the record", function(assert) { run(function() { familyReference.load().then(function(record) { - assert.equal(get(record, 'name'), "Coreleone"); + assert.equal(get(record, 'name'), 'Coreleone'); done(); }); }); }); -test("load() fetches link when remoteType is link", function(assert) { +test('load() fetches link when remoteType is link', function(assert) { var done = assert.async(); env.adapter.findBelongsTo = function(store, snapshot, link) { - assert.equal(link, "/families/1"); + assert.equal(link, '/families/1'); return resolve({ data: { id: 1, type: 'family', - attributes: { name: "Coreleone" } - } + attributes: { name: 'Coreleone' }, + }, }); }; @@ -489,26 +492,26 @@ test("load() fetches link when remoteType is link", function(assert) { id: 1, relationships: { family: { - links: { related: '/families/1' } - } - } - } + links: { related: '/families/1' }, + }, + }, + }, }); }); var familyReference = person.belongsTo('family'); - assert.equal(familyReference.remoteType(), "link"); + assert.equal(familyReference.remoteType(), 'link'); run(function() { familyReference.load().then(function(record) { - assert.equal(get(record, 'name'), "Coreleone"); + assert.equal(get(record, 'name'), 'Coreleone'); done(); }); }); }); -test("reload() - loads the record when not yet loaded", function(assert) { +test('reload() - loads the record when not yet loaded', function(assert) { var done = assert.async(); var count = 0; @@ -520,8 +523,8 @@ test("reload() - loads the record when not yet loaded", function(assert) { data: { id: 1, type: 'family', - attributes: { name: "Coreleone" } - } + attributes: { name: 'Coreleone' }, + }, }); }; @@ -533,10 +536,10 @@ test("reload() - loads the record when not yet loaded", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); }); @@ -544,14 +547,14 @@ test("reload() - loads the record when not yet loaded", function(assert) { run(function() { familyReference.reload().then(function(record) { - assert.equal(get(record, 'name'), "Coreleone"); + assert.equal(get(record, 'name'), 'Coreleone'); done(); }); }); }); -test("reload() - reloads the record when already loaded", function(assert) { +test('reload() - reloads the record when already loaded', function(assert) { var done = assert.async(); var count = 0; @@ -563,8 +566,8 @@ test("reload() - reloads the record when already loaded", function(assert) { data: { id: 1, type: 'family', - attributes: { name: "Coreleone" } - } + attributes: { name: 'Coreleone' }, + }, }); }; @@ -576,16 +579,16 @@ test("reload() - reloads the record when already loaded", function(assert) { id: 1, relationships: { family: { - data: { type: 'family', id: 1 } - } - } - } + data: { type: 'family', id: 1 }, + }, + }, + }, }); env.store.push({ data: { type: 'family', - id: 1 - } + id: 1, + }, }); }); @@ -593,25 +596,25 @@ test("reload() - reloads the record when already loaded", function(assert) { run(function() { familyReference.reload().then(function(record) { - assert.equal(get(record, 'name'), "Coreleone"); + assert.equal(get(record, 'name'), 'Coreleone'); done(); }); }); }); -test("reload() - uses link to reload record", function(assert) { +test('reload() - uses link to reload record', function(assert) { var done = assert.async(); env.adapter.findBelongsTo = function(store, snapshot, link) { - assert.equal(link, "/families/1"); + assert.equal(link, '/families/1'); return resolve({ data: { id: 1, type: 'family', - attributes: { name: "Coreleone" } - } + attributes: { name: 'Coreleone' }, + }, }); }; @@ -623,10 +626,10 @@ test("reload() - uses link to reload record", function(assert) { id: 1, relationships: { family: { - links: { related: '/families/1' } - } - } - } + links: { related: '/families/1' }, + }, + }, + }, }); }); @@ -634,7 +637,7 @@ test("reload() - uses link to reload record", function(assert) { run(function() { familyReference.reload().then(function(record) { - assert.equal(get(record, 'name'), "Coreleone"); + assert.equal(get(record, 'name'), 'Coreleone'); done(); }); diff --git a/tests/integration/references/has-many-test.js b/tests/integration/references/has-many-test.js index 030ca234fde..9682b97754c 100755 --- a/tests/integration/references/has-many-test.js +++ b/tests/integration/references/has-many-test.js @@ -8,24 +8,24 @@ import { module, test } from 'qunit'; var env, Person; -module("integration/references/has-many", { +module('integration/references/has-many', { beforeEach() { var Family = DS.Model.extend({ - persons: DS.hasMany({ async: true }) + persons: DS.hasMany({ async: true }), }); Person = DS.Model.extend({ name: DS.attr(), - family: DS.belongsTo() + family: DS.belongsTo(), }); env = setupStore({ person: Person, - family: Family + family: Family, }); }, afterEach() { run(env.container, 'destroy'); - } + }, }); testInDebug("record#hasMany asserts when specified relationship doesn't exist", function(assert) { @@ -34,37 +34,40 @@ testInDebug("record#hasMany asserts when specified relationship doesn't exist", family = env.store.push({ data: { type: 'family', - id: 1 - } + id: 1, + }, }); }); assert.expectAssertion(function() { run(function() { - family.hasMany("unknown-relationship"); + family.hasMany('unknown-relationship'); }); }, "There is no hasMany relationship named 'unknown-relationship' on a model of modelClass 'family'"); }); -testInDebug("record#hasMany asserts when the type of the specified relationship isn't the requested one", function(assert) { - var person; - run(function() { - person = env.store.push({ - data: { - type: 'person', - id: 1 - } - }); - }); - - assert.expectAssertion(function() { +testInDebug( + "record#hasMany asserts when the type of the specified relationship isn't the requested one", + function(assert) { + var person; run(function() { - person.hasMany("family"); - }); - }, "You tried to get the 'family' relationship on a 'person' via record.hasMany('family'), but the relationship is of kind 'belongsTo'. Use record.belongsTo('family') instead."); -}); + person = env.store.push({ + data: { + type: 'person', + id: 1, + }, + }); + }); + + assert.expectAssertion(function() { + run(function() { + person.hasMany('family'); + }); + }, "You tried to get the 'family' relationship on a 'person' via record.hasMany('family'), but the relationship is of kind 'belongsTo'. Use record.belongsTo('family') instead."); + } +); -test("record#hasMany", function(assert) { +test('record#hasMany', function(assert) { var family; run(function() { family = env.store.push({ @@ -73,13 +76,10 @@ test("record#hasMany", function(assert) { id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); }); @@ -90,7 +90,7 @@ test("record#hasMany", function(assert) { assert.deepEqual(personsReference.ids(), ['1', '2']); }); -test("record#hasMany for linked references", function(assert) { +test('record#hasMany for linked references', function(assert) { var family; run(function() { family = env.store.push({ @@ -99,10 +99,10 @@ test("record#hasMany for linked references", function(assert) { id: 1, relationships: { persons: { - links: { related: '/families/1/persons' } - } - } - } + links: { related: '/families/1/persons' }, + }, + }, + }, }); }); @@ -113,7 +113,7 @@ test("record#hasMany for linked references", function(assert) { assert.equal(personsReference.link(), '/families/1/persons'); }); -test("HasManyReference#parent is a reference to the parent where the relationship is defined", function(assert) { +test('HasManyReference#parent is a reference to the parent where the relationship is defined', function(assert) { var family; run(function() { family = env.store.push({ @@ -122,13 +122,10 @@ test("HasManyReference#parent is a reference to the parent where the relationshi id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); }); @@ -139,7 +136,7 @@ test("HasManyReference#parent is a reference to the parent where the relationshi assert.equal(personsReference.parent, familyReference); }); -test("HasManyReference#meta() returns the most recent meta for the relationship", function(assert) { +test('HasManyReference#meta() returns the most recent meta for the relationship', function(assert) { var family; run(function() { family = env.store.push({ @@ -150,11 +147,11 @@ test("HasManyReference#meta() returns the most recent meta for the relationship" persons: { links: { related: '/families/1/persons' }, meta: { - foo: true - } - } - } - } + foo: true, + }, + }, + }, + }, }); }); @@ -162,7 +159,7 @@ test("HasManyReference#meta() returns the most recent meta for the relationship" assert.deepEqual(personsReference.meta(), { foo: true }); }); -testInDebug("push(array)", function(assert) { +testInDebug('push(array)', function(assert) { var done = assert.async(); var family; @@ -173,13 +170,10 @@ testInDebug("push(array)", function(assert) { id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); }); @@ -187,22 +181,22 @@ testInDebug("push(array)", function(assert) { run(function() { var data = [ - { data: { type: 'person', id: 1, attributes: { name: "Vito" } } }, - { data: { type: 'person', id: 2, attributes: { name: "Michael" } } } + { data: { type: 'person', id: 1, attributes: { name: 'Vito' } } }, + { data: { type: 'person', id: 2, attributes: { name: 'Michael' } } }, ]; personsReference.push(data).then(function(records) { - assert.ok(records instanceof DS.ManyArray, "push resolves with the referenced records"); + assert.ok(records instanceof DS.ManyArray, 'push resolves with the referenced records'); assert.equal(get(records, 'length'), 2); - assert.equal(records.objectAt(0).get('name'), "Vito"); - assert.equal(records.objectAt(1).get('name'), "Michael"); + assert.equal(records.objectAt(0).get('name'), 'Vito'); + assert.equal(records.objectAt(1).get('name'), 'Michael'); done(); }); }); }); -testInDebug("push(array) works with polymorphic type", function(assert) { +testInDebug('push(array) works with polymorphic type', function(assert) { var done = assert.async(); env.registry.register('model:mafia-boss', Person.extend()); @@ -212,36 +206,34 @@ testInDebug("push(array) works with polymorphic type", function(assert) { family = env.store.push({ data: { type: 'family', - id: 1 - } + id: 1, + }, }); }); var personsReference = family.hasMany('persons'); run(() => { - var data = [ - { data: { type: 'mafia-boss', id: 1, attributes: { name: "Vito" } } } - ]; + var data = [{ data: { type: 'mafia-boss', id: 1, attributes: { name: 'Vito' } } }]; personsReference.push(data).then(function(records) { - assert.ok(records instanceof DS.ManyArray, "push resolves with the referenced records"); + assert.ok(records instanceof DS.ManyArray, 'push resolves with the referenced records'); assert.equal(get(records, 'length'), 1); - assert.equal(records.objectAt(0).get('name'), "Vito"); + assert.equal(records.objectAt(0).get('name'), 'Vito'); done(); }); }); }); -testInDebug("push(array) asserts polymorphic type", function(assert) { +testInDebug('push(array) asserts polymorphic type', function(assert) { var family; run(function() { family = env.store.push({ data: { type: 'family', - id: 1 - } + id: 1, + }, }); }); @@ -249,16 +241,14 @@ testInDebug("push(array) asserts polymorphic type", function(assert) { assert.expectAssertion(() => { run(() => { - var data = [ - { data: { type: 'family', id: 1 } } - ]; + var data = [{ data: { type: 'family', id: 1 } }]; personsReference.push(data); }); }, "You cannot add a record of modelClass 'family' to the 'family.persons' relationship (only 'person' allowed)"); }); -testInDebug("push(object) supports legacy, non-JSON-API-conform payload", function(assert) { +testInDebug('push(object) supports legacy, non-JSON-API-conform payload', function(assert) { var done = assert.async(); var family; @@ -269,13 +259,10 @@ testInDebug("push(object) supports legacy, non-JSON-API-conform payload", functi id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); }); @@ -284,23 +271,23 @@ testInDebug("push(object) supports legacy, non-JSON-API-conform payload", functi run(function() { var payload = { data: [ - { data: { type: 'person', id: 1, attributes: { name: "Vito" } } }, - { data: { type: 'person', id: 2, attributes: { name: "Michael" } } } - ] + { data: { type: 'person', id: 1, attributes: { name: 'Vito' } } }, + { data: { type: 'person', id: 2, attributes: { name: 'Michael' } } }, + ], }; personsReference.push(payload).then(function(records) { - assert.ok(records instanceof DS.ManyArray, "push resolves with the referenced records"); + assert.ok(records instanceof DS.ManyArray, 'push resolves with the referenced records'); assert.equal(get(records, 'length'), 2); - assert.equal(records.objectAt(0).get('name'), "Vito"); - assert.equal(records.objectAt(1).get('name'), "Michael"); + assert.equal(records.objectAt(0).get('name'), 'Vito'); + assert.equal(records.objectAt(1).get('name'), 'Michael'); done(); }); }); }); -test("push(promise)", function(assert) { +test('push(promise)', function(assert) { var done = assert.async(); var push; @@ -313,13 +300,10 @@ test("push(promise)", function(assert) { id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); var personsReference = family.hasMany('persons'); push = personsReference.push(deferred.promise); @@ -330,9 +314,9 @@ test("push(promise)", function(assert) { run(function() { var payload = { data: [ - { data: { type: 'person', id: 1, attributes: { name: "Vito" } } }, - { data: { type: 'person', id: 2, attributes: { name: "Michael" } } } - ] + { data: { type: 'person', id: 1, attributes: { name: 'Vito' } } }, + { data: { type: 'person', id: 2, attributes: { name: 'Michael' } } }, + ], }; deferred.resolve(payload); @@ -340,17 +324,17 @@ test("push(promise)", function(assert) { run(function() { push.then(function(records) { - assert.ok(records instanceof DS.ManyArray, "push resolves with the referenced records"); + assert.ok(records instanceof DS.ManyArray, 'push resolves with the referenced records'); assert.equal(get(records, 'length'), 2); - assert.equal(records.objectAt(0).get('name'), "Vito"); - assert.equal(records.objectAt(1).get('name'), "Michael"); + assert.equal(records.objectAt(0).get('name'), 'Vito'); + assert.equal(records.objectAt(1).get('name'), 'Michael'); done(); }); }); }); -test("value() returns null when reference is not yet loaded", function(assert) { +test('value() returns null when reference is not yet loaded', function(assert) { var family; run(function() { family = env.store.push({ @@ -359,13 +343,10 @@ test("value() returns null when reference is not yet loaded", function(assert) { id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); }); @@ -373,7 +354,7 @@ test("value() returns null when reference is not yet loaded", function(assert) { assert.strictEqual(personsReference.value(), null); }); -test("value() returns the referenced records when all records are loaded", function(assert) { +test('value() returns the referenced records when all records are loaded', function(assert) { var family; run(function() { family = env.store.push({ @@ -382,16 +363,13 @@ test("value() returns the referenced records when all records are loaded", funct id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); - env.store.push({ data: { type: 'person', id: 1, attributes: { name: "Vito" } } }); - env.store.push({ data: { type: 'person', id: 2, attributes: { name: "Michael" } } }); + env.store.push({ data: { type: 'person', id: 1, attributes: { name: 'Vito' } } }); + env.store.push({ data: { type: 'person', id: 2, attributes: { name: 'Michael' } } }); }); run(function() { @@ -402,7 +380,7 @@ test("value() returns the referenced records when all records are loaded", funct }); }); -test("value() returns an empty array when the reference is loaded and empty", function(assert) { +test('value() returns an empty array when the reference is loaded and empty', function(assert) { var family; run(function() { family = env.store.push({ @@ -411,10 +389,10 @@ test("value() returns an empty array when the reference is loaded and empty", fu id: 1, relationships: { persons: { - data: [] - } - } - } + data: [], + }, + }, + }, }); }); @@ -425,7 +403,7 @@ test("value() returns an empty array when the reference is loaded and empty", fu }); }); -test("_isLoaded() returns an true array when the reference is loaded and empty", function(assert) { +test('_isLoaded() returns an true array when the reference is loaded and empty', function(assert) { var family; run(function() { family = env.store.push({ @@ -434,10 +412,10 @@ test("_isLoaded() returns an true array when the reference is loaded and empty", id: 1, relationships: { persons: { - data: [] - } - } - } + data: [], + }, + }, + }, }); }); @@ -448,11 +426,16 @@ test("_isLoaded() returns an true array when the reference is loaded and empty", }); }); -test("load() fetches the referenced records", function(assert) { +test('load() fetches the referenced records', function(assert) { var done = assert.async(); env.adapter.findMany = function(store, type, id) { - return resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito" } }, { id: 2, type: 'person', attributes: { name: "Michael" } }] }); + return resolve({ + data: [ + { id: 1, type: 'person', attributes: { name: 'Vito' } }, + { id: 2, type: 'person', attributes: { name: 'Michael' } }, + ], + }); }; var family; @@ -463,13 +446,10 @@ test("load() fetches the referenced records", function(assert) { id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); }); @@ -477,23 +457,28 @@ test("load() fetches the referenced records", function(assert) { run(function() { personsReference.load().then(function(records) { - assert.ok(records instanceof DS.ManyArray, "push resolves with the referenced records"); + assert.ok(records instanceof DS.ManyArray, 'push resolves with the referenced records'); assert.equal(get(records, 'length'), 2); - assert.equal(records.objectAt(0).get('name'), "Vito"); - assert.equal(records.objectAt(1).get('name'), "Michael"); + assert.equal(records.objectAt(0).get('name'), 'Vito'); + assert.equal(records.objectAt(1).get('name'), 'Michael'); done(); }); }); }); -test("load() fetches link when remoteType is link", function(assert) { +test('load() fetches link when remoteType is link', function(assert) { var done = assert.async(); env.adapter.findHasMany = function(store, snapshot, link) { - assert.equal(link, "/families/1/persons"); + assert.equal(link, '/families/1/persons'); - return resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito" } }, { id: 2, type: 'person', attributes: { name: "Michael" } }] }); + return resolve({ + data: [ + { id: 1, type: 'person', attributes: { name: 'Vito' } }, + { id: 2, type: 'person', attributes: { name: 'Michael' } }, + ], + }); }; var family; @@ -504,31 +489,31 @@ test("load() fetches link when remoteType is link", function(assert) { id: 1, relationships: { persons: { - links: { related: '/families/1/persons' } - } - } - } + links: { related: '/families/1/persons' }, + }, + }, + }, }); }); var personsReference = family.hasMany('persons'); - assert.equal(personsReference.remoteType(), "link"); + assert.equal(personsReference.remoteType(), 'link'); run(function() { personsReference.load().then(function(records) { - assert.ok(records instanceof DS.ManyArray, "push resolves with the referenced records"); + assert.ok(records instanceof DS.ManyArray, 'push resolves with the referenced records'); assert.equal(get(records, 'length'), 2); - assert.equal(records.objectAt(0).get('name'), "Vito"); - assert.equal(records.objectAt(1).get('name'), "Michael"); + assert.equal(records.objectAt(0).get('name'), 'Vito'); + assert.equal(records.objectAt(1).get('name'), 'Michael'); done(); }); }); }); -test("load() fetches link when remoteType is link but an empty set of records is returned", function(assert) { +test('load() fetches link when remoteType is link but an empty set of records is returned', function(assert) { env.adapter.findHasMany = function(store, snapshot, link) { - assert.equal(link, "/families/1/persons"); + assert.equal(link, '/families/1/persons'); return resolve({ data: [] }); }; @@ -541,26 +526,26 @@ test("load() fetches link when remoteType is link but an empty set of records is id: 1, relationships: { persons: { - links: { related: '/families/1/persons' } - } - } - } + links: { related: '/families/1/persons' }, + }, + }, + }, }); }); let personsReference = family.hasMany('persons'); - assert.equal(personsReference.remoteType(), "link"); + assert.equal(personsReference.remoteType(), 'link'); return run(() => { - return personsReference.load().then((records) => { - assert.ok(records instanceof DS.ManyArray, "push resolves with the referenced records"); + return personsReference.load().then(records => { + assert.ok(records instanceof DS.ManyArray, 'push resolves with the referenced records'); assert.equal(get(records, 'length'), 0); assert.equal(get(personsReference.value(), 'length'), 0); }); }); }); -test("load() - only a single find is triggered", function(assert) { +test('load() - only a single find is triggered', function(assert) { var done = assert.async(); var deferred = defer(); @@ -581,13 +566,10 @@ test("load() - only a single find is triggered", function(assert) { id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); }); @@ -601,7 +583,12 @@ test("load() - only a single find is triggered", function(assert) { }); run(function() { - deferred.resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito" } }, { id: 2, type: 'person', attributes: { name: "Michael" } }] }); + deferred.resolve({ + data: [ + { id: 1, type: 'person', attributes: { name: 'Vito' } }, + { id: 2, type: 'person', attributes: { name: 'Michael' } }, + ], + }); }); run(function() { @@ -613,11 +600,16 @@ test("load() - only a single find is triggered", function(assert) { }); }); -test("reload()", function(assert) { +test('reload()', function(assert) { var done = assert.async(); env.adapter.findMany = function(store, type, id) { - return resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito Coreleone" } }, { id: 2, type: 'person', attributes: { name: "Michael Coreleone" } }] }); + return resolve({ + data: [ + { id: 1, type: 'person', attributes: { name: 'Vito Coreleone' } }, + { id: 2, type: 'person', attributes: { name: 'Michael Coreleone' } }, + ], + }); }; var family; @@ -628,44 +620,51 @@ test("reload()", function(assert) { id: 1, relationships: { persons: { - data: [ - { type: 'person', id: 1 }, - { type: 'person', id: 2 } - ] - } - } - } + data: [{ type: 'person', id: 1 }, { type: 'person', id: 2 }], + }, + }, + }, }); - env.store.push({ data: { type: 'person', id: 1, attributes: { name: "Vito" } } }); - env.store.push({ data: { type: 'person', id: 2, attributes: { name: "Michael" } } }); + env.store.push({ data: { type: 'person', id: 1, attributes: { name: 'Vito' } } }); + env.store.push({ data: { type: 'person', id: 2, attributes: { name: 'Michael' } } }); }); var personsReference = family.hasMany('persons'); run(function() { personsReference.reload().then(function(records) { - assert.ok(records instanceof DS.ManyArray, "push resolves with the referenced records"); + assert.ok(records instanceof DS.ManyArray, 'push resolves with the referenced records'); assert.equal(get(records, 'length'), 2); - assert.equal(records.objectAt(0).get('name'), "Vito Coreleone"); - assert.equal(records.objectAt(1).get('name'), "Michael Coreleone"); + assert.equal(records.objectAt(0).get('name'), 'Vito Coreleone'); + assert.equal(records.objectAt(1).get('name'), 'Michael Coreleone'); done(); }); }); }); -test("reload() fetches link when remoteType is link", function(assert) { +test('reload() fetches link when remoteType is link', function(assert) { var done = assert.async(); var count = 0; env.adapter.findHasMany = function(store, snapshot, link) { count++; - assert.equal(link, "/families/1/persons"); + assert.equal(link, '/families/1/persons'); if (count === 1) { - return resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito" } }, { id: 2, type: 'person', attributes: { name: "Michael" } }] }); + return resolve({ + data: [ + { id: 1, type: 'person', attributes: { name: 'Vito' } }, + { id: 2, type: 'person', attributes: { name: 'Michael' } }, + ], + }); } else { - return resolve({ data: [{ id: 1, type: 'person', attributes: { name: "Vito Coreleone" } }, { id: 2, type: 'person', attributes: { name: "Michael Coreleone" } }] }); + return resolve({ + data: [ + { id: 1, type: 'person', attributes: { name: 'Vito Coreleone' } }, + { id: 2, type: 'person', attributes: { name: 'Michael Coreleone' } }, + ], + }); } }; @@ -677,26 +676,29 @@ test("reload() fetches link when remoteType is link", function(assert) { id: 1, relationships: { persons: { - links: { related: '/families/1/persons' } - } - } - } + links: { related: '/families/1/persons' }, + }, + }, + }, }); }); var personsReference = family.hasMany('persons'); - assert.equal(personsReference.remoteType(), "link"); + assert.equal(personsReference.remoteType(), 'link'); run(function() { - personsReference.load().then(function() { - return personsReference.reload(); - }).then(function(records) { - assert.ok(records instanceof DS.ManyArray, "push resolves with the referenced records"); - assert.equal(get(records, 'length'), 2); - assert.equal(records.objectAt(0).get('name'), "Vito Coreleone"); - assert.equal(records.objectAt(1).get('name'), "Michael Coreleone"); + personsReference + .load() + .then(function() { + return personsReference.reload(); + }) + .then(function(records) { + assert.ok(records instanceof DS.ManyArray, 'push resolves with the referenced records'); + assert.equal(get(records, 'length'), 2); + assert.equal(records.objectAt(0).get('name'), 'Vito Coreleone'); + assert.equal(records.objectAt(1).get('name'), 'Michael Coreleone'); - done(); - }); + done(); + }); }); }); diff --git a/tests/integration/references/record-test.js b/tests/integration/references/record-test.js index 3701206cebd..d5484cfd814 100644 --- a/tests/integration/references/record-test.js +++ b/tests/integration/references/record-test.js @@ -7,24 +7,24 @@ import { module, test } from 'qunit'; var env, Person; -module("integration/references/record", { +module('integration/references/record', { beforeEach() { Person = DS.Model.extend({ - name: DS.attr() + name: DS.attr(), }); env = setupStore({ - person: Person + person: Person, }); }, afterEach() { run(env.store, 'unloadAll'); run(env.container, 'destroy'); - } + }, }); -test("a RecordReference can be retrieved via store.getReference(type, id)", function(assert) { +test('a RecordReference can be retrieved via store.getReference(type, id)', function(assert) { var recordReference = env.store.getReference('person', 1); assert.equal(recordReference.remoteType(), 'identity'); @@ -32,7 +32,7 @@ test("a RecordReference can be retrieved via store.getReference(type, id)", func assert.equal(recordReference.id(), 1); }); -test("push(object)", function(assert) { +test('push(object)', function(assert) { var done = assert.async(); var push; @@ -44,9 +44,9 @@ test("push(object)", function(assert) { type: 'person', id: 1, attributes: { - name: "le name" - } - } + name: 'le name', + }, + }, }); }); @@ -54,15 +54,15 @@ test("push(object)", function(assert) { run(function() { push.then(function(record) { - assert.ok(record instanceof Person, "push resolves with the record"); - assert.equal(get(record, 'name'), "le name"); + assert.ok(record instanceof Person, 'push resolves with the record'); + assert.equal(get(record, 'name'), 'le name'); done(); }); }); }); -test("push(promise)", function(assert) { +test('push(promise)', function(assert) { var done = assert.async(); var push; @@ -81,35 +81,35 @@ test("push(promise)", function(assert) { type: 'person', id: 1, attributes: { - name: "le name" - } - } + name: 'le name', + }, + }, }); }); run(function() { push.then(function(record) { - assert.ok(record instanceof Person, "push resolves with the record"); - assert.equal(get(record, 'name'), "le name", "name is updated"); + assert.ok(record instanceof Person, 'push resolves with the record'); + assert.equal(get(record, 'name'), 'le name', 'name is updated'); done(); }); }); }); -test("value() returns null when not yet loaded", function(assert) { +test('value() returns null when not yet loaded', function(assert) { var recordReference = env.store.getReference('person', 1); assert.strictEqual(recordReference.value(), null); }); -test("value() returns the record when loaded", function(assert) { +test('value() returns the record when loaded', function(assert) { var person; run(function() { person = env.store.push({ data: { type: 'person', - id: 1 - } + id: 1, + }, }); }); @@ -117,7 +117,7 @@ test("value() returns the record when loaded", function(assert) { assert.equal(recordReference.value(), person); }); -test("load() fetches the record", function(assert) { +test('load() fetches the record', function(assert) { var done = assert.async(); env.adapter.findRecord = function(store, type, id) { @@ -126,9 +126,9 @@ test("load() fetches the record", function(assert) { id: 1, type: 'person', attributes: { - name: 'Vito' - } - } + name: 'Vito', + }, + }, }); }; @@ -136,20 +136,24 @@ test("load() fetches the record", function(assert) { run(function() { recordReference.load().then(function(record) { - assert.equal(get(record, 'name'), "Vito"); + assert.equal(get(record, 'name'), 'Vito'); done(); }); }); }); -test("load() only a single find is triggered", function(assert) { +test('load() only a single find is triggered', function(assert) { var done = assert.async(); var deferred = defer(); var count = 0; - env.adapter.shouldReloadRecord = function() { return false; }; - env.adapter.shouldBackgroundReloadRecord = function() { return false; }; + env.adapter.shouldReloadRecord = function() { + return false; + }; + env.adapter.shouldBackgroundReloadRecord = function() { + return false; + }; env.adapter.findRecord = function(store, type, id) { count++; assert.equal(count, 1); @@ -162,7 +166,7 @@ test("load() only a single find is triggered", function(assert) { run(function() { recordReference.load(); recordReference.load().then(function(record) { - assert.equal(get(record, 'name'), "Vito"); + assert.equal(get(record, 'name'), 'Vito'); }); }); @@ -172,22 +176,22 @@ test("load() only a single find is triggered", function(assert) { id: 1, type: 'person', attributes: { - name: 'Vito' - } - } + name: 'Vito', + }, + }, }); }); run(function() { recordReference.load().then(function(record) { - assert.equal(get(record, 'name'), "Vito"); + assert.equal(get(record, 'name'), 'Vito'); done(); }); }); }); -test("reload() loads the record if not yet loaded", function(assert) { +test('reload() loads the record if not yet loaded', function(assert) { var done = assert.async(); var count = 0; @@ -200,9 +204,9 @@ test("reload() loads the record if not yet loaded", function(assert) { id: 1, type: 'person', attributes: { - name: 'Vito Coreleone' - } - } + name: 'Vito Coreleone', + }, + }, }); }; @@ -210,14 +214,14 @@ test("reload() loads the record if not yet loaded", function(assert) { run(function() { recordReference.reload().then(function(record) { - assert.equal(get(record, 'name'), "Vito Coreleone"); + assert.equal(get(record, 'name'), 'Vito Coreleone'); done(); }); }); }); -test("reload() fetches the record", function(assert) { +test('reload() fetches the record', function(assert) { var done = assert.async(); env.adapter.findRecord = function(store, type, id) { @@ -226,9 +230,9 @@ test("reload() fetches the record", function(assert) { id: 1, type: 'person', attributes: { - name: 'Vito Coreleone' - } - } + name: 'Vito Coreleone', + }, + }, }); }; @@ -238,9 +242,9 @@ test("reload() fetches the record", function(assert) { type: 'person', id: 1, attributes: { - name: 'Vito' - } - } + name: 'Vito', + }, + }, }); }); @@ -248,7 +252,7 @@ test("reload() fetches the record", function(assert) { run(function() { recordReference.reload().then(function(record) { - assert.equal(get(record, 'name'), "Vito Coreleone"); + assert.equal(get(record, 'name'), 'Vito Coreleone'); done(); }); diff --git a/tests/integration/relationships/belongs-to-test.js b/tests/integration/relationships/belongs-to-test.js index cb0ecbc143b..605e2a8353d 100644 --- a/tests/integration/relationships/belongs-to-test.js +++ b/tests/integration/relationships/belongs-to-test.js @@ -6,7 +6,7 @@ import setupStore from 'dummy/tests/helpers/store'; import testInDebug from 'dummy/tests/helpers/test-in-debug'; import { setup as setupModelFactoryInjections, - reset as resetModelFactoryInjection + reset as resetModelFactoryInjection, } from 'dummy/tests/helpers/model-factory-injection'; import { module, test } from 'qunit'; @@ -17,43 +17,43 @@ const { hash } = RSVP; let env, store, User, Message, Post, Comment, Book, Chapter, Author, NewMessage; -module("integration/relationship/belongs_to Belongs-To Relationships", { +module('integration/relationship/belongs_to Belongs-To Relationships', { beforeEach() { User = DS.Model.extend({ name: attr('string'), messages: hasMany('message', { polymorphic: true, async: false }), - favouriteMessage: belongsTo('message', { polymorphic: true, inverse: null, async: false }) + favouriteMessage: belongsTo('message', { polymorphic: true, inverse: null, async: false }), }); Message = DS.Model.extend({ user: belongsTo('user', { inverse: 'messages', async: false }), - created_at: attr('date') + created_at: attr('date'), }); Post = Message.extend({ title: attr('string'), - comments: hasMany('comment', { async: false, inverse: null }) + comments: hasMany('comment', { async: false, inverse: null }), }); Comment = Message.extend({ body: DS.attr('string'), - message: DS.belongsTo('message', { polymorphic: true, async: false, inverse: null }) + message: DS.belongsTo('message', { polymorphic: true, async: false, inverse: null }), }); Book = DS.Model.extend({ name: attr('string'), author: belongsTo('author', { async: false }), - chapters: hasMany('chapters', { async: false, inverse: 'book' }) + chapters: hasMany('chapters', { async: false, inverse: 'book' }), }); Chapter = DS.Model.extend({ title: attr('string'), - book: belongsTo('book', { async: false, inverse: 'chapters' }) + book: belongsTo('book', { async: false, inverse: 'chapters' }), }); Author = DS.Model.extend({ name: attr('string'), - books: hasMany('books', { async: false }) + books: hasMany('books', { async: false }), }); env = setupStore({ @@ -63,43 +63,52 @@ module("integration/relationship/belongs_to Belongs-To Relationships", { message: Message, book: Book, chapter: Chapter, - author: Author + author: Author, }); env.registry.optionsForType('serializer', { singleton: false }); env.registry.optionsForType('adapter', { singleton: false }); - env.registry.register('serializer:user', DS.JSONAPISerializer.extend({ - attrs: { - favouriteMessage: { embedded: 'always' } - } - })); + env.registry.register( + 'serializer:user', + DS.JSONAPISerializer.extend({ + attrs: { + favouriteMessage: { embedded: 'always' }, + }, + }) + ); store = env.store; - User = store.modelFor('user'); - Post = store.modelFor('post'); + User = store.modelFor('user'); + Post = store.modelFor('post'); Comment = store.modelFor('comment'); Message = store.modelFor('message'); - Book = store.modelFor('book'); + Book = store.modelFor('book'); Chapter = store.modelFor('chapter'); - Author = store.modelFor('author'); + Author = store.modelFor('author'); }, afterEach() { resetModelFactoryInjection(); run(env.container, 'destroy'); - } + }, }); -test("returning a null relationship from payload sets the relationship to null on both sides", function(assert) { - env.registry.register('model:app', DS.Model.extend({ - name: attr('string'), - team: belongsTo('team', { async: true }) - })); - env.registry.register('model:team', DS.Model.extend({ - apps: hasMany('app', {async: true}) - })); +test('returning a null relationship from payload sets the relationship to null on both sides', function(assert) { + env.registry.register( + 'model:app', + DS.Model.extend({ + name: attr('string'), + team: belongsTo('team', { async: true }), + }) + ); + env.registry.register( + 'model:team', + DS.Model.extend({ + apps: hasMany('app', { async: true }), + }) + ); run(() => { env.store.push({ data: { @@ -109,10 +118,10 @@ test("returning a null relationship from payload sets the relationship to null o team: { data: { id: '1', - type: 'team' - } - } - } + type: 'team', + }, + }, + }, }, included: [ { @@ -120,21 +129,30 @@ test("returning a null relationship from payload sets the relationship to null o type: 'team', relationships: { apps: { - data: [{ - id: '1', - type: 'app' - }] - } - } - } - ] + data: [ + { + id: '1', + type: 'app', + }, + ], + }, + }, + }, + ], }); }); const app = env.store.peekRecord('app', '1'); const team = env.store.peekRecord('team', '1'); assert.equal(app.get('team.id'), team.get('id'), 'sets team correctly on app'); - assert.deepEqual(team.get('apps').toArray().mapBy('id'), ['1'], 'sets apps correctly on team'); + assert.deepEqual( + team + .get('apps') + .toArray() + .mapBy('id'), + ['1'], + 'sets apps correctly on team' + ); env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.updateRecord = (store, type, snapshot) => { @@ -143,14 +161,14 @@ test("returning a null relationship from payload sets the relationship to null o id: '1', type: 'app', attributes: { - name: 'Hello' + name: 'Hello', }, relationships: { team: { - data: null - } - } - } + data: null, + }, + }, + }, }); }; @@ -158,19 +176,26 @@ test("returning a null relationship from payload sets the relationship to null o app.set('name', 'Hello'); return app.save().then(() => { assert.equal(app.get('team.id'), null, 'team removed from app relationship'); - assert.deepEqual(team.get('apps').toArray().mapBy('id'), [], 'app removed from team apps relationship'); + assert.deepEqual( + team + .get('apps') + .toArray() + .mapBy('id'), + [], + 'app removed from team apps relationship' + ); }); }); }); -test("The store can materialize a non loaded monomorphic belongsTo association", function(assert) { +test('The store can materialize a non loaded monomorphic belongsTo association', function(assert) { assert.expect(1); env.store.modelFor('post').reopen({ user: DS.belongsTo('user', { async: true, - inverse: 'messages' - }) + inverse: 'messages', + }), }); env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.findRecord = function(store, type, id, snapshot) { @@ -178,8 +203,8 @@ test("The store can materialize a non loaded monomorphic belongsTo association", return resolve({ data: { id, - type: snapshot.modelName - } + type: snapshot.modelName, + }, }); }; @@ -192,11 +217,11 @@ test("The store can materialize a non loaded monomorphic belongsTo association", user: { data: { id: '2', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); }); @@ -207,149 +232,149 @@ test("The store can materialize a non loaded monomorphic belongsTo association", }); }); -testInDebug("Invalid belongsTo relationship identifiers throw errors", function(assert) { +testInDebug('Invalid belongsTo relationship identifiers throw errors', function(assert) { assert.expect(2); let { store } = env; // test null id - assert.expectAssertion( - () => { - run(() => { - let post = store.push({ - data: { - id: '1', - type: 'post', - relationships: { - user: { - data: { - id: null, - type: 'user' - } - } - } - } - }); - post.get('user'); + assert.expectAssertion(() => { + run(() => { + let post = store.push({ + data: { + id: '1', + type: 'post', + relationships: { + user: { + data: { + id: null, + type: 'user', + }, + }, + }, + }, }); - }, - `Assertion Failed: Encountered a relationship identifier without an id for the belongsTo relationship 'user' on , expected a json-api identifier but found '{"id":null,"type":"user"}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.` - ); + post.get('user'); + }); + }, `Assertion Failed: Encountered a relationship identifier without an id for the belongsTo relationship 'user' on , expected a json-api identifier but found '{"id":null,"type":"user"}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`); // test missing type - assert.expectAssertion( - () => { - run(() => { - let post = store.push({ - data: { - id: '2', - type: 'post', - relationships: { - user: { - data: { - id: '1', - type: null - } - } - } - } - }); - post.get('user'); + assert.expectAssertion(() => { + run(() => { + let post = store.push({ + data: { + id: '2', + type: 'post', + relationships: { + user: { + data: { + id: '1', + type: null, + }, + }, + }, + }, }); - }, - `Assertion Failed: Encountered a relationship identifier without a type for the belongsTo relationship 'user' on , expected a json-api identifier with type 'user' but found '{"id":"1","type":null}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.` - ); + post.get('user'); + }); + }, `Assertion Failed: Encountered a relationship identifier without a type for the belongsTo relationship 'user' on , expected a json-api identifier with type 'user' but found '{"id":"1","type":null}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`); }); -testInDebug("Only a record of the same modelClass can be used with a monomorphic belongsTo relationship", function(assert) { - assert.expect(1); - env.adapter.shouldBackgroundReloadRecord = () => false; - run(() => { - store.push({ - data: { - id: '1', - type: 'post' - } - }); - store.push({ - data: { - id: '2', - type: 'comment' - } +testInDebug( + 'Only a record of the same modelClass can be used with a monomorphic belongsTo relationship', + function(assert) { + assert.expect(1); + env.adapter.shouldBackgroundReloadRecord = () => false; + run(() => { + store.push({ + data: { + id: '1', + type: 'post', + }, + }); + store.push({ + data: { + id: '2', + type: 'comment', + }, + }); }); - }); - - return run(() => { - return hash({ - post: store.findRecord('post', 1), - comment: store.findRecord('comment', 2) - }).then(records => { - assert.expectAssertion(() => { - records.post.set('user', records.comment); - }, /You cannot add a record of modelClass 'comment' to the 'post.user' relationship/); + return run(() => { + return hash({ + post: store.findRecord('post', 1), + comment: store.findRecord('comment', 2), + }).then(records => { + assert.expectAssertion(() => { + records.post.set('user', records.comment); + }, /You cannot add a record of modelClass 'comment' to the 'post.user' relationship/); + }); }); - }); -}); + } +); -testInDebug("Only a record of the same base modelClass can be used with a polymorphic belongsTo relationship", function(assert) { - env.adapter.shouldBackgroundReloadRecord = () => false; - assert.expect(1); - run(() => { - store.push({ - data: [{ - id: '1', - type: 'comment' - }, - { - id: '2', - type: 'comment' - }] - }); - store.push({ - data: { - id: '1', - type: 'post' - } - }); - store.push({ - data: { - id: '3', - type: 'user' - } +testInDebug( + 'Only a record of the same base modelClass can be used with a polymorphic belongsTo relationship', + function(assert) { + env.adapter.shouldBackgroundReloadRecord = () => false; + assert.expect(1); + run(() => { + store.push({ + data: [ + { + id: '1', + type: 'comment', + }, + { + id: '2', + type: 'comment', + }, + ], + }); + store.push({ + data: { + id: '1', + type: 'post', + }, + }); + store.push({ + data: { + id: '3', + type: 'user', + }, + }); }); - }); - - return run(() => { - let asyncRecords = hash({ - user: store.findRecord('user', 3), - post: store.findRecord('post', 1), - comment: store.findRecord('comment', 1), - anotherComment: store.findRecord('comment', 2) - }); + return run(() => { + let asyncRecords = hash({ + user: store.findRecord('user', 3), + post: store.findRecord('post', 1), + comment: store.findRecord('comment', 1), + anotherComment: store.findRecord('comment', 2), + }); - return asyncRecords.then(records => { - let comment = records.comment; + return asyncRecords.then(records => { + let comment = records.comment; - comment.set('message', records.anotherComment); - comment.set('message', records.post); - comment.set('message', null); + comment.set('message', records.anotherComment); + comment.set('message', records.post); + comment.set('message', null); - assert.expectAssertion(() => { - comment.set('message', records.user); - }, /You cannot add a record of modelClass 'user' to the 'comment.message' relationship \(only 'message' allowed\)/); + assert.expectAssertion(() => { + comment.set('message', records.user); + }, /You cannot add a record of modelClass 'user' to the 'comment.message' relationship \(only 'message' allowed\)/); + }); }); - }); -}); + } +); -test("The store can load a polymorphic belongsTo association", function(assert) { +test('The store can load a polymorphic belongsTo association', function(assert) { env.adapter.shouldBackgroundReloadRecord = () => false; run(() => { env.store.push({ data: { id: '1', - type: 'post' - } + type: 'post', + }, }); env.store.push({ @@ -360,39 +385,39 @@ test("The store can load a polymorphic belongsTo association", function(assert) message: { data: { id: '1', - type: 'post' - } - } - } - } + type: 'post', + }, + }, + }, + }, }); }); return run(() => { return hash({ message: store.findRecord('post', 1), - comment: store.findRecord('comment', 2) + comment: store.findRecord('comment', 2), }).then(records => { assert.equal(records.comment.get('message'), records.message); }); }); }); -test("The store can serialize a polymorphic belongsTo association", function(assert) { +test('The store can serialize a polymorphic belongsTo association', function(assert) { env.adapter.shouldBackgroundReloadRecord = () => false; let serializerInstance = store.serializerFor('comment'); serializerInstance.serializePolymorphicType = function(record, json, relationship) { assert.ok(true, "The serializer's serializePolymorphicType method should be called"); - json["message_type"] = "post"; + json['message_type'] = 'post'; }; return run(() => { env.store.push({ data: { id: '1', - type: 'post' - } + type: 'post', + }, }); env.store.push({ @@ -403,11 +428,11 @@ test("The store can serialize a polymorphic belongsTo association", function(ass message: { data: { id: '1', - type: 'post' - } - } - } - } + type: 'post', + }, + }, + }, + }, }); return store.findRecord('comment', 2).then(comment => { @@ -418,14 +443,14 @@ test("The store can serialize a polymorphic belongsTo association", function(ass }); }); -test("A serializer can materialize a belongsTo as a link that gets sent back to findBelongsTo", function(assert) { +test('A serializer can materialize a belongsTo as a link that gets sent back to findBelongsTo', function(assert) { env.adapter.shouldBackgroundReloadRecord = () => false; let Group = DS.Model.extend({ - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); let Person = DS.Model.extend({ - group: DS.belongsTo({ async: true }) + group: DS.belongsTo({ async: true }), }); env.registry.register('model:group', Group); @@ -439,11 +464,11 @@ test("A serializer can materialize a belongsTo as a link that gets sent back to relationships: { group: { links: { - related: '/people/1/group' - } - } - } - } + related: '/people/1/group', + }, + }, + }, + }, }); }); @@ -454,7 +479,7 @@ test("A serializer can materialize a belongsTo as a link that gets sent back to env.adapter.findBelongsTo = function(store, snapshot, link, relationship) { assert.equal(relationship.type, 'group'); assert.equal(relationship.key, 'group'); - assert.equal(link, "/people/1/group"); + assert.equal(link, '/people/1/group'); return resolve({ data: { @@ -462,31 +487,34 @@ test("A serializer can materialize a belongsTo as a link that gets sent back to type: 'group', relationships: { people: { - data: [{ id: 1, type: 'person' }] - } - } - } + data: [{ id: 1, type: 'person' }], + }, + }, + }, }); }; return run(() => { - return env.store.findRecord('person', 1).then(person => { - return person.get('group'); - }).then(group => { - assert.ok(group instanceof Group, "A group object is loaded"); - assert.ok(group.get('id') === '1', 'It is the group we are expecting'); - }); + return env.store + .findRecord('person', 1) + .then(person => { + return person.get('group'); + }) + .then(group => { + assert.ok(group instanceof Group, 'A group object is loaded'); + assert.ok(group.get('id') === '1', 'It is the group we are expecting'); + }); }); }); test('A record with an async belongsTo relationship always returns a promise for that relationship', function(assert) { env.adapter.shouldBackgroundReloadRecord = () => false; let Seat = DS.Model.extend({ - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); let Person = DS.Model.extend({ - seat: DS.belongsTo('seat', { async: true }) + seat: DS.belongsTo('seat', { async: true }), }); env.registry.register('model:seat', Seat); @@ -500,11 +528,11 @@ test('A record with an async belongsTo relationship always returns a promise for relationships: { seat: { links: { - related: '/people/1/seat' - } - } - } - } + related: '/people/1/seat', + }, + }, + }, + }, }); }); @@ -528,16 +556,16 @@ test('A record with an async belongsTo relationship always returns a promise for }); }); -test("A record with an async belongsTo relationship returning null should resolve null", function(assert) { +test('A record with an async belongsTo relationship returning null should resolve null', function(assert) { assert.expect(1); env.adapter.shouldBackgroundReloadRecord = () => false; let Group = DS.Model.extend({ - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); let Person = DS.Model.extend({ - group: DS.belongsTo({ async: true }) + group: DS.belongsTo({ async: true }), }); env.registry.register('model:group', Group); @@ -551,11 +579,11 @@ test("A record with an async belongsTo relationship returning null should resolv relationships: { group: { links: { - related: '/people/1/group' - } - } - } - } + related: '/people/1/group', + }, + }, + }, + }, }); }); @@ -567,23 +595,26 @@ test("A record with an async belongsTo relationship returning null should resolv return resolve({ data: null }); }; - return env.store.findRecord('person', '1').then(person => { - return person.get('group'); - }).then(group => { - assert.ok(group === null, "group should be null"); - }); + return env.store + .findRecord('person', '1') + .then(person => { + return person.get('group'); + }) + .then(group => { + assert.ok(group === null, 'group should be null'); + }); }); -test("A record can be created with a resolved belongsTo promise", function(assert) { +test('A record can be created with a resolved belongsTo promise', function(assert) { assert.expect(1); env.adapter.shouldBackgroundReloadRecord = () => false; let Group = DS.Model.extend({ - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); let Person = DS.Model.extend({ - group: DS.belongsTo({ async: true }) + group: DS.belongsTo({ async: true }), }); env.registry.register('model:group', Group); @@ -593,21 +624,21 @@ test("A record can be created with a resolved belongsTo promise", function(asser store.push({ data: { id: 1, - type: 'group' - } + type: 'group', + }, }); }); let groupPromise = store.findRecord('group', 1); return groupPromise.then(group => { let person = env.store.createRecord('person', { - group: groupPromise + group: groupPromise, }); assert.equal(person.get('group.content'), group); }); }); -test("polymorphic belongsTo class-checks check the superclass when MODEL_FACTORY_INJECTIONS is enabled", function(assert) { +test('polymorphic belongsTo class-checks check the superclass when MODEL_FACTORY_INJECTIONS is enabled', function(assert) { assert.expect(1); run(() => { @@ -620,7 +651,7 @@ test("polymorphic belongsTo class-checks check the superclass when MODEL_FACTORY }); }); -test("the subclass in a polymorphic belongsTo relationship is an instanceof its superclass", function(assert) { +test('the subclass in a polymorphic belongsTo relationship is an instanceof its superclass', function(assert) { setupModelFactoryInjections(false); assert.expect(1); @@ -629,8 +660,7 @@ test("the subclass in a polymorphic belongsTo relationship is an instanceof its assert.ok(comment instanceof Message, 'a comment is an instance of a message'); }); -test("relationshipsByName does not cache a factory", function(assert) { - +test('relationshipsByName does not cache a factory', function(assert) { // The model is loaded up via a container. It has relationshipsByName // called on it. let modelViaFirstFactory = store.modelFor('user'); @@ -646,25 +676,28 @@ test("relationshipsByName does not cache a factory", function(assert) { // A new store is created. env = setupStore({ user: User, - message: NewMessage + message: NewMessage, }); store = env.store; // relationshipsByName is called again. let modelViaSecondFactory = store.modelFor('user'); - let relationshipsByName = get(modelViaSecondFactory, 'relationshipsByName'); - let messageType = relationshipsByName.get('messages').type; + let relationshipsByName = get(modelViaSecondFactory, 'relationshipsByName'); + let messageType = relationshipsByName.get('messages').type; // A model is looked up in the store based on a string, via user input - let messageModelFromStore = store.modelFor('message'); + let messageModelFromStore = store.modelFor('message'); // And the model is lookup up internally via the relationship type let messageModelFromRelationType = store.modelFor(messageType); - assert.equal(messageModelFromRelationType, messageModelFromStore, - "model factory based on relationship type matches the model based on store.modelFor"); + assert.equal( + messageModelFromRelationType, + messageModelFromStore, + 'model factory based on relationship type matches the model based on store.modelFor' + ); }); -test("relationship changes shouldn’t cause async fetches", function(assert) { +test('relationship changes shouldn’t cause async fetches', function(assert) { assert.expect(2); /* Scenario: @@ -683,12 +716,12 @@ test("relationship changes shouldn’t cause async fetches", function(assert) { env.store.modelFor('post').reopen({ comments: DS.hasMany('comment', { async: true, - inverse: 'post' - }) + inverse: 'post', + }), }); env.store.modelFor('comment').reopen({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); let comment; run(() => { @@ -698,19 +731,23 @@ test("relationship changes shouldn’t cause async fetches", function(assert) { type: 'post', relationships: { comments: { - data: [{ - id: '1', - type: 'comment' - }, { - id: '2', - type: 'comment' - }, { - id: '3', - type: 'comment' - }] - } - } - } + data: [ + { + id: '1', + type: 'comment', + }, + { + id: '2', + type: 'comment', + }, + { + id: '3', + type: 'comment', + }, + ], + }, + }, + }, }); comment = env.store.push({ @@ -721,11 +758,11 @@ test("relationship changes shouldn’t cause async fetches", function(assert) { post: { data: { id: '1', - type: 'post' - } - } - } - } + type: 'post', + }, + }, + }, + }, }); }); @@ -742,21 +779,21 @@ test("relationship changes shouldn’t cause async fetches", function(assert) { run(comment, 'destroyRecord'); }); -test("Destroying a record with an unloaded aync belongsTo association does not fetch the record", function(assert) { +test('Destroying a record with an unloaded aync belongsTo association does not fetch the record', function(assert) { assert.expect(2); let post; env.store.modelFor('message').reopen({ user: DS.hasMany('user', { - async: true - }) + async: true, + }), }); env.store.modelFor('post').reopen({ user: DS.belongsTo('user', { async: true, - inverse: 'messages' - }) + inverse: 'messages', + }), }); run(() => { @@ -768,11 +805,11 @@ test("Destroying a record with an unloaded aync belongsTo association does not f user: { data: { id: '2', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); }); @@ -789,24 +826,24 @@ test("Destroying a record with an unloaded aync belongsTo association does not f type: 'post', attributes: { title: null, - 'created-at': null + 'created-at': null, }, relationships: { user: { data: { id: '2', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }; }; run(post, 'destroyRecord'); }); -testInDebug("A sync belongsTo errors out if the record is unlaoded", function(assert) { +testInDebug('A sync belongsTo errors out if the record is unlaoded', function(assert) { let message; run(() => { message = env.store.push({ @@ -817,13 +854,12 @@ testInDebug("A sync belongsTo errors out if the record is unlaoded", function(as user: { data: { id: '2', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); - }); assert.expectAssertion(() => { @@ -831,9 +867,9 @@ testInDebug("A sync belongsTo errors out if the record is unlaoded", function(as }, /You looked up the 'user' relationship on a 'message' with id 1 but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async \(`DS.belongsTo\({ async: true }\)`\)/); }); -test("Rollbacking attributes for a deleted record restores implicit relationship - async", function(assert) { +test('Rollbacking attributes for a deleted record restores implicit relationship - async', function(assert) { Book.reopen({ - author: DS.belongsTo('author', { async: true }) + author: DS.belongsTo('author', { async: true }), }); let book, author; run(() => { @@ -842,28 +878,27 @@ test("Rollbacking attributes for a deleted record restores implicit relationship id: '1', type: 'book', attributes: { - name: "Stanley's Amazing Adventures" + name: "Stanley's Amazing Adventures", }, relationships: { author: { data: { id: '2', - type: 'author' - } - } - } - } + type: 'author', + }, + }, + }, + }, }); author = env.store.push({ data: { id: '2', type: 'author', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); - }); return run(() => { author.deleteRecord(); @@ -875,7 +910,7 @@ test("Rollbacking attributes for a deleted record restores implicit relationship }); }); -test("Rollbacking attributes for a deleted record restores implicit relationship - sync", function(assert) { +test('Rollbacking attributes for a deleted record restores implicit relationship - sync', function(assert) { let book, author; run(() => { @@ -884,17 +919,17 @@ test("Rollbacking attributes for a deleted record restores implicit relationship id: '1', type: 'book', attributes: { - name: "Stanley's Amazing Adventures" + name: "Stanley's Amazing Adventures", }, relationships: { author: { data: { id: '2', - type: 'author' - } - } - } - } + type: 'author', + }, + }, + }, + }, }); author = env.store.push({ @@ -902,13 +937,13 @@ test("Rollbacking attributes for a deleted record restores implicit relationship id: '2', type: 'author', attributes: { - name: "Stanley" - } - } + name: 'Stanley', + }, + }, }); }); - run(() =>{ + run(() => { author.deleteRecord(); author.rollbackAttributes(); }); @@ -916,23 +951,23 @@ test("Rollbacking attributes for a deleted record restores implicit relationship assert.equal(book.get('author'), author, 'Book has an author after rollback attributes'); }); -testInDebug("Passing a model as type to belongsTo should not work", function(assert) { +testInDebug('Passing a model as type to belongsTo should not work', function(assert) { assert.expect(1); assert.expectAssertion(() => { User = DS.Model.extend(); DS.Model.extend({ - user: belongsTo(User, { async: false }) + user: belongsTo(User, { async: false }), }); }, /The first argument to DS.belongsTo must be a string/); }); -test("belongsTo hasAnyRelationshipData async loaded", function(assert) { +test('belongsTo hasAnyRelationshipData async loaded', function(assert) { assert.expect(1); Book.reopen({ - author: belongsTo('author', { async: true }) + author: belongsTo('author', { async: true }), }); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -942,9 +977,9 @@ test("belongsTo hasAnyRelationshipData async loaded", function(assert) { type: 'book', attributes: { name: 'The Greatest Book' }, relationships: { - author: { data: { id: 2, type: 'author'} } - } - } + author: { data: { id: 2, type: 'author' } }, + }, + }, }); }; @@ -956,7 +991,7 @@ test("belongsTo hasAnyRelationshipData async loaded", function(assert) { }); }); -test("belongsTo hasAnyRelationshipData sync loaded", function(assert) { +test('belongsTo hasAnyRelationshipData sync loaded', function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -966,9 +1001,9 @@ test("belongsTo hasAnyRelationshipData sync loaded", function(assert) { type: 'book', attributes: { name: 'The Greatest Book' }, relationships: { - author: { data: { id: 2, type: 'author'} } - } - } + author: { data: { id: 2, type: 'author' } }, + }, + }, }); }; @@ -980,11 +1015,11 @@ test("belongsTo hasAnyRelationshipData sync loaded", function(assert) { }); }); -test("belongsTo hasAnyRelationshipData async not loaded", function(assert) { +test('belongsTo hasAnyRelationshipData async not loaded', function(assert) { assert.expect(1); Book.reopen({ - author: belongsTo('author', { async: true }) + author: belongsTo('author', { async: true }), }); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -994,9 +1029,9 @@ test("belongsTo hasAnyRelationshipData async not loaded", function(assert) { type: 'book', attributes: { name: 'The Greatest Book' }, relationships: { - author: { links: { related: 'author'} } - } - } + author: { links: { related: 'author' } }, + }, + }, }); }; @@ -1008,7 +1043,7 @@ test("belongsTo hasAnyRelationshipData async not loaded", function(assert) { }); }); -test("belongsTo hasAnyRelationshipData sync not loaded", function(assert) { +test('belongsTo hasAnyRelationshipData sync not loaded', function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -1016,10 +1051,10 @@ test("belongsTo hasAnyRelationshipData sync not loaded", function(assert) { data: { id: 1, type: 'book', - attributes: { name: 'The Greatest Book' } - } + attributes: { name: 'The Greatest Book' }, + }, }); - } + }; return run(() => { return store.findRecord('book', 1).then(book => { @@ -1029,11 +1064,11 @@ test("belongsTo hasAnyRelationshipData sync not loaded", function(assert) { }); }); -test("belongsTo hasAnyRelationshipData NOT created", function(assert) { +test('belongsTo hasAnyRelationshipData NOT created', function(assert) { assert.expect(2); Book.reopen({ - author: belongsTo('author', { async: true }) + author: belongsTo('author', { async: true }), }); run(() => { @@ -1045,7 +1080,7 @@ test("belongsTo hasAnyRelationshipData NOT created", function(assert) { book = store.createRecord('book', { name: 'The Greatest Book', - author + author, }); relationship = book._internalModel._relationships.get('author'); @@ -1054,13 +1089,13 @@ test("belongsTo hasAnyRelationshipData NOT created", function(assert) { }); }); -test("belongsTo hasAnyRelationshipData sync created", function(assert) { +test('belongsTo hasAnyRelationshipData sync created', function(assert) { assert.expect(2); run(() => { let author = store.createRecord('author'); let book = store.createRecord('book', { - name: 'The Greatest Book' + name: 'The Greatest Book', }); let relationship = book._internalModel._relationships.get('author'); @@ -1068,7 +1103,7 @@ test("belongsTo hasAnyRelationshipData sync created", function(assert) { book = store.createRecord('book', { name: 'The Greatest Book', - author + author, }); relationship = book._internalModel._relationships.get('author'); @@ -1083,11 +1118,14 @@ test("Model's belongsTo relationship should not be created during model creation user = env.store.push({ data: { id: '1', - type: 'user' - } + type: 'user', + }, }); - assert.ok(!user._internalModel._relationships.has('favouriteMessage'), 'Newly created record should not have relationships'); + assert.ok( + !user._internalModel._relationships.has('favouriteMessage'), + 'Newly created record should not have relationships' + ); }); }); @@ -1095,10 +1133,13 @@ test("Model's belongsTo relationship should be created during model creation if let message = env.store.createRecord('message'); let user = env.store.createRecord('user', { name: 'John Doe', - favouriteMessage: message + favouriteMessage: message, }); - assert.ok(user._internalModel._relationships.has('favouriteMessage'), "Newly created record with relationships in params passed in its constructor should have relationships"); + assert.ok( + user._internalModel._relationships.has('favouriteMessage'), + 'Newly created record with relationships in params passed in its constructor should have relationships' + ); }); test("Model's belongsTo relationship should be created during 'set' method", function(assert) { @@ -1108,7 +1149,10 @@ test("Model's belongsTo relationship should be created during 'set' method", fun message = env.store.createRecord('message'); user = env.store.createRecord('user'); user.set('favouriteMessage', message); - assert.ok(user._internalModel._relationships.has('favouriteMessage'), "Newly created record with relationships in params passed in its constructor should have relationships"); + assert.ok( + user._internalModel._relationships.has('favouriteMessage'), + 'Newly created record with relationships in params passed in its constructor should have relationships' + ); }); }); @@ -1118,15 +1162,18 @@ test("Model's belongsTo relationship should be created during 'get' method", fun run(() => { user = env.store.createRecord('user'); user.get('favouriteMessage'); - assert.ok(user._internalModel._relationships.has('favouriteMessage'), "Newly created record with relationships in params passed in its constructor should have relationships"); + assert.ok( + user._internalModel._relationships.has('favouriteMessage'), + 'Newly created record with relationships in params passed in its constructor should have relationships' + ); }); }); -test("Related link should be fetched when no relationship data is present", function(assert) { +test('Related link should be fetched when no relationship data is present', function(assert) { assert.expect(3); Book.reopen({ - author: DS.belongsTo('author', { async: true }) + author: DS.belongsTo('author', { async: true }), }); env.adapter.findBelongsTo = function(store, snapshot, url, relationship) { @@ -1136,8 +1183,8 @@ test("Related link should be fetched when no relationship data is present", func data: { id: '1', type: 'author', - attributes: { name: 'This is author' } - } + attributes: { name: 'This is author' }, + }, }); }; @@ -1149,11 +1196,11 @@ test("Related link should be fetched when no relationship data is present", func relationships: { author: { links: { - related: 'author' - } - } - } - } + related: 'author', + }, + }, + }, + }, }); return book.get('author').then(author => { @@ -1162,11 +1209,11 @@ test("Related link should be fetched when no relationship data is present", func }); }); -test("Related link should take precedence over relationship data if no local record data is available", function(assert) { +test('Related link should take precedence over relationship data if no local record data is available', function(assert) { assert.expect(2); Book.reopen({ - author: DS.belongsTo('author', { async: true }) + author: DS.belongsTo('author', { async: true }), }); env.adapter.findBelongsTo = function(store, snapshot, url, relationship) { @@ -1175,8 +1222,8 @@ test("Related link should take precedence over relationship data if no local rec data: { id: 1, type: 'author', - attributes: { name: 'This is author' } - } + attributes: { name: 'This is author' }, + }, }); }; @@ -1192,12 +1239,12 @@ test("Related link should take precedence over relationship data if no local rec relationships: { author: { links: { - related: 'author' + related: 'author', }, - data: { type: 'author', id: '1' } - } - } - } + data: { type: 'author', id: '1' }, + }, + }, + }, }); return book.get('author').then(author => { @@ -1206,14 +1253,16 @@ test("Related link should take precedence over relationship data if no local rec }); }); -test("Relationship data should take precedence over related link when local record data is available", function(assert) { +test('Relationship data should take precedence over related link when local record data is available', function(assert) { assert.expect(1); Book.reopen({ - author: DS.belongsTo('author', { async: true }) + author: DS.belongsTo('author', { async: true }), }); - env.adapter.shouldBackgroundReloadRecord = () => { return false; }; + env.adapter.shouldBackgroundReloadRecord = () => { + return false; + }; env.adapter.findBelongsTo = function(store, snapshot, url, relationship) { assert.ok(false, "The adapter's findBelongsTo method should not be called"); }; @@ -1230,19 +1279,19 @@ test("Relationship data should take precedence over related link when local reco relationships: { author: { links: { - related: 'author' + related: 'author', }, - data: { type: 'author', id: '1' } - } - } + data: { type: 'author', id: '1' }, + }, + }, }, included: [ { id: '1', type: 'author', - attributes: { name: 'This is author' } - } - ] + attributes: { name: 'This is author' }, + }, + ], }); return book.get('author').then(author => { @@ -1251,11 +1300,11 @@ test("Relationship data should take precedence over related link when local reco }); }); -test("New related link should take precedence over local data", function(assert) { +test('New related link should take precedence over local data', function(assert) { assert.expect(3); Book.reopen({ - author: DS.belongsTo('author', { async: true }) + author: DS.belongsTo('author', { async: true }), }); env.adapter.findBelongsTo = function(store, snapshot, url, relationship) { @@ -1265,8 +1314,8 @@ test("New related link should take precedence over local data", function(assert) data: { id: 1, type: 'author', - attributes: { name: 'This is author' } - } + attributes: { name: 'This is author' }, + }, }); }; @@ -1283,11 +1332,11 @@ test("New related link should take precedence over local data", function(assert) author: { data: { type: 'author', - id: '1' - } - } - } - } + id: '1', + }, + }, + }, + }, }); env.store.push({ @@ -1297,24 +1346,24 @@ test("New related link should take precedence over local data", function(assert) relationships: { author: { links: { - related: 'author-new-link' - } - } - } - } + related: 'author-new-link', + }, + }, + }, + }, }); - book.get('author').then((author) => { + book.get('author').then(author => { assert.equal(author.get('name'), 'This is author', 'author name is correct'); }); }); }); -test("Updated related link should take precedence over relationship data and local record data", function(assert) { +test('Updated related link should take precedence over relationship data and local record data', function(assert) { assert.expect(4); Book.reopen({ - author: DS.belongsTo('author', { async: true }) + author: DS.belongsTo('author', { async: true }), }); env.adapter.findBelongsTo = function(store, snapshot, url, relationship) { @@ -1325,9 +1374,9 @@ test("Updated related link should take precedence over relationship data and loc id: '1', type: 'author', attributes: { - name: 'This is updated author' - } - } + name: 'This is updated author', + }, + }, }); }; @@ -1343,53 +1392,55 @@ test("Updated related link should take precedence over relationship data and loc relationships: { author: { links: { - related: 'author' + related: 'author', }, - data: { type: 'author', id: '1' } - } - } + data: { type: 'author', id: '1' }, + }, + }, }, included: [ { type: 'author', id: '1', attributes: { - name: 'This is author' - } - } - ] + name: 'This is author', + }, + }, + ], }); - return book.get('author').then((author) => { - assert.equal(author.get('name'), 'This is author', 'author name is correct'); - }).then(() => { - - env.store.push({ - data: { - type: 'book', - id: '1', - relationships: { - author: { - links: { - related: 'author-updated-link' - } - } - } - } - }); + return book + .get('author') + .then(author => { + assert.equal(author.get('name'), 'This is author', 'author name is correct'); + }) + .then(() => { + env.store.push({ + data: { + type: 'book', + id: '1', + relationships: { + author: { + links: { + related: 'author-updated-link', + }, + }, + }, + }, + }); - return book.get('author').then((author) => { - assert.equal(author.get('name'), 'This is updated author', 'author name is correct'); + return book.get('author').then(author => { + assert.equal(author.get('name'), 'This is updated author', 'author name is correct'); + }); }); - }); }); }); -test("Updated identical related link should not take precedence over local data", function(assert) { +test('Updated identical related link should not take precedence over local data', function(assert) { assert.expect(2); Book.reopen({ - author: DS.belongsTo('author', { async: true }) + author: DS.belongsTo('author', { async: true }), }); env.adapter.findBelongsTo = function() { @@ -1408,49 +1459,53 @@ test("Updated identical related link should not take precedence over local data" relationships: { author: { links: { - related: 'author' + related: 'author', }, - data: { type: 'author', id: '1' } - } - } + data: { type: 'author', id: '1' }, + }, + }, }, - included: [{ - type: 'author', - id: '1', - attributes: { - name: 'This is author' - } - }] - }); - - return book.get('author').then((author) => { - assert.equal(author.get('name'), 'This is author', 'author name is correct'); - }).then(() => { - - env.store.push({ - data: { - type: 'book', + included: [ + { + type: 'author', id: '1', - relationships: { - author: { - links: { - related: 'author' - } - } - } - } - }); + attributes: { + name: 'This is author', + }, + }, + ], + }); - return book.get('author').then((author) => { + return book + .get('author') + .then(author => { assert.equal(author.get('name'), 'This is author', 'author name is correct'); + }) + .then(() => { + env.store.push({ + data: { + type: 'book', + id: '1', + relationships: { + author: { + links: { + related: 'author', + }, + }, + }, + }, + }); + + return book.get('author').then(author => { + assert.equal(author.get('name'), 'This is author', 'author name is correct'); + }); }); - }); }); }); -test("A belongsTo relationship can be reloaded using the reference if it was fetched via link", function(assert) { +test('A belongsTo relationship can be reloaded using the reference if it was fetched via link', function(assert) { Chapter.reopen({ - book: DS.belongsTo({ async: true }) + book: DS.belongsTo({ async: true }), }); env.adapter.findRecord = function() { @@ -1460,10 +1515,10 @@ test("A belongsTo relationship can be reloaded using the reference if it was fet type: 'chapter', relationships: { book: { - links: { related: '/books/1' } - } - } - } + links: { related: '/books/1' }, + }, + }, + }, }); }; @@ -1472,41 +1527,45 @@ test("A belongsTo relationship can be reloaded using the reference if it was fet data: { id: 1, type: 'book', - attributes: { name: "book title" } - } + attributes: { name: 'book title' }, + }, }); }; return run(() => { let chapter; - return store.findRecord('chapter', 1).then(_chapter => { - chapter = _chapter; + return store + .findRecord('chapter', 1) + .then(_chapter => { + chapter = _chapter; - return chapter.get('book'); - }).then(book => { - assert.equal(book.get('name'), "book title"); + return chapter.get('book'); + }) + .then(book => { + assert.equal(book.get('name'), 'book title'); - env.adapter.findBelongsTo = function() { - return resolve({ - data: { - id: 1, - type: 'book', - attributes: { name: "updated book title" } - } - }); - }; + env.adapter.findBelongsTo = function() { + return resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: 'updated book title' }, + }, + }); + }; - return chapter.belongsTo('book').reload(); - }).then(book => { - assert.equal(book.get('name'), "updated book title"); - }); + return chapter.belongsTo('book').reload(); + }) + .then(book => { + assert.equal(book.get('name'), 'updated book title'); + }); }); }); -test("A synchronous belongsTo relationship can be reloaded using a reference if it was fetched via id", function(assert) { +test('A synchronous belongsTo relationship can be reloaded using a reference if it was fetched via id', function(assert) { Chapter.reopen({ - book: DS.belongsTo({ async: false }) + book: DS.belongsTo({ async: false }), }); let chapter; @@ -1517,19 +1576,19 @@ test("A synchronous belongsTo relationship can be reloaded using a reference if id: '1', relationships: { book: { - data: { type: 'book', id: '1' } - } - } - } + data: { type: 'book', id: '1' }, + }, + }, + }, }); env.store.push({ data: { type: 'book', id: '1', attributes: { - name: "book title" - } - } + name: 'book title', + }, + }, }); }); @@ -1538,24 +1597,27 @@ test("A synchronous belongsTo relationship can be reloaded using a reference if data: { id: '1', type: 'book', - attributes: { name: 'updated book title' } - } + attributes: { name: 'updated book title' }, + }, }); }; return run(() => { let book = chapter.get('book'); - assert.equal(book.get('name'), "book title"); + assert.equal(book.get('name'), 'book title'); - return chapter.belongsTo('book').reload().then(function(book) { - assert.equal(book.get('name'), "updated book title"); - }); + return chapter + .belongsTo('book') + .reload() + .then(function(book) { + assert.equal(book.get('name'), 'updated book title'); + }); }); }); -test("A belongsTo relationship can be reloaded using a reference if it was fetched via id", function(assert) { +test('A belongsTo relationship can be reloaded using a reference if it was fetched via id', function(assert) { Chapter.reopen({ - book: DS.belongsTo({ async: true }) + book: DS.belongsTo({ async: true }), }); let chapter; @@ -1566,10 +1628,10 @@ test("A belongsTo relationship can be reloaded using a reference if it was fetch id: 1, relationships: { book: { - data: { type: 'book', id: 1 } - } - } - } + data: { type: 'book', id: 1 }, + }, + }, + }, }); }); @@ -1578,54 +1640,60 @@ test("A belongsTo relationship can be reloaded using a reference if it was fetch data: { id: 1, type: 'book', - attributes: { name: "book title" } - } + attributes: { name: 'book title' }, + }, }); }; return run(() => { - return chapter.get('book').then(book => { - assert.equal(book.get('name'), "book title"); + return chapter + .get('book') + .then(book => { + assert.equal(book.get('name'), 'book title'); - env.adapter.findRecord = function() { - return resolve({ - data: { - id: 1, - type: 'book', - attributes: { name: "updated book title" } - } - }); - }; + env.adapter.findRecord = function() { + return resolve({ + data: { + id: 1, + type: 'book', + attributes: { name: 'updated book title' }, + }, + }); + }; - return chapter.belongsTo('book').reload(); - }).then(book => { - assert.equal(book.get('name'), "updated book title"); - }); + return chapter.belongsTo('book').reload(); + }) + .then(book => { + assert.equal(book.get('name'), 'updated book title'); + }); }); }); -testInDebug("A belongsTo relationship warns if malformatted data is pushed into the store", function(assert) { - assert.expectAssertion(() => { - run(() => { - let chapter = env.store.push({ - data: { - type: 'chapter', - id: 1, - relationships: { - book: { - data: { id: 1, name: 'The Gallic Wars' } - } - } - } +testInDebug( + 'A belongsTo relationship warns if malformatted data is pushed into the store', + function(assert) { + assert.expectAssertion(() => { + run(() => { + let chapter = env.store.push({ + data: { + type: 'chapter', + id: 1, + relationships: { + book: { + data: { id: 1, name: 'The Gallic Wars' }, + }, + }, + }, + }); + chapter.get('book'); }); - chapter.get('book'); - }); - }, /Encountered a relationship identifier without a type for the belongsTo relationship 'book' on , expected a json-api identifier with type 'book'/); -}); + }, /Encountered a relationship identifier without a type for the belongsTo relationship 'book' on , expected a json-api identifier with type 'book'/); + } +); test("belongsTo relationship with links doesn't trigger extra change notifications - #4942", function(assert) { Chapter.reopen({ - book: DS.belongsTo({ async: true }) + book: DS.belongsTo({ async: true }), }); run(() => { @@ -1636,11 +1704,11 @@ test("belongsTo relationship with links doesn't trigger extra change notificatio relationships: { book: { data: { type: 'book', id: '1' }, - links: { related: '/chapter/1/book' } - } - } + links: { related: '/chapter/1/book' }, + }, + }, }, - included: [{ type: 'book', id: '1' }] + included: [{ type: 'book', id: '1' }], }); }); diff --git a/tests/integration/relationships/has-many-test.js b/tests/integration/relationships/has-many-test.js index 4f5c0414a6b..ac4efc97327 100644 --- a/tests/integration/relationships/has-many-test.js +++ b/tests/integration/relationships/has-many-test.js @@ -2,17 +2,11 @@ import { setup as setupModelFactoryInjections, - reset as resetModelFactoryInjections + reset as resetModelFactoryInjections, } from 'dummy/tests/helpers/model-factory-injection'; import { A } from '@ember/array'; -import { - resolve, - Promise as EmberPromise, - all, - reject, - hash -} from 'rsvp'; +import { resolve, Promise as EmberPromise, all, reject, hash } from 'rsvp'; import { get } from '@ember/object'; import { run } from '@ember/runloop'; @@ -28,62 +22,62 @@ let Book, Chapter, Page; const { attr, hasMany, belongsTo } = DS; -module("integration/relationships/has_many - Has-Many Relationships", { +module('integration/relationships/has_many - Has-Many Relationships', { beforeEach() { User = DS.Model.extend({ name: attr('string'), messages: hasMany('message', { polymorphic: true, async: false }), - contacts: hasMany('user', { inverse: null, async: false }) + contacts: hasMany('user', { inverse: null, async: false }), }); Contact = DS.Model.extend({ - user: belongsTo('user', { async: false }) + user: belongsTo('user', { async: false }), }); Contact.reopenClass({ toString: () => 'Contact' }); Email = Contact.extend({ - email: attr('string') + email: attr('string'), }); Email.reopenClass({ toString: () => 'Email' }); Phone = Contact.extend({ - number: attr('string') + number: attr('string'), }); Phone.reopenClass({ toString: () => 'Phone' }); Message = DS.Model.extend({ user: belongsTo('user', { async: false }), - created_at: attr('date') + created_at: attr('date'), }); Message.reopenClass({ toString: () => 'Message' }); Post = Message.extend({ title: attr('string'), - comments: hasMany('comment', { async: false }) + comments: hasMany('comment', { async: false }), }); Post.reopenClass({ toString: () => 'Post' }); Comment = Message.extend({ body: DS.attr('string'), - message: DS.belongsTo('post', { polymorphic: true, async: true }) + message: DS.belongsTo('post', { polymorphic: true, async: true }), }); Comment.reopenClass({ toString: () => 'Comment' }); Book = DS.Model.extend({ title: attr(), - chapters: hasMany('chapter', { async: true }) + chapters: hasMany('chapter', { async: true }), }); Book.reopenClass({ toString: () => 'Book' }); Chapter = DS.Model.extend({ title: attr(), - pages: hasMany('page', { async: false }) + pages: hasMany('page', { async: false }), }); Chapter.reopenClass({ toString: () => 'Chapter' }); Page = DS.Model.extend({ number: attr('number'), - chapter: belongsTo('chapter', { async: false }) + chapter: belongsTo('chapter', { async: false }), }); Page.reopenClass({ toString: () => 'Page' }); @@ -97,7 +91,7 @@ module("integration/relationships/has_many - Has-Many Relationships", { message: Message, book: Book, chapter: Chapter, - page: Page + page: Page, }); store = env.store; @@ -105,59 +99,49 @@ module("integration/relationships/has_many - Has-Many Relationships", { afterEach() { run(env.container, 'destroy'); - } + }, }); -testInDebug("Invalid hasMany relationship identifiers throw errors", function(assert) { +testInDebug('Invalid hasMany relationship identifiers throw errors', function(assert) { assert.expect(2); let { store } = env; // test null id - assert.expectAssertion( - () => { - run(() => { - let post = store.push({ - data: { - id: '1', - type: 'post', - relationships: { - comments: { - data: [ - { id: null, type: 'comment' } - ] - } - } - } - }); - - post.get('comments'); + assert.expectAssertion(() => { + run(() => { + let post = store.push({ + data: { + id: '1', + type: 'post', + relationships: { + comments: { + data: [{ id: null, type: 'comment' }], + }, + }, + }, }); - }, - `Assertion Failed: Encountered a relationship identifier without an id for the hasMany relationship 'comments' on , expected a json-api identifier but found '{"id":null,"type":"comment"}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.` - ); + + post.get('comments'); + }); + }, `Assertion Failed: Encountered a relationship identifier without an id for the hasMany relationship 'comments' on , expected a json-api identifier but found '{"id":null,"type":"comment"}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`); // test missing type - assert.expectAssertion( - () => { - run(() => { - let post = store.push({ - data: { - id: '2', - type: 'post', - relationships: { - comments: { - data: [ - { id: '1', type: null } - ] - } - } - } - }); - post.get('comments') + assert.expectAssertion(() => { + run(() => { + let post = store.push({ + data: { + id: '2', + type: 'post', + relationships: { + comments: { + data: [{ id: '1', type: null }], + }, + }, + }, }); - }, - `Assertion Failed: Encountered a relationship identifier without a type for the hasMany relationship 'comments' on , expected a json-api identifier with type 'comment' but found '{"id":"1","type":null}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.` - ); + post.get('comments'); + }); + }, `Assertion Failed: Encountered a relationship identifier without a type for the hasMany relationship 'comments' on , expected a json-api identifier with type 'comment' but found '{"id":"1","type":null}'. Please check your serializer and make sure it is serializing the relationship payload into a JSON API format.`); }); test("When a hasMany relationship is accessed, the adapter's findMany method should not be called if all the records in the relationship are already loaded", function(assert) { @@ -168,11 +152,9 @@ test("When a hasMany relationship is accessed, the adapter's findMany method sho id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '1' } - ] - } - } + data: [{ type: 'comment', id: '1' }], + }, + }, }; env.adapter.findMany = function(store, type, ids, snapshots) { @@ -186,10 +168,12 @@ test("When a hasMany relationship is accessed, the adapter's findMany method sho return run(() => { env.store.push({ data: postData, - included: [{ - type: 'comment', - id: '1' - }] + included: [ + { + type: 'comment', + id: '1', + }, + ], }); return env.store.findRecord('post', 1).then(post => { @@ -198,33 +182,33 @@ test("When a hasMany relationship is accessed, the adapter's findMany method sho }); }); -test("hasMany + canonical vs currentState + destroyRecord ", function(assert) { +test('hasMany + canonical vs currentState + destroyRecord ', function(assert) { assert.expect(6); let postData = { type: 'user', id: '1', attributes: { - name: 'omg' + name: 'omg', }, relationships: { contacts: { data: [ { type: 'user', - id: 2 + id: 2, }, { type: 'user', - id: 3 + id: 3, }, { type: 'user', - id: 4 - } - ] - } - } + id: 4, + }, + ], + }, + }, }; run(() => { @@ -233,17 +217,17 @@ test("hasMany + canonical vs currentState + destroyRecord ", function(assert) { included: [ { type: 'user', - id: 2 + id: 2, }, { type: 'user', - id: 3 + id: 3, }, { type: 'user', - id: 4 - } - ] + id: 4, + }, + ], }); }); @@ -254,7 +238,11 @@ test("hasMany + canonical vs currentState + destroyRecord ", function(assert) { return { data: { type: 'user', id: 2 } }; }; - assert.deepEqual(contacts.map(c => c.get('id')), ['2','3','4'], 'user should have expected contacts'); + assert.deepEqual( + contacts.map(c => c.get('id')), + ['2', '3', '4'], + 'user should have expected contacts' + ); run(() => { contacts.addObject(env.store.createRecord('user', { id: 5 })); @@ -262,51 +250,63 @@ test("hasMany + canonical vs currentState + destroyRecord ", function(assert) { contacts.addObject(env.store.createRecord('user', { id: 7 })); }); - assert.deepEqual(contacts.map(c => c.get('id')), ['2','3','4','5','6','7'], 'user should have expected contacts'); + assert.deepEqual( + contacts.map(c => c.get('id')), + ['2', '3', '4', '5', '6', '7'], + 'user should have expected contacts' + ); run(() => { env.store.peekRecord('user', 2).destroyRecord(); env.store.peekRecord('user', 6).destroyRecord(); }); - assert.deepEqual(contacts.map(c => c.get('id')), ['3','4','5','7'], `user's contacts should have expected contacts`); + assert.deepEqual( + contacts.map(c => c.get('id')), + ['3', '4', '5', '7'], + `user's contacts should have expected contacts` + ); assert.equal(contacts, user.get('contacts')); run(() => { contacts.addObject(env.store.createRecord('user', { id: 8 })); }); - assert.deepEqual(contacts.map(c => c.get('id')), ['3','4','5','7','8'], `user's contacts should have expected contacts`); + assert.deepEqual( + contacts.map(c => c.get('id')), + ['3', '4', '5', '7', '8'], + `user's contacts should have expected contacts` + ); assert.equal(contacts, user.get('contacts')); }); -test("hasMany + canonical vs currentState + unloadRecord", function(assert) { +test('hasMany + canonical vs currentState + unloadRecord', function(assert) { assert.expect(6); let postData = { type: 'user', id: '1', attributes: { - name: 'omg' + name: 'omg', }, relationships: { contacts: { data: [ { type: 'user', - id: 2 + id: 2, }, { type: 'user', - id: 3 + id: 3, }, { type: 'user', - id: 4 - } - ] - } - } + id: 4, + }, + ], + }, + }, }; run(() => { @@ -315,17 +315,17 @@ test("hasMany + canonical vs currentState + unloadRecord", function(assert) { included: [ { type: 'user', - id: 2 + id: 2, }, { type: 'user', - id: 3 + id: 3, }, { type: 'user', - id: 4 - } - ] + id: 4, + }, + ], }); }); @@ -336,7 +336,11 @@ test("hasMany + canonical vs currentState + unloadRecord", function(assert) { return { data: { type: 'user', id: 2 } }; }; - assert.deepEqual(contacts.map(c => c.get('id')), ['2','3','4'], 'user should have expected contacts'); + assert.deepEqual( + contacts.map(c => c.get('id')), + ['2', '3', '4'], + 'user should have expected contacts' + ); run(() => { contacts.addObject(env.store.createRecord('user', { id: 5 })); @@ -344,25 +348,37 @@ test("hasMany + canonical vs currentState + unloadRecord", function(assert) { contacts.addObject(env.store.createRecord('user', { id: 7 })); }); - assert.deepEqual(contacts.map(c => c.get('id')), ['2','3','4','5','6','7'], 'user should have expected contacts'); + assert.deepEqual( + contacts.map(c => c.get('id')), + ['2', '3', '4', '5', '6', '7'], + 'user should have expected contacts' + ); run(() => { env.store.peekRecord('user', 2).unloadRecord(); env.store.peekRecord('user', 6).unloadRecord(); }); - assert.deepEqual(contacts.map(c => c.get('id')), ['3','4','5','7'], `user's contacts should have expected contacts`); + assert.deepEqual( + contacts.map(c => c.get('id')), + ['3', '4', '5', '7'], + `user's contacts should have expected contacts` + ); assert.equal(contacts, user.get('contacts')); run(() => { contacts.addObject(env.store.createRecord('user', { id: 8 })); }); - assert.deepEqual(contacts.map(c => c.get('id')), ['3','4','5','7','8'], `user's contacts should have expected contacts`); + assert.deepEqual( + contacts.map(c => c.get('id')), + ['3', '4', '5', '7', '8'], + `user's contacts should have expected contacts` + ); assert.equal(contacts, user.get('contacts')); }); -test("adapter.findMany only gets unique IDs even if duplicate IDs are present in the hasMany relationship", function(assert) { +test('adapter.findMany only gets unique IDs even if duplicate IDs are present in the hasMany relationship', function(assert) { assert.expect(2); let bookData = { @@ -373,10 +389,10 @@ test("adapter.findMany only gets unique IDs even if duplicate IDs are present in data: [ { type: 'chapter', id: '2' }, { type: 'chapter', id: '3' }, - { type: 'chapter', id: '3' } - ] - } - } + { type: 'chapter', id: '3' }, + ], + }, + }, }; env.adapter.findMany = function(store, type, ids, snapshots) { @@ -386,8 +402,8 @@ test("adapter.findMany only gets unique IDs even if duplicate IDs are present in return resolve({ data: [ { id: 2, type: 'chapter', attributes: { title: 'Chapter One' } }, - { id: 3, type: 'chapter', attributes: { title: 'Chapter Two' } } - ] + { id: 3, type: 'chapter', attributes: { title: 'Chapter Two' } }, + ], }); }; @@ -397,7 +413,7 @@ test("adapter.findMany only gets unique IDs even if duplicate IDs are present in return run(() => { env.store.push({ - data: bookData + data: bookData, }); return env.store.findRecord('book', 1).then(book => { @@ -412,14 +428,14 @@ test("adapter.findMany only gets unique IDs even if duplicate IDs are present in // is loaded later. test("A serializer can materialize a hasMany as an opaque token that can be lazily fetched via the adapter's findHasMany hook", function(assert) { Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); // When the store asks the adapter for the record with ID 1, // provide some fake data. env.adapter.findRecord = function(store, type, id, snapshot) { - assert.equal(type, Post, "find type was Post"); - assert.equal(id, "1", "find id was 1"); + assert.equal(type, Post, 'find type was Post'); + assert.equal(id, '1', 'find id was 1'); return resolve({ data: { @@ -428,11 +444,11 @@ test("A serializer can materialize a hasMany as an opaque token that can be lazi relationships: { comments: { links: { - related: "/posts/1/comments" - } - } - } - } + related: '/posts/1/comments', + }, + }, + }, + }, }); }; //({ id: 1, links: { comments: "/posts/1/comments" } }); @@ -442,37 +458,40 @@ test("A serializer can materialize a hasMany as an opaque token that can be lazi }; env.adapter.findHasMany = function(store, snapshot, link, relationship) { - assert.equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments"); - assert.equal(relationship.type, "comment", "relationship was passed correctly"); + assert.equal(link, '/posts/1/comments', 'findHasMany link was /posts/1/comments'); + assert.equal(relationship.type, 'comment', 'relationship was passed correctly'); return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ] + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], }); }; return run(() => { - return env.store.findRecord('post', 1).then(post => { - return post.get('comments'); - }).then(comments => { - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(comments.get('length'), 2, "comments have 2 length"); - assert.equal(comments.objectAt(0).get('body'), 'First', "comment loaded successfully"); - }); + return env.store + .findRecord('post', 1) + .then(post => { + return post.get('comments'); + }) + .then(comments => { + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(comments.get('length'), 2, 'comments have 2 length'); + assert.equal(comments.objectAt(0).get('body'), 'First', 'comment loaded successfully'); + }); }); }); -test("Accessing a hasMany backed by a link multiple times triggers only one request", function(assert) { +test('Accessing a hasMany backed by a link multiple times triggers only one request', function(assert) { assert.expect(2); let count = 0; Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); Comment.reopen({ - message: DS.belongsTo('post', { async: true }) + message: DS.belongsTo('post', { async: true }), }); let post; @@ -484,25 +503,25 @@ test("Accessing a hasMany backed by a link multiple times triggers only one requ relationships: { comments: { links: { - related: '/posts/1/comments' - } - } - } - } + related: '/posts/1/comments', + }, + }, + }, + }, }); post = env.store.peekRecord('post', 1); }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { count++; - assert.equal(count, 1, "findHasMany has only been called once"); + assert.equal(count, 1, 'findHasMany has only been called once'); return new EmberPromise((resolve, reject) => { setTimeout(() => { let value = { data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ] + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], }; resolve(value); }, 100); @@ -520,38 +539,39 @@ test("Accessing a hasMany backed by a link multiple times triggers only one requ id: '1', relationships: { message: { - data: { type: 'post', id: '1' } - } - } - } + data: { type: 'post', id: '1' }, + }, + }, + }, }); promise2 = post.get('comments'); }); - return all([ - promise1, - promise2 - ]).then(() => { - assert.equal(promise1.get('promise'), promise2.get('promise'), "Same promise is returned both times"); - }) + return all([promise1, promise2]).then(() => { + assert.equal( + promise1.get('promise'), + promise2.get('promise'), + 'Same promise is returned both times' + ); + }); }); -test("A hasMany backed by a link remains a promise after a record has been added to it", function(assert) { +test('A hasMany backed by a link remains a promise after a record has been added to it', function(assert) { assert.expect(1); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); Comment.reopen({ - message: DS.belongsTo('post', { async: true }) + message: DS.belongsTo('post', { async: true }), }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ] + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], }); }; let post; @@ -563,11 +583,11 @@ test("A hasMany backed by a link remains a promise after a record has been added relationships: { comments: { links: { - related: '/posts/1/comments' - } - } - } - } + related: '/posts/1/comments', + }, + }, + }, + }, }); post = env.store.peekRecord('post', 1); }); @@ -580,10 +600,10 @@ test("A hasMany backed by a link remains a promise after a record has been added id: '3', relationships: { message: { - data: { type: 'post', id: '1' } - } - } - } + data: { type: 'post', id: '1' }, + }, + }, + }, }); return post.get('comments').then(() => { @@ -593,13 +613,13 @@ test("A hasMany backed by a link remains a promise after a record has been added }); }); -test("A hasMany updated link should not remove new children", function(assert) { +test('A hasMany updated link should not remove new children', function(assert) { Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); Comment.reopen({ - message: DS.belongsTo('post', { async: true }) + message: DS.belongsTo('post', { async: true }), }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { @@ -613,10 +633,10 @@ test("A hasMany updated link should not remove new children", function(assert) { type: 'post', relationships: { comments: { - links: { related: '/some/link' } - } - } - } + links: { related: '/some/link' }, + }, + }, + }, }); }; @@ -624,7 +644,8 @@ test("A hasMany updated link should not remove new children", function(assert) { let post = env.store.createRecord('post', {}); env.store.createRecord('comment', { message: post }); - return post.get('comments') + return post + .get('comments') .then(comments => { assert.equal(comments.get('length'), 1, 'initially we have one comment'); @@ -637,19 +658,19 @@ test("A hasMany updated link should not remove new children", function(assert) { }); }); -test("A hasMany updated link should not remove new children when the parent record has children already", function(assert) { +test('A hasMany updated link should not remove new children when the parent record has children already', function(assert) { Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); Comment.reopen({ - message: DS.belongsTo('post', { async: true }) + message: DS.belongsTo('post', { async: true }), }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return resolve({ data: [ - { id: 5, type: 'comment', attributes: { body: 'hello' } } - ]}); + return resolve({ + data: [{ id: 5, type: 'comment', attributes: { body: 'hello' } }], + }); }; env.adapter.createRecord = function(store, snapshot, link, relationship) { @@ -659,10 +680,10 @@ test("A hasMany updated link should not remove new children when the parent reco type: 'post', relationships: { comments: { - links: { related: '/some/link' } - } - } - } + links: { related: '/some/link' }, + }, + }, + }, }); }; @@ -670,12 +691,13 @@ test("A hasMany updated link should not remove new children when the parent reco let post = env.store.createRecord('post', {}); env.store.createRecord('comment', { message: post }); - return post.get('comments') + return post + .get('comments') .then(comments => { assert.equal(comments.get('length'), 1); return post.save(); }) - .then(() =>post.get('comments')) + .then(() => post.get('comments')) .then(comments => { assert.equal(comments.get('length'), 2); }); @@ -683,13 +705,12 @@ test("A hasMany updated link should not remove new children when the parent reco }); test("A hasMany relationship doesn't contain duplicate children, after the canonical state of the relationship is updated via store#push", function(assert) { - Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); Comment.reopen({ - message: DS.belongsTo('post', { async: true }) + message: DS.belongsTo('post', { async: true }), }); env.adapter.createRecord = function(store, snapshot, link, relationship) { @@ -703,7 +724,8 @@ test("A hasMany relationship doesn't contain duplicate children, after the canon // relationship of post let localComment = env.store.createRecord('comment', { id: 'local', message: post }); - return post.get('comments') + return post + .get('comments') .then(comments => { assert.equal(comments.get('length'), 1); assert.equal(localComment.get('isNew'), true); @@ -711,7 +733,6 @@ test("A hasMany relationship doesn't contain duplicate children, after the canon return post.save(); }) .then(() => { - // Now the post is saved but the locally created comment with the id // 'local' is still in the created state since it hasn't been saved // yet. @@ -730,14 +751,11 @@ test("A hasMany relationship doesn't contain duplicate children, after the canon id: 1, relationships: { comments: { - data: [ - { id: 'local', type: 'comment' } - ] - } - } - } + data: [{ id: 'local', type: 'comment' }], + }, + }, + }, }); - }) .then(() => post.get('comments')) .then(comments => { @@ -747,15 +765,14 @@ test("A hasMany relationship doesn't contain duplicate children, after the canon }); }); - -test("A hasMany relationship can be reloaded if it was fetched via a link", function(assert) { +test('A hasMany relationship can be reloaded if it was fetched via a link', function(assert) { Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findRecord = function(store, type, id, snapshot) { - assert.equal(type, Post, "find type was Post"); - assert.equal(id, "1", "find id was 1"); + assert.equal(type, Post, 'find type was Post'); + assert.equal(id, '1', 'find id was 1'); return resolve({ data: { @@ -763,58 +780,65 @@ test("A hasMany relationship can be reloaded if it was fetched via a link", func type: 'post', relationships: { comments: { - links: { related: "/posts/1/comments" } - } - } - } + links: { related: '/posts/1/comments' }, + }, + }, + }, }); }; env.adapter.findHasMany = function(store, snapshot, link, relationship) { - assert.equal(relationship.type, 'comment', "findHasMany relationship type was Comment"); - assert.equal(relationship.key, 'comments', "findHasMany relationship key was comments"); - assert.equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments"); + assert.equal(relationship.type, 'comment', 'findHasMany relationship type was Comment'); + assert.equal(relationship.key, 'comments', 'findHasMany relationship key was comments'); + assert.equal(link, '/posts/1/comments', 'findHasMany link was /posts/1/comments'); - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; run(function() { - run(env.store, 'findRecord', 'post', 1).then(function(post) { - return post.get('comments'); - }).then(function(comments) { - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(comments.get('length'), 2, "comments have 2 length"); + run(env.store, 'findRecord', 'post', 1) + .then(function(post) { + return post.get('comments'); + }) + .then(function(comments) { + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(comments.get('length'), 2, 'comments have 2 length'); - env.adapter.findHasMany = function(store, snapshot, link, relationship) { - assert.equal(relationship.type, 'comment', "findHasMany relationship type was Comment"); - assert.equal(relationship.key, 'comments', "findHasMany relationship key was comments"); - assert.equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments"); + env.adapter.findHasMany = function(store, snapshot, link, relationship) { + assert.equal(relationship.type, 'comment', 'findHasMany relationship type was Comment'); + assert.equal(relationship.key, 'comments', 'findHasMany relationship key was comments'); + assert.equal(link, '/posts/1/comments', 'findHasMany link was /posts/1/comments'); - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } }, - { id: 3, type: 'comment', attributes: { body: "Thirds" } } - ]}); - }; + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + { id: 3, type: 'comment', attributes: { body: 'Thirds' } }, + ], + }); + }; - return comments.reload(); - }).then(function(newComments) { - assert.equal(newComments.get('length'), 3, "reloaded comments have 3 length"); - }); + return comments.reload(); + }) + .then(function(newComments) { + assert.equal(newComments.get('length'), 3, 'reloaded comments have 3 length'); + }); }); }); -test("A sync hasMany relationship can be reloaded if it was fetched via ids", function(assert) { +test('A sync hasMany relationship can be reloaded if it was fetched via ids', function(assert) { Post.reopen({ - comments: DS.hasMany('comment', { async: false }) + comments: DS.hasMany('comment', { async: false }), }); env.adapter.findRecord = function(store, type, id, snapshot) { - assert.equal(type, Post, "find type was Post"); - assert.equal(id, "1", "find id was 1"); + assert.equal(type, Post, 'find type was Post'); + assert.equal(id, '1', 'find id was 1'); return resolve({ data: { @@ -822,60 +846,69 @@ test("A sync hasMany relationship can be reloaded if it was fetched via ids", fu type: 'post', relationships: { comments: { - data: [ - { id: 1, type: 'comment' }, - { id: 2, type: 'comment' } - ] - } - } - } + data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }], + }, + }, + }, }); }; run(function() { env.store.push({ - data: [{ - type: 'comment', - id: '1', - attributes: { - body: 'First' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'Second' - } - }] + data: [ + { + type: 'comment', + id: '1', + attributes: { + body: 'First', + }, + }, + { + type: 'comment', + id: '2', + attributes: { + body: 'Second', + }, + }, + ], }); - env.store.findRecord('post', '1').then(function(post) { - let comments = post.get('comments'); - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(comments.get('length'), 2, "comments have a length of 2"); + env.store + .findRecord('post', '1') + .then(function(post) { + let comments = post.get('comments'); + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(comments.get('length'), 2, 'comments have a length of 2'); - env.adapter.findMany = function(store, type, ids, snapshots) { - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); - }; + env.adapter.findMany = function(store, type, ids, snapshots) { + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'FirstUpdated' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); + }; - return comments.reload(); - }).then(function(newComments) { - assert.equal(newComments.get('firstObject.body'), 'FirstUpdated', "Record body was correctly updated"); - }); + return comments.reload(); + }) + .then(function(newComments) { + assert.equal( + newComments.get('firstObject.body'), + 'FirstUpdated', + 'Record body was correctly updated' + ); + }); }); }); -test("A hasMany relationship can be reloaded if it was fetched via ids", function(assert) { +test('A hasMany relationship can be reloaded if it was fetched via ids', function(assert) { Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findRecord = function(store, type, id, snapshot) { - assert.equal(type, Post, "find type was Post"); - assert.equal(id, "1", "find id was 1"); + assert.equal(type, Post, 'find type was Post'); + assert.equal(id, '1', 'find id was 1'); return resolve({ data: { @@ -883,46 +916,58 @@ test("A hasMany relationship can be reloaded if it was fetched via ids", functio type: 'post', relationships: { comments: { - data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }] - } - } - } + data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }], + }, + }, + }, }); }; env.adapter.findMany = function(store, type, ids, snapshots) { - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; run(function() { - env.store.findRecord('post', 1).then(function(post) { - return post.get('comments'); - }).then(function(comments) { - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(comments.get('length'), 2, "comments have 2 length"); + env.store + .findRecord('post', 1) + .then(function(post) { + return post.get('comments'); + }) + .then(function(comments) { + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(comments.get('length'), 2, 'comments have 2 length'); - env.adapter.findMany = function(store, type, ids, snapshots) { - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); - }; + env.adapter.findMany = function(store, type, ids, snapshots) { + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'FirstUpdated' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); + }; - return comments.reload(); - }).then(function(newComments) { - assert.equal(newComments.get('firstObject.body'), 'FirstUpdated', "Record body was correctly updated"); - }); + return comments.reload(); + }) + .then(function(newComments) { + assert.equal( + newComments.get('firstObject.body'), + 'FirstUpdated', + 'Record body was correctly updated' + ); + }); }); }); -test("A hasMany relationship can be reloaded even if it failed at the first time", function(assert) { +test('A hasMany relationship can be reloaded even if it failed at the first time', function(assert) { assert.expect(4); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findRecord = function(store, type, id) { @@ -932,10 +977,10 @@ test("A hasMany relationship can be reloaded even if it failed at the first time type: 'post', relationships: { comments: { - links: { related: "/posts/1/comments" } - } - } - } + links: { related: '/posts/1/comments' }, + }, + }, + }, }); }; @@ -945,41 +990,57 @@ test("A hasMany relationship can be reloaded even if it failed at the first time if (loadingCount % 2 === 0) { return reject(); } else { - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'FirstUpdated' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); } }; run(function() { env.store.findRecord('post', 1).then(function(post) { let comments = post.get('comments'); - return comments.catch(function() { - return comments.reload(); - }).then(function(manyArray) { - assert.equal(manyArray.get('isLoaded'), true, "the reload worked, comments are now loaded"); - return manyArray.reload().catch(function () { - assert.equal(manyArray.get('isLoaded'), true, "the second reload failed, comments are still loaded though"); - return manyArray.reload().then(function(reloadedManyArray) { - assert.equal(reloadedManyArray.get('isLoaded'), true, "the third reload worked, comments are loaded again"); - assert.ok(reloadedManyArray === manyArray, "the many array stays the same"); + return comments + .catch(function() { + return comments.reload(); + }) + .then(function(manyArray) { + assert.equal( + manyArray.get('isLoaded'), + true, + 'the reload worked, comments are now loaded' + ); + return manyArray.reload().catch(function() { + assert.equal( + manyArray.get('isLoaded'), + true, + 'the second reload failed, comments are still loaded though' + ); + return manyArray.reload().then(function(reloadedManyArray) { + assert.equal( + reloadedManyArray.get('isLoaded'), + true, + 'the third reload worked, comments are loaded again' + ); + assert.ok(reloadedManyArray === manyArray, 'the many array stays the same'); + }); }); }); - }); }); }); }); -test("A hasMany relationship can be directly reloaded if it was fetched via links", function(assert) { +test('A hasMany relationship can be directly reloaded if it was fetched via links', function(assert) { assert.expect(6); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findRecord = function(store, type, id) { - assert.equal(type, Post, "find type was Post"); - assert.equal(id, "1", "find id was 1"); + assert.equal(type, Post, 'find type was Post'); + assert.equal(id, '1', 'find id was 1'); return resolve({ data: { @@ -987,38 +1048,47 @@ test("A hasMany relationship can be directly reloaded if it was fetched via link type: 'post', relationships: { comments: { - links: { related: "/posts/1/comments" } - } - } - } + links: { related: '/posts/1/comments' }, + }, + }, + }, }); }; env.adapter.findHasMany = function(store, record, link, relationship) { - assert.equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments"); + assert.equal(link, '/posts/1/comments', 'findHasMany link was /posts/1/comments'); - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'FirstUpdated' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; run(function() { env.store.findRecord('post', 1).then(function(post) { - return post.get('comments').reload().then(function(comments) { - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(comments.get('length'), 2, "comments have 2 length"); - assert.equal(comments.get('firstObject.body'), "FirstUpdated", "Record body was correctly updated"); - }); + return post + .get('comments') + .reload() + .then(function(comments) { + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(comments.get('length'), 2, 'comments have 2 length'); + assert.equal( + comments.get('firstObject.body'), + 'FirstUpdated', + 'Record body was correctly updated' + ); + }); }); }); }); -test("Has many via links - Calling reload multiple times does not send a new request if the first one is not settled", function(assert) { +test('Has many via links - Calling reload multiple times does not send a new request if the first one is not settled', function(assert) { assert.expect(1); let done = assert.async(); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findRecord = function(store, type, id) { @@ -1028,26 +1098,32 @@ test("Has many via links - Calling reload multiple times does not send a new req type: 'post', relationships: { comments: { - links: { related: "/posts/1/comments" } - } - } - } + links: { related: '/posts/1/comments' }, + }, + }, + }, }); }; let count = 0; env.adapter.findHasMany = function(store, record, link, relationship) { count++; - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; run(function() { env.store.findRecord('post', 1).then(function(post) { post.get('comments').then(function(comments) { all([comments.reload(), comments.reload(), comments.reload()]).then(function(comments) { - assert.equal(count, 2, "One request for the original access and only one request for the mulitple reloads"); + assert.equal( + count, + 2, + 'One request for the original access and only one request for the mulitple reloads' + ); done(); }); }); @@ -1055,14 +1131,14 @@ test("Has many via links - Calling reload multiple times does not send a new req }); }); -test("A hasMany relationship can be directly reloaded if it was fetched via ids", function(assert) { +test('A hasMany relationship can be directly reloaded if it was fetched via ids', function(assert) { Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findRecord = function(store, type, id, snapshot) { - assert.equal(type, Post, "find type was Post"); - assert.equal(id, "1", "find id was 1"); + assert.equal(type, Post, 'find type was Post'); + assert.equal(id, '1', 'find id was 1'); return resolve({ data: { @@ -1070,37 +1146,46 @@ test("A hasMany relationship can be directly reloaded if it was fetched via ids" type: 'post', relationships: { comments: { - data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }] - } - } - } + data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }], + }, + }, + }, }); }; env.adapter.findMany = function(store, type, ids, snapshots) { - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'FirstUpdated' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; run(function() { env.store.findRecord('post', 1).then(function(post) { - return post.get('comments').reload().then(function(comments) { - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(comments.get('length'), 2, "comments have 2 length"); - assert.equal(comments.get('firstObject.body'), "FirstUpdated", "Record body was correctly updated"); - }); + return post + .get('comments') + .reload() + .then(function(comments) { + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(comments.get('length'), 2, 'comments have 2 length'); + assert.equal( + comments.get('firstObject.body'), + 'FirstUpdated', + 'Record body was correctly updated' + ); + }); }); }); }); -test("Has many via ids - Calling reload multiple times does not send a new request if the first one is not settled", function(assert) { +test('Has many via ids - Calling reload multiple times does not send a new request if the first one is not settled', function(assert) { assert.expect(1); let done = assert.async(); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -1110,27 +1195,33 @@ test("Has many via ids - Calling reload multiple times does not send a new reque type: 'post', relationships: { comments: { - data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }] - } - } - } + data: [{ id: 1, type: 'comment' }, { id: 2, type: 'comment' }], + }, + }, + }, }); }; let count = 0; env.adapter.findMany = function(store, type, ids, snapshots) { count++; - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "FirstUpdated" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'FirstUpdated' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; run(function() { env.store.findRecord('post', 1).then(function(post) { post.get('comments').then(function(comments) { all([comments.reload(), comments.reload(), comments.reload()]).then(function(comments) { - assert.equal(count, 2, "One request for the original access and only one request for the mulitple reloads"); + assert.equal( + count, + 2, + 'One request for the original access and only one request for the mulitple reloads' + ); done(); }); }); @@ -1138,18 +1229,20 @@ test("Has many via ids - Calling reload multiple times does not send a new reque }); }); -test("PromiseArray proxies createRecord to its ManyArray once the hasMany is loaded", function(assert) { +test('PromiseArray proxies createRecord to its ManyArray once the hasMany is loaded', function(assert) { assert.expect(4); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; let post; @@ -1161,39 +1254,41 @@ test("PromiseArray proxies createRecord to its ManyArray once the hasMany is loa relationships: { comments: { links: { - related: 'someLink' - } - } - } - } + related: 'someLink', + }, + }, + }, + }, }); post = env.store.peekRecord('post', 1); }); run(function() { post.get('comments').then(function(comments) { - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(comments.get('length'), 2, "comments have 2 length"); + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(comments.get('length'), 2, 'comments have 2 length'); let newComment = post.get('comments').createRecord({ body: 'Third' }); - assert.equal(newComment.get('body'), 'Third', "new comment is returned"); - assert.equal(comments.get('length'), 3, "comments have 3 length, including new record"); + assert.equal(newComment.get('body'), 'Third', 'new comment is returned'); + assert.equal(comments.get('length'), 3, 'comments have 3 length, including new record'); }); }); }); -test("PromiseArray proxies evented methods to its ManyArray", function(assert) { +test('PromiseArray proxies evented methods to its ManyArray', function(assert) { assert.expect(6); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; let post, comments; @@ -1205,17 +1300,16 @@ test("PromiseArray proxies evented methods to its ManyArray", function(assert) { relationships: { comments: { links: { - related: 'someLink' - } - } - } - } + related: 'someLink', + }, + }, + }, + }, }); post = env.store.peekRecord('post', 1); comments = post.get('comments'); }); - comments.on('on-event', function() { assert.ok(true); }); @@ -1247,26 +1341,30 @@ test("PromiseArray proxies evented methods to its ManyArray", function(assert) { assert.equal(comments.has('one-event'), false); }); -test("An updated `links` value should invalidate a relationship cache", function(assert) { +test('An updated `links` value should invalidate a relationship cache', function(assert) { assert.expect(8); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - assert.equal(relationship.type, "comment", "relationship was passed correctly"); + assert.equal(relationship.type, 'comment', 'relationship was passed correctly'); if (link === '/first') { - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); } else if (link === '/second') { - return resolve({ data: [ - { id: 3, type: 'comment', attributes: { body: "Third" } }, - { id: 4, type: 'comment', attributes: { body: "Fourth" } }, - { id: 5, type: 'comment', attributes: { body: "Fifth" } } - ]}); + return resolve({ + data: [ + { id: 3, type: 'comment', attributes: { body: 'Third' } }, + { id: 4, type: 'comment', attributes: { body: 'Fourth' } }, + { id: 5, type: 'comment', attributes: { body: 'Fifth' } }, + ], + }); } }; let post; @@ -1279,20 +1377,20 @@ test("An updated `links` value should invalidate a relationship cache", function relationships: { comments: { links: { - related: '/first' - } - } - } - } - }); - post = env.store.peekRecord('post', 1); + related: '/first', + }, + }, + }, + }, + }); + post = env.store.peekRecord('post', 1); }); run(function() { post.get('comments').then(function(comments) { - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(comments.get('length'), 2, "comments have 2 length"); - assert.equal(comments.objectAt(0).get('body'), 'First', "comment 1 successfully loaded"); + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(comments.get('length'), 2, 'comments have 2 length'); + assert.equal(comments.objectAt(0).get('body'), 'First', 'comment 1 successfully loaded'); env.store.push({ data: { type: 'post', @@ -1300,16 +1398,20 @@ test("An updated `links` value should invalidate a relationship cache", function relationships: { comments: { links: { - related: '/second' - } - } - } - } + related: '/second', + }, + }, + }, + }, }); post.get('comments').then(function(newComments) { - assert.equal(comments, newComments, "hasMany array was kept the same"); - assert.equal(newComments.get('length'), 3, "comments updated successfully"); - assert.equal(newComments.objectAt(0).get('body'), 'Third', "third comment loaded successfully"); + assert.equal(comments, newComments, 'hasMany array was kept the same'); + assert.equal(newComments.get('length'), 3, 'comments updated successfully'); + assert.equal( + newComments.objectAt(0).get('body'), + 'Third', + 'third comment loaded successfully' + ); }); }); }); @@ -1323,12 +1425,9 @@ test("When a polymorphic hasMany relationship is accessed, the adapter's findMan id: '1', relationships: { messages: { - data: [ - { type: 'post', id: '1' }, - { type: 'comment', id: '3' } - ] - } - } + data: [{ type: 'post', id: '1' }, { type: 'comment', id: '3' }], + }, + }, }; env.adapter.findMany = function(store, type, ids, snapshots) { @@ -1342,27 +1441,30 @@ test("When a polymorphic hasMany relationship is accessed, the adapter's findMan run(function() { env.store.push({ data: userData, - included: [{ - type: 'post', - id: '1' - }, { - type: 'comment', - id: '3' - }] + included: [ + { + type: 'post', + id: '1', + }, + { + type: 'comment', + id: '3', + }, + ], }); }); run(function() { env.store.findRecord('user', 1).then(function(user) { let messages = user.get('messages'); - assert.equal(messages.get('length'), 2, "The messages are correctly loaded"); + assert.equal(messages.get('length'), 2, 'The messages are correctly loaded'); }); }); }); test("When a polymorphic hasMany relationship is accessed, the store can call multiple adapters' findMany or find methods if the records are not loaded", function(assert) { User.reopen({ - messages: hasMany('message', { polymorphic: true, async: true }) + messages: hasMany('message', { polymorphic: true, async: true }), }); env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.findRecord = function(store, type, id, snapshot) { @@ -1380,47 +1482,47 @@ test("When a polymorphic hasMany relationship is accessed, the store can call mu id: '1', relationships: { messages: { - data: [ - { type: 'post', id: '1' }, - { type: 'comment', id: '3' } - ] - } - } - } + data: [{ type: 'post', id: '1' }, { type: 'comment', id: '3' }], + }, + }, + }, }); }); run(function() { - env.store.findRecord('user', 1).then(function(user) { - return user.get('messages'); - }).then(function(messages) { - assert.equal(messages.get('length'), 2, "The messages are correctly loaded"); - }); + env.store + .findRecord('user', 1) + .then(function(user) { + return user.get('messages'); + }) + .then(function(messages) { + assert.equal(messages.get('length'), 2, 'The messages are correctly loaded'); + }); }); }); -test("polymorphic hasMany type-checks check the superclass when MODEL_FACTORY_INJECTIONS is enabled", function(assert) { +test('polymorphic hasMany type-checks check the superclass when MODEL_FACTORY_INJECTIONS is enabled', function(assert) { assert.expect(1); setupModelFactoryInjections(); try { - run(function () { + run(function() { let igor = env.store.createRecord('user', { name: 'Igor' }); - let comment = env.store.createRecord('comment', { body: "Well I thought the title was fine" }); + let comment = env.store.createRecord('comment', { + body: 'Well I thought the title was fine', + }); igor.get('messages').addObject(comment); - assert.equal(igor.get('messages.firstObject.body'), "Well I thought the title was fine"); + assert.equal(igor.get('messages.firstObject.body'), 'Well I thought the title was fine'); }); } finally { resetModelFactoryInjections(); } }); - - -test("Type can be inferred from the key of a hasMany relationship", function(assert) { +test('Type can be inferred from the key of a hasMany relationship', function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, ids, snapshots) { @@ -1430,10 +1532,10 @@ test("Type can be inferred from the key of a hasMany relationship", function(ass type: 'user', relationships: { contacts: { - data: [{ id: 1, type: 'contact' }] - } - } - } + data: [{ id: 1, type: 'contact' }], + }, + }, + }, }; }; @@ -1444,32 +1546,35 @@ test("Type can be inferred from the key of a hasMany relationship", function(ass id: '1', relationships: { contacts: { - data: [ - { type: 'contact', id: '1' } - ] - } - } + data: [{ type: 'contact', id: '1' }], + }, + }, }, - included: [{ - type: 'contact', - id: '1' - }] + included: [ + { + type: 'contact', + id: '1', + }, + ], }); }); run(function() { - env.store.findRecord('user', 1).then(function(user) { - return user.get('contacts'); - }).then(function(contacts) { - assert.equal(contacts.get('length'), 1, "The contacts relationship is correctly set up"); - }); + env.store + .findRecord('user', 1) + .then(function(user) { + return user.get('contacts'); + }) + .then(function(contacts) { + assert.equal(contacts.get('length'), 1, 'The contacts relationship is correctly set up'); + }); }); }); -test("Type can be inferred from the key of an async hasMany relationship", function(assert) { +test('Type can be inferred from the key of an async hasMany relationship', function(assert) { assert.expect(1); User.reopen({ - contacts: DS.hasMany({ async: true }) + contacts: DS.hasMany({ async: true }), }); env.adapter.findRecord = function(store, type, ids, snapshots) { @@ -1479,10 +1584,10 @@ test("Type can be inferred from the key of an async hasMany relationship", funct type: 'user', relationships: { contacts: { - data: [{ id: 1, type: 'contact' }] - } - } - } + data: [{ id: 1, type: 'contact' }], + }, + }, + }, }; }; @@ -1493,30 +1598,33 @@ test("Type can be inferred from the key of an async hasMany relationship", funct id: '1', relationships: { contacts: { - data: [ - { type: 'contact', id: '1' } - ] - } - } + data: [{ type: 'contact', id: '1' }], + }, + }, }, - included: [{ - type: 'contact', - id: '1' - }] + included: [ + { + type: 'contact', + id: '1', + }, + ], }); }); run(function() { - env.store.findRecord('user', 1).then(function(user) { - return user.get('contacts'); - }).then(function(contacts) { - assert.equal(contacts.get('length'), 1, "The contacts relationship is correctly set up"); - }); + env.store + .findRecord('user', 1) + .then(function(user) { + return user.get('contacts'); + }) + .then(function(contacts) { + assert.equal(contacts.get('length'), 1, 'The contacts relationship is correctly set up'); + }); }); }); -test("Polymorphic relationships work with a hasMany whose type is inferred", function(assert) { +test('Polymorphic relationships work with a hasMany whose type is inferred', function(assert) { User.reopen({ - contacts: DS.hasMany({ polymorphic: true, async: false }) + contacts: DS.hasMany({ polymorphic: true, async: false }), }); env.adapter.findRecord = function(store, type, ids, snapshots) { @@ -1531,49 +1639,56 @@ test("Polymorphic relationships work with a hasMany whose type is inferred", fun id: '1', relationships: { contacts: { - data: [ - { type: 'email', id: '1' }, - { type: 'phone', id: '2' } - ] - } - } + data: [{ type: 'email', id: '1' }, { type: 'phone', id: '2' }], + }, + }, }, - included: [{ - 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) { - return user.get('contacts'); - }).then(function(contacts) { - assert.equal(contacts.get('length'), 2, "The contacts relationship is correctly set up"); - }); + env.store + .findRecord('user', 1) + .then(function(user) { + return user.get('contacts'); + }) + .then(function(contacts) { + assert.equal(contacts.get('length'), 2, 'The contacts relationship is correctly set up'); + }); }); }); -test("Polymorphic relationships with a hasMany is set up correctly on both sides", function(assert) { +test('Polymorphic relationships with a hasMany is set up correctly on both sides', function(assert) { assert.expect(2); Contact.reopen({ - posts: DS.hasMany('post', { async: false }) + posts: DS.hasMany('post', { async: false }), }); Post.reopen({ - contact: DS.belongsTo('contact', { polymorphic: true, async: false }) + contact: DS.belongsTo('contact', { polymorphic: true, async: false }), }); let email = env.store.createRecord('email'); let post = env.store.createRecord('post', { - contact: email + contact: email, }); assert.equal(post.get('contact'), email, 'The polymorphic belongsTo is set up correctly'); - assert.equal(get(email, 'posts.length'), 1, "The inverse has many is set up correctly on the email side."); + assert.equal( + get(email, 'posts.length'), + 1, + 'The inverse has many is set up correctly on the email side.' + ); }); testInDebug("A record can't be created from a polymorphic hasMany relationship", function(assert) { @@ -1585,118 +1700,137 @@ testInDebug("A record can't be created from a polymorphic hasMany relationship", id: '1', relationships: { messages: { - data: [] - } - } - } + data: [], + }, + }, + }, }); }); run(function() { - env.store.findRecord('user', 1).then(function(user) { - return user.get('messages'); - }).then(function(messages) { - assert.expectAssertion(function() { - messages.createRecord(); - }, /You cannot add 'message' records to this polymorphic relationship/); - }); + env.store + .findRecord('user', 1) + .then(function(user) { + return user.get('messages'); + }) + .then(function(messages) { + assert.expectAssertion(function() { + messages.createRecord(); + }, /You cannot add 'message' records to this polymorphic relationship/); + }); }); }); -testInDebug("Only records of the same type can be added to a monomorphic hasMany relationship", function(assert) { - assert.expect(1); - env.adapter.shouldBackgroundReloadRecord = () => false; - run(function() { - env.store.push({ - data: [{ - type: 'post', - id: '1', - relationships: { - comments: { - data: [] - } - } - }, { - type: 'post', - id: '2' - }] - }); - }); - - run(function() { - all([ - env.store.findRecord('post', 1), - env.store.findRecord('post', 2) - ]).then(function(records) { - assert.expectAssertion(function() { - records[0].get('comments').pushObject(records[1]); - }, /You cannot add a record of modelClass 'post' to the 'post.comments' relationship \(only 'comment' allowed\)/); +testInDebug( + 'Only records of the same type can be added to a monomorphic hasMany relationship', + function(assert) { + assert.expect(1); + env.adapter.shouldBackgroundReloadRecord = () => false; + run(function() { + env.store.push({ + data: [ + { + type: 'post', + id: '1', + relationships: { + comments: { + data: [], + }, + }, + }, + { + type: 'post', + id: '2', + }, + ], + }); }); - }); -}); -testInDebug("Only records of the same base modelClass can be added to a polymorphic hasMany relationship", function(assert) { - assert.expect(2); - env.adapter.shouldBackgroundReloadRecord = () => false; - run(function() { - 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' - }] + run(function() { + all([env.store.findRecord('post', 1), env.store.findRecord('post', 2)]).then(function( + records + ) { + assert.expectAssertion(function() { + records[0].get('comments').pushObject(records[1]); + }, /You cannot add a record of modelClass 'post' to the 'post.comments' relationship \(only 'comment' allowed\)/); + }); }); - }); - let asyncRecords; - - run(function() { - asyncRecords = hash({ - user: env.store.findRecord('user', 1), - anotherUser: env.store.findRecord('user', 2), - post: env.store.findRecord('post', 1), - comment: env.store.findRecord('comment', 3) + } +); + +testInDebug( + 'Only records of the same base modelClass can be added to a polymorphic hasMany relationship', + function(assert) { + assert.expect(2); + env.adapter.shouldBackgroundReloadRecord = () => false; + run(function() { + 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', + }, + ], + }); }); + let asyncRecords; - asyncRecords.then(function(records) { - records.messages = records.user.get('messages'); - return hash(records); - }).then(function(records) { - records.messages.pushObject(records.post); - records.messages.pushObject(records.comment); - assert.equal(records.messages.get('length'), 2, "The messages are correctly added"); + run(function() { + asyncRecords = hash({ + user: env.store.findRecord('user', 1), + anotherUser: env.store.findRecord('user', 2), + post: env.store.findRecord('post', 1), + comment: env.store.findRecord('comment', 3), + }); - assert.expectAssertion(function() { - records.messages.pushObject(records.anotherUser); - }, /You cannot add a record of modelClass 'user' to the 'user.messages' relationship \(only 'message' allowed\)/); + asyncRecords + .then(function(records) { + records.messages = records.user.get('messages'); + return hash(records); + }) + .then(function(records) { + records.messages.pushObject(records.post); + records.messages.pushObject(records.comment); + assert.equal(records.messages.get('length'), 2, 'The messages are correctly added'); + + assert.expectAssertion(function() { + records.messages.pushObject(records.anotherUser); + }, /You cannot add a record of modelClass 'user' to the 'user.messages' relationship \(only 'message' allowed\)/); + }); }); - }); -}); + } +); -test("A record can be removed from a polymorphic association", function(assert) { +test('A record can be removed from a polymorphic association', function(assert) { assert.expect(4); env.adapter.shouldBackgroundReloadRecord = () => false; run(function() { @@ -1706,16 +1840,16 @@ test("A record can be removed from a polymorphic association", function(assert) id: '1', relationships: { messages: { - data: [ - { type: 'comment', id: '3' } - ] - } - } + data: [{ type: 'comment', id: '3' }], + }, + }, }, - included: [{ - type: 'comment', - id: '3' - }] + included: [ + { + type: 'comment', + id: '3', + }, + ], }); }); let asyncRecords; @@ -1723,119 +1857,126 @@ test("A record can be removed from a polymorphic association", function(assert) run(function() { asyncRecords = hash({ user: env.store.findRecord('user', 1), - comment: env.store.findRecord('comment', 3) + comment: env.store.findRecord('comment', 3), }); - asyncRecords.then(function(records) { - records.messages = records.user.get('messages'); - return hash(records); - }).then(function(records) { - assert.equal(records.messages.get('length'), 1, "The user has 1 message"); + asyncRecords + .then(function(records) { + records.messages = records.user.get('messages'); + return hash(records); + }) + .then(function(records) { + assert.equal(records.messages.get('length'), 1, 'The user has 1 message'); - let removedObject = records.messages.popObject(); + let removedObject = records.messages.popObject(); - assert.equal(removedObject, records.comment, "The message is correctly removed"); - assert.equal(records.messages.get('length'), 0, "The user does not have any messages"); - assert.equal(records.messages.objectAt(0), null, "No messages can't be fetched"); - }); + assert.equal(removedObject, records.comment, 'The message is correctly removed'); + assert.equal(records.messages.get('length'), 0, 'The user does not have any messages'); + assert.equal(records.messages.objectAt(0), null, "No messages can't be fetched"); + }); }); }); -test("When a record is created on the client, its hasMany arrays should be in a loaded state", function(assert) { +test('When a record is created on the client, its hasMany arrays should be in a loaded state', function(assert) { assert.expect(3); let post = env.store.createRecord('post'); - assert.ok(get(post, 'isLoaded'), "The post should have isLoaded flag"); + assert.ok(get(post, 'isLoaded'), 'The post should have isLoaded flag'); let comments; run(function() { comments = get(post, 'comments'); }); - assert.equal(get(comments, 'length'), 0, "The comments should be an empty array"); + assert.equal(get(comments, 'length'), 0, 'The comments should be an empty array'); - assert.ok(get(comments, 'isLoaded'), "The comments should have isLoaded flag"); + assert.ok(get(comments, 'isLoaded'), 'The comments should have isLoaded flag'); }); -test("When a record is created on the client, its async hasMany arrays should be in a loaded state", function(assert) { +test('When a record is created on the client, its async hasMany arrays should be in a loaded state', function(assert) { assert.expect(4); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); let post = env.store.createRecord('post'); - assert.ok(get(post, 'isLoaded'), "The post should have isLoaded flag"); + assert.ok(get(post, 'isLoaded'), 'The post should have isLoaded flag'); run(function() { get(post, 'comments').then(function(comments) { - assert.ok(true, "Comments array successfully resolves"); - assert.equal(get(comments, 'length'), 0, "The comments should be an empty array"); - assert.ok(get(comments, 'isLoaded'), "The comments should have isLoaded flag"); + assert.ok(true, 'Comments array successfully resolves'); + assert.equal(get(comments, 'length'), 0, 'The comments should be an empty array'); + assert.ok(get(comments, 'isLoaded'), 'The comments should have isLoaded flag'); }); }); }); -test("we can set records SYNC HM relationship", function(assert) { +test('we can set records SYNC HM relationship', function(assert) { assert.expect(1); let post = env.store.createRecord('post'); run(function() { env.store.push({ - data: [{ - type: 'comment', - id: '1', - attributes: { - body: 'First' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'Second' - } - }] + data: [ + { + type: 'comment', + id: '1', + attributes: { + body: 'First', + }, + }, + { + type: 'comment', + id: '2', + attributes: { + body: 'Second', + }, + }, + ], }); post.set('comments', env.store.peekAll('comment')); }); - assert.equal(get(post, 'comments.length'), 2, "we can set HM relationship"); + assert.equal(get(post, 'comments.length'), 2, 'we can set HM relationship'); }); - -test("We can set records ASYNC HM relationship", function(assert) { +test('We can set records ASYNC HM relationship', function(assert) { assert.expect(1); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); let post = env.store.createRecord('post'); run(function() { env.store.push({ - data: [{ - type: 'comment', - id: '1', - attributes: { - body: 'First' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'Second' - } - }] + data: [ + { + type: 'comment', + id: '1', + attributes: { + body: 'First', + }, + }, + { + type: 'comment', + id: '2', + attributes: { + body: 'Second', + }, + }, + ], }); post.set('comments', env.store.peekAll('comment')); }); return post.get('comments').then(comments => { - assert.equal(comments.get('length') , 2, "we can set async HM relationship"); + assert.equal(comments.get('length'), 2, 'we can set async HM relationship'); }); }); -test("When a record is saved, its unsaved hasMany records should be kept", function(assert) { +test('When a record is saved, its unsaved hasMany records should be kept', function(assert) { assert.expect(1); let post, comment; @@ -1850,17 +1991,21 @@ test("When a record is saved, its unsaved hasMany records should be kept", funct post.get('comments').pushObject(comment); return post.save(); }).then(() => { - assert.equal(get(post, 'comments.length'), 1, "The unsaved comment should be in the post's comments array"); + assert.equal( + get(post, 'comments.length'), + 1, + "The unsaved comment should be in the post's comments array" + ); }); }); -test("dual non-async HM <-> BT", function(assert) { +test('dual non-async HM <-> BT', function(assert) { Post.reopen({ - comments: DS.hasMany('comment', { inverse: 'post', async: false }) + comments: DS.hasMany('comment', { inverse: 'post', async: false }), }); Comment.reopen({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); env.adapter.createRecord = function(store, type, snapshot) { @@ -1877,12 +2022,10 @@ test("dual non-async HM <-> BT", function(assert) { id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '1' } - ] - } - } - } + data: [{ type: 'comment', id: '1' }], + }, + }, + }, }); env.store.push({ data: { @@ -1890,34 +2033,47 @@ test("dual non-async HM <-> BT", function(assert) { id: '1', relationships: { comments: { - post: { type: 'post', id: '1' } - } - } - } + post: { type: 'post', id: '1' }, + }, + }, + }, }); post = env.store.peekRecord('post', 1); firstComment = env.store.peekRecord('comment', 1); - env.store.createRecord('comment', { - post: post - }).save().then(function(comment) { - let commentPost = comment.get('post'); - let postComments = comment.get('post.comments'); - let postCommentsLength = comment.get('post.comments.length'); - - assert.deepEqual(post, commentPost, 'expect the new comments post, to be the correct post'); - assert.ok(postComments, "comments should exist"); - assert.equal(postCommentsLength, 2, "comment's post should have a internalModel back to comment"); - assert.ok(postComments && postComments.indexOf(firstComment) !== -1, 'expect to contain first comment'); - assert.ok(postComments && postComments.indexOf(comment) !== -1, 'expected to contain the new comment'); - }); + env.store + .createRecord('comment', { + post: post, + }) + .save() + .then(function(comment) { + let commentPost = comment.get('post'); + let postComments = comment.get('post.comments'); + let postCommentsLength = comment.get('post.comments.length'); + + assert.deepEqual(post, commentPost, 'expect the new comments post, to be the correct post'); + assert.ok(postComments, 'comments should exist'); + assert.equal( + postCommentsLength, + 2, + "comment's post should have a internalModel back to comment" + ); + assert.ok( + postComments && postComments.indexOf(firstComment) !== -1, + 'expect to contain first comment' + ); + assert.ok( + postComments && postComments.indexOf(comment) !== -1, + 'expected to contain the new comment' + ); + }); }); }); -test("When an unloaded record is added to the hasMany, it gets fetched once the hasMany is accessed even if the hasMany has been already fetched", function(assert) { +test('When an unloaded record is added to the hasMany, it gets fetched once the hasMany is accessed even if the hasMany has been already fetched', function(assert) { assert.expect(6); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); let findManyCalls = 0; @@ -1925,10 +2081,12 @@ test("When an unloaded record is added to the hasMany, it gets fetched once the env.adapter.findMany = function(store, type, ids, snapshots) { assert.ok(true, `findMany called ${++findManyCalls}x`); - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: 'first' } }, - { id: 2, type: 'comment', attributes: { body: 'second' } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'first' } }, + { id: 2, type: 'comment', attributes: { body: 'second' } }, + ], + }); }; env.adapter.findRecord = function(store, type, id, snapshot) { @@ -1944,13 +2102,10 @@ test("When an unloaded record is added to the hasMany, it gets fetched once the id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '1' }, - { type: 'comment', id: '2' } - ] - } - } - } + data: [{ type: 'comment', id: '1' }, { type: 'comment', id: '2' }], + }, + }, + }, }); post = env.store.peekRecord('post', 1); }); @@ -1958,7 +2113,11 @@ test("When an unloaded record is added to the hasMany, it gets fetched once the return run(() => { return post.get('comments').then(fetchedComments => { assert.equal(fetchedComments.get('length'), 2, 'comments fetched successfully'); - assert.equal(fetchedComments.objectAt(0).get('body'), 'first', 'first comment loaded successfully'); + assert.equal( + fetchedComments.objectAt(0).get('body'), + 'first', + 'first comment loaded successfully' + ); env.store.push({ data: { @@ -1969,16 +2128,24 @@ test("When an unloaded record is added to the hasMany, it gets fetched once the data: [ { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + { type: 'comment', id: '3' }, + ], + }, + }, + }, }); return post.get('comments').then(newlyFetchedComments => { - assert.equal(newlyFetchedComments.get('length'), 3, 'all three comments fetched successfully'); - assert.equal(newlyFetchedComments.objectAt(2).get('body'), 'third', 'third comment loaded successfully'); + assert.equal( + newlyFetchedComments.get('length'), + 3, + 'all three comments fetched successfully' + ); + assert.equal( + newlyFetchedComments.objectAt(2).get('body'), + 'third', + 'third comment loaded successfully' + ); }); }); }); @@ -1992,13 +2159,10 @@ testInDebug('A sync hasMany errors out if there are unlaoded records in it', fun id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '1' }, - { type: 'comment', id: '2' } - ] - } - } - } + data: [{ type: 'comment', id: '1' }, { type: 'comment', id: '2' }], + }, + }, + }, }); return env.store.peekRecord('post', 1); }); @@ -2016,15 +2180,11 @@ test('After removing and unloading a record, a hasMany relationship should still id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '1' } - ] - } - } + data: [{ type: 'comment', id: '1' }], + }, + }, }, - included: [ - { type: 'comment', id: '1' } - ] + included: [{ type: 'comment', id: '1' }], }); const post = env.store.peekRecord('post', 1); const comments = post.get('comments'); @@ -2039,25 +2199,30 @@ test('After removing and unloading a record, a hasMany relationship should still assert.equal(run(post, 'get', 'comments.length'), 0); }); -test("If reordered hasMany data has been pushed to the store, the many array reflects the ordering change - sync", function(assert) { +test('If reordered hasMany data has been pushed to the store, the many array reflects the ordering change - sync', function(assert) { let comment1, comment2, comment3, comment4; let post; run(() => { env.store.push({ - data: [{ - type: 'comment', - id: '1' - }, { - type: 'comment', - id: '2' - }, { - type: 'comment', - id: '3' - }, { - type: 'comment', - id: '4' - }] + data: [ + { + type: 'comment', + id: '1', + }, + { + type: 'comment', + id: '2', + }, + { + type: 'comment', + id: '3', + }, + { + type: 'comment', + id: '4', + }, + ], }); comment1 = env.store.peekRecord('comment', 1); @@ -2073,17 +2238,18 @@ test("If reordered hasMany data has been pushed to the store, the many array ref id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '1' }, - { type: 'comment', id: '2' } - ] - } - } - } + data: [{ type: 'comment', id: '1' }, { type: 'comment', id: '2' }], + }, + }, + }, }); post = env.store.peekRecord('post', 1); - assert.deepEqual(post.get('comments').toArray(), [comment1, comment2], 'Initial ordering is correct'); + assert.deepEqual( + post.get('comments').toArray(), + [comment1, comment2], + 'Initial ordering is correct' + ); }); run(() => { @@ -2093,16 +2259,17 @@ test("If reordered hasMany data has been pushed to the store, the many array ref id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '2' }, - { type: 'comment', id: '1' } - ] - } - } - } + data: [{ type: 'comment', id: '2' }, { type: 'comment', id: '1' }], + }, + }, + }, }); }); - assert.deepEqual(post.get('comments').toArray(), [comment2, comment1], 'Updated ordering is correct'); + assert.deepEqual( + post.get('comments').toArray(), + [comment2, comment1], + 'Updated ordering is correct' + ); run(() => { env.store.push({ @@ -2111,12 +2278,10 @@ test("If reordered hasMany data has been pushed to the store, the many array ref id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '2' } - ] - } - } - } + data: [{ type: 'comment', id: '2' }], + }, + }, + }, }); }); assert.deepEqual(post.get('comments').toArray(), [comment2], 'Updated ordering is correct'); @@ -2132,14 +2297,18 @@ test("If reordered hasMany data has been pushed to the store, the many array ref { type: 'comment', id: '1' }, { type: 'comment', id: '2' }, { type: 'comment', id: '3' }, - { type: 'comment', id: '4' } - ] - } - } - } + { type: 'comment', id: '4' }, + ], + }, + }, + }, }); }); - assert.deepEqual(post.get('comments').toArray(), [comment1, comment2, comment3, comment4], 'Updated ordering is correct'); + assert.deepEqual( + post.get('comments').toArray(), + [comment1, comment2, comment3, comment4], + 'Updated ordering is correct' + ); run(() => { env.store.push({ @@ -2148,16 +2317,17 @@ test("If reordered hasMany data has been pushed to the store, the many array ref id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '4' }, - { type: 'comment', id: '3' } - ] - } - } - } + data: [{ type: 'comment', id: '4' }, { type: 'comment', id: '3' }], + }, + }, + }, }); }); - assert.deepEqual(post.get('comments').toArray(), [comment4, comment3], 'Updated ordering is correct'); + assert.deepEqual( + post.get('comments').toArray(), + [comment4, comment3], + 'Updated ordering is correct' + ); run(() => { env.store.push({ @@ -2170,18 +2340,22 @@ test("If reordered hasMany data has been pushed to the store, the many array ref { type: 'comment', id: '4' }, { type: 'comment', id: '2' }, { type: 'comment', id: '3' }, - { type: 'comment', id: '1' } - ] - } - } - } + { type: 'comment', id: '1' }, + ], + }, + }, + }, }); }); - assert.deepEqual(post.get('comments').toArray(), [comment4, comment2, comment3, comment1], 'Updated ordering is correct'); + assert.deepEqual( + post.get('comments').toArray(), + [comment4, comment2, comment3, comment1], + 'Updated ordering is correct' + ); }); -test("Rollbacking attributes for deleted record restores implicit relationship correctly when the hasMany side has been deleted - async", function(assert) { +test('Rollbacking attributes for deleted record restores implicit relationship correctly when the hasMany side has been deleted - async', function(assert) { let book, chapter; run(() => { @@ -2190,23 +2364,23 @@ test("Rollbacking attributes for deleted record restores implicit relationship c type: 'book', id: '1', attributes: { - title: "Stanley's Amazing Adventures" + title: "Stanley's Amazing Adventures", }, relationships: { chapters: { - data: [ - { type: 'chapter', id: '2' } - ] - } - } + data: [{ type: 'chapter', id: '2' }], + }, + }, }, - included: [{ - type: 'chapter', - id: '2', - attributes: { - title: 'Sailing the Seven Seas' - } - }] + included: [ + { + type: 'chapter', + id: '2', + attributes: { + title: 'Sailing the Seven Seas', + }, + }, + ], }); book = env.store.peekRecord('book', 1); chapter = env.store.peekRecord('chapter', 2); @@ -2219,12 +2393,16 @@ test("Rollbacking attributes for deleted record restores implicit relationship c return run(() => { return book.get('chapters').then(fetchedChapters => { - assert.equal(fetchedChapters.objectAt(0), chapter, 'Book has a chapter after rollback attributes'); + assert.equal( + fetchedChapters.objectAt(0), + chapter, + 'Book has a chapter after rollback attributes' + ); }); }); }); -test("Rollbacking attributes for deleted record restores implicit relationship correctly when the hasMany side has been deleted - sync", function(assert) { +test('Rollbacking attributes for deleted record restores implicit relationship correctly when the hasMany side has been deleted - sync', function(assert) { let book, chapter; run(() => { @@ -2233,23 +2411,23 @@ test("Rollbacking attributes for deleted record restores implicit relationship c type: 'book', id: '1', attributes: { - title: "Stanley's Amazing Adventures" + title: "Stanley's Amazing Adventures", }, relationships: { chapters: { - data: [ - { type: 'chapter', id: '2' } - ] - } - } + data: [{ type: 'chapter', id: '2' }], + }, + }, }, - included: [{ - type: 'chapter', - id: '2', - attributes: { - title: 'Sailing the Seven Seas' - } - }] + included: [ + { + type: 'chapter', + id: '2', + attributes: { + title: 'Sailing the Seven Seas', + }, + }, + ], }); book = env.store.peekRecord('book', 1); chapter = env.store.peekRecord('chapter', 2); @@ -2261,13 +2439,17 @@ test("Rollbacking attributes for deleted record restores implicit relationship c }); run(() => { - assert.equal(book.get('chapters.firstObject'), chapter, "Book has a chapter after rollback attributes"); + assert.equal( + book.get('chapters.firstObject'), + chapter, + 'Book has a chapter after rollback attributes' + ); }); }); -test("Rollbacking attributes for deleted record restores implicit relationship correctly when the belongsTo side has been deleted - async", function(assert) { +test('Rollbacking attributes for deleted record restores implicit relationship correctly when the belongsTo side has been deleted - async', function(assert) { Page.reopen({ - chapter: DS.belongsTo('chapter', { async: true }) + chapter: DS.belongsTo('chapter', { async: true }), }); let chapter, page; @@ -2278,21 +2460,23 @@ test("Rollbacking attributes for deleted record restores implicit relationship c type: 'chapter', id: '2', attributes: { - title: 'Sailing the Seven Seas' - } + title: 'Sailing the Seven Seas', + }, }, - included: [{ - type: 'page', - id: '3', - attributes: { - number: 1 + included: [ + { + type: 'page', + id: '3', + attributes: { + number: 1, + }, + relationships: { + chapter: { + data: { type: 'chapter', id: '2' }, + }, + }, }, - relationships: { - chapter: { - data: { type: 'chapter', id: '2' } - } - } - }] + ], }); chapter = env.store.peekRecord('chapter', 2); page = env.store.peekRecord('page', 3); @@ -2310,7 +2494,7 @@ 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(assert) { +test('Rollbacking attributes for deleted record restores implicit relationship correctly when the belongsTo side has been deleted - sync', function(assert) { let chapter, page; run(() => { env.store.push({ @@ -2318,21 +2502,23 @@ test("Rollbacking attributes for deleted record restores implicit relationship c type: 'chapter', id: '2', attributes: { - title: 'Sailing the Seven Seas' - } + title: 'Sailing the Seven Seas', + }, }, - included: [{ - type: 'page', - id: '3', - attributes: { - number: 1 + included: [ + { + type: 'page', + id: '3', + attributes: { + number: 1, + }, + relationships: { + chapter: { + data: { type: 'chapter', id: '2' }, + }, + }, }, - relationships: { - chapter: { - data: { type: 'chapter', id: '2' } - } - } - }] + ], }); chapter = env.store.peekRecord('chapter', 2); page = env.store.peekRecord('page', 3); @@ -2344,44 +2530,45 @@ test("Rollbacking attributes for deleted record restores implicit relationship c }); run(() => { - assert.equal(page.get('chapter'), chapter, "Page has a chapter after rollback attributes"); + assert.equal(page.get('chapter'), chapter, 'Page has a chapter after rollback attributes'); }); }); -test("ManyArray notifies the array observers and flushes bindings when removing", function(assert) { +test('ManyArray notifies the array observers and flushes bindings when removing', function(assert) { assert.expect(2); let chapter, page, page2; let observe = false; run(() => { 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' + data: [ + { + type: 'page', + id: '1', + attributes: { + number: 1, + }, }, - relationships: { - pages: { - data: [ - { type: 'page', id: '1' }, - { type: 'page', id: '2' } - ] - } - } - }] + { + 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); @@ -2397,7 +2584,7 @@ test("ManyArray notifies the array observers and flushes bindings when removing" if (observe) { assert.equal(removeCount, 1, 'removeCount is correct'); } - } + }, }); }); @@ -2408,39 +2595,41 @@ test("ManyArray notifies the array observers and flushes bindings when removing" }); }); -test("ManyArray notifies the array observers and flushes bindings when adding", function(assert) { +test('ManyArray notifies the array observers and flushes bindings when adding', function(assert) { assert.expect(2); let chapter, page, page2; let observe = false; run(() => { 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' + data: [ + { + type: 'page', + id: '1', + attributes: { + number: 1, + }, }, - relationships: { - pages: { - data: [ - { type: 'page', id: '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); @@ -2456,7 +2645,7 @@ test("ManyArray notifies the array observers and flushes bindings when adding", if (observe) { assert.equal(pages.objectAt(index), page2, 'page2 is passed to didChange'); } - } + }, }); }); @@ -2467,70 +2656,72 @@ test("ManyArray notifies the array observers and flushes bindings when adding", }); }); -testInDebug("Passing a model as type to hasMany should not work", function(assert) { +testInDebug('Passing a model as type to hasMany should not work', function(assert) { assert.expect(1); assert.expectAssertion(() => { User = DS.Model.extend(); Contact = DS.Model.extend({ - users: hasMany(User, { async: false }) + users: hasMany(User, { async: false }), }); }, /The first argument to DS.hasMany must be a string/); }); -test("Relationship.clear removes all records correctly", function(assert) { +test('Relationship.clear removes all records correctly', function(assert) { let post; Comment.reopen({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); Post.reopen({ - comments: DS.hasMany('comment', { inverse: 'post', async: false }) + comments: DS.hasMany('comment', { inverse: 'post', async: false }), }); run(() => { env.store.push({ - data: [{ - type: 'post', - id: '2', - attributes: { - title: 'Sailing the Seven Seas' + data: [ + { + type: 'post', + id: '2', + attributes: { + title: 'Sailing the Seven Seas', + }, + relationships: { + comments: { + data: [{ type: 'comment', id: '1' }, { type: 'comment', id: '2' }], + }, + }, }, - 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' } - } - } - }] + { + 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); }); @@ -2546,46 +2737,47 @@ test('unloading a record with associated records does not prevent the store from let post; Comment.reopen({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); Post.reopen({ - comments: DS.hasMany('comment', { inverse: 'post', async: false }) + comments: DS.hasMany('comment', { inverse: 'post', async: false }), }); run(() => { env.store.push({ - data: [{ - type: 'post', - id: '2', - attributes: { - title: 'Sailing the Seven Seas' + data: [ + { + type: 'post', + id: '2', + attributes: { + title: 'Sailing the Seven Seas', + }, + relationships: { + comments: { + data: [{ type: 'comment', id: '1' }, { type: 'comment', id: '2' }], + }, + }, }, - 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: '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); @@ -2602,22 +2794,22 @@ test('unloading a record with associated records does not prevent the store from run(() => { env.store.destroy(); }); - assert.ok(true, "store destroyed correctly"); + assert.ok(true, 'store destroyed correctly'); } catch (error) { - assert.ok(false, "store prevented from being destroyed"); + assert.ok(false, 'store prevented from being destroyed'); } }); -test("adding and removing records from hasMany relationship #2666", function(assert) { +test('adding and removing records from hasMany relationship #2666', function(assert) { assert.expect(4); let Post = DS.Model.extend({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); Post.reopenClass({ toString: () => 'Post' }); let Comment = DS.Model.extend({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); Comment.reopenClass({ toString: () => 'Comment' }); @@ -2625,88 +2817,100 @@ test("adding and removing records from hasMany relationship #2666", function(ass post: Post, comment: Comment, adapter: DS.RESTAdapter.extend({ - shouldBackgroundReloadRecord: () => false - }) + shouldBackgroundReloadRecord: () => false, + }), }); let commentId = 4; - env.registry.register('adapter:comment', DS.RESTAdapter.extend({ - deleteRecord(record) { - return resolve(); - }, - updateRecord(record) { - return resolve(); - }, - createRecord() { - return resolve({ comments: { id: commentId++ }}); - } - })); + env.registry.register( + 'adapter:comment', + DS.RESTAdapter.extend({ + deleteRecord(record) { + return resolve(); + }, + updateRecord(record) { + return resolve(); + }, + createRecord() { + return resolve({ comments: { id: commentId++ } }); + }, + }) + ); run(() => { 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' - }] + 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', + }, + ], }); }); return run(() => { return env.store.findRecord('post', 1).then(post => { let comments = post.get('comments'); - assert.equal(comments.get('length'), 3, "Initial comments count"); + assert.equal(comments.get('length'), 3, 'Initial comments count'); // Add comment #4 let comment = env.store.createRecord('comment'); comments.addObject(comment); - return comment.save().then(() => { - let comments = post.get('comments'); - assert.equal(comments.get('length'), 4, "Comments count after first add"); - - // Delete comment #4 - return comments.get('lastObject').destroyRecord(); - }).then(() => { - let comments = post.get('comments'); - let length = comments.get('length'); - - assert.equal(length, 3, "Comments count after destroy"); - - // Add another comment #4 - let comment = env.store.createRecord('comment'); - comments.addObject(comment); - return comment.save(); - }).then(() => { - let comments = post.get('comments'); - assert.equal(comments.get('length'), 4, "Comments count after second add"); - }); + return comment + .save() + .then(() => { + let comments = post.get('comments'); + assert.equal(comments.get('length'), 4, 'Comments count after first add'); + + // Delete comment #4 + return comments.get('lastObject').destroyRecord(); + }) + .then(() => { + let comments = post.get('comments'); + let length = comments.get('length'); + + assert.equal(length, 3, 'Comments count after destroy'); + + // Add another comment #4 + let comment = env.store.createRecord('comment'); + comments.addObject(comment); + return comment.save(); + }) + .then(() => { + let comments = post.get('comments'); + assert.equal(comments.get('length'), 4, 'Comments count after second add'); + }); }); }); }); -test("hasMany hasAnyRelationshipData async loaded", function(assert) { +test('hasMany hasAnyRelationshipData async loaded', function(assert) { assert.expect(1); Chapter.reopen({ - pages: hasMany('pages', { async: true }) + pages: hasMany('pages', { async: true }), }); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -2717,10 +2921,10 @@ test("hasMany hasAnyRelationshipData async loaded", function(assert) { attributes: { title: 'The Story Begins' }, relationships: { pages: { - data: [{ id: 2, type: 'page' }, { id: 3, type: 'page' }] - } - } - } + data: [{ id: 2, type: 'page' }, { id: 3, type: 'page' }], + }, + }, + }, }); }; @@ -2732,7 +2936,7 @@ test("hasMany hasAnyRelationshipData async loaded", function(assert) { }); }); -test("hasMany hasAnyRelationshipData sync loaded", function(assert) { +test('hasMany hasAnyRelationshipData sync loaded', function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -2743,10 +2947,10 @@ test("hasMany hasAnyRelationshipData sync loaded", function(assert) { attributes: { title: 'The Story Begins' }, relationships: { pages: { - data: [{ id: 2, type: 'page' }, { id: 3, type: 'page' }] - } - } - } + data: [{ id: 2, type: 'page' }, { id: 3, type: 'page' }], + }, + }, + }, }); }; @@ -2758,11 +2962,11 @@ test("hasMany hasAnyRelationshipData sync loaded", function(assert) { }); }); -test("hasMany hasAnyRelationshipData async not loaded", function(assert) { +test('hasMany hasAnyRelationshipData async not loaded', function(assert) { assert.expect(1); Chapter.reopen({ - pages: hasMany('pages', { async: true }) + pages: hasMany('pages', { async: true }), }); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -2773,10 +2977,10 @@ test("hasMany hasAnyRelationshipData async not loaded", function(assert) { attributes: { title: 'The Story Begins' }, relationships: { pages: { - links: { related: 'pages' } - } - } - } + links: { related: 'pages' }, + }, + }, + }, }); }; @@ -2788,7 +2992,7 @@ test("hasMany hasAnyRelationshipData async not loaded", function(assert) { }); }); -test("hasMany hasAnyRelationshipData sync not loaded", function(assert) { +test('hasMany hasAnyRelationshipData sync not loaded', function(assert) { assert.expect(1); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -2796,8 +3000,8 @@ test("hasMany hasAnyRelationshipData sync not loaded", function(assert) { data: { id: 1, type: 'chapter', - attributes: { title: 'The Story Begins' } - } + attributes: { title: 'The Story Begins' }, + }, }); }; @@ -2809,11 +3013,11 @@ test("hasMany hasAnyRelationshipData sync not loaded", function(assert) { }); }); -test("hasMany hasAnyRelationshipData async created", function(assert) { +test('hasMany hasAnyRelationshipData async created', function(assert) { assert.expect(2); Chapter.reopen({ - pages: hasMany('pages', { async: true }) + pages: hasMany('pages', { async: true }), }); let chapter = store.createRecord('chapter', { title: 'The Story Begins' }); @@ -2824,14 +3028,14 @@ test("hasMany hasAnyRelationshipData async created", function(assert) { chapter = store.createRecord('chapter', { title: 'The Story Begins', - pages: [page] + pages: [page], }); relationship = chapter._internalModel._relationships.get('pages'); assert.equal(relationship.hasAnyRelationshipData, true, 'relationship has data'); }); -test("hasMany hasAnyRelationshipData sync created", function(assert) { +test('hasMany hasAnyRelationshipData sync created', function(assert) { assert.expect(2); let chapter = store.createRecord('chapter', { title: 'The Story Begins' }); @@ -2841,7 +3045,7 @@ test("hasMany hasAnyRelationshipData sync created", function(assert) { chapter = store.createRecord('chapter', { title: 'The Story Begins', - pages: [store.createRecord('page')] + pages: [store.createRecord('page')], }); relationship = chapter._internalModel._relationships.get('pages'); @@ -2854,11 +3058,14 @@ test("Model's hasMany relationship should not be created during model creation", env.store.push({ data: { type: 'user', - id: '1' - } + id: '1', + }, }); user = env.store.peekRecord('user', 1); - assert.ok(!user._internalModel._relationships.has('messages'), 'Newly created record should not have relationships'); + assert.ok( + !user._internalModel._relationships.has('messages'), + 'Newly created record should not have relationships' + ); }); }); @@ -2867,11 +3074,14 @@ test("Model's belongsTo relationship should be created during 'get' method", fun run(() => { user = env.store.createRecord('user'); user.get('messages'); - assert.ok(user._internalModel._relationships.has('messages'), "Newly created record with relationships in params passed in its constructor should have relationships"); + assert.ok( + user._internalModel._relationships.has('messages'), + 'Newly created record with relationships in params passed in its constructor should have relationships' + ); }); }); -test("metadata is accessible when pushed as a meta property for a relationship", function(assert) { +test('metadata is accessible when pushed as a meta property for a relationship', function(assert) { assert.expect(1); let book; env.adapter.findHasMany = function() { @@ -2884,41 +3094,42 @@ test("metadata is accessible when pushed as a meta property for a relationship", type: 'book', id: '1', attributes: { - title: 'Sailing the Seven Seas' + title: 'Sailing the Seven Seas', }, relationships: { chapters: { meta: { - where: 'the lefkada sea' + where: 'the lefkada sea', }, links: { - related: '/chapters' - } - } - } - } + related: '/chapters', + }, + }, + }, + }, }); book = env.store.peekRecord('book', 1); }); run(() => { - assert.equal(book._internalModel._relationships.get('chapters').meta.where, 'the lefkada sea', 'meta is there'); + assert.equal( + book._internalModel._relationships.get('chapters').meta.where, + 'the lefkada sea', + 'meta is there' + ); }); }); -test("metadata is accessible when return from a fetchLink", function(assert) { +test('metadata is accessible when return from a fetchLink', function(assert) { assert.expect(1); env.registry.register('serializer:application', DS.RESTSerializer); env.adapter.findHasMany = function() { return resolve({ meta: { - foo: 'bar' + foo: 'bar', }, - chapters: [ - { id: '2' }, - { id: '3' } - ] + chapters: [{ id: '2' }, { id: '3' }], }); }; @@ -2930,16 +3141,16 @@ test("metadata is accessible when return from a fetchLink", function(assert) { type: 'book', id: '1', attributes: { - title: 'Sailing the Seven Seas' + title: 'Sailing the Seven Seas', }, relationships: { chapters: { links: { - related: '/chapters' - } - } - } - } + related: '/chapters', + }, + }, + }, + }, }); book = env.store.peekRecord('book', 1); }); @@ -2952,19 +3163,16 @@ test("metadata is accessible when return from a fetchLink", function(assert) { }); }); -test("metadata should be reset between requests", function(assert) { +test('metadata should be reset between requests', function(assert) { let counter = 0; env.registry.register('serializer:application', DS.RESTSerializer); env.adapter.findHasMany = function() { let data = { meta: { - foo: 'bar' + foo: 'bar', }, - chapters: [ - { id: '2' }, - { id: '3' } - ] + chapters: [{ id: '2' }, { id: '3' }], }; assert.ok(true, 'findHasMany should be called twice'); @@ -2982,33 +3190,36 @@ test("metadata should be reset between requests", function(assert) { run(() => { env.store.push({ - data: [{ - type: 'book', - id: '1', - attributes: { - title: 'Sailing the Seven Seas' + data: [ + { + type: 'book', + id: '1', + attributes: { + title: 'Sailing the Seven Seas', + }, + relationships: { + chapters: { + links: { + related: 'chapters', + }, + }, + }, }, - relationships: { - chapters: { - links: { - related: 'chapters' - } - } - } - }, { - type: 'book', - id: '2', - attributes: { - title: 'Another book title' + { + type: 'book', + id: '2', + attributes: { + title: 'Another book title', + }, + relationships: { + chapters: { + links: { + related: 'chapters', + }, + }, + }, }, - relationships: { - chapters: { - links: { - related: 'chapters' - } - } - } - }] + ], }); book1 = env.store.peekRecord('book', 1); book2 = env.store.peekRecord('book', 2); @@ -3027,16 +3238,18 @@ test("metadata should be reset between requests", function(assert) { }); }); -test("Related link should be fetched when no relationship data is present", function(assert) { +test('Related link should be fetched when no relationship data is present', function(assert) { assert.expect(3); Post.reopen({ - comments: DS.hasMany('comment', { async: true, inverse: 'post' }) + comments: DS.hasMany('comment', { async: true, inverse: 'post' }), }); Comment.reopen({ - post: DS.belongsTo('post', { async: false, inverse: 'comments' }) + post: DS.belongsTo('post', { async: false, inverse: 'comments' }), }); - env.adapter.shouldBackgroundReloadRecord = () => { return false; }; + env.adapter.shouldBackgroundReloadRecord = () => { + return false; + }; env.adapter.findRecord = () => { assert.ok(false, "The adapter's findRecord method should not be called"); }; @@ -3053,10 +3266,10 @@ test("Related link should be fetched when no relationship data is present", func id: '1', type: 'comment', attributes: { - body: 'This is comment' - } - } - ] + body: 'This is comment', + }, + }, + ], }); }; @@ -3068,11 +3281,11 @@ test("Related link should be fetched when no relationship data is present", func relationships: { comments: { links: { - related: 'get-comments' - } - } - } - } + related: 'get-comments', + }, + }, + }, + }, }); return post.get('comments').then(comments => { @@ -3081,16 +3294,18 @@ test("Related link should be fetched when no relationship data is present", func }); }); -test("Related link should take precedence over relationship data when local record data is missing", function(assert) { +test('Related link should take precedence over relationship data when local record data is missing', function(assert) { assert.expect(3); Post.reopen({ - comments: DS.hasMany('comment', { async: true, inverse: 'post' }) + comments: DS.hasMany('comment', { async: true, inverse: 'post' }), }); Comment.reopen({ - post: DS.belongsTo('post', { async: false, inverse: 'comments' }) + post: DS.belongsTo('post', { async: false, inverse: 'comments' }), }); - env.adapter.shouldBackgroundReloadRecord = () => { return false; }; + env.adapter.shouldBackgroundReloadRecord = () => { + return false; + }; env.adapter.findRecord = () => { assert.ok(false, "The adapter's findRecord method should not be called"); }; @@ -3107,10 +3322,10 @@ test("Related link should take precedence over relationship data when local reco id: '1', type: 'comment', attributes: { - body: 'This is comment' - } - } - ] + body: 'This is comment', + }, + }, + ], }); }; @@ -3122,14 +3337,12 @@ test("Related link should take precedence over relationship data when local reco relationships: { comments: { links: { - related: 'get-comments' + related: 'get-comments', }, - data: [ - { type: 'comment', id: '1' } - ] - } - } - } + data: [{ type: 'comment', id: '1' }], + }, + }, + }, }); return post.get('comments').then(comments => { @@ -3138,16 +3351,18 @@ test("Related link should take precedence over relationship data when local reco }); }); -test("Local relationship data should take precedence over related link when local record data is available", function(assert) { +test('Local relationship data should take precedence over related link when local record data is available', function(assert) { assert.expect(1); Post.reopen({ - comments: DS.hasMany('comment', { async: true, inverse: 'post' }) + comments: DS.hasMany('comment', { async: true, inverse: 'post' }), }); Comment.reopen({ - post: DS.belongsTo('post', { async: false, inverse: 'comments' }) + post: DS.belongsTo('post', { async: false, inverse: 'comments' }), }); - env.adapter.shouldBackgroundReloadRecord = () => { return false; }; + env.adapter.shouldBackgroundReloadRecord = () => { + return false; + }; env.adapter.findRecord = () => { assert.ok(false, "The adapter's findRecord method should not be called"); }; @@ -3167,23 +3382,21 @@ test("Local relationship data should take precedence over related link when loca relationships: { comments: { links: { - related: 'get-comments' + related: 'get-comments', }, - data: [ - { type: 'comment', id: '1' } - ] - } - } + data: [{ type: 'comment', id: '1' }], + }, + }, }, included: [ { id: '1', type: 'comment', attributes: { - body: 'This is comment' - } - } - ] + body: 'This is comment', + }, + }, + ], }); return post.get('comments').then(comments => { @@ -3192,16 +3405,18 @@ test("Local relationship data should take precedence over related link when loca }); }); -test("Related link should take precedence over local record data when relationship data is not initially available", function(assert) { +test('Related link should take precedence over local record data when relationship data is not initially available', function(assert) { assert.expect(3); Post.reopen({ - comments: DS.hasMany('comment', { async: true, inverse: 'post' }) + comments: DS.hasMany('comment', { async: true, inverse: 'post' }), }); Comment.reopen({ - post: DS.belongsTo('post', { async: false, inverse: 'comments' }) + post: DS.belongsTo('post', { async: false, inverse: 'comments' }), }); - env.adapter.shouldBackgroundReloadRecord = () => { return false; }; + env.adapter.shouldBackgroundReloadRecord = () => { + return false; + }; env.adapter.findRecord = () => { assert.ok(false, "The adapter's findRecord method should not be called"); }; @@ -3218,10 +3433,10 @@ test("Related link should take precedence over local record data when relationsh id: '1', type: 'comment', attributes: { - body: 'This is comment fetched by link' - } - } - ] + body: 'This is comment fetched by link', + }, + }, + ], }); }; @@ -3233,49 +3448,53 @@ test("Related link should take precedence over local record data when relationsh relationships: { comments: { links: { - related: 'get-comments' - } - } - } + related: 'get-comments', + }, + }, + }, }, included: [ { id: '1', type: 'comment', attributes: { - body: 'This is comment' + body: 'This is comment', }, relationships: { post: { data: { type: 'post', - id: '1' - } - } - } - } - ] + id: '1', + }, + }, + }, + }, + ], }); return post.get('comments').then(comments => { - assert.equal(comments.get('firstObject.body'), 'This is comment fetched by link', 'comment body is correct'); + assert.equal( + comments.get('firstObject.body'), + 'This is comment fetched by link', + 'comment body is correct' + ); }); }); }); -test("Updated related link should take precedence over relationship data and local record data", function(assert) { +test('Updated related link should take precedence over relationship data and local record data', function(assert) { assert.expect(3); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findHasMany = function(store, snapshot, url, relationship) { assert.equal(url, 'comments-updated-link', 'url is correct'); assert.ok(true, "The adapter's findHasMany method should be called"); - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: 'This is updated comment' } } - ]}); + return resolve({ + data: [{ id: 1, type: 'comment', attributes: { body: 'This is updated comment' } }], + }); }; env.adapter.findRecord = function(store, type, id, snapshot) { @@ -3290,14 +3509,12 @@ test("Updated related link should take precedence over relationship data and loc relationships: { comments: { links: { - related: 'comments' + related: 'comments', }, - data: [ - { type: 'comment', id: '1' } - ] - } - } - } + data: [{ type: 'comment', id: '1' }], + }, + }, + }, }); env.store.push({ @@ -3307,31 +3524,37 @@ test("Updated related link should take precedence over relationship data and loc relationships: { comments: { links: { - related: 'comments-updated-link' - } - } - } - } + related: 'comments-updated-link', + }, + }, + }, + }, }); return post.get('comments').then(comments => { - assert.equal(comments.get('firstObject.body'), 'This is updated comment', 'comment body is correct'); + assert.equal( + comments.get('firstObject.body'), + 'This is updated comment', + 'comment body is correct' + ); }); }); }); -test("PromiseArray proxies createRecord to its ManyArray before the hasMany is loaded", function(assert) { +test('PromiseArray proxies createRecord to its ManyArray before the hasMany is loaded', function(assert) { assert.expect(1); Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); env.adapter.findHasMany = function(store, record, link, relationship) { - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; return run(() => { @@ -3342,27 +3565,27 @@ test("PromiseArray proxies createRecord to its ManyArray before the hasMany is l relationships: { comments: { links: { - related: 'someLink' - } - } - } - } + related: 'someLink', + }, + }, + }, + }, }); let comments = post.get('comments'); comments.createRecord(); return comments.then(comments => { - assert.equal(comments.get('length'), 3, "comments have 3 length, including new record"); + assert.equal(comments.get('length'), 3, 'comments have 3 length, including new record'); }); }); }); -test("deleteRecord + unloadRecord fun", function(assert) { +test('deleteRecord + unloadRecord fun', function(assert) { User.reopen({ - posts: DS.hasMany('post', { inverse: null }) + posts: DS.hasMany('post', { inverse: null }), }); Post.reopen({ - user: DS.belongsTo('user', { inverse: null, async: false }) + user: DS.belongsTo('user', { inverse: null, async: false }), }); run(() => { @@ -3372,7 +3595,7 @@ test("deleteRecord + unloadRecord fun", function(assert) { type: 'user', id: 'user-1', attributes: { - name: 'Adolfo Builes' + name: 'Adolfo Builes', }, relationships: { posts: { @@ -3381,17 +3604,17 @@ test("deleteRecord + unloadRecord fun", function(assert) { { type: 'post', id: 'post-2' }, { type: 'post', id: 'post-3' }, { type: 'post', id: 'post-4' }, - { type: 'post', id: 'post-5' } - ] - } - } + { type: 'post', id: 'post-5' }, + ], + }, + }, }, { type: 'post', id: 'post-1' }, { type: 'post', id: 'post-2' }, { type: 'post', id: 'post-3' }, { type: 'post', id: 'post-4' }, - { type: 'post', id: 'post-5' } - ] + { type: 'post', id: 'post-5' }, + ], }); let user = env.store.peekRecord('user', 'user-1'); @@ -3402,51 +3625,70 @@ test("deleteRecord + unloadRecord fun", function(assert) { return { data: null }; }; - assert.deepEqual(posts.map(x => x.get('id')), ['post-1', 'post-2', 'post-3', 'post-4', 'post-5']); + assert.deepEqual(posts.map(x => x.get('id')), [ + 'post-1', + 'post-2', + 'post-3', + 'post-4', + 'post-5', + ]); return run(() => { - return env.store.peekRecord('post', 'post-2').destroyRecord().then(record => { - return env.store.unloadRecord(record); - }); - }).then(() => { - assert.deepEqual(posts.map(x => x.get('id')), ['post-1', 'post-3', 'post-4', 'post-5']); - return env.store.peekRecord('post', 'post-3').destroyRecord().then(record => { - return env.store.unloadRecord(record); - }); - }).then(() => { - assert.deepEqual(posts.map(x => x.get('id')), ['post-1', 'post-4', 'post-5']); - return env.store.peekRecord('post', 'post-4').destroyRecord().then(record => { - return env.store.unloadRecord(record); + return env.store + .peekRecord('post', 'post-2') + .destroyRecord() + .then(record => { + return env.store.unloadRecord(record); + }); + }) + .then(() => { + assert.deepEqual(posts.map(x => x.get('id')), ['post-1', 'post-3', 'post-4', 'post-5']); + return env.store + .peekRecord('post', 'post-3') + .destroyRecord() + .then(record => { + return env.store.unloadRecord(record); + }); + }) + .then(() => { + assert.deepEqual(posts.map(x => x.get('id')), ['post-1', 'post-4', 'post-5']); + return env.store + .peekRecord('post', 'post-4') + .destroyRecord() + .then(record => { + return env.store.unloadRecord(record); + }); + }) + .then(() => { + assert.deepEqual(posts.map(x => x.get('id')), ['post-1', 'post-5']); }); - }).then(() => { - assert.deepEqual(posts.map(x => x.get('id')), ['post-1', 'post-5']); - }); }); }); -test("unloading and reloading a record with hasMany relationship - #3084", function(assert) { +test('unloading and reloading a record with hasMany relationship - #3084', function(assert) { let user; let message; run(() => { env.store.push({ - data: [{ - type: 'user', - id: 'user-1', - attributes: { - name: 'Adolfo Builes' + data: [ + { + type: 'user', + id: 'user-1', + attributes: { + name: 'Adolfo Builes', + }, + relationships: { + messages: { + data: [{ type: 'message', id: 'message-1' }], + }, + }, }, - relationships: { - messages: { - data: [ - { type: 'message', id: 'message-1' } - ] - } - } - }, { - type: 'message', - id: 'message-1' - }] + { + type: 'message', + id: 'message-1', + }, + ], }); user = env.store.peekRecord('user', 'user-1'); @@ -3463,20 +3705,20 @@ test("unloading and reloading a record with hasMany relationship - #3084", funct run(() => { // The record is resurrected for some reason. env.store.push({ - data: [{ - type: 'user', - id: 'user-1', - attributes: { - name: 'Adolfo Builes' + data: [ + { + type: 'user', + id: 'user-1', + attributes: { + name: 'Adolfo Builes', + }, + relationships: { + messages: { + data: [{ type: 'message', id: 'message-1' }], + }, + }, }, - relationships: { - messages: { - data: [ - { type: 'message', id: 'message-1' } - ] - } - } - }] + ], }); user = env.store.peekRecord('user', 'user-1'); @@ -3486,7 +3728,7 @@ test("unloading and reloading a record with hasMany relationship - #3084", funct }); }); -test("deleted records should stay deleted", function(assert) { +test('deleted records should stay deleted', function(assert) { let user; let message; @@ -3496,27 +3738,28 @@ test("deleted records should stay deleted", function(assert) { run(() => { env.store.push({ - data: [{ - type: 'user', - id: 'user-1', - attributes: { - name: 'Adolfo Builes' + data: [ + { + type: 'user', + id: 'user-1', + attributes: { + name: 'Adolfo Builes', + }, + relationships: { + messages: { + data: [{ type: 'message', id: 'message-1' }, { type: 'message', id: 'message-2' }], + }, + }, }, - relationships: { - messages: { - data: [ - { type: 'message', id: 'message-1' }, - { type: 'message', id: 'message-2' } - ] - } - } - }, { - type: 'message', - id: 'message-1' - }, { - type: 'message', - id: 'message-2' - }] + { + type: 'message', + id: 'message-1', + }, + { + type: 'message', + id: 'message-2', + }, + ], }); user = env.store.peekRecord('user', 'user-1'); @@ -3531,15 +3774,17 @@ test("deleted records should stay deleted", function(assert) { // a new message is added to the user should not resurrected the // deleted message env.store.push({ - data: [{ - type: 'message', - id: 'message-3', - relationships: { - user: { - data: { type: 'user', id: 'user-1' } - } - } - }] + data: [ + { + type: 'message', + id: 'message-3', + relationships: { + user: { + data: { type: 'user', id: 'user-1' }, + }, + }, + }, + ], }); assert.deepEqual( @@ -3559,11 +3804,11 @@ test("hasMany relationship with links doesn't trigger extra change notifications relationships: { chapters: { data: [{ type: 'chapter', id: '1' }], - links: { related: '/book/1/chapters' } - } - } + links: { related: '/book/1/chapters' }, + }, + }, }, - included: [{ type: 'chapter', id: '1' }] + included: [{ type: 'chapter', id: '1' }], }); }); @@ -3581,13 +3826,13 @@ test("hasMany relationship with links doesn't trigger extra change notifications assert.equal(count, 0); }); -test("A hasMany relationship with a link will trigger the link request even if a inverse related object is pushed to the store", function(assert) { +test('A hasMany relationship with a link will trigger the link request even if a inverse related object is pushed to the store', function(assert) { Post.reopen({ - comments: DS.hasMany('comment', { async: true }) + comments: DS.hasMany('comment', { async: true }), }); Comment.reopen({ - message: DS.belongsTo('post', { async: true}) + message: DS.belongsTo('post', { async: true }), }); const postID = '1'; @@ -3601,11 +3846,11 @@ test("A hasMany relationship with a link will trigger the link request even if a relationships: { comments: { links: { - related: '/posts/1/comments' - } - } - } - } + related: '/posts/1/comments', + }, + }, + }, + }, }); // if a related comment is pushed into the store, @@ -3616,13 +3861,13 @@ test("A hasMany relationship with a link will trigger the link request even if a data: { type: 'comment', id: '1', - attributes: { body: "First" }, + attributes: { body: 'First' }, relationships: { message: { - data: { type: 'post', id: postID } - } - } - } + data: { type: 'post', id: postID }, + }, + }, + }, }); env.adapter.findRecord = function(store, type, id, snapshot) { @@ -3631,28 +3876,33 @@ test("A hasMany relationship with a link will trigger the link request even if a let hasManyCounter = 0; env.adapter.findHasMany = function(store, snapshot, link, relationship) { - assert.equal(relationship.type, 'comment', "findHasMany relationship type was Comment"); - assert.equal(relationship.key, 'comments', "findHasMany relationship key was comments"); - assert.equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments"); + assert.equal(relationship.type, 'comment', 'findHasMany relationship type was Comment'); + assert.equal(relationship.key, 'comments', 'findHasMany relationship key was comments'); + assert.equal(link, '/posts/1/comments', 'findHasMany link was /posts/1/comments'); hasManyCounter++; - return resolve({ data: [ - { id: 1, type: 'comment', attributes: { body: "First" } }, - { id: 2, type: 'comment', attributes: { body: "Second" } } - ]}); + return resolve({ + data: [ + { id: 1, type: 'comment', attributes: { body: 'First' } }, + { id: 2, type: 'comment', attributes: { body: 'Second' } }, + ], + }); }; const post = env.store.peekRecord('post', postID); post.get('comments').then(function(comments) { - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(hasManyCounter, 1, "link was requested"); - assert.equal(comments.get('length'), 2, "comments have 2 length"); - - post.hasMany('comments').reload().then(function(comments) { - assert.equal(comments.get('isLoaded'), true, "comments are loaded"); - assert.equal(hasManyCounter, 2, "link was requested"); - assert.equal(comments.get('length'), 2, "comments have 2 length"); - }); + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(hasManyCounter, 1, 'link was requested'); + assert.equal(comments.get('length'), 2, 'comments have 2 length'); + + post + .hasMany('comments') + .reload() + .then(function(comments) { + assert.equal(comments.get('isLoaded'), true, 'comments are loaded'); + assert.equal(hasManyCounter, 2, 'link was requested'); + assert.equal(comments.get('length'), 2, 'comments have 2 length'); + }); }); }); }); diff --git a/tests/integration/relationships/inverse-relationships-test.js b/tests/integration/relationships/inverse-relationships-test.js index 5483d77e124..1c913b5e739 100644 --- a/tests/integration/relationships/inverse-relationships-test.js +++ b/tests/integration/relationships/inverse-relationships-test.js @@ -7,23 +7,19 @@ import { module, test } from 'qunit'; import DS from 'ember-data'; -let { - Model, - hasMany, - belongsTo -} = DS; +let { Model, hasMany, belongsTo } = DS; var Post, Comment, Message, User; module('integration/relationships/inverse_relationships - Inverse Relationships'); -test("When a record is added to a has-many relationship, the inverse belongsTo is determined automatically", function(assert) { +test('When a record is added to a has-many relationship, the inverse belongsTo is determined automatically', function(assert) { Post = DS.Model.extend({ - comments: DS.hasMany('comment', { async: false }) + comments: DS.hasMany('comment', { async: false }), }); Comment = DS.Model.extend({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); var env = setupStore({ post: Post, comment: Comment }); @@ -32,74 +28,90 @@ test("When a record is added to a has-many relationship, the inverse belongsTo i let comment = store.createRecord('comment'); let post = store.createRecord('post'); - assert.equal(comment.get('post'), null, "no post has been set on the comment"); + assert.equal(comment.get('post'), null, 'no post has been set on the comment'); run(function() { post.get('comments').pushObject(comment); }); - assert.equal(comment.get('post'), post, "post was set on the comment"); + assert.equal(comment.get('post'), post, 'post was set on the comment'); }); -test("Inverse relationships can be explicitly nullable", function(assert) { +test('Inverse relationships can be explicitly nullable', function(assert) { User = DS.Model.extend(); Post = DS.Model.extend({ lastParticipant: DS.belongsTo('user', { inverse: null, async: false }), - participants: DS.hasMany('user', { inverse: 'posts', async: false }) + participants: DS.hasMany('user', { inverse: 'posts', async: false }), }); User.reopen({ - posts: DS.hasMany('post', { inverse: 'participants', async: false }) + posts: DS.hasMany('post', { inverse: 'participants', async: false }), }); var store = createStore({ user: User, - post: Post + post: Post, }); let user = store.createRecord('user'); let post = store.createRecord('post'); - assert.equal(user.inverseFor('posts').name, 'participants', 'User.posts inverse is Post.participants'); + assert.equal( + user.inverseFor('posts').name, + 'participants', + 'User.posts inverse is Post.participants' + ); assert.equal(post.inverseFor('lastParticipant'), null, 'Post.lastParticipant has no inverse'); - assert.equal(post.inverseFor('participants').name, 'posts', 'Post.participants inverse is User.posts'); + assert.equal( + post.inverseFor('participants').name, + 'posts', + 'Post.participants inverse is User.posts' + ); }); -test("Null inverses are excluded from potential relationship resolutions", function(assert) { +test('Null inverses are excluded from potential relationship resolutions', function(assert) { User = Model.extend(); Post = Model.extend({ lastParticipant: belongsTo('user', { inverse: null, async: false }), - participants: hasMany('user', { async: false }) + participants: hasMany('user', { async: false }), }); User.reopen({ - posts: hasMany('post', { async: false }) + posts: hasMany('post', { async: false }), }); let store = createStore({ user: User, - post: Post + post: Post, }); let user = store.createRecord('user'); let post = store.createRecord('post'); - assert.equal(user.inverseFor('posts').name, 'participants', 'User.posts inverse is Post.participants'); + assert.equal( + user.inverseFor('posts').name, + 'participants', + 'User.posts inverse is Post.participants' + ); assert.equal(post.inverseFor('lastParticipant'), null, 'Post.lastParticipant has no inverse'); - assert.equal(post.inverseFor('participants').name, 'posts', 'Post.participants inverse is User.posts'); + assert.equal( + post.inverseFor('participants').name, + 'posts', + 'Post.participants inverse is User.posts' + ); }); -test("When a record is added to a has-many relationship, the inverse belongsTo can be set explicitly", function(assert) { +test('When a record is added to a has-many relationship, the inverse belongsTo can be set explicitly', function(assert) { Post = DS.Model.extend({ - comments: DS.hasMany('comment', { inverse: 'redPost', async: false }) + comments: DS.hasMany('comment', { inverse: 'redPost', async: false }), }); Comment = DS.Model.extend({ onePost: DS.belongsTo('post', { async: false }), twoPost: DS.belongsTo('post', { async: false }), redPost: DS.belongsTo('post', { async: false }), - bluePost: DS.belongsTo('post', { async: false }) + bluePost: DS.belongsTo('post', { async: false }), }); var env = setupStore({ post: Post, comment: Comment }); @@ -108,30 +120,30 @@ test("When a record is added to a has-many relationship, the inverse belongsTo c let comment = store.createRecord('comment'); let post = store.createRecord('post'); - assert.equal(comment.get('onePost'), null, "onePost has not been set on the comment"); - assert.equal(comment.get('twoPost'), null, "twoPost has not been set on the comment"); - assert.equal(comment.get('redPost'), null, "redPost has not been set on the comment"); - assert.equal(comment.get('bluePost'), null, "bluePost has not been set on the comment"); + assert.equal(comment.get('onePost'), null, 'onePost has not been set on the comment'); + assert.equal(comment.get('twoPost'), null, 'twoPost has not been set on the comment'); + assert.equal(comment.get('redPost'), null, 'redPost has not been set on the comment'); + assert.equal(comment.get('bluePost'), null, 'bluePost has not been set on the comment'); run(function() { post.get('comments').pushObject(comment); }); - assert.equal(comment.get('onePost'), null, "onePost has not been set on the comment"); - assert.equal(comment.get('twoPost'), null, "twoPost has not been set on the comment"); - assert.equal(comment.get('redPost'), post, "redPost has been set on the comment"); - assert.equal(comment.get('bluePost'), null, "bluePost has not been set on the comment"); + assert.equal(comment.get('onePost'), null, 'onePost has not been set on the comment'); + assert.equal(comment.get('twoPost'), null, 'twoPost has not been set on the comment'); + assert.equal(comment.get('redPost'), post, 'redPost has been set on the comment'); + assert.equal(comment.get('bluePost'), null, 'bluePost has not been set on the comment'); }); test("When a record's belongsTo relationship is set, it can specify the inverse hasMany to which the new child should be added", function(assert) { Post = DS.Model.extend({ meComments: DS.hasMany('comment', { async: false }), youComments: DS.hasMany('comment', { async: false }), - everyoneWeKnowComments: DS.hasMany('comment', { async: false }) + everyoneWeKnowComments: DS.hasMany('comment', { async: false }), }); Comment = DS.Model.extend({ - post: DS.belongsTo('post', { inverse: 'youComments', async: false }) + post: DS.belongsTo('post', { inverse: 'youComments', async: false }), }); var env = setupStore({ post: Post, comment: Comment }); @@ -142,27 +154,31 @@ test("When a record's belongsTo relationship is set, it can specify the inverse comment = store.createRecord('comment'); post = store.createRecord('post'); - assert.equal(post.get('meComments.length'), 0, "meComments has no posts"); - assert.equal(post.get('youComments.length'), 0, "youComments has no posts"); - assert.equal(post.get('everyoneWeKnowComments.length'), 0, "everyoneWeKnowComments has no posts"); + assert.equal(post.get('meComments.length'), 0, 'meComments has no posts'); + assert.equal(post.get('youComments.length'), 0, 'youComments has no posts'); + assert.equal( + post.get('everyoneWeKnowComments.length'), + 0, + 'everyoneWeKnowComments has no posts' + ); comment.set('post', post); }); assert.equal(comment.get('post'), post, 'The post that was set can be retrieved'); - assert.equal(post.get('meComments.length'), 0, "meComments has no posts"); - assert.equal(post.get('youComments.length'), 1, "youComments had the post added"); - assert.equal(post.get('everyoneWeKnowComments.length'), 0, "everyoneWeKnowComments has no posts"); + assert.equal(post.get('meComments.length'), 0, 'meComments has no posts'); + assert.equal(post.get('youComments.length'), 1, 'youComments had the post added'); + assert.equal(post.get('everyoneWeKnowComments.length'), 0, 'everyoneWeKnowComments has no posts'); }); -test("When setting a belongsTo, the OneToOne invariant is respected even when other records have been previously used", function(assert) { +test('When setting a belongsTo, the OneToOne invariant is respected even when other records have been previously used', function(assert) { Post = DS.Model.extend({ - bestComment: DS.belongsTo('comment', { async: false }) + bestComment: DS.belongsTo('comment', { async: false }), }); Comment = DS.Model.extend({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); var env = setupStore({ post: Post, comment: Comment }); @@ -190,18 +206,18 @@ test("When setting a belongsTo, the OneToOne invariant is respected even when ot assert.equal(post2.get('bestComment'), comment); }); -test("When setting a belongsTo, the OneToOne invariant is transitive", function(assert) { +test('When setting a belongsTo, the OneToOne invariant is transitive', function(assert) { Post = DS.Model.extend({ - bestComment: DS.belongsTo('comment', { async: false }) + bestComment: DS.belongsTo('comment', { async: false }), }); Comment = DS.Model.extend({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); var store = createStore({ post: Post, - comment: Comment + comment: Comment, }); let comment = store.createRecord('comment'); @@ -225,18 +241,18 @@ test("When setting a belongsTo, the OneToOne invariant is transitive", function( assert.equal(post2.get('bestComment'), comment); }); -test("When setting a belongsTo, the OneToOne invariant is commutative", function(assert) { +test('When setting a belongsTo, the OneToOne invariant is commutative', function(assert) { Post = DS.Model.extend({ - bestComment: DS.belongsTo('comment', { async: false }) + bestComment: DS.belongsTo('comment', { async: false }), }); Comment = DS.Model.extend({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); var store = createStore({ post: Post, - comment: Comment + comment: Comment, }); let post = store.createRecord('post'); @@ -260,14 +276,14 @@ test("When setting a belongsTo, the OneToOne invariant is commutative", function assert.equal(comment2.get('post'), post); }); -test("OneToNone relationship works", function(assert) { +test('OneToNone relationship works', function(assert) { assert.expect(3); Post = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); Comment = DS.Model.extend({ - post: DS.belongsTo('post', { async: false }) + post: DS.belongsTo('post', { async: false }), }); var env = setupStore({ post: Post, comment: Comment }); @@ -293,21 +309,20 @@ test("OneToNone relationship works", function(assert) { assert.equal(comment.get('post'), post1, 'the post is re-set to the first one'); }); - -test("When a record is added to or removed from a polymorphic has-many relationship, the inverse belongsTo can be set explicitly", function(assert) { +test('When a record is added to or removed from a polymorphic has-many relationship, the inverse belongsTo can be set explicitly', function(assert) { User = DS.Model.extend({ messages: DS.hasMany('message', { async: false, inverse: 'redUser', - polymorphic: true - }) + polymorphic: true, + }), }); Message = DS.Model.extend({ oneUser: DS.belongsTo('user', { async: false }), twoUser: DS.belongsTo('user', { async: false }), redUser: DS.belongsTo('user', { async: false }), - blueUser: DS.belongsTo('user', { async: false }) + blueUser: DS.belongsTo('user', { async: false }), }); Post = Message.extend(); @@ -318,39 +333,39 @@ test("When a record is added to or removed from a polymorphic has-many relations let post = store.createRecord('post'); let user = store.createRecord('user'); - assert.equal(post.get('oneUser'), null, "oneUser has not been set on the user"); - assert.equal(post.get('twoUser'), null, "twoUser has not been set on the user"); - assert.equal(post.get('redUser'), null, "redUser has not been set on the user"); - assert.equal(post.get('blueUser'), null, "blueUser has not been set on the user"); + assert.equal(post.get('oneUser'), null, 'oneUser has not been set on the user'); + assert.equal(post.get('twoUser'), null, 'twoUser has not been set on the user'); + assert.equal(post.get('redUser'), null, 'redUser has not been set on the user'); + assert.equal(post.get('blueUser'), null, 'blueUser has not been set on the user'); run(function() { user.get('messages').pushObject(post); }); - assert.equal(post.get('oneUser'), null, "oneUser has not been set on the user"); - assert.equal(post.get('twoUser'), null, "twoUser has not been set on the user"); - assert.equal(post.get('redUser'), user, "redUser has been set on the user"); - assert.equal(post.get('blueUser'), null, "blueUser has not been set on the user"); + assert.equal(post.get('oneUser'), null, 'oneUser has not been set on the user'); + assert.equal(post.get('twoUser'), null, 'twoUser has not been set on the user'); + assert.equal(post.get('redUser'), user, 'redUser has been set on the user'); + assert.equal(post.get('blueUser'), null, 'blueUser has not been set on the user'); run(function() { user.get('messages').popObject(); }); - assert.equal(post.get('oneUser'), null, "oneUser has not been set on the user"); - assert.equal(post.get('twoUser'), null, "twoUser has not been set on the user"); - assert.equal(post.get('redUser'), null, "redUser has bot been set on the user"); - assert.equal(post.get('blueUser'), null, "blueUser has not been set on the user"); + assert.equal(post.get('oneUser'), null, 'oneUser has not been set on the user'); + assert.equal(post.get('twoUser'), null, 'twoUser has not been set on the user'); + assert.equal(post.get('redUser'), null, 'redUser has bot been set on the user'); + assert.equal(post.get('blueUser'), null, 'blueUser has not been set on the user'); }); test("When a record's belongsTo relationship is set, it can specify the inverse polymorphic hasMany to which the new child should be added or removed", function(assert) { User = DS.Model.extend({ meMessages: DS.hasMany('message', { polymorphic: true, async: false }), youMessages: DS.hasMany('message', { polymorphic: true, async: false }), - everyoneWeKnowMessages: DS.hasMany('message', { polymorphic: true, async: false }) + everyoneWeKnowMessages: DS.hasMany('message', { polymorphic: true, async: false }), }); Message = DS.Model.extend({ - user: DS.belongsTo('user', { inverse: 'youMessages', async: false }) + user: DS.belongsTo('user', { inverse: 'youMessages', async: false }), }); Post = Message.extend(); @@ -361,32 +376,32 @@ test("When a record's belongsTo relationship is set, it can specify the inverse let user = store.createRecord('user'); let post = store.createRecord('post'); - assert.equal(user.get('meMessages.length'), 0, "meMessages has no posts"); - assert.equal(user.get('youMessages.length'), 0, "youMessages has no posts"); - assert.equal(user.get('everyoneWeKnowMessages.length'), 0, "everyoneWeKnowMessages has no posts"); + assert.equal(user.get('meMessages.length'), 0, 'meMessages has no posts'); + assert.equal(user.get('youMessages.length'), 0, 'youMessages has no posts'); + assert.equal(user.get('everyoneWeKnowMessages.length'), 0, 'everyoneWeKnowMessages has no posts'); run(function() { post.set('user', user); }); - assert.equal(user.get('meMessages.length'), 0, "meMessages has no posts"); - assert.equal(user.get('youMessages.length'), 1, "youMessages had the post added"); - assert.equal(user.get('everyoneWeKnowMessages.length'), 0, "everyoneWeKnowMessages has no posts"); + assert.equal(user.get('meMessages.length'), 0, 'meMessages has no posts'); + assert.equal(user.get('youMessages.length'), 1, 'youMessages had the post added'); + assert.equal(user.get('everyoneWeKnowMessages.length'), 0, 'everyoneWeKnowMessages has no posts'); run(function() { post.set('user', null); }); - assert.equal(user.get('meMessages.length'), 0, "meMessages has no posts"); - assert.equal(user.get('youMessages.length'), 0, "youMessages has no posts"); - assert.equal(user.get('everyoneWeKnowMessages.length'), 0, "everyoneWeKnowMessages has no posts"); + assert.equal(user.get('meMessages.length'), 0, 'meMessages has no posts'); + assert.equal(user.get('youMessages.length'), 0, 'youMessages has no posts'); + assert.equal(user.get('everyoneWeKnowMessages.length'), 0, 'everyoneWeKnowMessages has no posts'); }); test("When a record's polymorphic belongsTo relationship is set, it can specify the inverse hasMany to which the new child should be added", function(assert) { Message = DS.Model.extend({ meMessages: DS.hasMany('comment', { inverse: null, async: false }), youMessages: DS.hasMany('comment', { inverse: 'message', async: false }), - everyoneWeKnowMessages: DS.hasMany('comment', { inverse: null, async: false }) + everyoneWeKnowMessages: DS.hasMany('comment', { inverse: null, async: false }), }); Post = Message.extend(); @@ -395,8 +410,8 @@ test("When a record's polymorphic belongsTo relationship is set, it can specify message: DS.belongsTo('message', { async: false, polymorphic: true, - inverse: 'youMessages' - }) + inverse: 'youMessages', + }), }); var env = setupStore({ comment: Comment, message: Message, post: Post }); @@ -405,33 +420,35 @@ test("When a record's polymorphic belongsTo relationship is set, it can specify let comment = store.createRecord('comment'); let post = store.createRecord('post'); - assert.equal(post.get('meMessages.length'), 0, "meMessages has no posts"); - assert.equal(post.get('youMessages.length'), 0, "youMessages has no posts"); - assert.equal(post.get('everyoneWeKnowMessages.length'), 0, "everyoneWeKnowMessages has no posts"); + assert.equal(post.get('meMessages.length'), 0, 'meMessages has no posts'); + assert.equal(post.get('youMessages.length'), 0, 'youMessages has no posts'); + assert.equal(post.get('everyoneWeKnowMessages.length'), 0, 'everyoneWeKnowMessages has no posts'); run(function() { comment.set('message', post); }); - assert.equal(post.get('meMessages.length'), 0, "meMessages has no posts"); - assert.equal(post.get('youMessages.length'), 1, "youMessages had the post added"); - assert.equal(post.get('everyoneWeKnowMessages.length'), 0, "everyoneWeKnowMessages has no posts"); + assert.equal(post.get('meMessages.length'), 0, 'meMessages has no posts'); + assert.equal(post.get('youMessages.length'), 1, 'youMessages had the post added'); + assert.equal(post.get('everyoneWeKnowMessages.length'), 0, 'everyoneWeKnowMessages has no posts'); run(function() { comment.set('message', null); }); - assert.equal(post.get('meMessages.length'), 0, "meMessages has no posts"); - assert.equal(post.get('youMessages.length'), 0, "youMessages has no posts"); - assert.equal(post.get('everyoneWeKnowMessages.length'), 0, "everyoneWeKnowMessages has no posts"); + assert.equal(post.get('meMessages.length'), 0, 'meMessages has no posts'); + assert.equal(post.get('youMessages.length'), 0, 'youMessages has no posts'); + assert.equal(post.get('everyoneWeKnowMessages.length'), 0, 'everyoneWeKnowMessages has no posts'); }); -testInDebug("Inverse relationships that don't exist throw a nice error for a hasMany", function(assert) { +testInDebug("Inverse relationships that don't exist throw a nice error for a hasMany", function( + assert +) { User = DS.Model.extend(); Comment = DS.Model.extend(); Post = DS.Model.extend({ - comments: DS.hasMany('comment', { inverse: 'testPost', async: false }) + comments: DS.hasMany('comment', { inverse: 'testPost', async: false }), }); var env = setupStore({ post: Post, comment: Comment, user: User }); @@ -447,12 +464,14 @@ testInDebug("Inverse relationships that don't exist throw a nice error for a has }, /We found no inverse relationships by the name of 'testPost' on the 'comment' model/); }); -testInDebug("Inverse relationships that don't exist throw a nice error for a belongsTo", function(assert) { +testInDebug("Inverse relationships that don't exist throw a nice error for a belongsTo", function( + assert +) { User = DS.Model.extend(); Comment = DS.Model.extend(); Post = DS.Model.extend({ - user: DS.belongsTo('user', { inverse: 'testPost', async: false }) + user: DS.belongsTo('user', { inverse: 'testPost', async: false }), }); var env = setupStore({ post: Post, comment: Comment, user: User }); @@ -467,22 +486,22 @@ testInDebug("Inverse relationships that don't exist throw a nice error for a bel }, /We found no inverse relationships by the name of 'testPost' on the 'user' model/); }); -skipRecordData("inverseFor short-circuits when inverse is null", function(assert) { +skipRecordData('inverseFor short-circuits when inverse is null', function(assert) { assert.expect(4); Post = DS.Model.extend({ - comments: DS.hasMany('comment', { async: false, inverse: null }) + comments: DS.hasMany('comment', { async: false, inverse: null }), }); Comment = DS.Model.extend({ - post: DS.belongsTo('post', { async: false, inverse: null }) + post: DS.belongsTo('post', { async: false, inverse: null }), }); User = DS.Model.extend({ - messages: DS.hasMany('message', { async: false, inverse: 'user' }) + messages: DS.hasMany('message', { async: false, inverse: 'user' }), }); Message = DS.Model.extend({ - user: DS.belongsTo('user', { async: false, inverse: 'messages' }) + user: DS.belongsTo('user', { async: false, inverse: 'messages' }), }); var env = setupStore({ post: Post, comment: Comment, user: User, message: Message }); @@ -514,16 +533,16 @@ skipRecordData("inverseFor short-circuits when inverse is null", function(assert data: [ { id: '1', - type: 'comment' + type: 'comment', }, { id: '2', - type: 'comment' - } - ] - } - } - } + type: 'comment', + }, + ], + }, + }, + }, }); store.push({ data: [ @@ -534,10 +553,10 @@ skipRecordData("inverseFor short-circuits when inverse is null", function(assert post: { data: { id: '1', - type: 'post' - } - } - } + type: 'post', + }, + }, + }, }, { id: '2', @@ -546,12 +565,12 @@ skipRecordData("inverseFor short-circuits when inverse is null", function(assert post: { data: { id: '1', - type: 'post' - } - } - } - } - ] + type: 'post', + }, + }, + }, + }, + ], }); store.push({ data: { @@ -562,16 +581,16 @@ skipRecordData("inverseFor short-circuits when inverse is null", function(assert data: [ { id: '1', - type: 'message' + type: 'message', }, { id: '2', - type: 'message' - } - ] - } - } - } + type: 'message', + }, + ], + }, + }, + }, }); store.push({ data: [ @@ -582,10 +601,10 @@ skipRecordData("inverseFor short-circuits when inverse is null", function(assert user: { data: { id: '1', - type: 'user' - } - } - } + type: 'user', + }, + }, + }, }, { id: '2', @@ -594,32 +613,32 @@ skipRecordData("inverseFor short-circuits when inverse is null", function(assert post: { data: { id: '1', - type: 'user' - } - } - } - } - ] + type: 'user', + }, + }, + }, + }, + ], }); }); }); -testRecordData("inverseFor is only called when inverse is not null", function(assert) { +testRecordData('inverseFor is only called when inverse is not null', function(assert) { assert.expect(2); Post = DS.Model.extend({ - comments: DS.hasMany('comment', { async: false, inverse: null }) + comments: DS.hasMany('comment', { async: false, inverse: null }), }); Comment = DS.Model.extend({ - post: DS.belongsTo('post', { async: false, inverse: null }) + post: DS.belongsTo('post', { async: false, inverse: null }), }); User = DS.Model.extend({ - messages: DS.hasMany('message', { async: false, inverse: 'user' }) + messages: DS.hasMany('message', { async: false, inverse: 'user' }), }); Message = DS.Model.extend({ - user: DS.belongsTo('user', { async: false, inverse: 'messages' }) + user: DS.belongsTo('user', { async: false, inverse: 'messages' }), }); var env = setupStore({ post: Post, comment: Comment, user: User, message: Message }); @@ -651,16 +670,16 @@ testRecordData("inverseFor is only called when inverse is not null", function(as data: [ { id: '1', - type: 'comment' + type: 'comment', }, { id: '2', - type: 'comment' - } - ] - } - } - } + type: 'comment', + }, + ], + }, + }, + }, }); store.push({ data: [ @@ -671,10 +690,10 @@ testRecordData("inverseFor is only called when inverse is not null", function(as post: { data: { id: '1', - type: 'post' - } - } - } + type: 'post', + }, + }, + }, }, { id: '2', @@ -683,12 +702,12 @@ testRecordData("inverseFor is only called when inverse is not null", function(as post: { data: { id: '1', - type: 'post' - } - } - } - } - ] + type: 'post', + }, + }, + }, + }, + ], }); store.push({ data: { @@ -699,16 +718,16 @@ testRecordData("inverseFor is only called when inverse is not null", function(as data: [ { id: '1', - type: 'message' + type: 'message', }, { id: '2', - type: 'message' - } - ] - } - } - } + type: 'message', + }, + ], + }, + }, + }, }); store.push({ data: [ @@ -719,10 +738,10 @@ testRecordData("inverseFor is only called when inverse is not null", function(as user: { data: { id: '1', - type: 'user' - } - } - } + type: 'user', + }, + }, + }, }, { id: '2', @@ -731,27 +750,30 @@ testRecordData("inverseFor is only called when inverse is not null", function(as post: { data: { id: '1', - type: 'user' - } - } - } - } - ] + type: 'user', + }, + }, + }, + }, + ], }); }); }); -testInDebug("Inverse null relationships with models that don't exist throw a nice error if trying to use that relationship", function(assert) { - User = DS.Model.extend({ - post: DS.belongsTo('post', { inverse: null }) - }); +testInDebug( + "Inverse null relationships with models that don't exist throw a nice error if trying to use that relationship", + function(assert) { + User = DS.Model.extend({ + post: DS.belongsTo('post', { inverse: null }), + }); - let env = setupStore({ user: User }); + let env = setupStore({ user: User }); - assert.expectAssertion(() => { - env.store.createRecord('user', { post: {}}); - }, /No model was found for/) + assert.expectAssertion(() => { + env.store.createRecord('user', { post: {} }); + }, /No model was found for/); - // but don't error if the relationship is not used - env.store.createRecord('user', {}); -}); + // but don't error if the relationship is not used + env.store.createRecord('user', {}); + } +); diff --git a/tests/integration/relationships/json-api-links-test.js b/tests/integration/relationships/json-api-links-test.js index d92ea3d1879..d875ce1ed0a 100644 --- a/tests/integration/relationships/json-api-links-test.js +++ b/tests/integration/relationships/json-api-links-test.js @@ -2,39 +2,37 @@ import { run } from '@ember/runloop'; import { get } from '@ember/object'; import { resolve } from 'rsvp'; import setupStore from 'dummy/tests/helpers/store'; -import { - reset as resetModelFactoryInjection -} from 'dummy/tests/helpers/model-factory-injection'; +import { reset as resetModelFactoryInjection } from 'dummy/tests/helpers/model-factory-injection'; import { module, test } from 'qunit'; import DS from 'ember-data'; -import JSONAPIAdapter from "ember-data/adapters/json-api"; +import JSONAPIAdapter from 'ember-data/adapters/json-api'; import deepCopy from 'dummy/tests/helpers/deep-copy'; const { Model, attr, hasMany, belongsTo } = DS; let env, User, Organisation; -module("integration/relationship/json-api-links | Relationship state updates", { +module('integration/relationship/json-api-links | Relationship state updates', { beforeEach() {}, afterEach() { resetModelFactoryInjection(); run(env.container, 'destroy'); - } + }, }); -test("Loading link with inverse:null on other model caches the two ends separately", function (assert) { +test('Loading link with inverse:null on other model caches the two ends separately', function(assert) { User = DS.Model.extend({ - organisation: belongsTo('organisation', { inverse: null }) + organisation: belongsTo('organisation', { inverse: null }), }); Organisation = DS.Model.extend({ - adminUsers: hasMany('user', { inverse: null }) + adminUsers: hasMany('user', { inverse: null }), }); env = setupStore({ user: User, - organisation: Organisation + organisation: Organisation, }); env.registry.optionsForType('serializer', { singleton: false }); @@ -45,74 +43,89 @@ test("Loading link with inverse:null on other model caches the two ends separate User = store.modelFor('user'); Organisation = store.modelFor('organisation'); - env.registry.register('adapter:user', DS.JSONAPISerializer.extend({ - findRecord(store, type, id) { - return resolve({ - data: { - id, - type: 'user', - relationships: { - organisation: { - data: { id: 1, type: 'organisation' } - } - } - } - }); - } - })); - - env.registry.register('adapter:organisation', DS.JSONAPISerializer.extend({ - findRecord(store, type, id) { - return resolve({ - data: { - type: 'organisation', - id, - relationships: { - 'admin-users': { - links: { - related: '/org-admins' - } - } - } - } - }); - } - })); + env.registry.register( + 'adapter:user', + DS.JSONAPISerializer.extend({ + findRecord(store, type, id) { + return resolve({ + data: { + id, + type: 'user', + relationships: { + organisation: { + data: { id: 1, type: 'organisation' }, + }, + }, + }, + }); + }, + }) + ); + + env.registry.register( + 'adapter:organisation', + DS.JSONAPISerializer.extend({ + findRecord(store, type, id) { + return resolve({ + data: { + type: 'organisation', + id, + relationships: { + 'admin-users': { + links: { + related: '/org-admins', + }, + }, + }, + }, + }); + }, + }) + ); return run(() => { - return store.findRecord('user', 1) - .then(user1 => { - assert.ok(user1, 'user should be populated'); - - return store.findRecord('organisation', 2) - .then(org2FromFind => { - assert.equal(user1.belongsTo('organisation').remoteType(), 'id', `user's belongsTo is based on id`); - assert.equal(user1.belongsTo('organisation').id(), 1, `user's belongsTo has its id populated`); - - return user1.get('organisation') - .then(orgFromUser => { - assert.equal(user1.belongsTo('organisation').belongsToRelationship.relationshipIsStale, false, 'user should have loaded its belongsTo relationship'); - - assert.ok(org2FromFind, 'organisation we found should be populated'); - assert.ok(orgFromUser, 'user\'s organisation should be populated'); - }) - }) - }) + return store.findRecord('user', 1).then(user1 => { + assert.ok(user1, 'user should be populated'); + + return store.findRecord('organisation', 2).then(org2FromFind => { + assert.equal( + user1.belongsTo('organisation').remoteType(), + 'id', + `user's belongsTo is based on id` + ); + assert.equal( + user1.belongsTo('organisation').id(), + 1, + `user's belongsTo has its id populated` + ); + + return user1.get('organisation').then(orgFromUser => { + assert.equal( + user1.belongsTo('organisation').belongsToRelationship.relationshipIsStale, + false, + 'user should have loaded its belongsTo relationship' + ); + + assert.ok(org2FromFind, 'organisation we found should be populated'); + assert.ok(orgFromUser, "user's organisation should be populated"); + }); + }); + }); }); }); -test("Pushing child record should not mark parent:children as loaded", function (assert) { +test('Pushing child record should not mark parent:children as loaded', function(assert) { let Child = DS.Model.extend({ - parent: belongsTo('parent', { inverse: 'children' }) + parent: belongsTo('parent', { inverse: 'children' }), }); let Parent = DS.Model.extend({ - children: hasMany('child', { inverse: 'parent' }) + children: hasMany('child', { inverse: 'parent' }), }); env = setupStore({ parent: Parent, - child: Child + child: Child, }); env.registry.optionsForType('serializer', { singleton: false }); @@ -131,11 +144,11 @@ test("Pushing child record should not mark parent:children as loaded", function relationships: { children: { links: { - related: '/parent/1/children' - } - } - } - } + related: '/parent/1/children', + }, + }, + }, + }, }); store.push({ @@ -146,23 +159,27 @@ test("Pushing child record should not mark parent:children as loaded", function parent: { data: { id: 'p1', - type: 'parent' - } - } - } - } + type: 'parent', + }, + }, + }, + }, }); - assert.equal(parent.hasMany('children').hasManyRelationship.relationshipIsStale, true, 'parent should think that children still needs to be loaded'); + assert.equal( + parent.hasMany('children').hasManyRelationship.relationshipIsStale, + true, + 'parent should think that children still needs to be loaded' + ); }); }); -test("pushing has-many payloads with data (no links), then more data (no links) works as expected", function(assert) { +test('pushing has-many payloads with data (no links), then more data (no links) works as expected', function(assert) { const User = Model.extend({ - pets: hasMany('pet', { async: true, inverse: 'owner' }) + pets: hasMany('pet', { async: true, inverse: 'owner' }), }); const Pet = Model.extend({ - owner: belongsTo('user', { async: false, inverse: 'pets' }) + owner: belongsTo('user', { async: false, inverse: 'pets' }), }); const Adapter = JSONAPIAdapter.extend({ findHasMany() { @@ -179,63 +196,62 @@ test("pushing has-many payloads with data (no links), then more data (no links) id, relationships: { owner: { - data: { type: 'user', id: '1' } - } - } - } + data: { type: 'user', id: '1' }, + }, + }, + }, }); - } + }, }); env = setupStore({ adapter: Adapter, user: User, - pet: Pet + pet: Pet, }); let { store } = env; // push data, no links - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' } - ] - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }], + }, + }, + }, + }) + ); // push links, no data - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - data: [ - { type: 'pet', id: '2' }, - { type: 'pet', id: '3' } - ] - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + data: [{ type: 'pet', id: '2' }, { type: 'pet', id: '3' }], + }, + }, + }, + }) + ); let Chris = run(() => store.peekRecord('user', '1')); run(() => get(Chris, 'pets')); }); -test("pushing has-many payloads with data (no links), then links (no data) works as expected", function(assert) { +test('pushing has-many payloads with data (no links), then links (no data) works as expected', function(assert) { const User = Model.extend({ - pets: hasMany('pet', { async: true, inverse: 'owner' }) + pets: hasMany('pet', { async: true, inverse: 'owner' }), }); const Pet = Model.extend({ - owner: belongsTo('user', { async: false, inverse: 'pets' }) + owner: belongsTo('user', { async: false, inverse: 'pets' }), }); const Adapter = JSONAPIAdapter.extend({ findHasMany(_, __, link) { @@ -247,20 +263,20 @@ test("pushing has-many payloads with data (no links), then links (no data) works id: '1', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } + data: { type: 'user', id: '1' }, + }, + }, }, { type: 'pet', id: '2', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } - } - ] + data: { type: 'user', id: '1' }, + }, + }, + }, + ], }); }, findMany() { @@ -268,57 +284,59 @@ test("pushing has-many payloads with data (no links), then links (no data) works }, findRecord() { assert.ok(false, 'adapter findRecord called instead of using findHasMany with a link'); - } + }, }); env = setupStore({ adapter: Adapter, user: User, - pet: Pet + pet: Pet, }); let { store } = env; // push data, no links - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' } - ] - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }], + }, + }, + }, + }) + ); // push links, no data - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - links: { - related: './user/1/pets' - } - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + links: { + related: './user/1/pets', + }, + }, + }, + }, + }) + ); let Chris = run(() => store.peekRecord('user', '1')); run(() => get(Chris, 'pets')); }); -test("pushing has-many payloads with links (no data), then data (no links) works as expected", function(assert) { +test('pushing has-many payloads with links (no data), then data (no links) works as expected', function(assert) { const User = Model.extend({ - pets: hasMany('pet', { async: true, inverse: 'owner' }) + pets: hasMany('pet', { async: true, inverse: 'owner' }), }); const Pet = Model.extend({ - owner: belongsTo('user', { async: false, inverse: 'pets' }) + owner: belongsTo('user', { async: false, inverse: 'pets' }), }); const Adapter = JSONAPIAdapter.extend({ findHasMany(_, __, link) { @@ -330,20 +348,20 @@ test("pushing has-many payloads with links (no data), then data (no links) works id: '1', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } + data: { type: 'user', id: '1' }, + }, + }, }, { type: 'pet', id: '2', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } - } - ] + data: { type: 'user', id: '1' }, + }, + }, + }, + ], }); }, findMany() { @@ -351,46 +369,48 @@ test("pushing has-many payloads with links (no data), then data (no links) works }, findRecord() { assert.ok(false, 'adapter findRecord called instead of using findHasMany with a link'); - } + }, }); env = setupStore({ adapter: Adapter, user: User, - pet: Pet + pet: Pet, }); let { store } = env; // push links, no data - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - links: { - related: './user/1/pets' - } - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + links: { + related: './user/1/pets', + }, + }, + }, + }, + }) + ); // push data, no links - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' } - ] - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }], + }, + }, + }, + }) + ); let Chris = run(() => store.peekRecord('user', '1')); @@ -398,12 +418,12 @@ test("pushing has-many payloads with links (no data), then data (no links) works run(() => get(Chris, 'pets')); }); -test("pushing has-many payloads with links, then links again works as expected", function(assert) { +test('pushing has-many payloads with links, then links again works as expected', function(assert) { const User = Model.extend({ - pets: hasMany('pet', { async: true, inverse: 'owner' }) + pets: hasMany('pet', { async: true, inverse: 'owner' }), }); const Pet = Model.extend({ - owner: belongsTo('user', { async: false, inverse: 'pets' }) + owner: belongsTo('user', { async: false, inverse: 'pets' }), }); const Adapter = JSONAPIAdapter.extend({ findHasMany(_, __, link) { @@ -415,20 +435,20 @@ test("pushing has-many payloads with links, then links again works as expected", id: '1', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } + data: { type: 'user', id: '1' }, + }, + }, }, { type: 'pet', id: '2', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } - } - ] + data: { type: 'user', id: '1' }, + }, + }, + }, + ], }); }, findMany() { @@ -436,46 +456,50 @@ test("pushing has-many payloads with links, then links again works as expected", }, findRecord() { assert.ok(false, 'adapter findRecord called instead of using findHasMany with a link'); - } + }, }); env = setupStore({ adapter: Adapter, user: User, - pet: Pet + pet: Pet, }); let { store } = env; // push links, no data - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - links: { - related: './user/1/not-pets' - } - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + links: { + related: './user/1/not-pets', + }, + }, + }, + }, + }) + ); // push data, no links - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - links: { - related: './user/1/pets' - } - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + links: { + related: './user/1/pets', + }, + }, + }, + }, + }) + ); let Chris = run(() => store.peekRecord('user', '1')); @@ -483,12 +507,12 @@ test("pushing has-many payloads with links, then links again works as expected", run(() => get(Chris, 'pets')); }); -test("pushing has-many payloads with links and data works as expected", function(assert) { +test('pushing has-many payloads with links and data works as expected', function(assert) { const User = Model.extend({ - pets: hasMany('pet', { async: true, inverse: 'owner' }) + pets: hasMany('pet', { async: true, inverse: 'owner' }), }); const Pet = Model.extend({ - owner: belongsTo('user', { async: false, inverse: 'pets' }) + owner: belongsTo('user', { async: false, inverse: 'pets' }), }); const Adapter = JSONAPIAdapter.extend({ findHasMany(_, __, link) { @@ -500,20 +524,20 @@ test("pushing has-many payloads with links and data works as expected", function id: '1', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } + data: { type: 'user', id: '1' }, + }, + }, }, { type: 'pet', id: '2', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } - } - ] + data: { type: 'user', id: '1' }, + }, + }, + }, + ], }); }, findMany() { @@ -521,45 +545,45 @@ test("pushing has-many payloads with links and data works as expected", function }, findRecord() { assert.ok(false, 'adapter findRecord called instead of using findHasMany with a link'); - } + }, }); env = setupStore({ adapter: Adapter, user: User, - pet: Pet + pet: Pet, }); let { store } = env; // push data and links - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' } - ], - links: { - related: './user/1/pets' - } - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }], + links: { + related: './user/1/pets', + }, + }, + }, + }, + }) + ); let Chris = run(() => store.peekRecord('user', '1')); run(() => get(Chris, 'pets')); }); -test("pushing has-many payloads with links, then one with links and data works as expected", function(assert) { +test('pushing has-many payloads with links, then one with links and data works as expected', function(assert) { const User = Model.extend({ - pets: hasMany('pet', { async: true, inverse: 'owner' }) + pets: hasMany('pet', { async: true, inverse: 'owner' }), }); const Pet = Model.extend({ - owner: belongsTo('user', { async: false, inverse: 'pets' }) + owner: belongsTo('user', { async: false, inverse: 'pets' }), }); const Adapter = JSONAPIAdapter.extend({ findHasMany(_, __, link) { @@ -571,20 +595,20 @@ test("pushing has-many payloads with links, then one with links and data works a id: '1', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } + data: { type: 'user', id: '1' }, + }, + }, }, { type: 'pet', id: '2', relationships: { owner: { - data: { type: 'user', id: '1' } - } - } - } - ] + data: { type: 'user', id: '1' }, + }, + }, + }, + ], }); }, findMany() { @@ -592,70 +616,68 @@ test("pushing has-many payloads with links, then one with links and data works a }, findRecord() { assert.ok(false, 'adapter findRecord called instead of using findHasMany with a link'); - } + }, }); env = setupStore({ adapter: Adapter, user: User, - pet: Pet + pet: Pet, }); let { store } = env; // push data, no links - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' } - ] - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }], + }, + }, + }, + }) + ); // push links and data - run(() => store.push({ - data: { - type: 'user', - id: '1', - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' }, - { type: 'pet', id: '2' }, - { type: 'pet', id: '3' } - ], - links: { - related: './user/1/pets' - } - } - } - } - })); + run(() => + store.push({ + data: { + type: 'user', + id: '1', + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }, { type: 'pet', id: '2' }, { type: 'pet', id: '3' }], + links: { + related: './user/1/pets', + }, + }, + }, + }, + }) + ); let Chris = run(() => store.peekRecord('user', '1')); run(() => get(Chris, 'pets')); }); -module("integration/relationship/json-api-links | Relationship fetching", { +module('integration/relationship/json-api-links | Relationship fetching', { beforeEach() { const User = Model.extend({ name: attr(), pets: hasMany('pet', { async: true, inverse: 'owner' }), - home: belongsTo('home', { async: true, inverse: 'owner' }) + home: belongsTo('home', { async: true, inverse: 'owner' }), }); const Home = Model.extend({ address: attr(), - owner: belongsTo('user', { async: false, inverse: 'home' }) + owner: belongsTo('user', { async: false, inverse: 'home' }), }); const Pet = Model.extend({ name: attr(), - owner: belongsTo('user', { async: false, inverse: 'pets' }) + owner: belongsTo('user', { async: false, inverse: 'pets' }), }); const Adapter = JSONAPIAdapter.extend(); @@ -663,7 +685,7 @@ module("integration/relationship/json-api-links | Relationship fetching", { adapter: Adapter, user: User, pet: Pet, - home: Home + home: Home, }); }, @@ -671,7 +693,7 @@ module("integration/relationship/json-api-links | Relationship fetching", { resetModelFactoryInjection(); run(env.container, 'destroy'); env = null; - } + }, }); /* @@ -821,8 +843,7 @@ function shouldFetchLinkTests(description, payloads) { }; adapter.findBelongsTo = (_, __, link) => { assert.ok( - !homeRelWasEmpty && - link === payloads.user.data.relationships.home.links.related, + !homeRelWasEmpty && link === payloads.user.data.relationships.home.links.related, 'We fetched the appropriate link' ); return resolve(deepCopy(payloads.home)); @@ -850,21 +871,21 @@ shouldFetchLinkTests('a link (no data)', { type: 'user', id: '1', attributes: { - name: '@runspired' + name: '@runspired', }, relationships: { pets: { links: { - related: './runspired/pets' - } + related: './runspired/pets', + }, }, home: { links: { - related: './runspired/address' - } - } - } - } + related: './runspired/address', + }, + }, + }, + }, }, pets: { data: [ @@ -872,36 +893,36 @@ shouldFetchLinkTests('a link (no data)', { type: 'pet', id: '1', attributes: { - name: 'Shen' + name: 'Shen', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } - ] + id: '1', + }, + }, + }, + }, + ], }, home: { data: { type: 'home', id: '1', attributes: { - address: 'Oakland, Ca' + address: 'Oakland, Ca', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } - } + id: '1', + }, + }, + }, + }, + }, }); shouldFetchLinkTests('a link and data (not available in the store)', { @@ -910,25 +931,23 @@ shouldFetchLinkTests('a link and data (not available in the store)', { type: 'user', id: '1', attributes: { - name: '@runspired' + name: '@runspired', }, relationships: { pets: { links: { - related: './runspired/pets' + related: './runspired/pets', }, - data: [ - { type: 'pet', id: '1' } - ] + data: [{ type: 'pet', id: '1' }], }, home: { links: { - related: './runspired/address' + related: './runspired/address', }, - data: { type: 'home', id: '1' } - } - } - } + data: { type: 'home', id: '1' }, + }, + }, + }, }, pets: { data: [ @@ -936,42 +955,42 @@ shouldFetchLinkTests('a link and data (not available in the store)', { type: 'pet', id: '1', attributes: { - name: 'Shen' + name: 'Shen', }, relationships: { owner: { data: { type: 'user', - id: '1' + id: '1', }, links: { - related: './user/1' - } - } - } - } - ] + related: './user/1', + }, + }, + }, + }, + ], }, home: { data: { type: 'home', id: '1', attributes: { - address: 'Oakland, Ca' + address: 'Oakland, Ca', }, relationships: { owner: { data: { type: 'user', - id: '1' + id: '1', }, links: { - related: './user/1' - } - } - } - } - } + related: './user/1', + }, + }, + }, + }, + }, }); /* @@ -1087,7 +1106,7 @@ function shouldReloadWithLinkTests(description, payloads) { let user = run(() => store.push(deepCopy(payloads.user))); run(() => store.push(deepCopy(payloads.home))); let home; - run(() => user.get('home').then(h => home = h)); + run(() => user.get('home').then(h => (home = h))); assert.ok(!!home, 'We found our home'); @@ -1102,25 +1121,23 @@ shouldReloadWithLinkTests('a link and data (available in the store)', { type: 'user', id: '1', attributes: { - name: '@runspired' + name: '@runspired', }, relationships: { pets: { links: { - related: './runspired/pets' + related: './runspired/pets', }, - data: [ - { type: 'pet', id: '1' } - ] + data: [{ type: 'pet', id: '1' }], }, home: { links: { - related: './runspired/address' + related: './runspired/address', }, - data: { type: 'home', id: '1' } - } - } - } + data: { type: 'home', id: '1' }, + }, + }, + }, }, pets: { data: [ @@ -1128,167 +1145,173 @@ shouldReloadWithLinkTests('a link and data (available in the store)', { type: 'pet', id: '1', attributes: { - name: 'Shen' + name: 'Shen', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } - ] + id: '1', + }, + }, + }, + }, + ], }, home: { data: { type: 'home', id: '1', attributes: { - address: 'Oakland, Ca' + address: 'Oakland, Ca', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } - } + id: '1', + }, + }, + }, + }, + }, }); -shouldReloadWithLinkTests('a link and empty data (`data: []` or `data: null`), true inverse loaded', { - user: { - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: { - pets: { - links: { - related: './runspired/pets' +shouldReloadWithLinkTests( + 'a link and empty data (`data: []` or `data: null`), true inverse loaded', + { + user: { + data: { + type: 'user', + id: '1', + attributes: { + name: '@runspired', + }, + relationships: { + pets: { + links: { + related: './runspired/pets', + }, + data: [], + }, + home: { + links: { + related: './runspired/address', + }, + data: null, }, - data: [] }, - home: { - links: { - related: './runspired/address' + }, + }, + pets: { + data: [ + { + type: 'pet', + id: '1', + attributes: { + name: 'Shen', }, - data: null - } - } - } - }, - pets: { - data: [ - { - type: 'pet', + relationships: { + owner: { + data: { + type: 'user', + id: '1', + }, + links: { + related: './user/1', + }, + }, + }, + }, + ], + }, + home: { + data: { + type: 'home', id: '1', attributes: { - name: 'Shen' + address: 'Oakland, Ca', }, relationships: { owner: { data: { type: 'user', - id: '1' + id: '1', }, links: { - related: './user/1' - } - } - } - } - ] - }, - home: { - data: { - type: 'home', - id: '1', - attributes: { - address: 'Oakland, Ca' - }, - relationships: { - owner: { - data: { - type: 'user', - id: '1' + related: './user/1', + }, }, - links: { - related: './user/1' - } - } - } - } + }, + }, + }, } -}); +); -shouldReloadWithLinkTests('a link and empty data (`data: []` or `data: null`), true inverse unloaded', { - user: { - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: { - pets: { - links: { - related: './runspired/pets' +shouldReloadWithLinkTests( + 'a link and empty data (`data: []` or `data: null`), true inverse unloaded', + { + user: { + data: { + type: 'user', + id: '1', + attributes: { + name: '@runspired', + }, + relationships: { + pets: { + links: { + related: './runspired/pets', + }, + data: [], + }, + home: { + links: { + related: './runspired/address', + }, + data: null, }, - data: [] }, - home: { - links: { - related: './runspired/address' + }, + }, + pets: { + data: [ + { + type: 'pet', + id: '1', + attributes: { + name: 'Shen', }, - data: null - } - } - } - }, - pets: { - data: [ - { - type: 'pet', + relationships: { + owner: { + data: { + type: 'user', + id: '1', + }, + }, + }, + }, + ], + }, + home: { + data: { + type: 'home', id: '1', attributes: { - name: 'Shen' + address: 'Oakland, Ca', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } - ] - }, - home: { - data: { - type: 'home', - id: '1', - attributes: { - address: 'Oakland, Ca' + id: '1', + }, + }, + }, }, - relationships: { - owner: { - data: { - type: 'user', - id: '1' - } - } - } - } + }, } -}); +); /* Ad Hoc Situations when we don't have a link @@ -1307,17 +1330,17 @@ test(`get+reload hasMany with data, no links`, function(assert) { type: 'pet', id: '1', attributes: { - name: 'Shen' + name: 'Shen', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } + id: '1', + }, + }, + }, + }, }); }; adapter.findMany = () => { @@ -1328,25 +1351,25 @@ test(`get+reload hasMany with data, no links`, function(assert) { }; // setup user - let user = run(() => store.push({ - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' } - ] + let user = run(() => + store.push({ + data: { + type: 'user', + id: '1', + attributes: { + name: '@runspired', }, - home: { - data: { type: 'home', id: '1' } - } - } - } - })); + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }], + }, + home: { + data: { type: 'home', id: '1' }, + }, + }, + }, + }) + ); let pets = run(() => user.get('pets')); assert.ok(!!pets, 'We found our pets'); @@ -1365,17 +1388,17 @@ test(`get+unload+get hasMany with data, no links`, function(assert) { type: 'pet', id: '1', attributes: { - name: 'Shen' + name: 'Shen', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } + id: '1', + }, + }, + }, + }, }); }; adapter.findMany = () => { @@ -1386,25 +1409,25 @@ test(`get+unload+get hasMany with data, no links`, function(assert) { }; // setup user - let user = run(() => store.push({ - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' } - ] + let user = run(() => + store.push({ + data: { + type: 'user', + id: '1', + attributes: { + name: '@runspired', }, - home: { - data: { type: 'home', id: '1' } - } - } - } - })); + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }], + }, + home: { + data: { type: 'home', id: '1' }, + }, + }, + }, + }) + ); let pets = run(() => user.get('pets')); assert.ok(!!pets, 'We found our pets'); @@ -1424,17 +1447,17 @@ test(`get+reload belongsTo with data, no links`, function(assert) { type: 'home', id: '1', attributes: { - address: 'Oakland, CA' + address: 'Oakland, CA', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } + id: '1', + }, + }, + }, + }, }); }; adapter.findMany = () => { @@ -1444,27 +1467,26 @@ test(`get+reload belongsTo with data, no links`, function(assert) { assert.ok(false, 'We should not call findHasMany'); }; - // setup user - let user = run(() => store.push({ - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' } - ] + let user = run(() => + store.push({ + data: { + type: 'user', + id: '1', + attributes: { + name: '@runspired', }, - home: { - data: { type: 'home', id: '1' } - } - } - } - })); + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }], + }, + home: { + data: { type: 'home', id: '1' }, + }, + }, + }, + }) + ); let home = run(() => user.get('home')); assert.ok(!!home, 'We found our home'); @@ -1483,17 +1505,17 @@ test(`get+unload+get belongsTo with data, no links`, function(assert) { type: 'home', id: '1', attributes: { - address: 'Oakland, Ca' + address: 'Oakland, Ca', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } + id: '1', + }, + }, + }, + }, }); }; adapter.findMany = () => { @@ -1503,27 +1525,26 @@ test(`get+unload+get belongsTo with data, no links`, function(assert) { assert.ok(false, 'We should not call findHasMany'); }; - // setup user - let user = run(() => store.push({ - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: { - pets: { - data: [ - { type: 'pet', id: '1' } - ] + let user = run(() => + store.push({ + data: { + type: 'user', + id: '1', + attributes: { + name: '@runspired', }, - home: { - data: { type: 'home', id: '1' } - } - } - } - })); + relationships: { + pets: { + data: [{ type: 'pet', id: '1' }], + }, + home: { + data: { type: 'home', id: '1' }, + }, + }, + }, + }) + ); let home = run(() => user.get('home')); assert.ok(!!home, 'We found our home'); @@ -1545,17 +1566,17 @@ test(`get+reload hasMany with missing data setup from the other side, no links`, type: 'pet', id: '1', attributes: { - name: 'Shen' + name: 'Shen', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } + id: '1', + }, + }, + }, + }, }); }; adapter.findMany = () => { @@ -1566,33 +1587,35 @@ test(`get+reload hasMany with missing data setup from the other side, no links`, }; // setup user and pet - let user = run(() => store.push({ - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: {} - }, - included: [ - { - type: 'pet', + let user = run(() => + store.push({ + data: { + type: 'user', id: '1', attributes: { - name: 'Shen' + name: '@runspired', }, - relationships: { - owner: { - data: { - type: 'user', - id: '1' - } - } - } - } - ] - })); + relationships: {}, + }, + included: [ + { + type: 'pet', + id: '1', + attributes: { + name: 'Shen', + }, + relationships: { + owner: { + data: { + type: 'user', + id: '1', + }, + }, + }, + }, + ], + }) + ); let pets = run(() => user.get('pets')); assert.ok(!!pets, 'We found our pets'); @@ -1610,17 +1633,17 @@ test(`get+unload+get hasMany with missing data setup from the other side, no lin type: 'pet', id: '1', attributes: { - name: 'Shen' + name: 'Shen', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } + id: '1', + }, + }, + }, + }, }); }; adapter.findMany = () => { @@ -1631,33 +1654,35 @@ test(`get+unload+get hasMany with missing data setup from the other side, no lin }; // setup user and pet - let user = run(() => store.push({ - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: {} - }, - included: [ - { - type: 'pet', + let user = run(() => + store.push({ + data: { + type: 'user', id: '1', attributes: { - name: 'Shen' + name: '@runspired', }, - relationships: { - owner: { - data: { - type: 'user', - id: '1' - } - } - } - } - ] - })); + relationships: {}, + }, + included: [ + { + type: 'pet', + id: '1', + attributes: { + name: 'Shen', + }, + relationships: { + owner: { + data: { + type: 'user', + id: '1', + }, + }, + }, + }, + ], + }) + ); let pets = run(() => user.get('pets')); assert.ok(!!pets, 'We found our pets'); @@ -1677,17 +1702,17 @@ test(`get+reload belongsTo with missing data setup from the other side, no links type: 'home', id: '1', attributes: { - address: 'Oakland, CA' + address: 'Oakland, CA', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } + id: '1', + }, + }, + }, + }, }); }; adapter.findMany = () => { @@ -1698,33 +1723,35 @@ test(`get+reload belongsTo with missing data setup from the other side, no links }; // setup user and home - let user = run(() => store.push({ - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: {} - }, - included: [ - { - type: 'home', + let user = run(() => + store.push({ + data: { + type: 'user', id: '1', attributes: { - address: 'Oakland, CA' + name: '@runspired', }, - relationships: { - owner: { - data: { - type: 'user', - id: '1' - } - } - } - } - ] - })); + relationships: {}, + }, + included: [ + { + type: 'home', + id: '1', + attributes: { + address: 'Oakland, CA', + }, + relationships: { + owner: { + data: { + type: 'user', + id: '1', + }, + }, + }, + }, + ], + }) + ); let home = run(() => user.get('home')); assert.ok(!!home, 'We found our home'); @@ -1743,17 +1770,17 @@ test(`get+unload+get belongsTo with missing data setup from the other side, no l type: 'home', id: '1', attributes: { - address: 'Oakland, CA' + address: 'Oakland, CA', }, relationships: { owner: { data: { type: 'user', - id: '1' - } - } - } - } + id: '1', + }, + }, + }, + }, }); }; adapter.findMany = () => { @@ -1764,33 +1791,35 @@ test(`get+unload+get belongsTo with missing data setup from the other side, no l }; // setup user and home - let user = run(() => store.push({ - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: {} - }, - included: [ - { - type: 'home', + let user = run(() => + store.push({ + data: { + type: 'user', id: '1', attributes: { - address: 'Oakland, CA' + name: '@runspired', }, - relationships: { - owner: { - data: { - type: 'user', - id: '1' - } - } - } - } - ] - })); + relationships: {}, + }, + included: [ + { + type: 'home', + id: '1', + attributes: { + address: 'Oakland, CA', + }, + relationships: { + owner: { + data: { + type: 'user', + id: '1', + }, + }, + }, + }, + ], + }) + ); let home = run(() => user.get('home')); assert.ok(!!home, 'We found our home'); @@ -1816,23 +1845,25 @@ test(`get+reload hasMany with empty data, no links`, function(assert) { }; // setup user - let user = run(() => store.push({ - data: { - type: 'user', - id: '1', - attributes: { - name: '@runspired' - }, - relationships: { - pets: { - data: [] + let user = run(() => + store.push({ + data: { + type: 'user', + id: '1', + attributes: { + name: '@runspired', }, - home: { - data: null - } - } - } - })); + relationships: { + pets: { + data: [], + }, + home: { + data: null, + }, + }, + }, + }) + ); let pets = run(() => user.get('pets')); assert.ok(!!pets, 'We found our pets'); @@ -1852,34 +1883,34 @@ test('We should not fetch a hasMany relationship with links that we know is empt type: 'user', id: '1', attributes: { - name: '@runspired' + name: '@runspired', }, relationships: { pets: { links: { - related: './runspired/pets' + related: './runspired/pets', }, - data: [] // we are explicitly told this is empty - } - } - } + data: [], // we are explicitly told this is empty + }, + }, + }, }; let user2Payload = { data: { type: 'user', id: '2', attributes: { - name: '@hjdivad' + name: '@hjdivad', }, relationships: { pets: { links: { - related: './hjdivad/pets' - } + related: './hjdivad/pets', + }, // we have no data, so we do not know that this is empty - } - } - } + }, + }, + }, }; let requestedUser = null; let failureDescription = ''; @@ -1902,7 +1933,7 @@ test('We should not fetch a hasMany relationship with links that we know is empt } return resolve({ - data: [] + data: [], }); }; @@ -1926,6 +1957,7 @@ test('We should not fetch a hasMany relationship with links that we know is empt // should not fire a request requestedUser = null; - failureDescription = 'We fetched the link for a previously fetched and found to be empty relationship'; + failureDescription = + 'We fetched the link for a previously fetched and found to be empty relationship'; run(() => user2.get('pets')); }); diff --git a/tests/integration/relationships/many-to-many-test.js b/tests/integration/relationships/many-to-many-test.js index 5a614d08332..e0f56037619 100644 --- a/tests/integration/relationships/many-to-many-test.js +++ b/tests/integration/relationships/many-to-many-test.js @@ -19,17 +19,17 @@ module('integration/relationships/many_to_many_test - ManyToMany relationships', User = DS.Model.extend({ name: attr('string'), topics: hasMany('topic', { async: true }), - accounts: hasMany('account', { async: false }) + accounts: hasMany('account', { async: false }), }); Account = DS.Model.extend({ state: attr(), - users: hasMany('user', { async: false }) + users: hasMany('user', { async: false }), }); Topic = DS.Model.extend({ title: attr('string'), - users: hasMany('user', { async: true }) + users: hasMany('user', { async: true }), }); env = setupStore({ @@ -37,8 +37,8 @@ module('integration/relationships/many_to_many_test - ManyToMany relationships', topic: Topic, account: Account, adapter: DS.Adapter.extend({ - deleteRecord: () => resolve() - }) + deleteRecord: () => resolve(), + }), }); store = env.store; @@ -46,34 +46,37 @@ module('integration/relationships/many_to_many_test - ManyToMany relationships', afterEach() { run(() => env.container.destroy()); - } + }, }); /* Server loading tests */ -test("Loading from one hasMany side reflects on the other hasMany side - async", function(assert) { +test('Loading from one hasMany side reflects on the other hasMany side - async', function(assert) { run(() => { store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { topics: { - data: [{ - id: '2', - type: 'topic' - }, { - id: '3', - type: 'topic' - }] - } - } - } + data: [ + { + id: '2', + type: 'topic', + }, + { + id: '3', + type: 'topic', + }, + ], + }, + }, + }, }); }); @@ -83,9 +86,9 @@ test("Loading from one hasMany side reflects on the other hasMany side - async", id: '2', type: 'topic', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); @@ -96,7 +99,7 @@ test("Loading from one hasMany side reflects on the other hasMany side - async", }); }); -test("Relationship is available from one hasMany side even if only loaded from the other hasMany side - sync", function(assert) { +test('Relationship is available from one hasMany side even if only loaded from the other hasMany side - sync', function(assert) { var account; run(() => { account = store.push({ @@ -104,26 +107,28 @@ test("Relationship is available from one hasMany side even if only loaded from t id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); }); @@ -132,7 +137,7 @@ test("Relationship is available from one hasMany side even if only loaded from t }); }); -test("Fetching a hasMany where a record was removed reflects on the other hasMany side - async", function(assert) { +test('Fetching a hasMany where a record was removed reflects on the other hasMany side - async', function(assert) { let user, topic; run(() => { @@ -141,30 +146,28 @@ test("Fetching a hasMany where a record was removed reflects on the other hasMan id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { topics: { - data: [ - { id: '2', type: 'topic' } - ] - } - } - } + data: [{ id: '2', type: 'topic' }], + }, + }, + }, }); topic = store.push({ data: { id: '2', type: 'topic', attributes: { - title: 'EmberFest was great' + title: 'EmberFest was great', }, relationships: { users: { - data: [] - } - } - } + data: [], + }, + }, + }, }); }); @@ -180,7 +183,7 @@ test("Fetching a hasMany where a record was removed reflects on the other hasMan }); }); -test("Fetching a hasMany where a record was removed reflects on the other hasMany side - sync", function(assert) { +test('Fetching a hasMany where a record was removed reflects on the other hasMany side - sync', function(assert) { let account, user; run(() => { account = store.push({ @@ -188,40 +191,42 @@ test("Fetching a hasMany where a record was removed reflects on the other hasMan id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); account = store.push({ data: { id: '2', type: 'account', attributes: { - state: 'lonely' + state: 'lonely', }, relationships: { users: { - data: [] - } - } - } + data: [], + }, + }, + }, }); }); @@ -235,7 +240,7 @@ test("Fetching a hasMany where a record was removed reflects on the other hasMan Local edits */ -test("Pushing to a hasMany reflects on the other hasMany side - async", function(assert) { +test('Pushing to a hasMany reflects on the other hasMany side - async', function(assert) { assert.expect(1); let user, topic; @@ -245,23 +250,23 @@ test("Pushing to a hasMany reflects on the other hasMany side - async", function id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { topics: { - data: [] - } - } - } + data: [], + }, + }, + }, }); topic = store.push({ data: { id: '2', type: 'topic', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); @@ -275,7 +280,7 @@ test("Pushing to a hasMany reflects on the other hasMany side - async", function }); }); -test("Pushing to a hasMany reflects on the other hasMany side - sync", function(assert) { +test('Pushing to a hasMany reflects on the other hasMany side - sync', function(assert) { let account, stanley; run(() => { account = store.push({ @@ -283,18 +288,18 @@ test("Pushing to a hasMany reflects on the other hasMany side - sync", function( id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); stanley = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); stanley.get('accounts').pushObject(account); }); @@ -304,7 +309,7 @@ test("Pushing to a hasMany reflects on the other hasMany side - sync", function( }); }); -test("Removing a record from a hasMany reflects on the other hasMany side - async", function(assert) { +test('Removing a record from a hasMany reflects on the other hasMany side - async', function(assert) { let user, topic; run(() => { user = store.push({ @@ -312,26 +317,28 @@ test("Removing a record from a hasMany reflects on the other hasMany side - asyn id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { topics: { - data: [{ - id: '2', - type: 'topic' - }] - } - } - } + data: [ + { + id: '2', + type: 'topic', + }, + ], + }, + }, + }, }); topic = store.push({ data: { id: '2', type: 'topic', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); @@ -347,7 +354,7 @@ test("Removing a record from a hasMany reflects on the other hasMany side - asyn }); }); -test("Removing a record from a hasMany reflects on the other hasMany side - sync", function(assert) { +test('Removing a record from a hasMany reflects on the other hasMany side - sync', function(assert) { let account, user; run(() => { account = store.push({ @@ -355,26 +362,28 @@ test("Removing a record from a hasMany reflects on the other hasMany side - sync id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); }); @@ -390,7 +399,7 @@ test("Removing a record from a hasMany reflects on the other hasMany side - sync Rollback Attributes tests */ -test("Rollbacking attributes for a deleted record that has a ManyToMany relationship works correctly - async", function(assert) { +test('Rollbacking attributes for a deleted record that has a ManyToMany relationship works correctly - async', function(assert) { let user, topic; run(() => { user = store.push({ @@ -398,26 +407,28 @@ test("Rollbacking attributes for a deleted record that has a ManyToMany relation id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { topics: { - data: [{ - id: '2', - type: 'topic' - }] - } - } - } + data: [ + { + id: '2', + type: 'topic', + }, + ], + }, + }, + }, }); topic = store.push({ data: { id: '2', type: 'topic', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); @@ -435,14 +446,11 @@ test("Rollbacking attributes for a deleted record that has a ManyToMany relation assert.equal(fetchedTopics.get('length'), 1, 'Topic got rollbacked into the user'); }); - return EmberPromise.all([ - users, - topics - ]); + return EmberPromise.all([users, topics]); }); }); -test("Deleting a record that has a hasMany relationship removes it from the otherMany array but does not remove the other record from itself - sync", function(assert) { +test('Deleting a record that has a hasMany relationship removes it from the otherMany array but does not remove the other record from itself - sync', function(assert) { let account, user; run(() => { account = store.push({ @@ -450,26 +458,28 @@ test("Deleting a record that has a hasMany relationship removes it from the othe id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); }); @@ -481,7 +491,7 @@ test("Deleting a record that has a hasMany relationship removes it from the othe }); }); -test("Rollbacking attributes for a created record that has a ManyToMany relationship works correctly - async", function(assert) { +test('Rollbacking attributes for a created record that has a ManyToMany relationship works correctly - async', function(assert) { let user, topic; run(() => { user = store.push({ @@ -489,9 +499,9 @@ test("Rollbacking attributes for a created record that has a ManyToMany relation id: '1', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); topic = store.createRecord('topic'); @@ -512,15 +522,12 @@ test("Rollbacking attributes for a created record that has a ManyToMany relation assert.equal(fetchedTopics.objectAt(0), null, "Topic can't be fetched"); }); - return EmberPromise.all([ - users, - topics - ]); + return EmberPromise.all([users, topics]); }); }); }); -test("Deleting an unpersisted record via rollbackAttributes that has a hasMany relationship removes it from the otherMany array but does not remove the other record from itself - sync", function(assert) { +test('Deleting an unpersisted record via rollbackAttributes that has a hasMany relationship removes it from the otherMany array but does not remove the other record from itself - sync', function(assert) { let account, user; run(() => { account = store.push({ @@ -528,9 +535,9 @@ test("Deleting an unpersisted record via rollbackAttributes that has a hasMany r id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.createRecord('user'); @@ -545,7 +552,7 @@ test("Deleting an unpersisted record via rollbackAttributes that has a hasMany r assert.equal(user.get('accounts.length'), 0, 'Accounts got rolledback correctly'); }); -test("Re-loading a removed record should re add it to the relationship when the removed record is the last one in the relationship", function(assert) { +test('Re-loading a removed record should re add it to the relationship when the removed record is the last one in the relationship', function(assert) { let account, ada, byron; run(() => { @@ -554,43 +561,47 @@ test("Re-loading a removed record should re add it to the relationship when the id: '2', type: 'account', attributes: { - state: 'account 1' - } - } + state: 'account 1', + }, + }, }); ada = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Ada Lovelace' + name: 'Ada Lovelace', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); byron = store.push({ data: { id: '2', type: 'user', attributes: { - name: 'Lord Byron' + name: 'Lord Byron', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); account.get('users').removeObject(byron); account = store.push({ @@ -598,20 +609,23 @@ test("Re-loading a removed record should re add it to the relationship when the id: '2', type: 'account', attributes: { - state: 'account 1' + state: 'account 1', }, relationships: { users: { - data: [{ - id: '1', - type: 'user' - }, { - id: '2', - type: 'user' - }] - } - } - } + data: [ + { + id: '1', + type: 'user', + }, + { + id: '2', + type: 'user', + }, + ], + }, + }, + }, }); }); diff --git a/tests/integration/relationships/nested-relationship-test.js b/tests/integration/relationships/nested-relationship-test.js index f6eceffee47..6957fe16459 100644 --- a/tests/integration/relationships/nested-relationship-test.js +++ b/tests/integration/relationships/nested-relationship-test.js @@ -14,25 +14,25 @@ module('integration/relationships/nested_relationships_test - Nested relationshi beforeEach() { Elder = DS.Model.extend({ name: attr('string'), - middleAgers: hasMany('middle-ager') + middleAgers: hasMany('middle-ager'), }); MiddleAger = DS.Model.extend({ name: attr('string'), elder: belongsTo('elder'), - kids: hasMany('kid') + kids: hasMany('kid'), }); Kid = DS.Model.extend({ name: attr('string'), - middleAger: belongsTo('middle-ager') + middleAger: belongsTo('middle-ager'), }); env = setupStore({ elder: Elder, 'middle-ager': MiddleAger, kid: Kid, - adapter: DS.JSONAPIAdapter + adapter: DS.JSONAPIAdapter, }); store = env.store; @@ -40,7 +40,7 @@ module('integration/relationships/nested_relationships_test - Nested relationshi afterEach() { run(env.container, 'destroy'); - } + }, }); /* @@ -48,86 +48,88 @@ module('integration/relationships/nested_relationships_test - Nested relationshi */ test('Sideloaded nested relationships load correctly', function(assert) { - env.adapter.shouldBackgroundReloadRecord = () => { return false; }; + env.adapter.shouldBackgroundReloadRecord = () => { + return false; + }; run(() => { store.push({ data: { id: '1', type: 'kid', links: { - self: '/kids/1' + self: '/kids/1', }, attributes: { - name: 'Kid 1' + name: 'Kid 1', }, relationships: { middleAger: { links: { self: '/kids/1/relationships/middle-ager', - related: '/kids/1/middle-ager' + related: '/kids/1/middle-ager', }, - data:{ + data: { type: 'middle-ager', - id: '1' - } - } - } + id: '1', + }, + }, + }, }, included: [ { id: '1', type: 'middle-ager', links: { - self: '/middle-ager/1' + self: '/middle-ager/1', }, attributes: { - name: 'Middle Ager 1' + name: 'Middle Ager 1', }, relationships: { elder: { links: { self: '/middle-agers/1/relationships/elder', - related: '/middle-agers/1/elder' + related: '/middle-agers/1/elder', }, data: { type: 'elder', - id: '1' - } + id: '1', + }, }, kids: { links: { self: '/middle-agers/1/relationships/kids', - related: '/middle-agers/1/kids' + related: '/middle-agers/1/kids', }, data: [ { type: 'kid', - id: '1' - } - ] - } - } + id: '1', + }, + ], + }, + }, }, { id: '1', type: 'elder', links: { - self: '/elders/1' + self: '/elders/1', }, attributes: { - name: 'Elder 1' + name: 'Elder 1', }, relationships: { middleAger: { links: { self: '/elders/1/relationships/middle-agers', - related: '/elders/1/middle-agers' - } - } - } - } - ] + related: '/elders/1/middle-agers', + }, + }, + }, + }, + ], }); }); @@ -149,4 +151,3 @@ test('Sideloaded nested relationships load correctly', function(assert) { }); }); }); - diff --git a/tests/integration/relationships/one-to-many-test.js b/tests/integration/relationships/one-to-many-test.js index 2f095d0cb4a..fb32bb94ac8 100644 --- a/tests/integration/relationships/one-to-many-test.js +++ b/tests/integration/relationships/one-to-many-test.js @@ -18,17 +18,17 @@ module('integration/relationships/one_to_many_test - OneToMany relationships', { User = DS.Model.extend({ name: attr('string'), messages: hasMany('message', { async: true }), - accounts: hasMany('account', { async: false }) + accounts: hasMany('account', { async: false }), }); Account = DS.Model.extend({ state: attr(), - user: belongsTo('user', { async: false }) + user: belongsTo('user', { async: false }), }); Message = DS.Model.extend({ title: attr('string'), - user: belongsTo('user', { async: true }) + user: belongsTo('user', { async: true }), }); env = setupStore({ @@ -36,8 +36,8 @@ module('integration/relationships/one_to_many_test - OneToMany relationships', { message: Message, account: Account, adapter: DS.Adapter.extend({ - deleteRecord: () => resolve() - }) + deleteRecord: () => resolve(), + }), }); store = env.store; @@ -45,41 +45,43 @@ module('integration/relationships/one_to_many_test - OneToMany relationships', { afterEach() { run(env.container, 'destroy'); - } + }, }); /* Server loading tests */ -test("Relationship is available from the belongsTo side even if only loaded from the hasMany side - async", function(assert) { +test('Relationship is available from the belongsTo side even if only loaded from the hasMany side - async', function(assert) { var user, message; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '2', - type: 'message' - }] - } - } - } + data: [ + { + id: '2', + type: 'message', + }, + ], + }, + }, + }, }); message = store.push({ data: { id: '2', type: 'message', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); run(function() { @@ -89,164 +91,179 @@ test("Relationship is available from the belongsTo side even if only loaded from }); }); -test("Relationship is available from the belongsTo side even if only loaded from the hasMany side - sync", function(assert) { +test('Relationship is available from the belongsTo side even if only loaded from the hasMany side - sync', function(assert) { var account, user; - run(function () { + run(function() { account = store.push({ data: { id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); }); assert.equal(account.get('user'), user, 'User relationship was set up correctly'); }); -test("Relationship is available from the hasMany side even if only loaded from the belongsTo side - async", function(assert) { +test('Relationship is available from the hasMany side even if only loaded from the belongsTo side - async', function(assert) { var user, message; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); message = store.push({ data: { id: '2', type: 'message', attributes: { - title: 'EmberFest was great' + title: 'EmberFest was great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); }); run(function() { user.get('messages').then(function(fetchedMessages) { - assert.equal(fetchedMessages.objectAt(0), message, 'Messages relationship was set up correctly'); + assert.equal( + fetchedMessages.objectAt(0), + message, + 'Messages relationship was set up correctly' + ); }); }); }); -test("Relationship is available from the hasMany side even if only loaded from the belongsTo side - sync", function(assert) { +test('Relationship is available from the hasMany side even if only loaded from the belongsTo side - sync', function(assert) { var user, account; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); account = store.push({ data: { id: '2', type: 'account', attributes: { - state: 'lonely' + state: 'lonely', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); }); run(function() { - assert.equal(user.get('accounts').objectAt(0), account, 'Accounts relationship was set up correctly'); + assert.equal( + user.get('accounts').objectAt(0), + account, + 'Accounts relationship was set up correctly' + ); }); }); -test("Fetching a belongsTo that is set to null removes the record from a relationship - async", function(assert) { +test('Fetching a belongsTo that is set to null removes the record from a relationship - async', function(assert) { var user; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '1', - type: 'message' - }, { - id: '2', - type: 'message' - }] - } - } - } + data: [ + { + id: '1', + type: 'message', + }, + { + id: '2', + type: 'message', + }, + ], + }, + }, + }, }); }); - run(function () { + run(function() { store.push({ - data: [{ - id: '1', - type: 'message', - attributes: { - title: 'EmberFest was great' + data: [ + { + id: '1', + type: 'message', + attributes: { + title: 'EmberFest was great', + }, + relationships: { + user: { + data: { + id: '1', + type: 'user', + }, + }, + }, }, - relationships: { - user: { - data: { - id: '1', - type: 'user' - } - } - } - }, - { - id: '2', - type: 'message', - attributes: { - title: 'EmberConf will be better' + { + id: '2', + type: 'message', + attributes: { + title: 'EmberConf will be better', + }, + relationships: { + user: { + data: null, + }, + }, }, - relationships: { - user: { - data: null - } - } - }] + ], }); }); run(function() { @@ -256,17 +273,17 @@ test("Fetching a belongsTo that is set to null removes the record from a relatio }); }); -test("Fetching a belongsTo that is set to null removes the record from a relationship - sync", function(assert) { +test('Fetching a belongsTo that is set to null removes the record from a relationship - sync', function(assert) { var user; - run(function () { + run(function() { store.push({ data: { id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.push({ @@ -274,17 +291,19 @@ test("Fetching a belongsTo that is set to null removes the record from a relatio id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); store.push({ @@ -292,14 +311,14 @@ test("Fetching a belongsTo that is set to null removes the record from a relatio id: '2', type: 'account', attributes: { - state: 'lonely' + state: 'lonely', }, relationships: { user: { - data: null - } - } - } + data: null, + }, + }, + }, }); }); @@ -308,53 +327,59 @@ test("Fetching a belongsTo that is set to null removes the record from a relatio }); }); -test("Fetching a belongsTo that is not defined does not remove the record from a relationship - async", function(assert) { +test('Fetching a belongsTo that is not defined does not remove the record from a relationship - async', function(assert) { var user; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '1', - type: 'message' - }, { - id: '2', - type: 'message' - }] - } - } - } + data: [ + { + id: '1', + type: 'message', + }, + { + id: '2', + type: 'message', + }, + ], + }, + }, + }, }); }); - run(function () { + run(function() { store.push({ - data: [{ - id: '1', - type: 'message', - attributes: { - title: 'EmberFest was great' + data: [ + { + id: '1', + type: 'message', + attributes: { + title: 'EmberFest was great', + }, + relationships: { + user: { + data: { + id: '1', + type: 'user', + }, + }, + }, }, - relationships: { - user: { - data: { - id: '1', - type: 'user' - } - } - } - }, { - id: '2', - type: 'message', - attributes: { - title: 'EmberConf will be better' - } - }] + { + id: '2', + type: 'message', + attributes: { + title: 'EmberConf will be better', + }, + }, + ], }); }); run(function() { @@ -364,43 +389,45 @@ test("Fetching a belongsTo that is not defined does not remove the record from a }); }); -test("Fetching a belongsTo that is not defined does not remove the record from a relationship - sync", function(assert) { +test('Fetching a belongsTo that is not defined does not remove the record from a relationship - sync', function(assert) { var account, user; - run(function () { + run(function() { account = store.push({ data: { id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); account = store.push({ data: { id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); }); @@ -411,68 +438,72 @@ test("Fetching a belongsTo that is not defined does not remove the record from a test("Fetching the hasMany that doesn't contain the belongsTo, sets the belongsTo to null - async", function(assert) { var user, message, message2; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '1', - type: 'message' - }] - } - } - } + data: [ + { + id: '1', + type: 'message', + }, + ], + }, + }, + }, }); message = store.push({ data: { id: '1', type: 'message', attributes: { - title: 'EmberFest was great' + title: 'EmberFest was great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); message2 = store.push({ data: { id: '2', type: 'message', attributes: { - title: 'EmberConf is gonna be better' - } - } + title: 'EmberConf is gonna be better', + }, + }, }); }); - run(function () { + run(function() { store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '2', - type: 'message' - }] - } - } - } + data: [ + { + id: '2', + type: 'message', + }, + ], + }, + }, + }, }); }); run(function() { @@ -491,23 +522,21 @@ test("Fetching the hasMany that doesn't contain the belongsTo, sets the belongsT let account2; let user; - run(function () { + run(function() { // tell the store user:1 has account:1 user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [ - { id: '1', type: 'account' } - ] - } - } - } + data: [{ id: '1', type: 'account' }], + }, + }, + }, }); // tell the store account:1 has user:1 @@ -516,14 +545,14 @@ test("Fetching the hasMany that doesn't contain the belongsTo, sets the belongsT id: '1', type: 'account', attributes: { - state: 'great' + state: 'great', }, relationships: { user: { - data: { id: '1', type: 'user' } - } - } - } + data: { id: '1', type: 'user' }, + }, + }, + }, }); // tell the store account:2 has no user @@ -532,9 +561,9 @@ test("Fetching the hasMany that doesn't contain the belongsTo, sets the belongsT id: '2', type: 'account', attributes: { - state: 'awesome' - } - } + state: 'awesome', + }, + }, }); // tell the store user:1 has account:2 and not account:1 @@ -543,16 +572,14 @@ test("Fetching the hasMany that doesn't contain the belongsTo, sets the belongsT id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [ - { id: '2', type: 'account' } - ] - } - } - } + data: [{ id: '2', type: 'account' }], + }, + }, + }, }); }); @@ -562,51 +589,53 @@ test("Fetching the hasMany that doesn't contain the belongsTo, sets the belongsT }); }); -test("Fetching the hasMany side where the hasMany is undefined does not change the belongsTo side - async", function(assert) { +test('Fetching the hasMany side where the hasMany is undefined does not change the belongsTo side - async', function(assert) { var message, user; - run(function () { + run(function() { store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '1', - type: 'message' - }] - } - } - } + data: [ + { + id: '1', + type: 'message', + }, + ], + }, + }, + }, }); message = store.push({ data: { id: '1', type: 'message', attributes: { - title: 'EmberFest was great' + title: 'EmberFest was great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); }); @@ -617,60 +646,62 @@ test("Fetching the hasMany side where the hasMany is undefined does not change t }); }); -test("Fetching the hasMany side where the hasMany is undefined does not change the belongsTo side - sync", function(assert) { +test('Fetching the hasMany side where the hasMany is undefined does not change the belongsTo side - sync', function(assert) { var account, user; - run(function () { + run(function() { store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '1', - type: 'account' - }] - } - } - } + data: [ + { + id: '1', + type: 'account', + }, + ], + }, + }, + }, }); account = store.push({ data: { id: '1', type: 'account', attributes: { - state: 'great' + state: 'great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); store.push({ data: { id: '2', type: 'account', attributes: { - state: 'awesome' - } - } + state: 'awesome', + }, + }, }); user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); }); @@ -683,43 +714,45 @@ test("Fetching the hasMany side where the hasMany is undefined does not change t Local edits */ -test("Pushing to the hasMany reflects the change on the belongsTo side - async", function(assert) { +test('Pushing to the hasMany reflects the change on the belongsTo side - async', function(assert) { var user, message2; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '1', - type: 'message' - }] - } - } - } + data: [ + { + id: '1', + type: 'message', + }, + ], + }, + }, + }, }); store.push({ data: { id: '1', type: 'message', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); message2 = store.push({ data: { id: '2', type: 'message', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); @@ -727,48 +760,50 @@ test("Pushing to the hasMany reflects the change on the belongsTo side - async", user.get('messages').then(function(fetchedMessages) { fetchedMessages.pushObject(message2); message2.get('user').then(function(fetchedUser) { - assert.equal(fetchedUser, user, "user got set correctly"); + assert.equal(fetchedUser, user, 'user got set correctly'); }); }); }); }); -test("Pushing to the hasMany reflects the change on the belongsTo side - sync", function(assert) { +test('Pushing to the hasMany reflects the change on the belongsTo side - sync', function(assert) { var user, account2; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '1', - type: 'account' - }] - } - } - } + data: [ + { + id: '1', + type: 'account', + }, + ], + }, + }, + }, }); store.push({ data: { id: '1', type: 'account', attributes: { - state: 'great' + state: 'great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); account2 = store.push({ @@ -776,9 +811,9 @@ test("Pushing to the hasMany reflects the change on the belongsTo side - sync", id: '2', type: 'account', attributes: { - state: 'awesome' - } - } + state: 'awesome', + }, + }, }); user.get('accounts').pushObject(account2); }); @@ -786,34 +821,36 @@ test("Pushing to the hasMany reflects the change on the belongsTo side - sync", assert.equal(account2.get('user'), user, 'user got set correctly'); }); -test("Removing from the hasMany side reflects the change on the belongsTo side - async", function(assert) { +test('Removing from the hasMany side reflects the change on the belongsTo side - async', function(assert) { var user, message; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '1', - type: 'message' - }] - } - } - } + data: [ + { + id: '1', + type: 'message', + }, + ], + }, + }, + }, }); message = store.push({ data: { id: '1', type: 'message', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); @@ -821,48 +858,50 @@ test("Removing from the hasMany side reflects the change on the belongsTo side - user.get('messages').then(function(fetchedMessages) { fetchedMessages.removeObject(message); message.get('user').then(function(fetchedUser) { - assert.equal(fetchedUser, null, "user got removed correctly"); + assert.equal(fetchedUser, null, 'user got removed correctly'); }); }); }); }); -test("Removing from the hasMany side reflects the change on the belongsTo side - sync", function(assert) { +test('Removing from the hasMany side reflects the change on the belongsTo side - sync', function(assert) { var user, account; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attirbutes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '1', - type: 'account' - }] - } - } - } + data: [ + { + id: '1', + type: 'account', + }, + ], + }, + }, + }, }); account = store.push({ data: { id: '1', type: 'account', attirbutes: { - state: 'great' + state: 'great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); }); run(function() { @@ -872,44 +911,46 @@ test("Removing from the hasMany side reflects the change on the belongsTo side - assert.equal(account.get('user'), null, 'user got removed correctly'); }); -test("Pushing to the hasMany side keeps the oneToMany invariant on the belongsTo side - async", function(assert) { +test('Pushing to the hasMany side keeps the oneToMany invariant on the belongsTo side - async', function(assert) { assert.expect(2); var user, user2, message; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '1', - type: 'message' - }] - } - } - } + data: [ + { + id: '1', + type: 'message', + }, + ], + }, + }, + }, }); user2 = store.push({ data: { id: '2', type: 'user', attributes: { - name: 'Tomhuda' - } - } + name: 'Tomhuda', + }, + }, }); message = store.push({ data: { id: '1', type: 'message', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); @@ -918,53 +959,59 @@ test("Pushing to the hasMany side keeps the oneToMany invariant on the belongsTo fetchedMessages.pushObject(message); message.get('user').then(function(fetchedUser) { - assert.equal(fetchedUser, user2, "user got set correctly"); + assert.equal(fetchedUser, user2, 'user got set correctly'); }); user.get('messages').then(function(newFetchedMessages) { - assert.equal(get(newFetchedMessages, 'length'), 0, 'message got removed from the old messages hasMany'); + assert.equal( + get(newFetchedMessages, 'length'), + 0, + 'message got removed from the old messages hasMany' + ); }); }); }); }); -test("Pushing to the hasMany side keeps the oneToMany invariant - sync", function(assert) { +test('Pushing to the hasMany side keeps the oneToMany invariant - sync', function(assert) { var user, user2, account; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '1', - type: 'account' - }] - } - } - } + data: [ + { + id: '1', + type: 'account', + }, + ], + }, + }, + }, }); user2 = store.push({ data: { id: '2', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); account = store.push({ data: { id: '1', type: 'account', attributes: { - state: 'great' - } - } + state: 'great', + }, + }, }); user2.get('accounts').pushObject(account); }); @@ -973,113 +1020,125 @@ test("Pushing to the hasMany side keeps the oneToMany invariant - sync", functio assert.equal(user2.get('accounts.length'), 1, 'the account got pushed correctly'); }); -test("Setting the belongsTo side keeps the oneToMany invariant on the hasMany- async", function(assert) { +test('Setting the belongsTo side keeps the oneToMany invariant on the hasMany- async', function(assert) { assert.expect(2); var user, user2, message; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '1', - type: 'message' - }] - } - } - } + data: [ + { + id: '1', + type: 'message', + }, + ], + }, + }, + }, }); user2 = store.push({ data: { id: '2', type: 'user', attributes: { - name: 'Tomhuda' - } - } + name: 'Tomhuda', + }, + }, }); message = store.push({ data: { id: '1', type: 'message', attributes: { - title: 'EmberFest was great' + title: 'EmberFest was great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); message.set('user', user2); }); run(function() { user.get('messages').then(function(fetchedMessages) { - assert.equal(get(fetchedMessages, 'length'), 0, 'message got removed from the first user correctly'); + assert.equal( + get(fetchedMessages, 'length'), + 0, + 'message got removed from the first user correctly' + ); }); }); run(function() { user2.get('messages').then(function(fetchedMessages) { - assert.equal(get(fetchedMessages, 'length'), 1, 'message got added to the second user correctly'); + assert.equal( + get(fetchedMessages, 'length'), + 1, + 'message got added to the second user correctly' + ); }); }); }); -test("Setting the belongsTo side keeps the oneToMany invariant on the hasMany- sync", function(assert) { +test('Setting the belongsTo side keeps the oneToMany invariant on the hasMany- sync', function(assert) { var user, user2, account; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '1', - type: 'account' - }] - } - } - } + data: [ + { + id: '1', + type: 'account', + }, + ], + }, + }, + }, }); user2 = store.push({ data: { id: '2', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); account = store.push({ data: { id: '1', type: 'account', attributes: { - state: 'great' + state: 'great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); account.set('user', user2); }); @@ -1088,50 +1147,55 @@ test("Setting the belongsTo side keeps the oneToMany invariant on the hasMany- s assert.equal(user2.get('accounts.length'), 1, 'the account got pushed correctly'); }); - -test("Setting the belongsTo side to null removes the record from the hasMany side - async", function(assert) { +test('Setting the belongsTo side to null removes the record from the hasMany side - async', function(assert) { assert.expect(2); var user, message; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '1', - type: 'message' - }] - } - } - } + data: [ + { + id: '1', + type: 'message', + }, + ], + }, + }, + }, }); message = store.push({ data: { id: '1', type: 'message', attributes: { - title: 'EmberFest was great' + title: 'EmberFest was great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); message.set('user', null); }); run(function() { user.get('messages').then(function(fetchedMessages) { - assert.equal(get(fetchedMessages, 'length'), 0, 'message got removed from the user correctly'); + assert.equal( + get(fetchedMessages, 'length'), + 0, + 'message got removed from the user correctly' + ); }); }); @@ -1142,42 +1206,44 @@ test("Setting the belongsTo side to null removes the record from the hasMany sid }); }); -test("Setting the belongsTo side to null removes the record from the hasMany side - sync", function(assert) { +test('Setting the belongsTo side to null removes the record from the hasMany side - sync', function(assert) { var user, account; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '1', - type: 'account' - }] - } - } - } + data: [ + { + id: '1', + type: 'account', + }, + ], + }, + }, + }, }); account = store.push({ data: { id: '1', type: 'account', attributes: { - state: 'great' + state: 'great', }, relationships: { user: { data: { id: '1', - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); account.set('user', null); }); @@ -1191,34 +1257,36 @@ test("Setting the belongsTo side to null removes the record from the hasMany sid Rollback attributes from deleted state */ -test("Rollbacking attributes of a deleted record works correctly when the hasMany side has been deleted - async", function(assert) { +test('Rollbacking attributes of a deleted record works correctly when the hasMany side has been deleted - async', function(assert) { var user, message; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '2', - type: 'message' - }] - } - } - } + data: [ + { + id: '2', + type: 'message', + }, + ], + }, + }, + }, }); message = store.push({ data: { id: '2', type: 'message', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); run(function() { @@ -1235,72 +1303,76 @@ test("Rollbacking attributes of a deleted record works correctly when the hasMan }); }); -test("Rollbacking attributes of a deleted record works correctly when the hasMany side has been deleted - sync", function(assert) { +test('Rollbacking attributes of a deleted record works correctly when the hasMany side has been deleted - sync', function(assert) { var account, user; - run(function () { + run(function() { account = store.push({ data: { id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); }); run(function() { account.deleteRecord(); account.rollbackAttributes(); - assert.equal(user.get('accounts.length'), 1, "Accounts are rolled back"); + assert.equal(user.get('accounts.length'), 1, 'Accounts are rolled back'); assert.equal(account.get('user'), user, 'Account still has the user'); }); }); -test("Rollbacking attributes of deleted record works correctly when the belongsTo side has been deleted - async", function(assert) { +test('Rollbacking attributes of deleted record works correctly when the belongsTo side has been deleted - async', function(assert) { var user, message; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { messages: { - data: [{ - id: '2', - type: 'message' - }] - } - } - } + data: [ + { + id: '2', + type: 'message', + }, + ], + }, + }, + }, }); message = store.push({ data: { id: '2', type: 'message', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); }); run(function() { @@ -1317,40 +1389,42 @@ test("Rollbacking attributes of deleted record works correctly when the belongsT }); }); -test("Rollbacking attributes of a deleted record works correctly when the belongsTo side has been deleted - sync", function(assert) { +test('Rollbacking attributes of a deleted record works correctly when the belongsTo side has been deleted - sync', function(assert) { var account, user; - run(function () { + run(function() { account = store.push({ data: { id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { accounts: { - data: [{ - id: '2', - type: 'account' - }] - } - } - } + data: [ + { + id: '2', + type: 'account', + }, + ], + }, + }, + }, }); }); run(function() { user.deleteRecord(); user.rollbackAttributes(); - assert.equal(user.get('accounts.length'), 1, "User still has the accounts"); + assert.equal(user.get('accounts.length'), 1, 'User still has the accounts'); assert.equal(account.get('user'), user, 'Account has the user again'); }); }); @@ -1359,20 +1433,20 @@ test("Rollbacking attributes of a deleted record works correctly when the belong Rollback attributes from created state */ -test("Rollbacking attributes of a created record works correctly when the hasMany side has been created - async", function(assert) { +test('Rollbacking attributes of a created record works correctly when the hasMany side has been created - async', function(assert) { var user, message; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); message = store.createRecord('message', { - user: user + user: user, }); }); run(message, 'rollbackAttributes'); @@ -1387,38 +1461,38 @@ test("Rollbacking attributes of a created record works correctly when the hasMan }); }); -test("Rollbacking attributes of a created record works correctly when the hasMany side has been created - sync", function(assert) { +test('Rollbacking attributes of a created record works correctly when the hasMany side has been created - sync', function(assert) { var user, account; - run(function () { + run(function() { user = store.push({ data: { id: '1', type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); account = store.createRecord('account', { - user: user + user: user, }); }); run(account, 'rollbackAttributes'); - assert.equal(user.get('accounts.length'), 0, "Accounts are rolled back"); + assert.equal(user.get('accounts.length'), 0, 'Accounts are rolled back'); assert.equal(account.get('user'), null, 'Account does not have the user anymore'); }); -test("Rollbacking attributes of a created record works correctly when the belongsTo side has been created - async", function(assert) { +test('Rollbacking attributes of a created record works correctly when the belongsTo side has been created - async', function(assert) { var message, user; - run(function () { + run(function() { message = store.push({ data: { id: '2', type: 'message', attributes: { - title: 'EmberFest was great' - } - } + title: 'EmberFest was great', + }, + }, }); user = store.createRecord('user'); }); @@ -1437,17 +1511,17 @@ test("Rollbacking attributes of a created record works correctly when the belong }); }); -test("Rollbacking attributes of a created record works correctly when the belongsTo side has been created - sync", function(assert) { +test('Rollbacking attributes of a created record works correctly when the belongsTo side has been created - sync', function(assert) { var account, user; - run(function () { + run(function() { account = store.push({ data: { id: '2', type: 'account', attributes: { - state: 'lonely' - } - } + state: 'lonely', + }, + }, }); user = store.createRecord('user'); }); @@ -1455,22 +1529,23 @@ test("Rollbacking attributes of a created record works correctly when the belong user.get('accounts').pushObject(account); }); run(user, 'rollbackAttributes'); - assert.equal(user.get('accounts.length'), 0, "User does not have the account anymore"); + assert.equal(user.get('accounts.length'), 0, 'User does not have the account anymore'); assert.equal(account.get('user'), null, 'Account does not have the user anymore'); }); -test("createRecord updates inverse record array which has observers", function(assert) { - +test('createRecord updates inverse record array which has observers', function(assert) { env.adapter.findAll = () => { return { - data: [{ - id: '2', - type: 'user', - attributes: { - name: 'Stanley' - } - }] - } + data: [ + { + id: '2', + type: 'user', + attributes: { + name: 'Stanley', + }, + }, + ], + }; }; return store.findAll('user').then(users => { diff --git a/tests/integration/relationships/one-to-one-test.js b/tests/integration/relationships/one-to-one-test.js index c65f848b149..88cabe9e72f 100644 --- a/tests/integration/relationships/one-to-one-test.js +++ b/tests/integration/relationships/one-to-one-test.js @@ -17,20 +17,20 @@ module('integration/relationships/one_to_one_test - OneToOne relationships', { User = DS.Model.extend({ name: attr('string'), bestFriend: belongsTo('user', { async: true, inverse: 'bestFriend' }), - job: belongsTo('job', { async: false }) + job: belongsTo('job', { async: false }), }); Job = DS.Model.extend({ isGood: attr(), - user: belongsTo('user', { async: false }) + user: belongsTo('user', { async: false }), }); env = setupStore({ user: User, job: Job, adapter: DS.Adapter.extend({ - deleteRecord: () => resolve() - }) + deleteRecord: () => resolve(), + }), }); store = env.store; @@ -38,14 +38,14 @@ module('integration/relationships/one_to_one_test - OneToOne relationships', { afterEach() { run(env.container, 'destroy'); - } + }, }); /* Server loading tests */ -test("Relationship is available from both sides even if only loaded from one side - async", function(assert) { +test('Relationship is available from both sides even if only loaded from one side - async', function(assert) { var stanley, stanleysFriend; run(function() { stanley = store.push({ @@ -53,26 +53,26 @@ test("Relationship is available from both sides even if only loaded from one sid id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { bestFriend: { data: { id: 2, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); stanleysFriend = store.push({ data: { id: 2, type: 'user', attributes: { - name: "Stanley's friend" - } - } + name: "Stanley's friend", + }, + }, }); stanleysFriend.get('bestFriend').then(function(fetchedUser) { @@ -81,8 +81,7 @@ test("Relationship is available from both sides even if only loaded from one sid }); }); - -test("Relationship is available from both sides even if only loaded from one side - sync", function(assert) { +test('Relationship is available from both sides even if only loaded from one side - sync', function(assert) { var job, user; run(function() { job = store.push({ @@ -90,32 +89,32 @@ test("Relationship is available from both sides even if only loaded from one sid id: 2, type: 'job', attributes: { - isGood: true - } - } + isGood: true, + }, + }, }); user = store.push({ data: { id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { job: { data: { id: 2, - type: 'job' - } - } - } - } + type: 'job', + }, + }, + }, + }, }); }); assert.equal(job.get('user'), user, 'User relationship was set up correctly'); }); -test("Fetching a belongsTo that is set to null removes the record from a relationship - async", function(assert) { +test('Fetching a belongsTo that is set to null removes the record from a relationship - async', function(assert) { var stanleysFriend; run(function() { stanleysFriend = store.push({ @@ -123,31 +122,31 @@ test("Fetching a belongsTo that is set to null removes the record from a relatio id: 2, type: 'user', attributes: { - name: "Stanley's friend" + name: "Stanley's friend", }, relationships: { bestFriend: { data: { id: 1, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); store.push({ data: { id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { bestFriend: { - data: null - } - } - } + data: null, + }, + }, + }, }); stanleysFriend.get('bestFriend').then(function(fetchedUser) { assert.equal(fetchedUser, null, 'User relationship was removed correctly'); @@ -155,8 +154,7 @@ test("Fetching a belongsTo that is set to null removes the record from a relatio }); }); - -test("Fetching a belongsTo that is set to null removes the record from a relationship - sync", function(assert) { +test('Fetching a belongsTo that is set to null removes the record from a relationship - sync', function(assert) { var job; run(function() { job = store.push({ @@ -164,26 +162,26 @@ test("Fetching a belongsTo that is set to null removes the record from a relatio id: 2, type: 'job', attributes: { - isGood: true - } - } + isGood: true, + }, + }, }); store.push({ data: { id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { job: { data: { id: 2, - type: 'job' - } - } - } - } + type: 'job', + }, + }, + }, + }, }); }); run(function() { @@ -192,21 +190,20 @@ test("Fetching a belongsTo that is set to null removes the record from a relatio id: 2, type: 'job', attributes: { - isGood: true + isGood: true, }, relationships: { user: { - data: null - } - } - } + data: null, + }, + }, + }, }); }); assert.equal(job.get('user'), null, 'User relationship was removed correctly'); }); - -test("Fetching a belongsTo that is set to a different record, sets the old relationship to null - async", function(assert) { +test('Fetching a belongsTo that is set to a different record, sets the old relationship to null - async', function(assert) { assert.expect(3); var stanley, stanleysFriend; run(function() { @@ -215,34 +212,34 @@ test("Fetching a belongsTo that is set to a different record, sets the old relat id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { bestFriend: { data: { id: 2, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); stanleysFriend = store.push({ data: { id: 2, type: 'user', attributes: { - name: "Stanley's friend" + name: "Stanley's friend", }, relationships: { bestFriend: { data: { id: 1, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); stanleysFriend.get('bestFriend').then(function(fetchedUser) { @@ -254,22 +251,26 @@ test("Fetching a belongsTo that is set to a different record, sets the old relat id: 3, type: 'user', attributes: { - name: "Stanley's New friend" + name: "Stanley's New friend", }, relationships: { bestFriend: { data: { id: 1, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); }); stanley.get('bestFriend').then(function(fetchedNewFriend) { - assert.equal(fetchedNewFriend, stanleysNewFriend, 'User relationship was updated correctly'); + assert.equal( + fetchedNewFriend, + stanleysNewFriend, + 'User relationship was updated correctly' + ); }); stanleysFriend.get('bestFriend').then(function(fetchedOldFriend) { @@ -279,8 +280,7 @@ test("Fetching a belongsTo that is set to a different record, sets the old relat }); }); - -test("Fetching a belongsTo that is set to a different record, sets the old relationship to null - sync", function(assert) { +test('Fetching a belongsTo that is set to a different record, sets the old relationship to null - sync', function(assert) { var job, user, newBetterJob; run(function() { job = store.push({ @@ -288,26 +288,26 @@ test("Fetching a belongsTo that is set to a different record, sets the old relat id: 2, type: 'job', attributes: { - isGood: false - } - } + isGood: false, + }, + }, }); user = store.push({ data: { id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { job: { data: { id: 2, - type: 'job' - } - } - } - } + type: 'job', + }, + }, + }, + }, }); }); assert.equal(job.get('user'), user, 'Job and user initially setup correctly'); @@ -317,17 +317,17 @@ test("Fetching a belongsTo that is set to a different record, sets the old relat id: 3, type: 'job', attributes: { - isGood: true + isGood: true, }, relationships: { user: { data: { id: 1, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); }); @@ -340,7 +340,7 @@ test("Fetching a belongsTo that is set to a different record, sets the old relat Local edits */ -test("Setting a OneToOne relationship reflects correctly on the other side- async", function(assert) { +test('Setting a OneToOne relationship reflects correctly on the other side- async', function(assert) { var stanley, stanleysFriend; run(function() { stanley = store.push({ @@ -348,18 +348,18 @@ test("Setting a OneToOne relationship reflects correctly on the other side- asyn id: 1, type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); stanleysFriend = store.push({ data: { id: 2, type: 'user', attributes: { - name: "Stanley's friend" - } - } + name: "Stanley's friend", + }, + }, }); }); run(function() { @@ -370,8 +370,7 @@ test("Setting a OneToOne relationship reflects correctly on the other side- asyn }); }); - -test("Setting a OneToOne relationship reflects correctly on the other side- sync", function(assert) { +test('Setting a OneToOne relationship reflects correctly on the other side- sync', function(assert) { var job, user; run(function() { job = store.push({ @@ -379,18 +378,18 @@ test("Setting a OneToOne relationship reflects correctly on the other side- sync id: 2, type: 'job', attributes: { - isGood: true - } - } + isGood: true, + }, + }, }); user = store.push({ data: { id: 1, type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); }); run(function() { @@ -399,8 +398,7 @@ test("Setting a OneToOne relationship reflects correctly on the other side- sync assert.equal(job.get('user'), user, 'User relationship was set up correctly'); }); - -test("Setting a BelongsTo to a promise unwraps the promise before setting- async", function(assert) { +test('Setting a BelongsTo to a promise unwraps the promise before setting- async', function(assert) { var stanley, stanleysFriend, newFriend; run(function() { stanley = store.push({ @@ -408,35 +406,35 @@ test("Setting a BelongsTo to a promise unwraps the promise before setting- async id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { bestFriend: { data: { id: 2, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); stanleysFriend = store.push({ data: { id: 2, type: 'user', attributes: { - name: "Stanley's friend" - } - } + name: "Stanley's friend", + }, + }, }); newFriend = store.push({ data: { id: 3, type: 'user', attributes: { - name: "New friend" - } - } + name: 'New friend', + }, + }, }); }); run(function() { @@ -450,8 +448,7 @@ test("Setting a BelongsTo to a promise unwraps the promise before setting- async }); }); - -test("Setting a BelongsTo to a promise works when the promise returns null- async", function(assert) { +test('Setting a BelongsTo to a promise works when the promise returns null- async', function(assert) { var igor, newFriend; run(function() { store.push({ @@ -459,35 +456,35 @@ test("Setting a BelongsTo to a promise works when the promise returns null- asyn id: 1, type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); igor = store.push({ data: { id: 2, type: 'user', attributes: { - name: "Igor" - } - } + name: 'Igor', + }, + }, }); newFriend = store.push({ data: { id: 3, type: 'user', attributes: { - name: "New friend" + name: 'New friend', }, relationships: { bestFriend: { data: { id: 1, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); }); run(function() { @@ -498,46 +495,48 @@ test("Setting a BelongsTo to a promise works when the promise returns null- asyn }); }); - -testInDebug("Setting a BelongsTo to a promise that didn't come from a relationship errors out", function(assert) { - var stanley, igor; - run(function() { - stanley = store.push({ - data: { - id: 1, - type: 'user', - attributes: { - name: 'Stanley' +testInDebug( + "Setting a BelongsTo to a promise that didn't come from a relationship errors out", + function(assert) { + var stanley, igor; + run(function() { + stanley = store.push({ + data: { + id: 1, + type: 'user', + attributes: { + name: 'Stanley', + }, + relationships: { + bestFriend: { + data: { + id: 2, + type: 'user', + }, + }, + }, }, - relationships: { - bestFriend: { - data: { - id: 2, - type: 'user' - } - } - } - } - }); - igor = store.push({ - data: { - id: 3, - type: 'user', - attributes: { - name: 'Igor' - } - } + }); + igor = store.push({ + data: { + id: 3, + type: 'user', + attributes: { + name: 'Igor', + }, + }, + }); }); - }); - assert.expectAssertion(function() { - run(function() { - stanley.set('bestFriend', resolve(igor)); - }); - }, /You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call./); -}); + assert.expectAssertion(function() { + run(function() { + stanley.set('bestFriend', resolve(igor)); + }); + }, /You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call./); + } +); -test("Setting a BelongsTo to a promise multiple times is resistant to race conditions- async", function(assert) { +test('Setting a BelongsTo to a promise multiple times is resistant to race conditions- async', function(assert) { assert.expect(1); var stanley, igor, newFriend; run(function() { @@ -546,43 +545,43 @@ test("Setting a BelongsTo to a promise multiple times is resistant to race condi id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { bestFriend: { data: { id: 2, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); igor = store.push({ data: { id: 3, type: 'user', attributes: { - name: "Igor" + name: 'Igor', }, relationships: { bestFriend: { data: { id: 5, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); newFriend = store.push({ data: { id: 7, type: 'user', attributes: { - name: "New friend" - } - } + name: 'New friend', + }, + }, }); }); @@ -604,12 +603,16 @@ test("Setting a BelongsTo to a promise multiple times is resistant to race condi newFriend.set('bestFriend', stanley.get('bestFriend')); newFriend.set('bestFriend', igor.get('bestFriend')); newFriend.get('bestFriend').then(function(fetchedUser) { - assert.equal(fetchedUser.get('name'), "Igor's friend", 'User relationship was updated correctly'); + assert.equal( + fetchedUser.get('name'), + "Igor's friend", + 'User relationship was updated correctly' + ); }); }); }); -test("Setting a OneToOne relationship to null reflects correctly on the other side - async", function(assert) { +test('Setting a OneToOne relationship to null reflects correctly on the other side - async', function(assert) { var stanley, stanleysFriend; run(function() { stanley = store.push({ @@ -617,34 +620,34 @@ test("Setting a OneToOne relationship to null reflects correctly on the other si id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { bestFriend: { data: { id: 2, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); stanleysFriend = store.push({ data: { id: 2, type: 'user', attributes: { - name: "Stanley's friend" + name: "Stanley's friend", }, relationships: { bestFriend: { data: { id: 1, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); }); @@ -656,7 +659,7 @@ test("Setting a OneToOne relationship to null reflects correctly on the other si }); }); -test("Setting a OneToOne relationship to null reflects correctly on the other side - sync", function(assert) { +test('Setting a OneToOne relationship to null reflects correctly on the other side - sync', function(assert) { var job, user; run(function() { job = store.push({ @@ -664,34 +667,34 @@ test("Setting a OneToOne relationship to null reflects correctly on the other si id: 2, type: 'job', attributes: { - isGood: false + isGood: false, }, relationships: { user: { data: { id: 1, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); user = store.push({ data: { id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { job: { data: { id: 2, - type: 'job' - } - } - } - } + type: 'job', + }, + }, + }, + }, }); }); @@ -701,7 +704,7 @@ test("Setting a OneToOne relationship to null reflects correctly on the other si assert.equal(job.get('user'), null, 'User relationship was removed correctly'); }); -test("Setting a belongsTo to a different record, sets the old relationship to null - async", function(assert) { +test('Setting a belongsTo to a different record, sets the old relationship to null - async', function(assert) { assert.expect(3); var stanley, stanleysFriend; @@ -711,37 +714,36 @@ test("Setting a belongsTo to a different record, sets the old relationship to nu id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { bestFriend: { data: { id: 2, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); stanleysFriend = store.push({ data: { id: 2, type: 'user', attributes: { - name: "Stanley's friend" + name: "Stanley's friend", }, relationships: { bestFriend: { data: { id: 1, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); - stanleysFriend.get('bestFriend').then(function(fetchedUser) { assert.equal(fetchedUser, stanley, 'User relationship was initally setup correctly'); var stanleysNewFriend = store.push({ @@ -749,9 +751,9 @@ test("Setting a belongsTo to a different record, sets the old relationship to nu id: 3, type: 'user', attributes: { - name: "Stanley's New friend" - } - } + name: "Stanley's New friend", + }, + }, }); run(function() { @@ -759,7 +761,11 @@ test("Setting a belongsTo to a different record, sets the old relationship to nu }); stanley.get('bestFriend').then(function(fetchedNewFriend) { - assert.equal(fetchedNewFriend, stanleysNewFriend, 'User relationship was updated correctly'); + assert.equal( + fetchedNewFriend, + stanleysNewFriend, + 'User relationship was updated correctly' + ); }); stanleysFriend.get('bestFriend').then(function(fetchedOldFriend) { @@ -769,7 +775,7 @@ test("Setting a belongsTo to a different record, sets the old relationship to nu }); }); -test("Setting a belongsTo to a different record, sets the old relationship to null - sync", function(assert) { +test('Setting a belongsTo to a different record, sets the old relationship to null - sync', function(assert) { var job, user, newBetterJob; run(function() { job = store.push({ @@ -777,26 +783,26 @@ test("Setting a belongsTo to a different record, sets the old relationship to nu id: 2, type: 'job', attributes: { - isGood: false - } - } + isGood: false, + }, + }, }); user = store.push({ data: { id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { job: { data: { id: 2, - type: 'job' - } - } - } - } + type: 'job', + }, + }, + }, + }, }); }); @@ -808,9 +814,9 @@ test("Setting a belongsTo to a different record, sets the old relationship to nu id: 3, type: 'job', attributes: { - isGood: true - } - } + isGood: true, + }, + }, }); newBetterJob.set('user', user); @@ -825,7 +831,7 @@ test("Setting a belongsTo to a different record, sets the old relationship to nu Rollback attributes tests */ -test("Rollbacking attributes of deleted record restores the relationship on both sides - async", function(assert) { +test('Rollbacking attributes of deleted record restores the relationship on both sides - async', function(assert) { var stanley, stanleysFriend; run(function() { stanley = store.push({ @@ -833,28 +839,27 @@ test("Rollbacking attributes of deleted record restores the relationship on both id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { bestFriend: { data: { id: 2, - type: 'user' - } - } - } - } + type: 'user', + }, + }, + }, + }, }); stanleysFriend = store.push({ data: { id: 2, type: 'user', attributes: { - name: "Stanley's friend" - } - } + name: "Stanley's friend", + }, + }, }); - }); run(function() { stanley.deleteRecord(); @@ -870,7 +875,7 @@ test("Rollbacking attributes of deleted record restores the relationship on both }); }); -test("Rollbacking attributes of deleted record restores the relationship on both sides - sync", function(assert) { +test('Rollbacking attributes of deleted record restores the relationship on both sides - sync', function(assert) { var job, user; run(function() { job = store.push({ @@ -878,26 +883,26 @@ test("Rollbacking attributes of deleted record restores the relationship on both id: 2, type: 'job', attributes: { - isGood: true - } - } + isGood: true, + }, + }, }); user = store.push({ data: { id: 1, type: 'user', attributes: { - name: 'Stanley' + name: 'Stanley', }, relationships: { job: { data: { id: 2, - type: 'job' - } - } - } - } + type: 'job', + }, + }, + }, + }, }); }); run(function() { @@ -908,7 +913,7 @@ test("Rollbacking attributes of deleted record restores the relationship on both assert.equal(job.get('user'), user, 'Job still has the user'); }); -test("Rollbacking attributes of created record removes the relationship on both sides - async", function(assert) { +test('Rollbacking attributes of created record removes the relationship on both sides - async', function(assert) { var stanleysFriend, stanley; run(function() { stanleysFriend = store.push({ @@ -916,9 +921,9 @@ test("Rollbacking attributes of created record removes the relationship on both id: 2, type: 'user', attributes: { - name: "Stanley's friend" - } - } + name: "Stanley's friend", + }, + }, }); stanley = store.createRecord('user', { bestFriend: stanleysFriend }); @@ -934,7 +939,7 @@ test("Rollbacking attributes of created record removes the relationship on both }); }); -test("Rollbacking attributes of created record removes the relationship on both sides - sync", function(assert) { +test('Rollbacking attributes of created record removes the relationship on both sides - sync', function(assert) { var user, job; run(function() { user = store.push({ @@ -942,9 +947,9 @@ test("Rollbacking attributes of created record removes the relationship on both id: 1, type: 'user', attributes: { - name: 'Stanley' - } - } + name: 'Stanley', + }, + }, }); job = store.createRecord('job', { user: user }); diff --git a/tests/integration/relationships/polymorphic-mixins-belongs-to-test.js b/tests/integration/relationships/polymorphic-mixins-belongs-to-test.js index 38e134012fa..3259d0b8a48 100644 --- a/tests/integration/relationships/polymorphic-mixins-belongs-to-test.js +++ b/tests/integration/relationships/polymorphic-mixins-belongs-to-test.js @@ -1,6 +1,6 @@ import { setup as setupModelFactoryInjections, - reset as resetModelFactoryInjections + reset as resetModelFactoryInjections, } from 'dummy/tests/helpers/model-factory-injection'; import Mixin from '@ember/object/mixin'; @@ -17,67 +17,73 @@ var env, store, User, Message, Video, NotMessage; var attr = DS.attr; var belongsTo = DS.belongsTo; -module('integration/relationships/polymorphic_mixins_belongs_to_test - Polymorphic belongsTo relationships with mixins', { - beforeEach() { - User = DS.Model.extend({ - name: attr('string'), - bestMessage: belongsTo('message', { async: true, polymorphic: true }) - }); +module( + 'integration/relationships/polymorphic_mixins_belongs_to_test - Polymorphic belongsTo relationships with mixins', + { + beforeEach() { + User = DS.Model.extend({ + name: attr('string'), + bestMessage: belongsTo('message', { async: true, polymorphic: true }), + }); - Message = Mixin.create({ - title: attr('string'), - user: belongsTo('user', { async: true }) - }); + Message = Mixin.create({ + title: attr('string'), + user: belongsTo('user', { async: true }), + }); - NotMessage = DS.Model.extend({ - video: attr() - }); + NotMessage = DS.Model.extend({ + video: attr(), + }); - Video = DS.Model.extend(Message, { - video: attr() - }); + Video = DS.Model.extend(Message, { + video: attr(), + }); - env = setupStore({ - user: User, - video: Video, - notMessage: NotMessage - }); + env = setupStore({ + user: User, + video: Video, + notMessage: NotMessage, + }); - env.registry.register('mixin:message', Message); - store = env.store; - }, + env.registry.register('mixin:message', Message); + store = env.store; + }, - afterEach() { - run(env.container, 'destroy'); + afterEach() { + run(env.container, 'destroy'); + }, } -}); +); /* Server loading tests */ -test("Relationship is available from the belongsTo side even if only loaded from the inverse side - async", function(assert) { +test('Relationship is available from the belongsTo side even if only loaded from the inverse side - async', function(assert) { var user, video; run(function() { store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' + data: [ + { + type: 'user', + id: '1', + attributes: { + name: 'Stanley', + }, + relationships: { + bestMessage: { + data: { type: 'video', id: '2' }, + }, + }, }, - relationships: { - bestMessage: { - data: { type: 'video', id: '2' } - } - } - }, { - type: 'video', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] + { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube', + }, + }, + ], }); user = store.peekRecord('user', 1); video = store.peekRecord('video', 2); @@ -95,23 +101,26 @@ test("Relationship is available from the belongsTo side even if only loaded from /* Local edits */ -test("Setting the polymorphic belongsTo gets propagated to the inverse side - async", function(assert) { +test('Setting the polymorphic belongsTo gets propagated to the inverse side - async', function(assert) { var user, video; run(function() { store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' - } - }, { - type: 'video', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] + 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); @@ -120,7 +129,7 @@ test("Setting the polymorphic belongsTo gets propagated to the inverse side - as run(function() { user.set('bestMessage', video); video.get('user').then(function(fetchedUser) { - assert.equal(fetchedUser, user, "user got set correctly"); + assert.equal(fetchedUser, user, 'user got set correctly'); }); user.get('bestMessage').then(function(message) { assert.equal(message, video, 'The message was set correctly'); @@ -128,37 +137,42 @@ test("Setting the polymorphic belongsTo gets propagated to the inverse side - as }); }); -testInDebug("Setting the polymorphic belongsTo with an object that does not implement the mixin errors out", function(assert) { - var user, video; - run(function() { - store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' - } - }, { - type: 'not-message', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] +testInDebug( + 'Setting the polymorphic belongsTo with an object that does not implement the mixin errors out', + function(assert) { + var user, video; + run(function() { + 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); }); - user = store.peekRecord('user', 1); - video = store.peekRecord('not-message', 2); - }); - - run(function() { - assert.expectAssertion(function() { - user.set('bestMessage', video); - }, /You cannot add a record of modelClass 'not-message' to the 'user.bestMessage' relationship \(only 'message' allowed\)/); - }); -}); + run(function() { + assert.expectAssertion(function() { + user.set('bestMessage', video); + }, /You cannot add a record of modelClass 'not-message' to the 'user.bestMessage' relationship \(only 'message' allowed\)/); + }); + } +); -test("Setting the polymorphic belongsTo gets propagated to the inverse side - model injections true", function(assert) { +test('Setting the polymorphic belongsTo gets propagated to the inverse side - model injections true', function(assert) { assert.expect(2); setupModelFactoryInjections(); @@ -166,19 +180,22 @@ test("Setting the polymorphic belongsTo gets propagated to the inverse side - mo var user, video; run(function() { store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' - } - }, { - type: 'video', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] + 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); @@ -187,7 +204,7 @@ test("Setting the polymorphic belongsTo gets propagated to the inverse side - mo run(function() { user.set('bestMessage', video); video.get('user').then(function(fetchedUser) { - assert.equal(fetchedUser, user, "user got set correctly"); + assert.equal(fetchedUser, user, 'user got set correctly'); }); user.get('bestMessage').then(function(message) { assert.equal(message, video, 'The message was set correctly'); @@ -198,37 +215,43 @@ test("Setting the polymorphic belongsTo gets propagated to the inverse side - mo } }); -testInDebug("Setting the polymorphic belongsTo with an object that does not implement the mixin errors out - model injections true", function(assert) { - setupModelFactoryInjections(); +testInDebug( + 'Setting the polymorphic belongsTo with an object that does not implement the mixin errors out - model injections true', + function(assert) { + setupModelFactoryInjections(); - try { - var user, video; - run(function() { - store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' - } - }, { - type: 'not-message', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] + try { + var user, video; + run(function() { + 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); }); - user = store.peekRecord('user', 1); - video = store.peekRecord('not-message', 2); - }); - run(function() { - assert.expectAssertion(function() { - user.set('bestMessage', video); - }, /You cannot add a record of modelClass 'not-message' to the 'user.bestMessage' relationship \(only 'message' allowed\)/); - }); - } finally { - resetModelFactoryInjections(); + run(function() { + assert.expectAssertion(function() { + user.set('bestMessage', video); + }, /You cannot add a record of modelClass 'not-message' to the 'user.bestMessage' relationship \(only 'message' allowed\)/); + }); + } finally { + resetModelFactoryInjections(); + } } -}); +); diff --git a/tests/integration/relationships/polymorphic-mixins-has-many-test.js b/tests/integration/relationships/polymorphic-mixins-has-many-test.js index 470e3dfd146..4d3ecd0ff7d 100644 --- a/tests/integration/relationships/polymorphic-mixins-has-many-test.js +++ b/tests/integration/relationships/polymorphic-mixins-has-many-test.js @@ -1,6 +1,6 @@ import { setup as setupModelFactoryInjections, - reset as resetModelFactoryInjections + reset as resetModelFactoryInjections, } from 'dummy/tests/helpers/model-factory-injection'; import Mixin from '@ember/object/mixin'; @@ -18,69 +18,73 @@ var attr = DS.attr; var hasMany = DS.hasMany; var belongsTo = DS.belongsTo; -module('integration/relationships/polymorphic_mixins_has_many_test - Polymorphic hasMany relationships with mixins', { - beforeEach() { - User = DS.Model.extend({ - name: attr('string'), - messages: hasMany('message', { async: true, polymorphic: true }) - }); +module( + 'integration/relationships/polymorphic_mixins_has_many_test - Polymorphic hasMany relationships with mixins', + { + beforeEach() { + User = DS.Model.extend({ + name: attr('string'), + messages: hasMany('message', { async: true, polymorphic: true }), + }); - Message = Mixin.create({ - title: attr('string'), - user: belongsTo('user', { async: true }) - }); + Message = Mixin.create({ + title: attr('string'), + user: belongsTo('user', { async: true }), + }); - Video = DS.Model.extend(Message, { - video: attr() - }); + Video = DS.Model.extend(Message, { + video: attr(), + }); - NotMessage = DS.Model.extend({ - video: attr() - }); + NotMessage = DS.Model.extend({ + video: attr(), + }); - env = setupStore({ - user: User, - video: Video, - notMessage: NotMessage - }); + env = setupStore({ + user: User, + video: Video, + notMessage: NotMessage, + }); - env.registry.register('mixin:message', Message); - store = env.store; - }, + env.registry.register('mixin:message', Message); + store = env.store; + }, - afterEach() { - run(env.container, 'destroy'); + afterEach() { + run(env.container, 'destroy'); + }, } -}); +); /* Server loading tests */ -test("Relationship is available from the belongsTo side even if only loaded from the hasMany side - async", function(assert) { +test('Relationship is available from the belongsTo side even if only loaded from the hasMany side - async', function(assert) { var user, video; run(function() { store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' + data: [ + { + type: 'user', + id: '1', + attributes: { + name: 'Stanley', + }, + relationships: { + messages: { + data: [{ type: 'video', id: '2' }], + }, + }, }, - relationships: { - messages: { - data: [ - { type: 'video', id: '2' } - ] - } - } - }, { - type: 'video', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] + { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube', + }, + }, + ], }); user = store.peekRecord('user', 1); video = store.peekRecord('video', 2); @@ -88,9 +92,12 @@ test("Relationship is available from the belongsTo side even if only loaded from run(function() { user.get('messages').then(function(messages) { assert.equal(messages.objectAt(0), video, 'The hasMany has loaded correctly'); - messages.objectAt(0).get('user').then(function(fetchedUser) { - assert.equal(fetchedUser, user, 'The inverse was setup correctly'); - }); + messages + .objectAt(0) + .get('user') + .then(function(fetchedUser) { + assert.equal(fetchedUser, user, 'The inverse was setup correctly'); + }); }); }); }); @@ -98,28 +105,31 @@ test("Relationship is available from the belongsTo side even if only loaded from /* Local edits */ -test("Pushing to the hasMany reflects the change on the belongsTo side - async", function(assert) { +test('Pushing to the hasMany reflects the change on the belongsTo side - async', function(assert) { var user, video; run(function() { store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' + data: [ + { + type: 'user', + id: '1', + attributes: { + name: 'Stanley', + }, + relationships: { + messages: { + data: [], + }, + }, + }, + { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube', + }, }, - relationships: { - messages: { - data: [] - } - } - }, { - type: 'video', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] + ], }); user = store.peekRecord('user', 1); video = store.peekRecord('video', 2); @@ -129,7 +139,7 @@ test("Pushing to the hasMany reflects the change on the belongsTo side - async", user.get('messages').then(function(fetchedMessages) { fetchedMessages.pushObject(video); video.get('user').then(function(fetchedUser) { - assert.equal(fetchedUser, user, "user got set correctly"); + assert.equal(fetchedUser, user, 'user got set correctly'); }); }); }); @@ -138,67 +148,76 @@ test("Pushing to the hasMany reflects the change on the belongsTo side - async", /* Local edits */ -testInDebug("Pushing a an object that does not implement the mixin to the mixin accepting array errors out", function(assert) { - var user,notMessage; - run(function() { - store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' - }, - relationships: { - messages: { - data: [] - } - } - }, { - type: 'not-message', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] +testInDebug( + 'Pushing a an object that does not implement the mixin to the mixin accepting array errors out', + function(assert) { + var user, notMessage; + run(function() { + 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); }); - user = store.peekRecord('user', 1); - notMessage = store.peekRecord('not-message', 2); - }); - run(function() { - user.get('messages').then(function(fetchedMessages) { - assert.expectAssertion(function() { - fetchedMessages.pushObject(notMessage); - }, /You cannot add a record of modelClass 'not-message' to the 'user.messages' relationship \(only 'message' allowed\)/); + run(function() { + user.get('messages').then(function(fetchedMessages) { + assert.expectAssertion(function() { + fetchedMessages.pushObject(notMessage); + }, /You cannot add a record of modelClass 'not-message' to the 'user.messages' relationship \(only 'message' allowed\)/); + }); }); - }); -}); + } +); -test("Pushing to the hasMany reflects the change on the belongsTo side - model injections true", function(assert) { +test('Pushing to the hasMany reflects the change on the belongsTo side - model injections true', function(assert) { setupModelFactoryInjections(); try { var user, video; run(function() { store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' + data: [ + { + type: 'user', + id: '1', + attributes: { + name: 'Stanley', + }, + relationships: { + messages: { + data: [], + }, + }, }, - relationships: { - messages: { - data: [] - } - } - }, { - type: 'video', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] + { + type: 'video', + id: '2', + attributes: { + video: 'Here comes Youtube', + }, + }, + ], }); user = store.peekRecord('user', 1); video = store.peekRecord('video', 2); @@ -208,7 +227,7 @@ test("Pushing to the hasMany reflects the change on the belongsTo side - model i user.get('messages').then(function(fetchedMessages) { fetchedMessages.pushObject(video); video.get('user').then(function(fetchedUser) { - assert.equal(fetchedUser, user, "user got set correctly"); + assert.equal(fetchedUser, user, 'user got set correctly'); }); }); }); @@ -220,44 +239,50 @@ test("Pushing to the hasMany reflects the change on the belongsTo side - model i /* Local edits */ -testInDebug("Pushing a an object that does not implement the mixin to the mixin accepting array errors out - model injections true", function(assert) { - setupModelFactoryInjections(); +testInDebug( + 'Pushing a an object that does not implement the mixin to the mixin accepting array errors out - model injections true', + function(assert) { + setupModelFactoryInjections(); - try { - var user,notMessage; - run(function() { - store.push({ - data: [{ - type: 'user', - id: '1', - attributes: { - name: 'Stanley' - }, - relationships: { - messages: { - data: [] - } - } - }, { - type: 'not-message', - id: '2', - attributes: { - video: 'Here comes Youtube' - } - }] + try { + var user, notMessage; + run(function() { + 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); }); - user = store.peekRecord('user', 1); - notMessage = store.peekRecord('not-message', 2); - }); - run(function() { - user.get('messages').then(function(fetchedMessages) { - assert.expectAssertion(function() { - fetchedMessages.pushObject(notMessage); - }, /You cannot add a record of modelClass 'not-message' to the 'user.messages' relationship \(only 'message' allowed\)/); + run(function() { + user.get('messages').then(function(fetchedMessages) { + assert.expectAssertion(function() { + fetchedMessages.pushObject(notMessage); + }, /You cannot add a record of modelClass 'not-message' to the 'user.messages' relationship \(only 'message' allowed\)/); + }); }); - }); - } finally { - resetModelFactoryInjections(); + } finally { + resetModelFactoryInjections(); + } } -}); +); diff --git a/tests/integration/serializers/embedded-records-mixin-test.js b/tests/integration/serializers/embedded-records-mixin-test.js index ee33f3b76a9..ba87ab65165 100644 --- a/tests/integration/serializers/embedded-records-mixin-test.js +++ b/tests/integration/serializers/embedded-records-mixin-test.js @@ -8,69 +8,80 @@ import { module, test } from 'qunit'; import DS from 'ember-data'; -var HomePlanet, SuperVillain, CommanderVillain, NormalMinion, EvilMinion, YellowMinion, RedMinion, - SecretLab, SecretWeapon, BatCave, Comment, env, LightSaber; - -module("integration/embedded_records_mixin - EmbeddedRecordsMixin", { +var HomePlanet, + SuperVillain, + CommanderVillain, + NormalMinion, + EvilMinion, + YellowMinion, + RedMinion, + SecretLab, + SecretWeapon, + BatCave, + Comment, + env, + LightSaber; + +module('integration/embedded_records_mixin - EmbeddedRecordsMixin', { beforeEach() { SuperVillain = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - homePlanet: DS.belongsTo('home-planet', { inverse: 'villains', async: true }), - secretLab: DS.belongsTo('secret-lab', { async: false }), - secretWeapons: DS.hasMany('secret-weapon', { async: false }), - evilMinions: DS.hasMany('evil-minion', { async: false }) + firstName: DS.attr('string'), + lastName: DS.attr('string'), + homePlanet: DS.belongsTo('home-planet', { inverse: 'villains', async: true }), + secretLab: DS.belongsTo('secret-lab', { async: false }), + secretWeapons: DS.hasMany('secret-weapon', { async: false }), + evilMinions: DS.hasMany('evil-minion', { async: false }), }); HomePlanet = DS.Model.extend({ - name: DS.attr('string'), - villains: DS.hasMany('super-villain', { inverse: 'homePlanet', async: false }) + name: DS.attr('string'), + villains: DS.hasMany('super-villain', { inverse: 'homePlanet', async: false }), }); SecretLab = DS.Model.extend({ - minionCapacity: DS.attr('number'), - vicinity: DS.attr('string'), - superVillain: DS.belongsTo('super-villain', { async: false }) + minionCapacity: DS.attr('number'), + vicinity: DS.attr('string'), + superVillain: DS.belongsTo('super-villain', { async: false }), }); BatCave = SecretLab.extend({ - infiltrated: DS.attr('boolean') + infiltrated: DS.attr('boolean'), }); SecretWeapon = DS.Model.extend({ - name: DS.attr('string'), - superVillain: DS.belongsTo('super-villain', { async: false }) + name: DS.attr('string'), + superVillain: DS.belongsTo('super-villain', { async: false }), }); LightSaber = SecretWeapon.extend({ - color: DS.attr('string') + color: DS.attr('string'), }); EvilMinion = DS.Model.extend({ - superVillain: DS.belongsTo('super-villain', { async: false }), - name: DS.attr('string') + superVillain: DS.belongsTo('super-villain', { async: false }), + name: DS.attr('string'), }); NormalMinion = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); YellowMinion = NormalMinion.extend(); RedMinion = NormalMinion.extend(); CommanderVillain = DS.Model.extend({ name: DS.attr('string'), - minions: DS.hasMany('normal-minion', { polymorphic: true }) + minions: DS.hasMany('normal-minion', { polymorphic: true }), }); Comment = DS.Model.extend({ - body: DS.attr('string'), - root: DS.attr('boolean'), - children: DS.hasMany('comment', { inverse: null, async: false }) + body: DS.attr('string'), + root: DS.attr('boolean'), + children: DS.hasMany('comment', { inverse: null, async: false }), }); env = setupStore({ - superVillain: SuperVillain, + superVillain: SuperVillain, commanderVillain: CommanderVillain, - homePlanet: HomePlanet, - secretLab: SecretLab, - batCave: BatCave, - secretWeapon: SecretWeapon, - lightSaber: LightSaber, - evilMinion: EvilMinion, - normalMinion: NormalMinion, - yellowMinion: YellowMinion, - redMinion: RedMinion, - comment: Comment + homePlanet: HomePlanet, + secretLab: SecretLab, + batCave: BatCave, + secretWeapon: SecretWeapon, + lightSaber: LightSaber, + evilMinion: EvilMinion, + normalMinion: NormalMinion, + yellowMinion: YellowMinion, + redMinion: RedMinion, + comment: Comment, }); env.store.modelFor('super-villain'); env.store.modelFor('commander-villain'); @@ -83,7 +94,10 @@ module("integration/embedded_records_mixin - EmbeddedRecordsMixin", { env.store.modelFor('comment'); env.registry.register('adapter:application', DS.RESTAdapter); - env.registry.register('serializer:application', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin)); + env.registry.register( + 'serializer:application', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin) + ); //env.amsSerializer = env.container.lookup("serializer:-active-model"); //env.amsAdapter = env.container.lookup("adapter:-active-model"); @@ -91,27 +105,32 @@ module("integration/embedded_records_mixin - EmbeddedRecordsMixin", { afterEach() { run(env.store, 'destroy'); - } + }, }); -test("normalizeResponse with embedded objects", function(assert) { - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' } - } - })); +test('normalizeResponse with embedded objects', function(assert) { + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("home-planet"); + var serializer = env.store.serializerFor('home-planet'); var json_hash = { homePlanet: { - id: "1", - name: "Umber", - villains: [{ - id: "2", - firstName: "Tom", - lastName: "Dale" - }] - } + id: '1', + name: 'Umber', + villains: [ + { + id: '2', + firstName: 'Tom', + lastName: 'Dale', + }, + ], + }, }; var json; @@ -120,61 +139,69 @@ test("normalizeResponse with embedded objects", function(assert) { }); assert.deepEqual(json, { - "data": { - "id": "1", - "type": "home-planet", - "attributes": { - "name": "Umber" - }, - "relationships": { - "villains": { - "data": [ - { "id": "2", "type": "super-villain" } - ] - } - } + data: { + id: '1', + type: 'home-planet', + attributes: { + name: 'Umber', + }, + relationships: { + villains: { + data: [{ id: '2', type: 'super-villain' }], + }, + }, }, - "included": [ + included: [ { - "id": "2", - "type": "super-villain", - "attributes": { - "firstName": "Tom", - "lastName": "Dale" + id: '2', + type: 'super-villain', + attributes: { + firstName: 'Tom', + lastName: 'Dale', }, - "relationships": {} - } - ] + relationships: {}, + }, + ], }); }); -test("normalizeResponse with embedded objects inside embedded objects", function(assert) { - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' } - } - })); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - evilMinions: { embedded: 'always' } - } - })); - - var serializer = env.store.serializerFor("home-planet"); +test('normalizeResponse with embedded objects inside embedded objects', function(assert) { + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + }, + }) + ); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + evilMinions: { embedded: 'always' }, + }, + }) + ); + + var serializer = env.store.serializerFor('home-planet'); var json_hash = { homePlanet: { - id: "1", - name: "Umber", - villains: [{ - id: "2", - firstName: "Tom", - lastName: "Dale", - evilMinions: [{ - id: "3", - name: "Alex" - }] - }] - } + id: '1', + name: 'Umber', + villains: [ + { + id: '2', + firstName: 'Tom', + lastName: 'Dale', + evilMinions: [ + { + id: '3', + name: 'Alex', + }, + ], + }, + ], + }, }; var json; @@ -183,308 +210,347 @@ test("normalizeResponse with embedded objects inside embedded objects", function }); assert.deepEqual(json, { - "data": { - "id": "1", - "type": "home-planet", - "attributes": { - "name": "Umber" - }, - "relationships": { - "villains": { - "data": [ - { "id": "2", "type": "super-villain" } - ] - } - } + data: { + id: '1', + type: 'home-planet', + attributes: { + name: 'Umber', + }, + relationships: { + villains: { + data: [{ id: '2', type: 'super-villain' }], + }, + }, }, - "included": [{ - "id": "2", - "type": "super-villain", - "attributes": { - "firstName": "Tom", - "lastName": "Dale" - }, - "relationships": { - "evilMinions": { - "data": [ - { "id": "3", "type": "evil-minion" } - ] - } - } - }, { - "id": "3", - "type": "evil-minion", - "attributes": { - "name": "Alex" + included: [ + { + id: '2', + type: 'super-villain', + attributes: { + firstName: 'Tom', + lastName: 'Dale', + }, + relationships: { + evilMinions: { + data: [{ id: '3', type: 'evil-minion' }], + }, + }, + }, + { + id: '3', + type: 'evil-minion', + attributes: { + name: 'Alex', + }, + relationships: {}, }, - "relationships": {} - }] + ], }); }); -test("normalizeResponse with embedded objects of same type", function(assert) { - env.registry.register('serializer:comment', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - children: { embedded: 'always' } - } - })); +test('normalizeResponse with embedded objects of same type', function(assert) { + env.registry.register( + 'serializer:comment', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + children: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("comment"); + var serializer = env.store.serializerFor('comment'); var json_hash = { comment: { - id: "1", - body: "Hello", + id: '1', + body: 'Hello', root: true, - children: [{ - id: "2", - body: "World", - root: false - }, { - id: "3", - body: "Foo", - root: false - }] - } + children: [ + { + id: '2', + body: 'World', + root: false, + }, + { + id: '3', + body: 'Foo', + root: false, + }, + ], + }, }; var json; run(function() { json = serializer.normalizeResponse(env.store, Comment, json_hash, '1', 'findRecord'); }); - assert.deepEqual(json, { - "data": { - "id": "1", - "type": "comment", - "attributes": { - "body": "Hello", - "root": true - }, - "relationships": { - "children": { - "data": [ - { "id": "2", "type": "comment" }, - { "id": "3", "type": "comment" } - ] - } - } + assert.deepEqual( + json, + { + data: { + id: '1', + type: 'comment', + attributes: { + body: 'Hello', + root: true, + }, + relationships: { + children: { + data: [{ id: '2', type: 'comment' }, { id: '3', type: 'comment' }], + }, + }, + }, + included: [ + { + id: '2', + type: 'comment', + attributes: { + body: 'World', + root: false, + }, + relationships: {}, + }, + { + id: '3', + type: 'comment', + attributes: { + body: 'Foo', + root: false, + }, + relationships: {}, + }, + ], }, - "included": [{ - "id": "2", - "type": "comment", - "attributes": { - "body": "World", - "root": false - }, - "relationships": {} - }, { - "id": "3", - "type": "comment", - "attributes": { - "body": "Foo", - "root": false - }, - "relationships": {} - }] - }, "Primary record was correct"); + 'Primary record was correct' + ); }); -test("normalizeResponse with embedded objects inside embedded objects of same type", function(assert) { - env.registry.register('serializer:comment', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - children: { embedded: 'always' } - } - })); +test('normalizeResponse with embedded objects inside embedded objects of same type', function(assert) { + env.registry.register( + 'serializer:comment', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + children: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("comment"); + var serializer = env.store.serializerFor('comment'); var json_hash = { comment: { - id: "1", - body: "Hello", + id: '1', + body: 'Hello', root: true, - children: [{ - id: "2", - body: "World", - root: false, - children: [{ - id: "4", - body: "Another", - root: false - }] - }, { - id: "3", - body: "Foo", - root: false - }] - } + children: [ + { + id: '2', + body: 'World', + root: false, + children: [ + { + id: '4', + body: 'Another', + root: false, + }, + ], + }, + { + id: '3', + body: 'Foo', + root: false, + }, + ], + }, }; var json; run(function() { json = serializer.normalizeResponse(env.store, Comment, json_hash, '1', 'findRecord'); }); - assert.deepEqual(json, { - "data": { - "id": "1", - "type": "comment", - "attributes": { - "body": "Hello", - "root": true - }, - "relationships": { - "children": { - "data": [ - { "id": "2", "type": "comment" }, - { "id": "3", "type": "comment" } - ] - } - } + assert.deepEqual( + json, + { + data: { + id: '1', + type: 'comment', + attributes: { + body: 'Hello', + root: true, + }, + relationships: { + children: { + data: [{ id: '2', type: 'comment' }, { id: '3', type: 'comment' }], + }, + }, + }, + included: [ + { + id: '2', + type: 'comment', + attributes: { + body: 'World', + root: false, + }, + relationships: { + children: { + data: [{ id: '4', type: 'comment' }], + }, + }, + }, + { + id: '4', + type: 'comment', + attributes: { + body: 'Another', + root: false, + }, + relationships: {}, + }, + { + id: '3', + type: 'comment', + attributes: { + body: 'Foo', + root: false, + }, + relationships: {}, + }, + ], }, - "included": [{ - "id": "2", - "type": "comment", - "attributes": { - "body": "World", - "root": false - }, - "relationships": { - "children": { - "data": [ - { "id": "4", "type": "comment" } - ] - } - } - }, { - "id": "4", - "type": "comment", - "attributes": { - "body": "Another", - "root": false - }, - "relationships": {} - }, { - "id": "3", - "type": "comment", - "attributes": { - "body": "Foo", - "root": false - }, - "relationships": {} - }] - }, "Primary record was correct"); + 'Primary record was correct' + ); }); -test("normalizeResponse with embedded objects of same type, but from separate attributes", function(assert) { +test('normalizeResponse with embedded objects of same type, but from separate attributes', function(assert) { HomePlanet.reopen({ - reformedVillains: DS.hasMany('superVillain', { inverse: null, async: false }) + reformedVillains: DS.hasMany('superVillain', { inverse: null, async: false }), }); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' }, - reformedVillains: { embedded: 'always' } - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + reformedVillains: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("home-planet"); + var serializer = env.store.serializerFor('home-planet'); var json_hash = { homePlanet: { - id: "1", - name: "Earth", - villains: [{ - id: "1", - firstName: "Tom" - }, { - id: "3", - firstName: "Yehuda" - }], - reformedVillains: [{ - id: "2", - firstName: "Alex" - },{ - id: "4", - firstName: "Erik" - }] - } + id: '1', + name: 'Earth', + villains: [ + { + id: '1', + firstName: 'Tom', + }, + { + id: '3', + firstName: 'Yehuda', + }, + ], + reformedVillains: [ + { + id: '2', + firstName: 'Alex', + }, + { + id: '4', + firstName: 'Erik', + }, + ], + }, }; var json; run(function() { json = serializer.normalizeResponse(env.store, HomePlanet, json_hash, '1', 'findRecord'); }); - assert.deepEqual(json, { - "data": { - "id": "1", - "type": "home-planet", - "attributes": { - "name": "Earth" - }, - "relationships": { - "villains": { - "data": [ - { "id": "1", "type": "super-villain" }, - { "id": "3", "type": "super-villain" } - ] - }, - "reformedVillains": { - "data": [ - { "id": "2", "type": "super-villain" }, - { "id": "4", "type": "super-villain" } - ] - } - } + assert.deepEqual( + json, + { + data: { + id: '1', + type: 'home-planet', + attributes: { + name: 'Earth', + }, + relationships: { + villains: { + data: [{ id: '1', type: 'super-villain' }, { id: '3', type: 'super-villain' }], + }, + reformedVillains: { + data: [{ id: '2', type: 'super-villain' }, { id: '4', type: 'super-villain' }], + }, + }, + }, + included: [ + { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + }, + relationships: {}, + }, + { + id: '3', + type: 'super-villain', + attributes: { + firstName: 'Yehuda', + }, + relationships: {}, + }, + { + id: '2', + type: 'super-villain', + attributes: { + firstName: 'Alex', + }, + relationships: {}, + }, + { + id: '4', + type: 'super-villain', + attributes: { + firstName: 'Erik', + }, + relationships: {}, + }, + ], }, - "included": [{ - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Tom" - }, - "relationships": {} - }, { - "id": "3", - "type": "super-villain", - "attributes": { - "firstName": "Yehuda" - }, - "relationships": {} - }, { - "id": "2", - "type": "super-villain", - "attributes": { - "firstName": "Alex" - }, - "relationships": {} - }, { - "id": "4", - "type": "super-villain", - "attributes": { - "firstName": "Erik" - }, - "relationships": {} - }] - }, "Primary hash was correct"); + 'Primary hash was correct' + ); }); -test("normalizeResponse with embedded objects", function(assert) { - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' } - } - })); +test('normalizeResponse with embedded objects', function(assert) { + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("home-planet"); + var serializer = env.store.serializerFor('home-planet'); var json_hash = { - homePlanets: [{ - id: "1", - name: "Umber", - villains: [{ - id: "1", - firstName: "Tom", - lastName: "Dale" - }] - }] + homePlanets: [ + { + id: '1', + name: 'Umber', + villains: [ + { + id: '1', + firstName: 'Tom', + lastName: 'Dale', + }, + ], + }, + ], }; var array; @@ -493,55 +559,67 @@ test("normalizeResponse with embedded objects", function(assert) { }); assert.deepEqual(array, { - "data": [{ - "id": "1", - "type": "home-planet", - "attributes": { - "name": "Umber" - }, - "relationships": { - "villains": { - "data": [ - { "id": "1", "type": "super-villain" } - ] - } - } - }], - "included": [{ - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Tom", - "lastName": "Dale" + data: [ + { + id: '1', + type: 'home-planet', + attributes: { + name: 'Umber', + }, + relationships: { + villains: { + data: [{ id: '1', type: 'super-villain' }], + }, + }, + }, + ], + included: [ + { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + lastName: 'Dale', + }, + relationships: {}, }, - "relationships": {} - }] + ], }); }); -test("normalizeResponse with embedded objects with custom primary key", function(assert) { +test('normalizeResponse with embedded objects with custom primary key', function(assert) { assert.expect(1); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend({ - primaryKey: 'villain_id' - })); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' } - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend({ + primaryKey: 'villain_id', + }) + ); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("home-planet"); + var serializer = env.store.serializerFor('home-planet'); var json_hash = { - homePlanets: [{ - id: "1", - name: "Umber", - villains: [{ - villain_id: "2", - firstName: "Alex", - lastName: "Baizeau" - }] - }] + homePlanets: [ + { + id: '1', + name: 'Umber', + villains: [ + { + villain_id: '2', + firstName: 'Alex', + lastName: 'Baizeau', + }, + ], + }, + ], }; var array; @@ -550,56 +628,65 @@ test("normalizeResponse with embedded objects with custom primary key", function }); assert.deepEqual(array, { - "data": [{ - "id": "1", - "type": "home-planet", - "attributes": { - "name": "Umber" - }, - "relationships": { - "villains": { - "data": [ - { "id": "2", "type": "super-villain" } - ] - } - } - }], - "included": [{ - "id": "2", - "type": "super-villain", - "attributes": { - "firstName": "Alex", - "lastName": "Baizeau" + data: [ + { + id: '1', + type: 'home-planet', + attributes: { + name: 'Umber', + }, + relationships: { + villains: { + data: [{ id: '2', type: 'super-villain' }], + }, + }, + }, + ], + included: [ + { + id: '2', + type: 'super-villain', + attributes: { + firstName: 'Alex', + lastName: 'Baizeau', + }, + relationships: {}, }, - "relationships": {} - }] + ], }); }); -test("normalizeResponse with embedded objects with identical relationship and attribute key ", function(assert) { +test('normalizeResponse with embedded objects with identical relationship and attribute key ', function(assert) { assert.expect(1); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' } - }, - //Makes the keyForRelationship and keyForAttribute collide. - keyForRelationship(key, type) { - return this.keyForAttribute(key, type); - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + }, + //Makes the keyForRelationship and keyForAttribute collide. + keyForRelationship(key, type) { + return this.keyForAttribute(key, type); + }, + }) + ); - var serializer = env.store.serializerFor("home-planet"); + var serializer = env.store.serializerFor('home-planet'); var json_hash = { - homePlanets: [{ - id: "1", - name: "Umber", - villains: [{ - id: "1", - firstName: "Alex", - lastName: "Baizeau" - }] - }] + homePlanets: [ + { + id: '1', + name: 'Umber', + villains: [ + { + id: '1', + firstName: 'Alex', + lastName: 'Baizeau', + }, + ], + }, + ], }; var array; @@ -608,56 +695,66 @@ test("normalizeResponse with embedded objects with identical relationship and at }); assert.deepEqual(array, { - "data": [{ - "id": "1", - "type": "home-planet", - "attributes": { - "name": "Umber" - }, - "relationships": { - "villains": { - "data": [ - { "id": "1", "type": "super-villain" } - ] - } - } - }], - "included": [{ - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Alex", - "lastName": "Baizeau" + data: [ + { + id: '1', + type: 'home-planet', + attributes: { + name: 'Umber', + }, + relationships: { + villains: { + data: [{ id: '1', type: 'super-villain' }], + }, + }, + }, + ], + included: [ + { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Alex', + lastName: 'Baizeau', + }, + relationships: {}, }, - "relationships": {} - }] + ], }); }); -test("normalizeResponse with embedded objects of same type as primary type", function(assert) { - env.registry.register('serializer:comment', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - children: { embedded: 'always' } - } - })); +test('normalizeResponse with embedded objects of same type as primary type', function(assert) { + env.registry.register( + 'serializer:comment', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + children: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("comment"); + var serializer = env.store.serializerFor('comment'); var json_hash = { - comments: [{ - id: "1", - body: "Hello", - root: true, - children: [{ - id: "2", - body: "World", - root: false - }, { - id: "3", - body: "Foo", - root: false - }] - }] + comments: [ + { + id: '1', + body: 'Hello', + root: true, + children: [ + { + id: '2', + body: 'World', + root: false, + }, + { + id: '3', + body: 'Foo', + root: false, + }, + ], + }, + ], }; var array; @@ -665,92 +762,116 @@ test("normalizeResponse with embedded objects of same type as primary type", fun array = serializer.normalizeResponse(env.store, Comment, json_hash, null, 'findAll'); }); - assert.deepEqual(array, { - "data": [{ - "id": "1", - "type": "comment", - "attributes": { - "body": "Hello", - "root": true - }, - "relationships": { - "children": { - "data": [ - { "id": "2", "type": "comment" }, - { "id": "3", "type": "comment" } - ] - } - } - }], - "included": [{ - "id": "2", - "type": "comment", - "attributes": { - "body": "World", - "root": false - }, - "relationships": {} - }, { - "id": "3", - "type": "comment", - "attributes": { - "body": "Foo", - "root": false - }, - "relationships": {} - }] - }, "Primary array is correct"); + assert.deepEqual( + array, + { + data: [ + { + id: '1', + type: 'comment', + attributes: { + body: 'Hello', + root: true, + }, + relationships: { + children: { + data: [{ id: '2', type: 'comment' }, { id: '3', type: 'comment' }], + }, + }, + }, + ], + included: [ + { + id: '2', + type: 'comment', + attributes: { + body: 'World', + root: false, + }, + relationships: {}, + }, + { + id: '3', + type: 'comment', + attributes: { + body: 'Foo', + root: false, + }, + relationships: {}, + }, + ], + }, + 'Primary array is correct' + ); }); -test("normalizeResponse with embedded objects of same type, but from separate attributes", function(assert) { +test('normalizeResponse with embedded objects of same type, but from separate attributes', function(assert) { HomePlanet.reopen({ - reformedVillains: DS.hasMany('superVillain', { async: false }) + reformedVillains: DS.hasMany('superVillain', { async: false }), }); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' }, - reformedVillains: { embedded: 'always' } - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + reformedVillains: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("home-planet"); + var serializer = env.store.serializerFor('home-planet'); var json_hash = { - homePlanets: [{ - id: "1", - name: "Earth", - villains: [{ - id: "1", - firstName: "Tom" - },{ - id: "3", - firstName: "Yehuda" - }], - reformedVillains: [{ - id: "2", - firstName: "Alex" - },{ - id: "4", - firstName: "Erik" - }] - },{ - id: "2", - name: "Mars", - villains: [{ - id: "1", - firstName: "Tom" - },{ - id: "3", - firstName: "Yehuda" - }], - reformedVillains: [{ - id: "5", - firstName: "Peter" - },{ - id: "6", - firstName: "Trek" - }] - }] + homePlanets: [ + { + id: '1', + name: 'Earth', + villains: [ + { + id: '1', + firstName: 'Tom', + }, + { + id: '3', + firstName: 'Yehuda', + }, + ], + reformedVillains: [ + { + id: '2', + firstName: 'Alex', + }, + { + id: '4', + firstName: 'Erik', + }, + ], + }, + { + id: '2', + name: 'Mars', + villains: [ + { + id: '1', + firstName: 'Tom', + }, + { + id: '3', + firstName: 'Yehuda', + }, + ], + reformedVillains: [ + { + id: '5', + firstName: 'Peter', + }, + { + id: '6', + firstName: 'Trek', + }, + ], + }, + ], }; var json; @@ -758,191 +879,222 @@ test("normalizeResponse with embedded objects of same type, but from separate at json = serializer.normalizeResponse(env.store, HomePlanet, json_hash, null, 'findAll'); }); - assert.deepEqual(json, { - "data": [{ - "id": "1", - "type": "home-planet", - "attributes": { - "name": "Earth" - }, - "relationships": { - "reformedVillains": { - "data": [ - { "id": "2", "type": "super-villain" }, - { "id": "4", "type": "super-villain" } - ] - }, - "villains": { - "data": [ - { "id": "1", "type": "super-villain" }, - { "id": "3", "type": "super-villain" } - ] - } - } - }, { - "id": "2", - "type": "home-planet", - "attributes": { - "name": "Mars" - }, - "relationships": { - "reformedVillains": { - "data": [ - { "id": "5", "type": "super-villain" }, - { "id": "6", "type": "super-villain" } - ] - }, - "villains": { - "data": [ - { "id": "1", "type": "super-villain" }, - { "id": "3", "type": "super-villain" } - ] - } - } - }], - "included": [{ - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Tom" - }, - "relationships": {} - }, { - "id": "3", - "type": "super-villain", - "attributes": { - "firstName": "Yehuda" - }, - "relationships": {} - }, { - "id": "2", - "type": "super-villain", - "attributes": { - "firstName": "Alex" - }, - "relationships": {} - }, { - "id": "4", - "type": "super-villain", - "attributes": { - "firstName": "Erik" - }, - "relationships": {} - }, { - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Tom" - }, - "relationships": {} - }, { - "id": "3", - "type": "super-villain", - "attributes": { - "firstName": "Yehuda" - }, - "relationships": {} - }, { - "id": "5", - "type": "super-villain", - "attributes": { - "firstName": "Peter" - }, - "relationships": {} - }, { - "id": "6", - "type": "super-villain", - "attributes": { - "firstName": "Trek" - }, - "relationships": {} - }] - }, "Primary array was correct"); + assert.deepEqual( + json, + { + data: [ + { + id: '1', + type: 'home-planet', + attributes: { + name: 'Earth', + }, + relationships: { + reformedVillains: { + data: [{ id: '2', type: 'super-villain' }, { id: '4', type: 'super-villain' }], + }, + villains: { + data: [{ id: '1', type: 'super-villain' }, { id: '3', type: 'super-villain' }], + }, + }, + }, + { + id: '2', + type: 'home-planet', + attributes: { + name: 'Mars', + }, + relationships: { + reformedVillains: { + data: [{ id: '5', type: 'super-villain' }, { id: '6', type: 'super-villain' }], + }, + villains: { + data: [{ id: '1', type: 'super-villain' }, { id: '3', type: 'super-villain' }], + }, + }, + }, + ], + included: [ + { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + }, + relationships: {}, + }, + { + id: '3', + type: 'super-villain', + attributes: { + firstName: 'Yehuda', + }, + relationships: {}, + }, + { + id: '2', + type: 'super-villain', + attributes: { + firstName: 'Alex', + }, + relationships: {}, + }, + { + id: '4', + type: 'super-villain', + attributes: { + firstName: 'Erik', + }, + relationships: {}, + }, + { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + }, + relationships: {}, + }, + { + id: '3', + type: 'super-villain', + attributes: { + firstName: 'Yehuda', + }, + relationships: {}, + }, + { + id: '5', + type: 'super-villain', + attributes: { + firstName: 'Peter', + }, + relationships: {}, + }, + { + id: '6', + type: 'super-villain', + attributes: { + firstName: 'Trek', + }, + relationships: {}, + }, + ], + }, + 'Primary array was correct' + ); }); -test("serialize supports serialize:false on non-relationship properties", function(assert) { - let tom = env.store.createRecord('super-villain', { firstName: "Tom", lastName: "Dale", id: '1' }); +test('serialize supports serialize:false on non-relationship properties', function(assert) { + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - firstName: { serialize: false } - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + firstName: { serialize: false }, + }, + }) + ); var serializer, json; run(function() { - serializer = env.store.serializerFor("super-villain"); + serializer = env.store.serializerFor('super-villain'); json = serializer.serialize(tom._createSnapshot()); }); assert.deepEqual(json, { - lastName: "Dale", + lastName: 'Dale', homePlanet: null, - secretLab: null + secretLab: null, }); }); -test("serialize with embedded objects (hasMany relationship)", function(assert) { - let league = env.store.createRecord('home-planet', { name: "Villain League", id: "123" }); - let tom = env.store.createRecord('super-villain', { firstName: "Tom", lastName: "Dale", homePlanet: league, id: '1' }); +test('serialize with embedded objects (hasMany relationship)', function(assert) { + let league = env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + homePlanet: league, + id: '1', + }); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' } - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + }, + }) + ); var serializer, json; run(function() { - serializer = env.store.serializerFor("home-planet"); + serializer = env.store.serializerFor('home-planet'); json = serializer.serialize(league._createSnapshot()); }); assert.deepEqual(json, { - name: "Villain League", - villains: [{ - id: get(tom, "id"), - firstName: "Tom", - lastName: "Dale", - homePlanet: get(league, "id"), - secretLab: null - }] + name: 'Villain League', + villains: [ + { + id: get(tom, 'id'), + firstName: 'Tom', + lastName: 'Dale', + homePlanet: get(league, 'id'), + secretLab: null, + }, + ], }); }); -test("serialize with embedded objects and a custom keyForAttribute (hasMany relationship)", function(assert) { - let league = env.store.createRecord('home-planet', { name: "Villain League", id: "123" }); - let tom = env.store.createRecord('super-villain', { firstName: "Tom", lastName: "Dale", homePlanet: league, id: '1' }); +test('serialize with embedded objects and a custom keyForAttribute (hasMany relationship)', function(assert) { + let league = env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + homePlanet: league, + id: '1', + }); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - keyForRelationship(key) { - return key + '-custom'; - }, - attrs: { - villains: { embedded: 'always' } - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + keyForRelationship(key) { + return key + '-custom'; + }, + attrs: { + villains: { embedded: 'always' }, + }, + }) + ); var serializer, json; run(function() { - serializer = env.store.serializerFor("home-planet"); + serializer = env.store.serializerFor('home-planet'); json = serializer.serialize(league._createSnapshot()); }); assert.deepEqual(json, { - "name": "Villain League", - "villains-custom": [{ - id: get(tom, "id"), - firstName: "Tom", - lastName: "Dale", - homePlanet: get(league, "id"), - secretLab: null - }] + name: 'Villain League', + 'villains-custom': [ + { + id: get(tom, 'id'), + firstName: 'Tom', + lastName: 'Dale', + homePlanet: get(league, 'id'), + secretLab: null, + }, + ], }); }); -testInDebug("serialize with embedded objects (unknown hasMany relationship)", function(assert) { +testInDebug('serialize with embedded objects (unknown hasMany relationship)', function(assert) { var league; run(function() { env.store.push({ @@ -950,623 +1102,761 @@ testInDebug("serialize with embedded objects (unknown hasMany relationship)", fu type: 'home-planet', id: '123', attributes: { - name: "Villain League" - } - } + name: 'Villain League', + }, + }, }); league = env.store.peekRecord('home-planet', 123); }); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' } - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + }, + }) + ); var serializer, json; assert.expectWarning(function() { run(function() { - serializer = env.store.serializerFor("home-planet"); + serializer = env.store.serializerFor('home-planet'); json = serializer.serialize(league._createSnapshot()); }); }, /The embedded relationship 'villains' is undefined for 'home-planet' with id '123'. Please include it in your original payload./); assert.deepEqual(json, { - name: "Villain League", - villains: [] + name: 'Villain League', + villains: [], }); }); -test("serialize with embedded objects (hasMany relationship) supports serialize:false", function(assert) { - let league = env.store.createRecord('home-planet', { name: "Villain League", id: "123" }); - env.store.createRecord('super-villain', { firstName: "Tom", lastName: "Dale", homePlanet: league, id: '1' }); +test('serialize with embedded objects (hasMany relationship) supports serialize:false', function(assert) { + let league = env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }); + env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + homePlanet: league, + id: '1', + }); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { serialize: false } - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { serialize: false }, + }, + }) + ); var serializer, json; run(function() { - serializer = env.store.serializerFor("home-planet"); + serializer = env.store.serializerFor('home-planet'); json = serializer.serialize(league._createSnapshot()); }); assert.deepEqual(json, { - name: "Villain League" + name: 'Villain League', }); }); -test("serialize with (new) embedded objects (hasMany relationship)", function(assert) { - let league = env.store.createRecord('home-planet', { name: "Villain League", id: "123" }); - env.store.createRecord('super-villain', { firstName: "Tom", lastName: "Dale", homePlanet: league }); +test('serialize with (new) embedded objects (hasMany relationship)', function(assert) { + let league = env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }); + env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + homePlanet: league, + }); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always' } - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always' }, + }, + }) + ); var serializer, json; run(function() { - serializer = env.store.serializerFor("home-planet"); + serializer = env.store.serializerFor('home-planet'); json = serializer.serialize(league._createSnapshot()); }); assert.deepEqual(json, { - name: "Villain League", - villains: [{ - firstName: "Tom", - lastName: "Dale", - homePlanet: get(league, "id"), - secretLab: null - }] + name: 'Villain League', + villains: [ + { + firstName: 'Tom', + lastName: 'Dale', + homePlanet: get(league, 'id'), + secretLab: null, + }, + ], }); }); -test("serialize with embedded objects (hasMany relationships, including related objects not embedded)", function(assert) { - let superVillain = env.store.createRecord('super-villain', { id: 1, firstName: "Super", lastName: "Villian" }); - let evilMinion = env.store.createRecord('evil-minion', { id: 1, name: "Evil Minion", superVillian: superVillain }); - let secretWeapon = env.store.createRecord('secret-weapon', { id: 1, name: "Secret Weapon", superVillain: superVillain }); +test('serialize with embedded objects (hasMany relationships, including related objects not embedded)', function(assert) { + let superVillain = env.store.createRecord('super-villain', { + id: 1, + firstName: 'Super', + lastName: 'Villian', + }); + let evilMinion = env.store.createRecord('evil-minion', { + id: 1, + name: 'Evil Minion', + superVillian: superVillain, + }); + let secretWeapon = env.store.createRecord('secret-weapon', { + id: 1, + name: 'Secret Weapon', + superVillain: superVillain, + }); run(function() { superVillain.get('evilMinions').pushObject(evilMinion); superVillain.get('secretWeapons').pushObject(secretWeapon); }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - evilMinions: { serialize: 'records', deserialize: 'records' }, - secretWeapons: { serialize: 'ids' } - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + evilMinions: { serialize: 'records', deserialize: 'records' }, + secretWeapons: { serialize: 'ids' }, + }, + }) + ); var serializer, json; run(function() { - serializer = env.container.lookup("serializer:super-villain"); + serializer = env.container.lookup('serializer:super-villain'); json = serializer.serialize(superVillain._createSnapshot()); }); assert.deepEqual(json, { - firstName: get(superVillain, "firstName"), - lastName: get(superVillain, "lastName"), + firstName: get(superVillain, 'firstName'), + lastName: get(superVillain, 'lastName'), homePlanet: null, - evilMinions: [{ - id: get(evilMinion, "id"), - name: get(evilMinion, "name"), - superVillain: "1" - }], + evilMinions: [ + { + id: get(evilMinion, 'id'), + name: get(evilMinion, 'name'), + superVillain: '1', + }, + ], secretLab: null, - secretWeapons: ["1"] + secretWeapons: ['1'], }); }); -test("serialize has many relationship using the `ids-and-types` strategy", function(assert) { - let yellowMinion = env.store.createRecord('yellow-minion', { id: 1, name: "Yellowy" }); - let redMinion = env.store.createRecord('red-minion', { id: 1, name: "Reddy" }); - let commanderVillain = env.store.createRecord('commander-villain', { id: 1, name: "Jeff", minions: [yellowMinion, redMinion] }); +test('serialize has many relationship using the `ids-and-types` strategy', function(assert) { + let yellowMinion = env.store.createRecord('yellow-minion', { id: 1, name: 'Yellowy' }); + let redMinion = env.store.createRecord('red-minion', { id: 1, name: 'Reddy' }); + let commanderVillain = env.store.createRecord('commander-villain', { + id: 1, + name: 'Jeff', + minions: [yellowMinion, redMinion], + }); - env.registry.register('serializer:commander-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - minions: { serialize: 'ids-and-types' } - } - })); + env.registry.register( + 'serializer:commander-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + minions: { serialize: 'ids-and-types' }, + }, + }) + ); var serializer, json; run(function() { - serializer = env.container.lookup("serializer:commander-villain"); + serializer = env.container.lookup('serializer:commander-villain'); var snapshot = commanderVillain._createSnapshot(); json = serializer.serialize(snapshot); }); assert.deepEqual(json, { name: 'Jeff', - minions: [{ - id: '1', - type: 'yellow-minion' - }, { - id: '1', - type: 'red-minion' - }] + minions: [ + { + id: '1', + type: 'yellow-minion', + }, + { + id: '1', + type: 'red-minion', + }, + ], }); }); -test("normalizeResponse with embedded object (belongsTo relationship)", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { embedded: 'always' } - } - })); +test('normalizeResponse with embedded object (belongsTo relationship)', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("super-villain"); + var serializer = env.store.serializerFor('super-villain'); var json_hash = { super_villain: { - id: "1", - firstName: "Tom", - lastName: "Dale", - homePlanet: "123", - evilMinions: ["1", "2", "3"], + id: '1', + firstName: 'Tom', + lastName: 'Dale', + homePlanet: '123', + evilMinions: ['1', '2', '3'], secretLab: { minionCapacity: 5000, - vicinity: "California, USA", - id: "101" + vicinity: 'California, USA', + id: '101', }, - secretWeapons: [] - } + secretWeapons: [], + }, }; let json = serializer.normalizeResponse(env.store, SuperVillain, json_hash, '1', 'findRecord'); assert.deepEqual(json, { - "data": { - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Tom", - "lastName": "Dale" - }, - "relationships": { - "evilMinions": { - "data": [ - { "id": "1", "type": "evil-minion" }, - { "id": "2", "type": "evil-minion" }, - { "id": "3", "type": "evil-minion" } - ] - }, - "homePlanet": { - "data": { "id": "123", "type": "home-planet" } - }, - "secretLab": { - "data": { "id": "101", "type": "secret-lab" } - }, - "secretWeapons": { - "data": [] - } - } + data: { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + lastName: 'Dale', + }, + relationships: { + evilMinions: { + data: [ + { id: '1', type: 'evil-minion' }, + { id: '2', type: 'evil-minion' }, + { id: '3', type: 'evil-minion' }, + ], + }, + homePlanet: { + data: { id: '123', type: 'home-planet' }, + }, + secretLab: { + data: { id: '101', type: 'secret-lab' }, + }, + secretWeapons: { + data: [], + }, + }, }, - "included": [{ - "id": "101", - "type": "secret-lab", - "attributes": { - "minionCapacity": 5000, - "vicinity": "California, USA" + included: [ + { + id: '101', + type: 'secret-lab', + attributes: { + minionCapacity: 5000, + vicinity: 'California, USA', + }, + relationships: {}, }, - "relationships": {} - }] + ], }); }); -test("serialize with embedded object (belongsTo relationship)", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { embedded: 'always' } - } - })); +test('serialize with embedded object (belongsTo relationship)', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { embedded: 'always' }, + }, + }) + ); // records with an id, persisted - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } - ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); - let json = env.store.serializerFor("super-villain").serialize(tom._createSnapshot()); + let json = env.store.serializerFor('super-villain').serialize(tom._createSnapshot()); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), secretLab: { - id: get(tom, "secretLab").get("id"), - minionCapacity: get(tom, "secretLab").get("minionCapacity"), - vicinity: get(tom, "secretLab").get("vicinity") - } + id: get(tom, 'secretLab').get('id'), + minionCapacity: get(tom, 'secretLab').get('minionCapacity'), + vicinity: get(tom, 'secretLab').get('vicinity'), + }, }); }); -test("serialize with embedded object (polymorphic belongsTo relationship)", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { embedded: 'always' } - } - })); +test('serialize with embedded object (polymorphic belongsTo relationship)', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { embedded: 'always' }, + }, + }) + ); SuperVillain.reopen({ - secretLab: DS.belongsTo('secret-lab', { polymorphic: true }) + secretLab: DS.belongsTo('secret-lab', { polymorphic: true }), }); - let tom = env.store.createRecord( - 'super-villain', - { - id: "1", - firstName: "Tom", - lastName: "Dale", - secretLab: env.store.createRecord('bat-cave', { - id: "101", - minionCapacity: 5000, - vicinity: "California, USA", - infiltrated: true - }), - homePlanet: env.store.createRecord('home-planet', { - id: "123", - name: "Villain League" - }) - } - ); + let tom = env.store.createRecord('super-villain', { + id: '1', + firstName: 'Tom', + lastName: 'Dale', + secretLab: env.store.createRecord('bat-cave', { + id: '101', + minionCapacity: 5000, + vicinity: 'California, USA', + infiltrated: true, + }), + homePlanet: env.store.createRecord('home-planet', { + id: '123', + name: 'Villain League', + }), + }); let json = tom.serialize(); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), secretLabType: 'batCave', secretLab: { - id: get(tom, "secretLab").get("id"), - minionCapacity: get(tom, "secretLab").get("minionCapacity"), - vicinity: get(tom, "secretLab").get("vicinity"), - infiltrated: true - } + id: get(tom, 'secretLab').get('id'), + minionCapacity: get(tom, 'secretLab').get('minionCapacity'), + vicinity: get(tom, 'secretLab').get('vicinity'), + infiltrated: true, + }, }); }); -test("serialize with embedded object (belongsTo relationship) works with different primaryKeys", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - primaryKey: '_id', - attrs: { - secretLab: { embedded: 'always' } - } - })); - env.registry.register('serializer:secret-lab', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - primaryKey: 'crazy_id' - })); +test('serialize with embedded object (belongsTo relationship) works with different primaryKeys', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + primaryKey: '_id', + attrs: { + secretLab: { embedded: 'always' }, + }, + }) + ); + env.registry.register( + 'serializer:secret-lab', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + primaryKey: 'crazy_id', + }) + ); - var serializer = env.store.serializerFor("super-villain"); + var serializer = env.store.serializerFor('super-villain'); // records with an id, persisted - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } - ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); let json = serializer.serialize(tom._createSnapshot()); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), secretLab: { - crazy_id: get(tom, "secretLab").get("id"), - minionCapacity: get(tom, "secretLab").get("minionCapacity"), - vicinity: get(tom, "secretLab").get("vicinity") - } + crazy_id: get(tom, 'secretLab').get('id'), + minionCapacity: get(tom, 'secretLab').get('minionCapacity'), + vicinity: get(tom, 'secretLab').get('vicinity'), + }, }); }); -test("serialize with embedded object (belongsTo relationship, new no id)", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { embedded: 'always' } - } - })); +test('serialize with embedded object (belongsTo relationship, new no id)', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { embedded: 'always' }, + }, + }) + ); - var serializer = env.store.serializerFor("super-villain"); + var serializer = env.store.serializerFor('super-villain'); // records without ids, new - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", - secretLab: env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } - ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + secretLab: env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); let json = serializer.serialize(tom._createSnapshot()); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), secretLab: { - minionCapacity: get(tom, "secretLab").get("minionCapacity"), - vicinity: get(tom, "secretLab").get("vicinity") - } + minionCapacity: get(tom, 'secretLab').get('minionCapacity'), + vicinity: get(tom, 'secretLab').get('vicinity'), + }, }); }); -test("serialize with embedded object (polymorphic belongsTo relationship) supports serialize:ids", function(assert) { +test('serialize with embedded object (polymorphic belongsTo relationship) supports serialize:ids', function(assert) { SuperVillain.reopen({ - secretLab: DS.belongsTo('secret-lab', { polymorphic: true }) + secretLab: DS.belongsTo('secret-lab', { polymorphic: true }), }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { serialize: 'ids' } - } - })); - - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('bat-cave', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { serialize: 'ids' }, + }, + }) ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('bat-cave', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); + let json = tom.serialize(); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), - secretLab: get(tom, "secretLab").get("id"), - secretLabType: 'batCave' + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), + secretLab: get(tom, 'secretLab').get('id'), + secretLabType: 'batCave', }); }); -test("serialize with embedded object (belongsTo relationship) supports serialize:id", function(assert) { +test('serialize with embedded object (belongsTo relationship) supports serialize:id', function(assert) { SuperVillain.reopen({ - secretLab: DS.belongsTo('secret-lab', { polymorphic: true }) + secretLab: DS.belongsTo('secret-lab', { polymorphic: true }), }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { serialize: 'id' } - } - })); - - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('bat-cave', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { serialize: 'id' }, + }, + }) ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('bat-cave', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); + let json = tom.serialize(); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), - secretLab: get(tom, "secretLab").get("id"), - secretLabType: 'batCave' + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), + secretLab: get(tom, 'secretLab').get('id'), + secretLabType: 'batCave', }); }); -test("serialize with embedded object (belongsTo relationship) supports serialize:id in conjunction with deserialize:records", function(assert) { +test('serialize with embedded object (belongsTo relationship) supports serialize:id in conjunction with deserialize:records', function(assert) { SuperVillain.reopen({ - secretLab: DS.belongsTo('secret-lab', { polymorphic: true }) + secretLab: DS.belongsTo('secret-lab', { polymorphic: true }), }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { serialize: 'id', deserialize: 'records' } - } - })); - - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('bat-cave', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { serialize: 'id', deserialize: 'records' }, + }, + }) ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('bat-cave', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); + let json = tom.serialize(); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), - secretLab: get(tom, "secretLab").get("id"), - secretLabType: 'batCave' + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), + secretLab: get(tom, 'secretLab').get('id'), + secretLabType: 'batCave', }); }); -test("serialize with embedded object (belongsTo relationship) supports serialize:ids", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { serialize: 'ids' } - } - })); - var serializer = env.store.serializerFor("super-villain"); +test('serialize with embedded object (belongsTo relationship) supports serialize:ids', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { serialize: 'ids' }, + }, + }) + ); + var serializer = env.store.serializerFor('super-villain'); // records with an id, persisted - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } - ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); let json = serializer.serialize(tom._createSnapshot()); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), - secretLab: get(tom, "secretLab").get("id") + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), + secretLab: get(tom, 'secretLab').get('id'), }); }); -test("serialize with embedded object (belongsTo relationship) supports serialize:id", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { serialize: 'id' } - } - })); +test('serialize with embedded object (belongsTo relationship) supports serialize:id', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { serialize: 'id' }, + }, + }) + ); - var serializer = env.store.serializerFor("super-villain"); + var serializer = env.store.serializerFor('super-villain'); // records with an id, persisted - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } - ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); let json = serializer.serialize(tom._createSnapshot()); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), - secretLab: get(tom, "secretLab").get("id") + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), + secretLab: get(tom, 'secretLab').get('id'), }); }); -test("serialize with embedded object (belongsTo relationship) supports serialize:id in conjunction with deserialize:records", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { serialize: 'id', deserialize: 'records' } - } - })); +test('serialize with embedded object (belongsTo relationship) supports serialize:id in conjunction with deserialize:records', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { serialize: 'id', deserialize: 'records' }, + }, + }) + ); - var serializer = env.store.serializerFor("super-villain"); + var serializer = env.store.serializerFor('super-villain'); // records with an id, persisted - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } - ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); let json = serializer.serialize(tom._createSnapshot()); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), - secretLab: get(tom, "secretLab").get("id") + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), + secretLab: get(tom, 'secretLab').get('id'), }); }); -test("serialize with embedded object (belongsTo relationship) supports serialize:false", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { serialize: false } - } - })); - var serializer = env.store.serializerFor("super-villain"); - +test('serialize with embedded object (belongsTo relationship) supports serialize:false', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { serialize: false }, + }, + }) + ); + var serializer = env.store.serializerFor('super-villain'); // records with an id, persisted - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } - ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); let json = serializer.serialize(tom._createSnapshot()); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id") + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), }); }); -test("serialize with embedded object (belongsTo relationship) serializes the id by default if no option specified", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin)); - var serializer = env.store.serializerFor("super-villain"); +test('serialize with embedded object (belongsTo relationship) serializes the id by default if no option specified', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin) + ); + var serializer = env.store.serializerFor('super-villain'); // records with an id, persisted - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - secretLab: env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }), - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } - ); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + secretLab: env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }), + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); let json = serializer.serialize(tom._createSnapshot()); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), - secretLab: get(tom, "secretLab").get("id") + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), + secretLab: get(tom, 'secretLab').get('id'), }); }); -test("when related record is not present, serialize embedded record (with a belongsTo relationship) as null", function(assert) { - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { embedded: 'always' } - } - })); - var serializer = env.store.serializerFor("super-villain"); - let tom = env.store.createRecord( - 'super-villain', - { firstName: "Tom", lastName: "Dale", id: "1", - homePlanet: env.store.createRecord('home-planet', { name: "Villain League", id: "123" }) - } +test('when related record is not present, serialize embedded record (with a belongsTo relationship) as null', function(assert) { + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { embedded: 'always' }, + }, + }) ); + var serializer = env.store.serializerFor('super-villain'); + let tom = env.store.createRecord('super-villain', { + firstName: 'Tom', + lastName: 'Dale', + id: '1', + homePlanet: env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }), + }); let json = serializer.serialize(tom._createSnapshot()); assert.deepEqual(json, { - firstName: get(tom, "firstName"), - lastName: get(tom, "lastName"), - homePlanet: get(tom, "homePlanet").get("id"), - secretLab: null + firstName: get(tom, 'firstName'), + lastName: get(tom, 'lastName'), + homePlanet: get(tom, 'homePlanet').get('id'), + secretLab: null, }); }); -test("normalizeResponse with multiply-nested belongsTo", function(assert) { - env.registry.register('serializer:evil-minion', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - superVillain: { embedded: 'always' } - } - })); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - homePlanet: { embedded: 'always' } - } - })); - - var serializer = env.store.serializerFor("evil-minion"); +test('normalizeResponse with multiply-nested belongsTo', function(assert) { + env.registry.register( + 'serializer:evil-minion', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + superVillain: { embedded: 'always' }, + }, + }) + ); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + homePlanet: { embedded: 'always' }, + }, + }) + ); + + var serializer = env.store.serializerFor('evil-minion'); var json_hash = { evilMinion: { - id: "1", - name: "Alex", + id: '1', + name: 'Alex', superVillain: { - id: "1", - firstName: "Tom", - lastName: "Dale", - evilMinions: ["1"], + id: '1', + firstName: 'Tom', + lastName: 'Dale', + evilMinions: ['1'], homePlanet: { - id: "1", - name: "Umber", - villains: ["1"] - } - } - } + id: '1', + name: 'Umber', + villains: ['1'], + }, + }, + }, }; var json; @@ -1574,84 +1864,90 @@ test("normalizeResponse with multiply-nested belongsTo", function(assert) { json = serializer.normalizeResponse(env.store, EvilMinion, json_hash, '1', 'findRecord'); }); - assert.deepEqual(json, { - "data": { - "id": "1", - "type": "evil-minion", - "attributes": { - "name": "Alex" - }, - "relationships": { - "superVillain": { - "data": { "id": "1", "type": "super-villain" } - } - } + assert.deepEqual( + json, + { + data: { + id: '1', + type: 'evil-minion', + attributes: { + name: 'Alex', + }, + relationships: { + superVillain: { + data: { id: '1', type: 'super-villain' }, + }, + }, + }, + included: [ + { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + lastName: 'Dale', + }, + relationships: { + evilMinions: { + data: [{ id: '1', type: 'evil-minion' }], + }, + homePlanet: { + data: { id: '1', type: 'home-planet' }, + }, + }, + }, + { + id: '1', + type: 'home-planet', + attributes: { + name: 'Umber', + }, + relationships: { + villains: { + data: [{ id: '1', type: 'super-villain' }], + }, + }, + }, + ], }, - "included": [{ - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Tom", - "lastName": "Dale" - }, - "relationships": { - "evilMinions": { - "data": [ - { "id": "1", "type": "evil-minion" } - ] - }, - "homePlanet": { - "data": { "id": "1", "type": "home-planet" } - } - } - }, { - "id": "1", - "type": "home-planet", - "attributes": { - "name": "Umber" - }, - "relationships": { - "villains": { - "data": [ - { "id": "1", "type": "super-villain" } - ] - } - } - }] - }, "Primary hash was correct"); + 'Primary hash was correct' + ); }); -test("normalizeResponse with polymorphic hasMany", function(assert) { +test('normalizeResponse with polymorphic hasMany', function(assert) { SuperVillain.reopen({ - secretWeapons: DS.hasMany("secretWeapon", { polymorphic: true, async: false }) + secretWeapons: DS.hasMany('secretWeapon', { polymorphic: true, async: false }), }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretWeapons: { embedded: 'always' } - } - })); - var serializer = env.store.serializerFor("super-villain"); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretWeapons: { embedded: 'always' }, + }, + }) + ); + var serializer = env.store.serializerFor('super-villain'); var json_hash = { super_villain: { - id: "1", - firstName: "Tom", - lastName: "Dale", + id: '1', + firstName: 'Tom', + lastName: 'Dale', secretWeapons: [ { - id: "1", - type: "LightSaber", + id: '1', + type: 'LightSaber', name: "Tom's LightSaber", - color: "Red" + color: 'Red', }, { - id: "1", - type: "SecretWeapon", - name: "The Death Star" - } - ] - } + id: '1', + type: 'SecretWeapon', + name: 'The Death Star', + }, + ], + }, }; var json; @@ -1659,76 +1955,86 @@ test("normalizeResponse with polymorphic hasMany", function(assert) { json = serializer.normalizeResponse(env.store, SuperVillain, json_hash, '1', 'findAll'); }); - assert.deepEqual(json, { - "data": { - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Tom", - "lastName": "Dale" - }, - "relationships": { - "secretWeapons": { - "data": [ - { "id": "1", "type": "light-saber" }, - { "id": "1", "type": "secret-weapon" } - ] - } - } + assert.deepEqual( + json, + { + data: { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + lastName: 'Dale', + }, + relationships: { + secretWeapons: { + data: [{ id: '1', type: 'light-saber' }, { id: '1', type: 'secret-weapon' }], + }, + }, + }, + included: [ + { + id: '1', + type: 'light-saber', + attributes: { + color: 'Red', + name: "Tom's LightSaber", + }, + relationships: {}, + }, + { + id: '1', + type: 'secret-weapon', + attributes: { + name: 'The Death Star', + }, + relationships: {}, + }, + ], }, - "included": [{ - "id": "1", - "type": "light-saber", - "attributes": { - "color": "Red", - "name": "Tom's LightSaber" - }, - "relationships": {} - }, { - "id": "1", - "type": "secret-weapon", - "attributes": { - "name": "The Death Star" - }, - "relationships": {} - }] - }, "Primary hash was correct"); + 'Primary hash was correct' + ); }); -test("normalizeResponse with polymorphic hasMany and custom primary key", function(assert) { +test('normalizeResponse with polymorphic hasMany and custom primary key', function(assert) { SuperVillain.reopen({ - secretWeapons: DS.hasMany("secretWeapon", { polymorphic: true, async: false }) + secretWeapons: DS.hasMany('secretWeapon', { polymorphic: true, async: false }), }); - env.registry.register('serializer:light-saber', DS.RESTSerializer.extend({ - primaryKey: 'custom' - })); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretWeapons: { embedded: 'always' } - } - })); - var serializer = env.store.serializerFor("super-villain"); + env.registry.register( + 'serializer:light-saber', + DS.RESTSerializer.extend({ + primaryKey: 'custom', + }) + ); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretWeapons: { embedded: 'always' }, + }, + }) + ); + var serializer = env.store.serializerFor('super-villain'); var json_hash = { super_villain: { - id: "1", - firstName: "Tom", - lastName: "Dale", + id: '1', + firstName: 'Tom', + lastName: 'Dale', secretWeapons: [ { - custom: "1", - type: "LightSaber", + custom: '1', + type: 'LightSaber', name: "Tom's LightSaber", - color: "Red" + color: 'Red', }, { - id: "1", - type: "SecretWeapon", - name: "The Death Star" - } - ] - } + id: '1', + type: 'SecretWeapon', + name: 'The Death Star', + }, + ], + }, }; var json; @@ -1736,68 +2042,72 @@ test("normalizeResponse with polymorphic hasMany and custom primary key", functi json = serializer.normalizeResponse(env.store, SuperVillain, json_hash, '1', 'findRecord'); }); - assert.deepEqual(json, { - "data": { - "attributes": { - "firstName": "Tom", - "lastName": "Dale" - }, - "id": "1", - "relationships": { - "secretWeapons": { - "data": [ - { "type": "light-saber", "id": "1" }, - { "type": "secret-weapon", "id": "1" } - ] - } - }, - "type": "super-villain" - }, - "included": [ - { - "attributes": { - "color": "Red", - "name": "Tom's LightSaber" + assert.deepEqual( + json, + { + data: { + attributes: { + firstName: 'Tom', + lastName: 'Dale', + }, + id: '1', + relationships: { + secretWeapons: { + data: [{ type: 'light-saber', id: '1' }, { type: 'secret-weapon', id: '1' }], + }, }, - "id": "1", - "relationships": {}, - "type": "light-saber" + type: 'super-villain', }, - { - "attributes": { - "name": "The Death Star" + included: [ + { + attributes: { + color: 'Red', + name: "Tom's LightSaber", + }, + id: '1', + relationships: {}, + type: 'light-saber', }, - "id": "1", - "relationships": {}, - "type": "secret-weapon" - } - ] - }, "Custom primary key of embedded hasMany is correctly normalized"); + { + attributes: { + name: 'The Death Star', + }, + id: '1', + relationships: {}, + type: 'secret-weapon', + }, + ], + }, + 'Custom primary key of embedded hasMany is correctly normalized' + ); }); -test("normalizeResponse with polymorphic belongsTo", function(assert) { +test('normalizeResponse with polymorphic belongsTo', function(assert) { SuperVillain.reopen({ - secretLab: DS.belongsTo("secretLab", { polymorphic: true, async: true }) + secretLab: DS.belongsTo('secretLab', { polymorphic: true, async: true }), }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { embedded: 'always' } - } - })); - var serializer = env.store.serializerFor("super-villain"); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { embedded: 'always' }, + }, + }) + ); + var serializer = env.store.serializerFor('super-villain'); var json_hash = { super_villain: { - id: "1", - firstName: "Tom", - lastName: "Dale", + id: '1', + firstName: 'Tom', + lastName: 'Dale', secretLab: { - id: "1", - type: "bat-cave", - infiltrated: true - } - } + id: '1', + type: 'bat-cave', + infiltrated: true, + }, + }, }; var json; @@ -1806,59 +2116,71 @@ test("normalizeResponse with polymorphic belongsTo", function(assert) { json = serializer.normalizeResponse(env.store, SuperVillain, json_hash, '1', 'findRecord'); }); - assert.deepEqual(json, { - "data": { - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Tom", - "lastName": "Dale" - }, - "relationships": { - "secretLab": { - "data": { "id": "1", "type": "bat-cave" } - } - } + assert.deepEqual( + json, + { + data: { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + lastName: 'Dale', + }, + relationships: { + secretLab: { + data: { id: '1', type: 'bat-cave' }, + }, + }, + }, + included: [ + { + id: '1', + type: 'bat-cave', + attributes: { + infiltrated: true, + }, + relationships: {}, + }, + ], }, - "included": [{ - "id": "1", - "type": "bat-cave", - "attributes": { - "infiltrated": true - }, - "relationships": {} - }] - }, "Primary has was correct"); + 'Primary has was correct' + ); }); -test("normalizeResponse with polymorphic belongsTo and custom primary key", function(assert) { +test('normalizeResponse with polymorphic belongsTo and custom primary key', function(assert) { assert.expect(1); SuperVillain.reopen({ - secretLab: DS.belongsTo("secretLab", { polymorphic: true, async: true }) + secretLab: DS.belongsTo('secretLab', { polymorphic: true, async: true }), }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretLab: { embedded: 'always' } - } - })); - env.registry.register('serializer:bat-cave', DS.RESTSerializer.extend({ - primaryKey: 'custom' - })); - var serializer = env.store.serializerFor("super-villain"); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretLab: { embedded: 'always' }, + }, + }) + ); + env.registry.register( + 'serializer:bat-cave', + DS.RESTSerializer.extend({ + primaryKey: 'custom', + }) + ); + var serializer = env.store.serializerFor('super-villain'); var json_hash = { superVillain: { - id: "1", - firstName: "Tom", - lastName: "Dale", + id: '1', + firstName: 'Tom', + lastName: 'Dale', secretLab: { - custom: "1", - type: "bat-cave", - infiltrated: true - } - } + custom: '1', + type: 'bat-cave', + infiltrated: true, + }, + }, }; var json; @@ -1867,95 +2189,126 @@ test("normalizeResponse with polymorphic belongsTo and custom primary key", func json = serializer.normalizeResponse(env.store, SuperVillain, json_hash, '1', 'findRecord'); }); - assert.deepEqual(json, { - "data": { - "attributes": { - "firstName": "Tom", - "lastName": "Dale" - }, - "id": "1", - "relationships": { - "secretLab": { - "data": { - "id": "1", - "type": "bat-cave" - } - } - }, - "type": "super-villain" - }, - "included": [ - { - "attributes": { - "infiltrated": true + assert.deepEqual( + json, + { + data: { + attributes: { + firstName: 'Tom', + lastName: 'Dale', }, - "id": "1", - "relationships": {}, - "type": "bat-cave" - } - ] - }, "Custom primary key is correctly normalized"); + id: '1', + relationships: { + secretLab: { + data: { + id: '1', + type: 'bat-cave', + }, + }, + }, + type: 'super-villain', + }, + included: [ + { + attributes: { + infiltrated: true, + }, + id: '1', + relationships: {}, + type: 'bat-cave', + }, + ], + }, + 'Custom primary key is correctly normalized' + ); }); -test("Mixin can be used with RESTSerializer which does not define keyForAttribute", function(assert) { - let homePlanet = env.store.createRecord('home-planet', { name: "Villain League", id: "123" }); - let secretLab = env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }); +test('Mixin can be used with RESTSerializer which does not define keyForAttribute', function(assert) { + let homePlanet = env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }); + let secretLab = env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }); let superVillain = env.store.createRecord('super-villain', { - id: "1", firstName: "Super", lastName: "Villian", homePlanet: homePlanet, secretLab: secretLab + id: '1', + firstName: 'Super', + lastName: 'Villian', + homePlanet: homePlanet, + secretLab: secretLab, + }); + let secretWeapon = env.store.createRecord('secret-weapon', { + id: '1', + name: 'Secret Weapon', + superVillain: superVillain, }); - let secretWeapon = env.store.createRecord('secret-weapon', { id: "1", name: "Secret Weapon", superVillain: superVillain }); let evilMinion; run(function() { superVillain.get('secretWeapons').pushObject(secretWeapon); - evilMinion = env.store.createRecord('evil-minion', { id: "1", name: "Evil Minion", superVillian: superVillain }); + evilMinion = env.store.createRecord('evil-minion', { + id: '1', + name: 'Evil Minion', + superVillian: superVillain, + }); superVillain.get('evilMinions').pushObject(evilMinion); }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - evilMinions: { serialize: 'records', deserialize: 'records' } - } - })); - let serializer = env.store.serializerFor("super-villain"); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + evilMinions: { serialize: 'records', deserialize: 'records' }, + }, + }) + ); + let serializer = env.store.serializerFor('super-villain'); let json = serializer.serialize(superVillain._createSnapshot()); assert.deepEqual(json, { - firstName: get(superVillain, "firstName"), - lastName: get(superVillain, "lastName"), - homePlanet: "123", - evilMinions: [{ - id: get(evilMinion, "id"), - name: get(evilMinion, "name"), - superVillain: "1" - }], - secretLab: "101" + firstName: get(superVillain, 'firstName'), + lastName: get(superVillain, 'lastName'), + homePlanet: '123', + evilMinions: [ + { + id: get(evilMinion, 'id'), + name: get(evilMinion, 'name'), + superVillain: '1', + }, + ], + secretLab: '101', // "manyToOne" relation does not serialize ids // sersecretWeapons: ["1"] }); }); -test("normalize with custom belongsTo primary key", function(assert) { - env.registry.register('serializer:evil-minion', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - superVillain: { embedded: 'always' } - } - })); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend({ - primaryKey: 'custom' - })); - - var serializer = env.store.serializerFor("evil-minion"); +test('normalize with custom belongsTo primary key', function(assert) { + env.registry.register( + 'serializer:evil-minion', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + superVillain: { embedded: 'always' }, + }, + }) + ); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend({ + primaryKey: 'custom', + }) + ); + + var serializer = env.store.serializerFor('evil-minion'); var json_hash = { evilMinion: { - id: "1", - name: "Alex", + id: '1', + name: 'Alex', superVillain: { - custom: "1", - firstName: "Tom", - lastName: "Dale" - } - } + custom: '1', + firstName: 'Tom', + lastName: 'Dale', + }, + }, }; var json; @@ -1963,43 +2316,65 @@ test("normalize with custom belongsTo primary key", function(assert) { json = serializer.normalizeResponse(env.store, EvilMinion, json_hash, '1', 'findRecord'); }); - assert.deepEqual(json, { - "data": { - "id": "1", - "type": "evil-minion", - "attributes": { - "name": "Alex" - }, - "relationships": { - "superVillain": { - "data": { "id": "1", "type": "super-villain" } - } - } + assert.deepEqual( + json, + { + data: { + id: '1', + type: 'evil-minion', + attributes: { + name: 'Alex', + }, + relationships: { + superVillain: { + data: { id: '1', type: 'super-villain' }, + }, + }, + }, + included: [ + { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + lastName: 'Dale', + }, + relationships: {}, + }, + ], }, - "included": [{ - "id": "1", - "type": "super-villain", - "attributes": { - "firstName": "Tom", - "lastName": "Dale" - }, - "relationships": {} - }] - }, "Primary hash was correct"); + 'Primary hash was correct' + ); }); -test("serializing relationships with an embedded and without calls super when not attr not present", function(assert) { - let homePlanet = env.store.createRecord('home-planet', { name: "Villain League", id: "123" }); - let secretLab = env.store.createRecord('secret-lab', { minionCapacity: 5000, vicinity: "California, USA", id: "101" }); +test('serializing relationships with an embedded and without calls super when not attr not present', function(assert) { + let homePlanet = env.store.createRecord('home-planet', { name: 'Villain League', id: '123' }); + let secretLab = env.store.createRecord('secret-lab', { + minionCapacity: 5000, + vicinity: 'California, USA', + id: '101', + }); let superVillain = env.store.createRecord('super-villain', { - id: "1", firstName: "Super", lastName: "Villian", homePlanet: homePlanet, secretLab: secretLab + id: '1', + firstName: 'Super', + lastName: 'Villian', + homePlanet: homePlanet, + secretLab: secretLab, + }); + let secretWeapon = env.store.createRecord('secret-weapon', { + id: '1', + name: 'Secret Weapon', + superVillain: superVillain, }); - let secretWeapon = env.store.createRecord('secret-weapon', { id: "1", name: "Secret Weapon", superVillain: superVillain }); let evilMinion; run(function() { superVillain.get('secretWeapons').pushObject(secretWeapon); - evilMinion = env.store.createRecord('evil-minion', { id: "1", name: "Evil Minion", superVillian: superVillain }); + evilMinion = env.store.createRecord('evil-minion', { + id: '1', + name: 'Evil Minion', + superVillian: superVillain, + }); superVillain.get('evilMinions').pushObject(evilMinion); }); @@ -2014,169 +2389,215 @@ test("serializing relationships with an embedded and without calls super when no serializeHasMany(snapshot, json, relationship) { calledSerializeHasMany = true; var key = relationship.key; - var payloadKey = this.keyForRelationship ? this.keyForRelationship(key, "hasMany") : key; + var payloadKey = this.keyForRelationship ? this.keyForRelationship(key, 'hasMany') : key; var relationshipType = snapshot.type.determineRelationshipType(relationship); // "manyToOne" not supported in DS.ActiveModelSerializer.prototype.serializeHasMany var relationshipTypes = w('manyToNone manyToMany manyToOne'); if (relationshipTypes.indexOf(relationshipType) > -1) { json[payloadKey] = snapshot.hasMany(key, { ids: true }); } - } + }, }); env.registry.register('serializer:evil-minion', Serializer); env.registry.register('serializer:secret-weapon', Serializer); - env.registry.register('serializer:super-villain', Serializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - evilMinions: { serialize: 'records', deserialize: 'records' } - // some relationships are not listed here, so super should be called on those - // e.g. secretWeapons: { serialize: 'ids' } - } - })); - let serializer = env.store.serializerFor("super-villain"); + env.registry.register( + 'serializer:super-villain', + Serializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + evilMinions: { serialize: 'records', deserialize: 'records' }, + // some relationships are not listed here, so super should be called on those + // e.g. secretWeapons: { serialize: 'ids' } + }, + }) + ); + let serializer = env.store.serializerFor('super-villain'); let json = serializer.serialize(superVillain._createSnapshot()); assert.deepEqual(json, { - firstName: get(superVillain, "firstName"), - lastName: get(superVillain, "lastName"), - homePlanet: "123", - evilMinions: [{ - id: get(evilMinion, "id"), - name: get(evilMinion, "name"), - superVillain: "1" - }], - secretLab: "101", + firstName: get(superVillain, 'firstName'), + lastName: get(superVillain, 'lastName'), + homePlanet: '123', + evilMinions: [ + { + id: get(evilMinion, 'id'), + name: get(evilMinion, 'name'), + superVillain: '1', + }, + ], + secretLab: '101', // customized serializeHasMany method to generate ids for "manyToOne" relation - secretWeapons: ["1"] + secretWeapons: ['1'], }); assert.ok(calledSerializeBelongsTo); assert.ok(calledSerializeHasMany); }); -test("serializing belongsTo correctly removes embedded foreign key", function(assert) { +test('serializing belongsTo correctly removes embedded foreign key', function(assert) { SecretWeapon.reopen({ - superVillain: null + superVillain: null, }); EvilMinion.reopen({ secretWeapon: DS.belongsTo('secret-weapon', { async: false }), - superVillain: null + superVillain: null, }); - let secretWeapon = env.store.createRecord('secret-weapon', { name: "Secret Weapon" }); - let evilMinion = env.store.createRecord('evil-minion', { name: "Evil Minion", secretWeapon: secretWeapon }); + let secretWeapon = env.store.createRecord('secret-weapon', { name: 'Secret Weapon' }); + let evilMinion = env.store.createRecord('evil-minion', { + name: 'Evil Minion', + secretWeapon: secretWeapon, + }); - env.registry.register('serializer:evil-minion', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - secretWeapon: { embedded: 'always' } - } - })); + env.registry.register( + 'serializer:evil-minion', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + secretWeapon: { embedded: 'always' }, + }, + }) + ); - let serializer = env.store.serializerFor("evil-minion"); + let serializer = env.store.serializerFor('evil-minion'); let json = serializer.serialize(evilMinion._createSnapshot()); assert.deepEqual(json, { - name: "Evil Minion", + name: 'Evil Minion', secretWeapon: { - name: "Secret Weapon" - } + name: 'Secret Weapon', + }, }); }); +test('serializing embedded belongsTo respects remapped attrs key', function(assert) { + let homePlanet = env.store.createRecord('home-planet', { name: 'Hoth' }); + let superVillain = env.store.createRecord('super-villain', { + firstName: 'Ice', + lastName: 'Creature', + homePlanet: homePlanet, + }); -test("serializing embedded belongsTo respects remapped attrs key", function(assert) { - let homePlanet = env.store.createRecord('home-planet', { name: "Hoth" }); - let superVillain = env.store.createRecord('super-villain', { firstName: "Ice", lastName: "Creature", homePlanet: homePlanet }); - - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - homePlanet: { embedded: 'always', key: 'favorite_place' } - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + homePlanet: { embedded: 'always', key: 'favorite_place' }, + }, + }) + ); - let serializer = env.store.serializerFor("super-villain"); + let serializer = env.store.serializerFor('super-villain'); let json = serializer.serialize(superVillain._createSnapshot()); assert.deepEqual(json, { - firstName: "Ice", - lastName: "Creature", + firstName: 'Ice', + lastName: 'Creature', favorite_place: { - name: "Hoth" + name: 'Hoth', }, - secretLab: null + secretLab: null, }); }); -test("serializing embedded hasMany respects remapped attrs key", function(assert) { - let homePlanet = env.store.createRecord('home-planet', { name: "Hoth" }); - env.store.createRecord('super-villain', { firstName: "Ice", lastName: "Creature", homePlanet: homePlanet }); +test('serializing embedded hasMany respects remapped attrs key', function(assert) { + let homePlanet = env.store.createRecord('home-planet', { name: 'Hoth' }); + env.store.createRecord('super-villain', { + firstName: 'Ice', + lastName: 'Creature', + homePlanet: homePlanet, + }); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { embedded: 'always', key: 'notable_persons' } - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { embedded: 'always', key: 'notable_persons' }, + }, + }) + ); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - homePlanet: { serialize: false }, - secretLab: { serialize: false } - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + homePlanet: { serialize: false }, + secretLab: { serialize: false }, + }, + }) + ); - let serializer = env.store.serializerFor("home-planet"); + let serializer = env.store.serializerFor('home-planet'); let json = serializer.serialize(homePlanet._createSnapshot()); assert.deepEqual(json, { - name: "Hoth", - notable_persons: [{ - firstName: 'Ice', - lastName: 'Creature' - }] + name: 'Hoth', + notable_persons: [ + { + firstName: 'Ice', + lastName: 'Creature', + }, + ], }); }); -test("serializing id belongsTo respects remapped attrs key", function(assert) { - let homePlanet = env.store.createRecord('home-planet', { name: "Hoth" }); - let superVillain = env.store.createRecord('super-villain', { firstName: "Ice", lastName: "Creature", homePlanet: homePlanet }); +test('serializing id belongsTo respects remapped attrs key', function(assert) { + let homePlanet = env.store.createRecord('home-planet', { name: 'Hoth' }); + let superVillain = env.store.createRecord('super-villain', { + firstName: 'Ice', + lastName: 'Creature', + homePlanet: homePlanet, + }); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - homePlanet: { serialize: 'id', key: 'favorite_place' } - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + homePlanet: { serialize: 'id', key: 'favorite_place' }, + }, + }) + ); - let serializer = env.store.serializerFor("super-villain"); + let serializer = env.store.serializerFor('super-villain'); let json = serializer.serialize(superVillain._createSnapshot()); assert.deepEqual(json, { - firstName: "Ice", - lastName: "Creature", + firstName: 'Ice', + lastName: 'Creature', favorite_place: homePlanet.id, - secretLab: null + secretLab: null, }); }); -test("serializing ids hasMany respects remapped attrs key", function(assert) { - let homePlanet = env.store.createRecord('home-planet', { name: "Hoth" }); - let superVillain = env.store.createRecord('super-villain', { firstName: "Ice", lastName: "Creature", homePlanet: homePlanet }); +test('serializing ids hasMany respects remapped attrs key', function(assert) { + let homePlanet = env.store.createRecord('home-planet', { name: 'Hoth' }); + let superVillain = env.store.createRecord('super-villain', { + firstName: 'Ice', + lastName: 'Creature', + homePlanet: homePlanet, + }); - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - villains: { serialize: 'ids', key: 'notable_persons' } - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + villains: { serialize: 'ids', key: 'notable_persons' }, + }, + }) + ); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - homePlanet: { serialize: false }, - secretLab: { serialize: false } - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + homePlanet: { serialize: false }, + secretLab: { serialize: false }, + }, + }) + ); - let serializer = env.store.serializerFor("home-planet"); + let serializer = env.store.serializerFor('home-planet'); let json = serializer.serialize(homePlanet._createSnapshot()); assert.deepEqual(json, { - name: "Hoth", - notable_persons: [superVillain.id] + name: 'Hoth', + notable_persons: [superVillain.id], }); }); diff --git a/tests/integration/serializers/json-api-serializer-test.js b/tests/integration/serializers/json-api-serializer-test.js index 57512906683..8f238c1727f 100644 --- a/tests/integration/serializers/json-api-serializer-test.js +++ b/tests/integration/serializers/json-api-serializer-test.js @@ -19,28 +19,28 @@ module('integration/serializers/json-api-serializer - JSONAPISerializer', { title: DS.attr('string'), handles: DS.hasMany('handle', { async: true, polymorphic: true }), company: DS.belongsTo('company', { async: true }), - reportsTo: DS.belongsTo('user', { async: true, inverse: null }) + reportsTo: DS.belongsTo('user', { async: true, inverse: null }), }); Handle = DS.Model.extend({ - user: DS.belongsTo('user', { async: true }) + user: DS.belongsTo('user', { async: true }), }); GithubHandle = Handle.extend({ - username: DS.attr('string') + username: DS.attr('string'), }); TwitterHandle = Handle.extend({ - nickname: DS.attr('string') + nickname: DS.attr('string'), }); Company = DS.Model.extend({ name: DS.attr('string'), - employees: DS.hasMany('user', { async: true }) + employees: DS.hasMany('user', { async: true }), }); Project = DS.Model.extend({ - 'company-name': DS.attr('string') + 'company-name': DS.attr('string'), }); env = setupStore({ @@ -51,7 +51,7 @@ module('integration/serializers/json-api-serializer - JSONAPISerializer', { 'github-handle': GithubHandle, 'twitter-handle': TwitterHandle, company: Company, - project: Project + project: Project, }); store = env.store; @@ -60,7 +60,7 @@ module('integration/serializers/json-api-serializer - JSONAPISerializer', { afterEach() { run(env.store, 'destroy'); - } + }, }); test('Calling pushPayload works', function(assert) { @@ -71,39 +71,40 @@ test('Calling pushPayload works', function(assert) { id: '1', attributes: { 'first-name': 'Yehuda', - 'last-name': 'Katz' + 'last-name': 'Katz', }, relationships: { company: { - data: { type: 'companies', id: '2' } + data: { type: 'companies', id: '2' }, }, handles: { - data: [ - { type: 'github-handles', id: '3' }, - { type: 'twitter-handles', id: '4' } - ] - } - } - }, - included: [{ - type: 'companies', - id: '2', - attributes: { - name: 'Tilde Inc.' - } - }, { - type: 'github-handles', - id: '3', - attributes: { - username: 'wycats' - } - }, { - type: 'twitter-handles', - id: '4', - attributes: { - nickname: '@wycats' - } - }] + data: [{ type: 'github-handles', id: '3' }, { type: 'twitter-handles', id: '4' }], + }, + }, + }, + included: [ + { + type: 'companies', + id: '2', + attributes: { + name: 'Tilde Inc.', + }, + }, + { + type: 'github-handles', + id: '3', + attributes: { + username: 'wycats', + }, + }, + { + type: 'twitter-handles', + id: '4', + attributes: { + nickname: '@wycats', + }, + }, + ], }); var user = store.peekRecord('user', 1); @@ -111,8 +112,16 @@ test('Calling pushPayload works', function(assert) { assert.equal(get(user, 'firstName'), 'Yehuda', 'firstName is correct'); assert.equal(get(user, 'lastName'), 'Katz', 'lastName is correct'); assert.equal(get(user, 'company.name'), 'Tilde Inc.', 'company.name is correct'); - assert.equal(get(user, 'handles.firstObject.username'), 'wycats', 'handles.firstObject.username is correct'); - assert.equal(get(user, 'handles.lastObject.nickname'), '@wycats', 'handles.lastObject.nickname is correct'); + assert.equal( + get(user, 'handles.firstObject.username'), + 'wycats', + 'handles.firstObject.username is correct' + ); + assert.equal( + get(user, 'handles.lastObject.nickname'), + '@wycats', + 'handles.lastObject.nickname is correct' + ); }); }); @@ -122,14 +131,16 @@ testInDebug('Warns when normalizing an unknown type', function(assert) { type: 'UnknownType', id: '1', attributes: { - foo: 'bar' - } - } + foo: 'bar', + }, + }, }; assert.expectWarning(function() { run(function() { - env.store.serializerFor('user').normalizeResponse(env.store, User, documentHash, '1', 'findRecord'); + env.store + .serializerFor('user') + .normalizeResponse(env.store, User, documentHash, '1', 'findRecord'); }); }, /Encountered a resource object with type "UnknownType", but no model was found for model name "unknown-type"/); }); @@ -141,47 +152,55 @@ testInDebug('Warns when normalizing payload with unknown type included', functio id: '1', attributes: { 'first-name': 'Yehuda', - 'last-name': 'Katz' + 'last-name': 'Katz', }, relationships: { company: { - data: { type: 'unknown-types', id: '2' } - } - } + data: { type: 'unknown-types', id: '2' }, + }, + }, }, - included: [{ - type: 'unknown-types', - id: '2', - attributes: { - name: 'WyKittens' - } - }] + included: [ + { + type: 'unknown-types', + id: '2', + attributes: { + name: 'WyKittens', + }, + }, + ], }; assert.expectWarning(function() { run(function() { - env.store.serializerFor('user').normalizeResponse(env.store, User, documentHash, '1', 'findRecord'); + env.store + .serializerFor('user') + .normalizeResponse(env.store, User, documentHash, '1', 'findRecord'); }); }, /Encountered a resource object with type "unknown-types", but no model was found for model name "unknown-type"/); }); -testInDebug('Warns but does not fail when pushing payload with unknown type included', function(assert) { +testInDebug('Warns but does not fail when pushing payload with unknown type included', function( + assert +) { var documentHash = { data: { type: 'users', id: '1', attributes: { 'first-name': 'Yehuda', - 'last-name': 'Katz' - } + 'last-name': 'Katz', + }, }, - included: [{ - type: 'unknown-types', - id: '2', - attributes: { - name: 'WyKittens' - } - }] + included: [ + { + type: 'unknown-types', + id: '2', + attributes: { + name: 'WyKittens', + }, + }, + ], }; assert.expectWarning(function() { @@ -194,21 +213,23 @@ testInDebug('Warns but does not fail when pushing payload with unknown type incl assert.equal(get(user, 'firstName'), 'Yehuda', 'firstName is correct'); }); -testInDebug('Errors when pushing payload with unknown type included in relationship', function(assert) { +testInDebug('Errors when pushing payload with unknown type included in relationship', function( + assert +) { var documentHash = { data: { type: 'users', id: '1', attributes: { 'first-name': 'Yehuda', - 'last-name': 'Katz' + 'last-name': 'Katz', }, relationships: { company: { - data: { type: 'unknown-types', id: '2' } - } - } - } + data: { type: 'unknown-types', id: '2' }, + }, + }, + }, }; assert.expectAssertion(function() { @@ -223,65 +244,77 @@ testInDebug('Warns when normalizing with type missing', function(assert) { data: { id: '1', attributes: { - foo: 'bar' - } - } + foo: 'bar', + }, + }, }; assert.expectAssertion(function() { run(function() { - env.store.serializerFor('user').normalizeResponse(env.store, User, documentHash, '1', 'findRecord'); + env.store + .serializerFor('user') + .normalizeResponse(env.store, User, documentHash, '1', 'findRecord'); }); }, /Encountered a resource object with an undefined type/); }); test('Serializer should respect the attrs hash when extracting attributes and relationships', function(assert) { - env.registry.register("serializer:user", DS.JSONAPISerializer.extend({ - attrs: { - firstName: 'firstname_attribute_key', - title: "title_attribute_key", - company: { key: 'company_relationship_key' } - } - })); + env.registry.register( + 'serializer:user', + DS.JSONAPISerializer.extend({ + attrs: { + firstName: 'firstname_attribute_key', + title: 'title_attribute_key', + company: { key: 'company_relationship_key' }, + }, + }) + ); var jsonHash = { data: { type: 'users', id: '1', attributes: { - 'firstname_attribute_key': 'Yehuda', - 'title_attribute_key': 'director' + firstname_attribute_key: 'Yehuda', + title_attribute_key: 'director', }, relationships: { - 'company_relationship_key': { - data: { type: 'companies', id: '2' } - } - } + company_relationship_key: { + data: { type: 'companies', id: '2' }, + }, + }, }, - included: [{ - type: 'companies', - id: '2', - attributes: { - name: 'Tilde Inc.' - } - }] + included: [ + { + type: 'companies', + id: '2', + attributes: { + name: 'Tilde Inc.', + }, + }, + ], }; - var user = env.store.serializerFor("user").normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); + var user = env.store + .serializerFor('user') + .normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); assert.equal(user.data.attributes.firstName, 'Yehuda'); - assert.equal(user.data.attributes.title, "director"); - assert.deepEqual(user.data.relationships.company.data, { id: "2", type: "company" }); + assert.equal(user.data.attributes.title, 'director'); + assert.deepEqual(user.data.relationships.company.data, { id: '2', type: 'company' }); }); test('Serializer should respect the attrs hash when serializing attributes and relationships', function(assert) { - env.registry.register("serializer:user", DS.JSONAPISerializer.extend({ - attrs: { - firstName: 'firstname_attribute_key', - title: "title_attribute_key", - company: { key: 'company_relationship_key' } - } - })); + env.registry.register( + 'serializer:user', + DS.JSONAPISerializer.extend({ + attrs: { + firstName: 'firstname_attribute_key', + title: 'title_attribute_key', + company: { key: 'company_relationship_key' }, + }, + }) + ); var company, user; run(function() { @@ -290,49 +323,61 @@ test('Serializer should respect the attrs hash when serializing attributes and r type: 'company', id: '1', attributes: { - name: "Tilde Inc." - } - } + name: 'Tilde Inc.', + }, + }, }); company = env.store.peekRecord('company', 1); - user = env.store.createRecord('user', { firstName: "Yehuda", title: "director", company: company }); + user = env.store.createRecord('user', { + firstName: 'Yehuda', + title: 'director', + company: company, + }); }); - var payload = env.store.serializerFor("user").serialize(user._createSnapshot()); + var payload = env.store.serializerFor('user').serialize(user._createSnapshot()); - assert.equal(payload.data.relationships['company_relationship_key'].data.id, "1"); + assert.equal(payload.data.relationships['company_relationship_key'].data.id, '1'); assert.equal(payload.data.attributes['firstname_attribute_key'], 'Yehuda'); - assert.equal(payload.data.attributes['title_attribute_key'], "director"); + assert.equal(payload.data.attributes['title_attribute_key'], 'director'); }); test('Serializer should respect the attrs hash when extracting attributes with not camelized keys', function(assert) { - env.registry.register('serializer:project', DS.JSONAPISerializer.extend({ - attrs: { - 'company-name': 'company_name' - } - })); + env.registry.register( + 'serializer:project', + DS.JSONAPISerializer.extend({ + attrs: { + 'company-name': 'company_name', + }, + }) + ); var jsonHash = { data: { type: 'projects', id: '1', attributes: { - 'company_name': 'Tilde Inc.' - } - } + company_name: 'Tilde Inc.', + }, + }, }; - var project = env.store.serializerFor('project').normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); + var project = env.store + .serializerFor('project') + .normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); assert.equal(project.data.attributes['company-name'], 'Tilde Inc.'); }); test('Serializer should respect the attrs hash when serializing attributes with not camelized keys', function(assert) { - env.registry.register('serializer:project', DS.JSONAPISerializer.extend({ - attrs: { - 'company-name': 'company_name' - } - })); + env.registry.register( + 'serializer:project', + DS.JSONAPISerializer.extend({ + attrs: { + 'company-name': 'company_name', + }, + }) + ); let project = env.store.createRecord('project', { 'company-name': 'Tilde Inc.' }); let payload = env.store.serializerFor('project').serialize(project._createSnapshot()); @@ -343,16 +388,19 @@ test('Serializer should respect the attrs hash when serializing attributes with test('options are passed to transform for serialization', function(assert) { assert.expect(1); - env.registry.register('transform:custom', DS.Transform.extend({ - serialize: function(deserialized, options) { - assert.deepEqual(options, { custom: 'config' }); - } - })); + env.registry.register( + 'transform:custom', + DS.Transform.extend({ + serialize: function(deserialized, options) { + assert.deepEqual(options, { custom: 'config' }); + }, + }) + ); User.reopen({ myCustomField: DS.attr('custom', { - custom: 'config' - }) + custom: 'config', + }), }); let user = env.store.createRecord('user', { myCustomField: 'value' }); @@ -363,7 +411,7 @@ test('options are passed to transform for serialization', function(assert) { testInDebug('Warns when defining extractMeta()', function(assert) { assert.expectWarning(function() { DS.JSONAPISerializer.extend({ - extractMeta() {} + extractMeta() {}, }).create(); }, /You've defined 'extractMeta' in/); }); @@ -373,8 +421,8 @@ test('a belongsTo relationship that is not set will not be in the relationships serializer.pushPayload(store, { data: { type: 'handles', - id: 1 - } + id: 1, + }, }); let handle = store.peekRecord('handle', 1); @@ -383,8 +431,8 @@ test('a belongsTo relationship that is not set will not be in the relationships assert.deepEqual(serialized, { data: { type: 'handles', - id: '1' - } + id: '1', + }, }); }); }); @@ -394,8 +442,8 @@ test('a belongsTo relationship that is set to null will show as null in the rela serializer.pushPayload(store, { data: { type: 'handles', - id: 1 - } + id: 1, + }, }); let handle = store.peekRecord('handle', 1); @@ -408,10 +456,10 @@ test('a belongsTo relationship that is set to null will show as null in the rela id: '1', relationships: { user: { - data: null - } - } - } + data: null, + }, + }, + }, }); }); }); @@ -421,8 +469,8 @@ test('a belongsTo relationship set to a new record will not show in the relation serializer.pushPayload(store, { data: { type: 'handles', - id: 1 - } + id: 1, + }, }); let handle = store.peekRecord('handle', 1); @@ -433,18 +481,21 @@ test('a belongsTo relationship set to a new record will not show in the relation assert.deepEqual(serialized, { data: { type: 'handles', - id: '1' - } + id: '1', + }, }); }); }); test('it should serialize a hasMany relationship', function(assert) { - env.registry.register("serializer:user", DS.JSONAPISerializer.extend({ - attrs: { - handles: { serialize: true } - } - })); + env.registry.register( + 'serializer:user', + DS.JSONAPISerializer.extend({ + attrs: { + handles: { serialize: true }, + }, + }) + ); run(function() { serializer.pushPayload(store, { @@ -453,17 +504,11 @@ test('it should serialize a hasMany relationship', function(assert) { id: 1, relationships: { handles: { - data: [ - { type: 'handles', id: 1 }, - { type: 'handles', id: 2 } - ] - } - } + data: [{ type: 'handles', id: 1 }, { type: 'handles', id: 2 }], + }, + }, }, - included: [ - { type: 'handles', id: 1 }, - { type: 'handles', id: 2 } - ] + included: [{ type: 'handles', id: 1 }, { type: 'handles', id: 2 }], }); let user = store.peekRecord('user', 1); @@ -477,27 +522,27 @@ test('it should serialize a hasMany relationship', function(assert) { attributes: { 'first-name': null, 'last-name': null, - title: null + title: null, }, relationships: { handles: { - data: [ - { type: 'handles', id: '1' }, - { type: 'handles', id: '2' } - ] - } - } - } + data: [{ type: 'handles', id: '1' }, { type: 'handles', id: '2' }], + }, + }, + }, }); }); }); test('it should not include new records when serializing a hasMany relationship', function(assert) { - env.registry.register("serializer:user", DS.JSONAPISerializer.extend({ - attrs: { - handles: { serialize: true } - } - })); + env.registry.register( + 'serializer:user', + DS.JSONAPISerializer.extend({ + attrs: { + handles: { serialize: true }, + }, + }) + ); run(function() { serializer.pushPayload(store, { @@ -506,17 +551,11 @@ test('it should not include new records when serializing a hasMany relationship' id: 1, relationships: { handles: { - data: [ - { type: 'handles', id: 1 }, - { type: 'handles', id: 2 } - ] - } - } + data: [{ type: 'handles', id: 1 }, { type: 'handles', id: 2 }], + }, + }, }, - included: [ - { type: 'handles', id: 1 }, - { type: 'handles', id: 2 } - ] + included: [{ type: 'handles', id: 1 }, { type: 'handles', id: 2 }], }); let user = store.peekRecord('user', 1); @@ -531,34 +570,34 @@ test('it should not include new records when serializing a hasMany relationship' attributes: { 'first-name': null, 'last-name': null, - title: null + title: null, }, relationships: { handles: { - data: [ - { type: 'handles', id: '1' }, - { type: 'handles', id: '2' } - ] - } - } - } + data: [{ type: 'handles', id: '1' }, { type: 'handles', id: '2' }], + }, + }, + }, }); }); }); test('it should not include any records when serializing a hasMany relationship if they are all new', function(assert) { - env.registry.register("serializer:user", DS.JSONAPISerializer.extend({ - attrs: { - handles: { serialize: true } - } - })); + env.registry.register( + 'serializer:user', + DS.JSONAPISerializer.extend({ + attrs: { + handles: { serialize: true }, + }, + }) + ); run(function() { serializer.pushPayload(store, { data: { type: 'users', - id: 1 - } + id: 1, + }, }); let user = store.peekRecord('user', 1); @@ -573,24 +612,27 @@ test('it should not include any records when serializing a hasMany relationship attributes: { 'first-name': null, 'last-name': null, - title: null + title: null, }, relationships: { handles: { - data: [] - } - } - } + data: [], + }, + }, + }, }); }); }); test('it should include an empty list when serializing an empty hasMany relationship', function(assert) { - env.registry.register("serializer:user", DS.JSONAPISerializer.extend({ - attrs: { - handles: { serialize: true } - } - })); + env.registry.register( + 'serializer:user', + DS.JSONAPISerializer.extend({ + attrs: { + handles: { serialize: true }, + }, + }) + ); run(function() { serializer.pushPayload(store, { @@ -599,17 +641,11 @@ test('it should include an empty list when serializing an empty hasMany relation id: 1, relationships: { handles: { - data: [ - { type: 'handles', id: 1 }, - { type: 'handles', id: 2 } - ] - } - } + data: [{ type: 'handles', id: 1 }, { type: 'handles', id: 2 }], + }, + }, }, - included: [ - { type: 'handles', id: 1 }, - { type: 'handles', id: 2 } - ] + included: [{ type: 'handles', id: 1 }, { type: 'handles', id: 2 }], }); let user = store.peekRecord('user', 1); @@ -627,14 +663,14 @@ test('it should include an empty list when serializing an empty hasMany relation attributes: { 'first-name': null, 'last-name': null, - title: null + title: null, }, relationships: { handles: { - data: [] - } - } - } + data: [], + }, + }, + }, }); }); }); @@ -645,34 +681,44 @@ testInDebug('JSON warns when combined with EmbeddedRecordsMixin', function(asser }, /The JSONAPISerializer does not work with the EmbeddedRecordsMixin/); }); -testInDebug('Asserts when normalized attribute key is not found in payload but original key is', function(assert) { - var jsonHash = { - data: { - type: 'users', - id: '1', - attributes: { - 'firstName': 'Yehuda' - } - } - }; - assert.expectAssertion(function() { - env.store.serializerFor("user").normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); - }, /Your payload for 'user' contains 'firstName', but your serializer is setup to look for 'first-name'/); -}); +testInDebug( + 'Asserts when normalized attribute key is not found in payload but original key is', + function(assert) { + var jsonHash = { + data: { + type: 'users', + id: '1', + attributes: { + firstName: 'Yehuda', + }, + }, + }; + assert.expectAssertion(function() { + env.store + .serializerFor('user') + .normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); + }, /Your payload for 'user' contains 'firstName', but your serializer is setup to look for 'first-name'/); + } +); -testInDebug('Asserts when normalized relationship key is not found in payload but original key is', function(assert) { - var jsonHash = { - data: { - type: 'users', - id: '1', - relationships: { - 'reportsTo': { - data: null - } - } - } - }; - assert.expectAssertion(function() { - env.store.serializerFor("user").normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); - }, /Your payload for 'user' contains 'reportsTo', but your serializer is setup to look for 'reports-to'/); -}); +testInDebug( + 'Asserts when normalized relationship key is not found in payload but original key is', + function(assert) { + var jsonHash = { + data: { + type: 'users', + id: '1', + relationships: { + reportsTo: { + data: null, + }, + }, + }, + }; + assert.expectAssertion(function() { + env.store + .serializerFor('user') + .normalizeResponse(env.store, User, jsonHash, '1', 'findRecord'); + }, /Your payload for 'user' contains 'reportsTo', but your serializer is setup to look for 'reports-to'/); + } +); diff --git a/tests/integration/serializers/json-serializer-test.js b/tests/integration/serializers/json-serializer-test.js index 0080703e330..c0fb9acc751 100644 --- a/tests/integration/serializers/json-serializer-test.js +++ b/tests/integration/serializers/json-serializer-test.js @@ -9,23 +9,23 @@ import DS from 'ember-data'; var Post, Comment, Favorite, env, serializer; -module("integration/serializer/json - JSONSerializer", { +module('integration/serializer/json - JSONSerializer', { beforeEach() { Post = DS.Model.extend({ title: DS.attr('string'), - comments: DS.hasMany('comment', { inverse: null, async: false }) + comments: DS.hasMany('comment', { inverse: null, async: false }), }); Comment = DS.Model.extend({ body: DS.attr('string'), - post: DS.belongsTo('post', { inverse: null, async: false }) + post: DS.belongsTo('post', { inverse: null, async: false }), }); Favorite = DS.Model.extend({ - post: DS.belongsTo('post', { inverse: null, async: true, polymorphic: true }) + post: DS.belongsTo('post', { inverse: null, async: true, polymorphic: true }), }); env = setupStore({ - post: Post, - comment: Comment, - favorite: Favorite + post: Post, + comment: Comment, + favorite: Favorite, }); env.store.modelFor('post'); env.store.modelFor('comment'); @@ -35,7 +35,7 @@ module("integration/serializer/json - JSONSerializer", { afterEach() { run(env.store, 'destroy'); - } + }, }); test("serialize doesn't include ID when includeId is false", function(assert) { @@ -43,22 +43,21 @@ test("serialize doesn't include ID when includeId is false", function(assert) { let json = serializer.serialize(post._createSnapshot(), { includeId: false }); assert.deepEqual(json, { - title: "Rails is omakase", - comments: [] + title: 'Rails is omakase', + comments: [], }); }); - test("serialize doesn't include relationship if not aware of one", function(assert) { let post = env.store.createRecord('post', { title: 'Rails is omakase' }); let json = serializer.serialize(post._createSnapshot()); assert.deepEqual(json, { - title: "Rails is omakase" + title: 'Rails is omakase', }); }); -test("serialize includes id when includeId is true", function(assert) { +test('serialize includes id when includeId is true', function(assert) { let post = env.store.createRecord('post', { title: 'Rails is omakase', comments: [] }); run(() => { @@ -70,101 +69,122 @@ test("serialize includes id when includeId is true", function(assert) { assert.deepEqual(json, { id: 'test', title: 'Rails is omakase', - comments: [] + comments: [], }); }); -test("serializeAttribute", function(assert) { - let post = env.store.createRecord('post', { title: "Rails is omakase" }); +test('serializeAttribute', function(assert) { + let post = env.store.createRecord('post', { title: 'Rails is omakase' }); let json = {}; - serializer.serializeAttribute(post._createSnapshot(), json, "title", { type: "string" }); + serializer.serializeAttribute(post._createSnapshot(), json, 'title', { type: 'string' }); assert.deepEqual(json, { - title: "Rails is omakase" + title: 'Rails is omakase', }); }); -test("serializeAttribute respects keyForAttribute", function(assert) { - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - keyForAttribute(key) { - return key.toUpperCase(); - } - })); +test('serializeAttribute respects keyForAttribute', function(assert) { + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + keyForAttribute(key) { + return key.toUpperCase(); + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase" }); + let post = env.store.createRecord('post', { title: 'Rails is omakase' }); let json = {}; - env.store.serializerFor("post").serializeAttribute(post._createSnapshot(), json, "title", { type: "string" }); + env.store + .serializerFor('post') + .serializeAttribute(post._createSnapshot(), json, 'title', { type: 'string' }); - assert.deepEqual(json, { TITLE: "Rails is omakase" }); + assert.deepEqual(json, { TITLE: 'Rails is omakase' }); }); -test("serializeBelongsTo", function(assert) { - let post = env.store.createRecord('post', { title: "Rails is omakase", id: "1" }); - let comment = env.store.createRecord('comment', { body: "Omakase is delicious", post: post }); +test('serializeBelongsTo', function(assert) { + let post = env.store.createRecord('post', { title: 'Rails is omakase', id: '1' }); + let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); let json = {}; - serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); + serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: 'post', options: {} }); - assert.deepEqual(json, { post: "1" }); + assert.deepEqual(json, { post: '1' }); }); -test("serializeBelongsTo with null", function(assert) { - let comment = env.store.createRecord('comment', { body: "Omakase is delicious", post: null }); +test('serializeBelongsTo with null', function(assert) { + let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: null }); let json = {}; - serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); + serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: 'post', options: {} }); - assert.deepEqual(json, { - post: null - }, "Can set a belongsTo to a null value"); + assert.deepEqual( + json, + { + post: null, + }, + 'Can set a belongsTo to a null value' + ); }); -test("async serializeBelongsTo with null", function(assert) { +test('async serializeBelongsTo with null', function(assert) { Comment.reopen({ - post: DS.belongsTo('post', { async: true }) + post: DS.belongsTo('post', { async: true }), }); - let comment = env.store.createRecord('comment', { body: "Omakase is delicious", post: null }); + let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: null }); let json = {}; - serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); + serializer.serializeBelongsTo(comment._createSnapshot(), json, { key: 'post', options: {} }); - assert.deepEqual(json, { - post: null - }, "Can set a belongsTo to a null value"); + assert.deepEqual( + json, + { + post: null, + }, + 'Can set a belongsTo to a null value' + ); }); -test("serializeBelongsTo respects keyForRelationship", function(assert) { - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - keyForRelationship(key, type) { - return key.toUpperCase(); - } - })); +test('serializeBelongsTo respects keyForRelationship', function(assert) { + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + keyForRelationship(key, type) { + return key.toUpperCase(); + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase", id: "1" }); - let comment = env.store.createRecord('comment', { body: "Omakase is delicious", post: post }); + let post = env.store.createRecord('post', { title: 'Rails is omakase', id: '1' }); + let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); let json = {}; - env.store.serializerFor("post").serializeBelongsTo(comment._createSnapshot(), json, { key: "post", options: {} }); + env.store + .serializerFor('post') + .serializeBelongsTo(comment._createSnapshot(), json, { key: 'post', options: {} }); assert.deepEqual(json, { - POST: "1" + POST: '1', }); }); -test("serializeHasMany respects keyForRelationship", function(assert) { - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - keyForRelationship(key, type) { - return key.toUpperCase(); - } - })); +test('serializeHasMany respects keyForRelationship', function(assert) { + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + keyForRelationship(key, type) { + return key.toUpperCase(); + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase", id: "1" }); + let post = env.store.createRecord('post', { title: 'Rails is omakase', id: '1' }); let comment = env.store.createRecord('comment', { - body: "Omakase is delicious", + body: 'Omakase is delicious', post: post, - id: "1" + id: '1', }); run(function() { @@ -173,245 +193,320 @@ test("serializeHasMany respects keyForRelationship", function(assert) { let json = {}; - env.store.serializerFor("post").serializeHasMany(post._createSnapshot(), json, { key: "comments", options: {} }); + env.store + .serializerFor('post') + .serializeHasMany(post._createSnapshot(), json, { key: 'comments', options: {} }); assert.deepEqual(json, { - COMMENTS: ["1"] + COMMENTS: ['1'], }); }); -test("serializeHasMany omits unknown relationships on pushed record", function(assert) { - let post = run(() => env.store.push({ - data: { - id: "1", - type: "post", - attributes: { - title: "Rails is omakase" - } - } - })); +test('serializeHasMany omits unknown relationships on pushed record', function(assert) { + let post = run(() => + env.store.push({ + data: { + id: '1', + type: 'post', + attributes: { + title: 'Rails is omakase', + }, + }, + }) + ); let json = {}; - env.store.serializerFor("post").serializeHasMany(post._createSnapshot(), json, { key: "comments", options: {} }); + env.store + .serializerFor('post') + .serializeHasMany(post._createSnapshot(), json, { key: 'comments', options: {} }); - assert.ok(!json.hasOwnProperty("comments"), "Does not add the relationship key to json"); + assert.ok(!json.hasOwnProperty('comments'), 'Does not add the relationship key to json'); }); -test("shouldSerializeHasMany", function(assert) { - let post = env.store.createRecord('post', { title: "Rails is omakase", id: "1" }); - env.store.createRecord('comment', { body: "Omakase is delicious", post: post, id: "1" }); +test('shouldSerializeHasMany', function(assert) { + let post = env.store.createRecord('post', { title: 'Rails is omakase', id: '1' }); + env.store.createRecord('comment', { body: 'Omakase is delicious', post: post, id: '1' }); var snapshot = post._createSnapshot(); var relationship = snapshot.record.relationshipFor('comments'); var key = relationship.key; - var shouldSerialize = env.store.serializerFor("post").shouldSerializeHasMany(snapshot, relationship, key); + var shouldSerialize = env.store + .serializerFor('post') + .shouldSerializeHasMany(snapshot, relationship, key); - assert.ok(shouldSerialize, 'shouldSerializeHasMany correctly identifies with hasMany relationship'); + assert.ok( + shouldSerialize, + 'shouldSerializeHasMany correctly identifies with hasMany relationship' + ); }); -test("serializeIntoHash", function(assert) { - let post = env.store.createRecord('post', { title: "Rails is omakase", comments: [] }); +test('serializeIntoHash', function(assert) { + let post = env.store.createRecord('post', { title: 'Rails is omakase', comments: [] }); let json = {}; serializer.serializeIntoHash(json, Post, post._createSnapshot()); assert.deepEqual(json, { - title: "Rails is omakase", - comments: [] + title: 'Rails is omakase', + comments: [], }); }); -test("serializePolymorphicType sync", function(assert) { +test('serializePolymorphicType sync', function(assert) { assert.expect(1); - env.registry.register('serializer:comment', DS.JSONSerializer.extend({ - serializePolymorphicType(record, json, relationship) { - let key = relationship.key; - let belongsTo = record.belongsTo(key); - json[relationship.key + "TYPE"] = belongsTo.modelName; - - assert.ok(true, 'serializePolymorphicType is called when serialize a polymorphic belongsTo'); - } - })); + env.registry.register( + 'serializer:comment', + DS.JSONSerializer.extend({ + serializePolymorphicType(record, json, relationship) { + let key = relationship.key; + let belongsTo = record.belongsTo(key); + json[relationship.key + 'TYPE'] = belongsTo.modelName; + + assert.ok( + true, + 'serializePolymorphicType is called when serialize a polymorphic belongsTo' + ); + }, + }) + ); let post = env.store.createRecord('post', { title: 'Rails is omakase', id: 1 }); let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); - env.store.serializerFor('comment').serializeBelongsTo(comment._createSnapshot(), {}, { key: 'post', options: { polymorphic: true } }); + env.store + .serializerFor('comment') + .serializeBelongsTo( + comment._createSnapshot(), + {}, + { key: 'post', options: { polymorphic: true } } + ); }); -test("serializePolymorphicType async", function(assert) { +test('serializePolymorphicType async', function(assert) { assert.expect(1); Comment.reopen({ - post: DS.belongsTo('post', { async: true }) + post: DS.belongsTo('post', { async: true }), }); - env.registry.register('serializer:comment', DS.JSONSerializer.extend({ - serializePolymorphicType(record, json, relationship) { - assert.ok(true, 'serializePolymorphicType is called when serialize a polymorphic belongsTo'); - } - })); + env.registry.register( + 'serializer:comment', + DS.JSONSerializer.extend({ + serializePolymorphicType(record, json, relationship) { + assert.ok( + true, + 'serializePolymorphicType is called when serialize a polymorphic belongsTo' + ); + }, + }) + ); let post = env.store.createRecord('post', { title: 'Rails is omakase', id: 1 }); let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); - env.store.serializerFor('comment').serializeBelongsTo(comment._createSnapshot(), {}, { key: 'post', options: { async: true, polymorphic: true } }); + env.store + .serializerFor('comment') + .serializeBelongsTo( + comment._createSnapshot(), + {}, + { key: 'post', options: { async: true, polymorphic: true } } + ); }); -test("normalizeResponse normalizes each record in the array", function(assert) { +test('normalizeResponse normalizes each record in the array', function(assert) { var postNormalizeCount = 0; - var posts = [ - { id: "1", title: "Rails is omakase" }, - { id: "2", title: "Another Post" } - ]; - - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - normalize() { - postNormalizeCount++; - return this._super.apply(this, arguments); - } - })); + var posts = [{ id: '1', title: 'Rails is omakase' }, { id: '2', title: 'Another Post' }]; + + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + normalize() { + postNormalizeCount++; + return this._super.apply(this, arguments); + }, + }) + ); run(function() { - env.store.serializerFor("post").normalizeResponse(env.store, Post, posts, null, 'findAll'); + env.store.serializerFor('post').normalizeResponse(env.store, Post, posts, null, 'findAll'); }); - assert.equal(postNormalizeCount, 2, "two posts are normalized"); + assert.equal(postNormalizeCount, 2, 'two posts are normalized'); }); test('Serializer should respect the attrs hash when extracting records', function(assert) { - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - attrs: { - title: "title_payload_key", - comments: { key: 'my_comments' } - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + title: 'title_payload_key', + comments: { key: 'my_comments' }, + }, + }) + ); var jsonHash = { - id: "1", - title_payload_key: "Rails is omakase", - my_comments: [1, 2] + id: '1', + title_payload_key: 'Rails is omakase', + my_comments: [1, 2], }; - var post = env.store.serializerFor("post").normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); + var post = env.store + .serializerFor('post') + .normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); - assert.equal(post.data.attributes.title, "Rails is omakase"); - assert.deepEqual(post.data.relationships.comments.data, [{ id: "1", type: "comment" }, { id: "2", type: "comment" }]); + assert.equal(post.data.attributes.title, 'Rails is omakase'); + assert.deepEqual(post.data.relationships.comments.data, [ + { id: '1', type: 'comment' }, + { id: '2', type: 'comment' }, + ]); }); test('Serializer should map `attrs` attributes directly when keyForAttribute also has a transform', function(assert) { Post = DS.Model.extend({ - authorName: DS.attr('string') + authorName: DS.attr('string'), }); env = setupStore({ - post: Post + post: Post, }); - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - keyForAttribute: underscore, - attrs: { - authorName: 'author_name_key' - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + keyForAttribute: underscore, + attrs: { + authorName: 'author_name_key', + }, + }) + ); var jsonHash = { - id: "1", - author_name_key: "DHH" + id: '1', + author_name_key: 'DHH', }; - var post = env.store.serializerFor("post").normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); + var post = env.store + .serializerFor('post') + .normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); - assert.equal(post.data.attributes.authorName, "DHH"); + assert.equal(post.data.attributes.authorName, 'DHH'); }); test('Serializer should respect the attrs hash when serializing records', function(assert) { Post.reopen({ - parentPost: DS.belongsTo('post', { inverse: null, async: true }) + parentPost: DS.belongsTo('post', { inverse: null, async: true }), }); - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - attrs: { - title: "title_payload_key", - parentPost: { key: "my_parent" } - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + title: 'title_payload_key', + parentPost: { key: 'my_parent' }, + }, + }) + ); + + let parentPost = run(() => + env.store.push({ + data: { + type: 'post', + id: '2', + attributes: { + title: 'Rails is omakase', + }, + }, + }) + ); + let post = env.store.createRecord('post', { title: 'Rails is omakase', parentPost: parentPost }); + let payload = env.store.serializerFor('post').serialize(post._createSnapshot()); - let parentPost = run(() => env.store.push({ - data: { - type: 'post', - id: '2', - attributes: { - title: "Rails is omakase" - } - } - })); - let post = env.store.createRecord('post', { title: "Rails is omakase", parentPost: parentPost }); - let payload = env.store.serializerFor("post").serialize(post._createSnapshot()); - - assert.equal(payload.title_payload_key, "Rails is omakase"); + assert.equal(payload.title_payload_key, 'Rails is omakase'); assert.equal(payload.my_parent, '2'); }); test('Serializer respects if embedded model has an attribute named "type" - #3726', function(assert) { - env.registry.register("serializer:child", DS.JSONSerializer); - env.registry.register("serializer:parent", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - child: { embedded: 'always' } - } - })); - env.registry.register("model:parent", DS.Model.extend({ - child: DS.belongsTo('child') - })); - env.registry.register("model:child", DS.Model.extend({ - type: DS.attr() - })); + env.registry.register('serializer:child', DS.JSONSerializer); + env.registry.register( + 'serializer:parent', + DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + child: { embedded: 'always' }, + }, + }) + ); + env.registry.register( + 'model:parent', + DS.Model.extend({ + child: DS.belongsTo('child'), + }) + ); + env.registry.register( + 'model:child', + DS.Model.extend({ + type: DS.attr(), + }) + ); var jsonHash = { id: 1, child: { id: 1, - type: 'first_type' - } + type: 'first_type', + }, }; var Parent = env.store.modelFor('parent'); - var payload = env.store.serializerFor('parent').normalizeResponse(env.store, Parent, jsonHash, '1', 'findRecord'); + var payload = env.store + .serializerFor('parent') + .normalizeResponse(env.store, Parent, jsonHash, '1', 'findRecord'); assert.deepEqual(payload.included, [ { id: '1', type: 'child', attributes: { - type: 'first_type' + type: 'first_type', }, - relationships: {} - } + relationships: {}, + }, ]); }); test('Serializer respects if embedded model has a relationship named "type" - #3726', function(assert) { - env.registry.register("serializer:child", DS.JSONSerializer); - env.registry.register("serializer:parent", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - child: { embedded: 'always' } - } - })); - env.registry.register("model:parent", DS.Model.extend({ - child: DS.belongsTo('child') - })); - env.registry.register("model:child", DS.Model.extend({ - type: DS.belongsTo('le-type') - })); - env.registry.register("model:le-type", DS.Model.extend()); + env.registry.register('serializer:child', DS.JSONSerializer); + env.registry.register( + 'serializer:parent', + DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + child: { embedded: 'always' }, + }, + }) + ); + env.registry.register( + 'model:parent', + DS.Model.extend({ + child: DS.belongsTo('child'), + }) + ); + env.registry.register( + 'model:child', + DS.Model.extend({ + type: DS.belongsTo('le-type'), + }) + ); + env.registry.register('model:le-type', DS.Model.extend()); var jsonHash = { id: 1, child: { id: 1, - type: "my_type_id" - } + type: 'my_type_id', + }, }; var Parent = env.store.modelFor('parent'); - var payload = env.store.serializerFor('parent').normalizeResponse(env.store, Parent, jsonHash, '1', 'findRecord'); + var payload = env.store + .serializerFor('parent') + .normalizeResponse(env.store, Parent, jsonHash, '1', 'findRecord'); assert.deepEqual(payload.included, [ { id: '1', @@ -421,230 +516,280 @@ test('Serializer respects if embedded model has a relationship named "type" - #3 type: { data: { id: 'my_type_id', - type: 'le-type' - } - } - } - } + type: 'le-type', + }, + }, + }, + }, ]); }); test('Serializer respects `serialize: false` on the attrs hash', function(assert) { assert.expect(2); - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - attrs: { - title: { serialize: false } - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + title: { serialize: false }, + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase" }); - let payload = env.store.serializerFor("post").serialize(post._createSnapshot()); + let post = env.store.createRecord('post', { title: 'Rails is omakase' }); + let payload = env.store.serializerFor('post').serialize(post._createSnapshot()); - assert.ok(!payload.hasOwnProperty('title'), "Does not add the key to instance"); - assert.ok(!payload.hasOwnProperty('[object Object]'), "Does not add some random key like [object Object]"); + assert.ok(!payload.hasOwnProperty('title'), 'Does not add the key to instance'); + assert.ok( + !payload.hasOwnProperty('[object Object]'), + 'Does not add some random key like [object Object]' + ); }); test('Serializer respects `serialize: false` on the attrs hash for a `hasMany` property', function(assert) { assert.expect(1); - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - attrs: { - comments: { serialize: false } - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + comments: { serialize: false }, + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase" }); - env.store.createRecord('comment', { body: "Omakase is delicious", post: post }); + let post = env.store.createRecord('post', { title: 'Rails is omakase' }); + env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); - var serializer = env.store.serializerFor("post"); + var serializer = env.store.serializerFor('post'); var serializedProperty = serializer.keyForRelationship('comments', 'hasMany'); var payload = serializer.serialize(post._createSnapshot()); - assert.ok(!payload.hasOwnProperty(serializedProperty), "Does not add the key to instance"); + assert.ok(!payload.hasOwnProperty(serializedProperty), 'Does not add the key to instance'); }); test('Serializer respects `serialize: false` on the attrs hash for a `belongsTo` property', function(assert) { assert.expect(1); - env.registry.register("serializer:comment", DS.JSONSerializer.extend({ - attrs: { - post: { serialize: false } - } - })); + env.registry.register( + 'serializer:comment', + DS.JSONSerializer.extend({ + attrs: { + post: { serialize: false }, + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase" }); - let comment = env.store.createRecord('comment', { body: "Omakase is delicious", post: post }); + let post = env.store.createRecord('post', { title: 'Rails is omakase' }); + let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); - var serializer = env.store.serializerFor("comment"); + var serializer = env.store.serializerFor('comment'); var serializedProperty = serializer.keyForRelationship('post', 'belongsTo'); var payload = serializer.serialize(comment._createSnapshot()); - assert.ok(!payload.hasOwnProperty(serializedProperty), "Does not add the key to instance"); + assert.ok(!payload.hasOwnProperty(serializedProperty), 'Does not add the key to instance'); }); test('Serializer respects `serialize: false` on the attrs hash for a `hasMany` property', function(assert) { assert.expect(1); - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - attrs: { - comments: { serialize: false } - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + comments: { serialize: false }, + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase" }); - env.store.createRecord('comment', { body: "Omakase is delicious", post: post }); + let post = env.store.createRecord('post', { title: 'Rails is omakase' }); + env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); - var serializer = env.store.serializerFor("post"); + var serializer = env.store.serializerFor('post'); var serializedProperty = serializer.keyForRelationship('comments', 'hasMany'); var payload = serializer.serialize(post._createSnapshot()); - assert.ok(!payload.hasOwnProperty(serializedProperty), "Does not add the key to instance"); + assert.ok(!payload.hasOwnProperty(serializedProperty), 'Does not add the key to instance'); }); test('Serializer respects `serialize: false` on the attrs hash for a `belongsTo` property', function(assert) { assert.expect(1); - env.registry.register("serializer:comment", DS.JSONSerializer.extend({ - attrs: { - post: { serialize: false } - } - })); + env.registry.register( + 'serializer:comment', + DS.JSONSerializer.extend({ + attrs: { + post: { serialize: false }, + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase" }); - let comment = env.store.createRecord('comment', { body: "Omakase is delicious", post: post }); + let post = env.store.createRecord('post', { title: 'Rails is omakase' }); + let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); - var serializer = env.store.serializerFor("comment"); + var serializer = env.store.serializerFor('comment'); var serializedProperty = serializer.keyForRelationship('post', 'belongsTo'); var payload = serializer.serialize(comment._createSnapshot()); - assert.ok(!payload.hasOwnProperty(serializedProperty), "Does not add the key to instance"); + assert.ok(!payload.hasOwnProperty(serializedProperty), 'Does not add the key to instance'); }); test('Serializer respects `serialize: true` on the attrs hash for a `hasMany` property', function(assert) { assert.expect(1); - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - attrs: { - comments: { serialize: true } - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + comments: { serialize: true }, + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase" }); - let comment = env.store.createRecord('comment', { body: "Omakase is delicious", post: post }); + let post = env.store.createRecord('post', { title: 'Rails is omakase' }); + let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); run(function() { post.get('comments').pushObject(comment); }); - var serializer = env.store.serializerFor("post"); + var serializer = env.store.serializerFor('post'); var serializedProperty = serializer.keyForRelationship('comments', 'hasMany'); var payload = serializer.serialize(post._createSnapshot()); - assert.ok(payload.hasOwnProperty(serializedProperty), "Add the key to instance"); + assert.ok(payload.hasOwnProperty(serializedProperty), 'Add the key to instance'); }); test('Serializer respects `serialize: true` on the attrs hash for a `belongsTo` property', function(assert) { assert.expect(1); - env.registry.register("serializer:comment", DS.JSONSerializer.extend({ - attrs: { - post: { serialize: true } - } - })); + env.registry.register( + 'serializer:comment', + DS.JSONSerializer.extend({ + attrs: { + post: { serialize: true }, + }, + }) + ); - let post = env.store.createRecord('post', { title: "Rails is omakase" }); - let comment = env.store.createRecord('comment', { body: "Omakase is delicious", post: post }); + let post = env.store.createRecord('post', { title: 'Rails is omakase' }); + let comment = env.store.createRecord('comment', { body: 'Omakase is delicious', post: post }); - var serializer = env.store.serializerFor("comment"); + var serializer = env.store.serializerFor('comment'); var serializedProperty = serializer.keyForRelationship('post', 'belongsTo'); var payload = serializer.serialize(comment._createSnapshot()); - assert.ok(payload.hasOwnProperty(serializedProperty), "Add the key to instance"); + assert.ok(payload.hasOwnProperty(serializedProperty), 'Add the key to instance'); }); -test("Serializer should merge attrs from superclasses", function(assert) { +test('Serializer should merge attrs from superclasses', function(assert) { assert.expect(4); Post.reopen({ description: DS.attr('string'), - anotherString: DS.attr('string') + anotherString: DS.attr('string'), }); var BaseSerializer = DS.JSONSerializer.extend({ attrs: { - title: "title_payload_key", - anotherString: "base_another_string_key" - } + title: 'title_payload_key', + anotherString: 'base_another_string_key', + }, }); - env.registry.register("serializer:post", BaseSerializer.extend({ - attrs: { - description: "description_payload_key", - anotherString: "overwritten_another_string_key" - } - })); + env.registry.register( + 'serializer:post', + BaseSerializer.extend({ + attrs: { + description: 'description_payload_key', + anotherString: 'overwritten_another_string_key', + }, + }) + ); - let post = env.store.createRecord("post", { title: "Rails is omakase", description: "Omakase is delicious", anotherString: "yet another string" }); - let payload = env.store.serializerFor("post").serialize(post._createSnapshot()); + let post = env.store.createRecord('post', { + title: 'Rails is omakase', + description: 'Omakase is delicious', + anotherString: 'yet another string', + }); + let payload = env.store.serializerFor('post').serialize(post._createSnapshot()); - assert.equal(payload.title_payload_key, "Rails is omakase"); - assert.equal(payload.description_payload_key, "Omakase is delicious"); - assert.equal(payload.overwritten_another_string_key, "yet another string"); - assert.ok(!payload.base_another_string_key, "overwritten key is not added"); + assert.equal(payload.title_payload_key, 'Rails is omakase'); + assert.equal(payload.description_payload_key, 'Omakase is delicious'); + assert.equal(payload.overwritten_another_string_key, 'yet another string'); + assert.ok(!payload.base_another_string_key, 'overwritten key is not added'); }); -test("Serializer should respect the primaryKey attribute when extracting records", function(assert) { - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - primaryKey: '_ID_' - })); +test('Serializer should respect the primaryKey attribute when extracting records', function(assert) { + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + primaryKey: '_ID_', + }) + ); - let jsonHash = { "_ID_": 1, title: "Rails is omakase" }; - let post = env.store.serializerFor("post").normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); + let jsonHash = { _ID_: 1, title: 'Rails is omakase' }; + let post = env.store + .serializerFor('post') + .normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); - assert.equal(post.data.id, "1"); - assert.equal(post.data.attributes.title, "Rails is omakase"); + assert.equal(post.data.id, '1'); + assert.equal(post.data.attributes.title, 'Rails is omakase'); }); -test("Serializer should respect the primaryKey attribute when serializing records", function(assert) { - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - primaryKey: '_ID_' - })); +test('Serializer should respect the primaryKey attribute when serializing records', function(assert) { + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + primaryKey: '_ID_', + }) + ); - let post = env.store.createRecord('post', { id: "1", title: "Rails is omakase" }); - let payload = env.store.serializerFor("post").serialize(post._createSnapshot(), { includeId: true }); + let post = env.store.createRecord('post', { id: '1', title: 'Rails is omakase' }); + let payload = env.store + .serializerFor('post') + .serialize(post._createSnapshot(), { includeId: true }); - assert.equal(payload._ID_, "1"); + assert.equal(payload._ID_, '1'); }); -test("Serializer should respect keyForAttribute when extracting records", function(assert) { - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - keyForAttribute(key) { - return key.toUpperCase(); - } - })); +test('Serializer should respect keyForAttribute when extracting records', function(assert) { + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + keyForAttribute(key) { + return key.toUpperCase(); + }, + }) + ); let jsonHash = { id: 1, TITLE: 'Rails is omakase' }; - let post = env.store.serializerFor("post").normalize(Post, jsonHash); + let post = env.store.serializerFor('post').normalize(Post, jsonHash); - assert.equal(post.data.id, "1"); - assert.equal(post.data.attributes.title, "Rails is omakase"); + assert.equal(post.data.id, '1'); + assert.equal(post.data.attributes.title, 'Rails is omakase'); }); -test("Serializer should respect keyForRelationship when extracting records", function(assert) { - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - keyForRelationship(key, type) { - return key.toUpperCase(); - } - })); +test('Serializer should respect keyForRelationship when extracting records', function(assert) { + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + keyForRelationship(key, type) { + return key.toUpperCase(); + }, + }) + ); let jsonHash = { id: 1, title: 'Rails is omakase', COMMENTS: ['1'] }; - let post = env.store.serializerFor("post").normalize(Post, jsonHash); + let post = env.store.serializerFor('post').normalize(Post, jsonHash); - assert.deepEqual(post.data.relationships.comments.data, [{ id: "1", type: "comment" }]); + assert.deepEqual(post.data.relationships.comments.data, [{ id: '1', type: 'comment' }]); }); -test("Calling normalize should normalize the payload (only the passed keys)", function(assert) { +test('Calling normalize should normalize the payload (only the passed keys)', function(assert) { assert.expect(1); var Person = DS.Model.extend({ - posts: DS.hasMany('post', { async: false }) + posts: DS.hasMany('post', { async: false }), }); - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - attrs: { - notInHash: 'aCustomAttrNotInHash', - inHash: 'aCustomAttrInHash' - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + notInHash: 'aCustomAttrNotInHash', + inHash: 'aCustomAttrInHash', + }, + }) + ); env.registry.register('model:person', Person); @@ -652,30 +797,30 @@ test("Calling normalize should normalize the payload (only the passed keys)", fu content: DS.attr('string'), author: DS.belongsTo('person', { async: false }), notInHash: DS.attr('string'), - inHash: DS.attr('string') + inHash: DS.attr('string'), }); - var normalizedPayload = env.store.serializerFor("post").normalize(Post, { + var normalizedPayload = env.store.serializerFor('post').normalize(Post, { id: '1', title: 'Ember rocks', author: 1, - aCustomAttrInHash: 'blah' + aCustomAttrInHash: 'blah', }); assert.deepEqual(normalizedPayload, { - "data": { - "id": "1", - "type": "post", - "attributes": { - "inHash": "blah", - "title": "Ember rocks" - }, - "relationships": { - "author": { - "data": { "id": "1", "type": "person" } - } - } - } + data: { + id: '1', + type: 'post', + attributes: { + inHash: 'blah', + title: 'Ember rocks', + }, + relationships: { + author: { + data: { id: '1', type: 'person' }, + }, + }, + }, }); }); @@ -683,47 +828,56 @@ test('serializeBelongsTo with async polymorphic', function(assert) { var json = {}; var expected = { post: '1', postTYPE: 'post' }; - env.registry.register('serializer:favorite', DS.JSONSerializer.extend({ - serializePolymorphicType(snapshot, json, relationship) { - var key = relationship.key; - json[key + 'TYPE'] = snapshot.belongsTo(key).modelName; - } - })); + env.registry.register( + 'serializer:favorite', + DS.JSONSerializer.extend({ + serializePolymorphicType(snapshot, json, relationship) { + var key = relationship.key; + json[key + 'TYPE'] = snapshot.belongsTo(key).modelName; + }, + }) + ); let post = env.store.createRecord('post', { title: 'Kitties are omakase', id: '1' }); let favorite = env.store.createRecord('favorite', { post: post, id: '3' }); - env.store.serializerFor('favorite').serializeBelongsTo(favorite._createSnapshot(), json, { key: 'post', options: { polymorphic: true, async: true } }); + env.store.serializerFor('favorite').serializeBelongsTo(favorite._createSnapshot(), json, { + key: 'post', + options: { polymorphic: true, async: true }, + }); assert.deepEqual(json, expected, 'returned JSON is correct'); }); test('extractErrors respects custom key mappings', function(assert) { - env.registry.register('serializer:post', DS.JSONSerializer.extend({ - attrs: { - title: 'le_title', - comments: { key: 'my_comments' } - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + title: 'le_title', + comments: { key: 'my_comments' }, + }, + }) + ); var payload = { errors: [ { source: { pointer: 'data/attributes/le_title' }, - detail: "title errors" + detail: 'title errors', }, { source: { pointer: 'data/attributes/my_comments' }, - detail: "comments errors" - } - ] + detail: 'comments errors', + }, + ], }; var errors = env.store.serializerFor('post').extractErrors(env.store, Post, payload); assert.deepEqual(errors, { - title: ["title errors"], - comments: ["comments errors"] + title: ['title errors'], + comments: ['comments errors'], }); }); @@ -731,172 +885,194 @@ test('extractErrors expects error information located on the errors property of env.registry.register('serializer:post', DS.JSONSerializer.extend()); var payload = { - attributeWhichWillBeRemovedinExtractErrors: ["true"], + attributeWhichWillBeRemovedinExtractErrors: ['true'], errors: [ { source: { pointer: 'data/attributes/title' }, - detail: "title errors" - } - ] + detail: 'title errors', + }, + ], }; var errors = env.store.serializerFor('post').extractErrors(env.store, Post, payload); - assert.deepEqual(errors, { title: ["title errors"] }); + assert.deepEqual(errors, { title: ['title errors'] }); }); test('extractErrors leaves payload untouched if it has no errors property', function(assert) { env.registry.register('serializer:post', DS.JSONSerializer.extend()); var payload = { - untouchedSinceNoErrorsSiblingPresent: ["true"] + untouchedSinceNoErrorsSiblingPresent: ['true'], }; var errors = env.store.serializerFor('post').extractErrors(env.store, Post, payload); - assert.deepEqual(errors, { untouchedSinceNoErrorsSiblingPresent: ["true"] }); + assert.deepEqual(errors, { untouchedSinceNoErrorsSiblingPresent: ['true'] }); }); test('normalizeResponse should extract meta using extractMeta', function(assert) { - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - extractMeta(store, modelClass, payload) { - let meta = this._super(...arguments); - meta.authors.push('Tomhuda'); - return meta; - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + extractMeta(store, modelClass, payload) { + let meta = this._super(...arguments); + meta.authors.push('Tomhuda'); + return meta; + }, + }) + ); var jsonHash = { - id: "1", - title_payload_key: "Rails is omakase", + id: '1', + title_payload_key: 'Rails is omakase', my_comments: [1, 2], meta: { - authors: ['Tomster'] - } + authors: ['Tomster'], + }, }; - var post = env.store.serializerFor("post").normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); + var post = env.store + .serializerFor('post') + .normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); assert.deepEqual(post.meta.authors, ['Tomster', 'Tomhuda']); }); test('normalizeResponse returns empty `included` payload by default', function(assert) { - env.registry.register("serializer:post", DS.JSONSerializer.extend()); + env.registry.register('serializer:post', DS.JSONSerializer.extend()); var jsonHash = { - id: "1", - title: "Rails is omakase" + id: '1', + title: 'Rails is omakase', }; - var post = env.store.serializerFor("post").normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); + var post = env.store + .serializerFor('post') + .normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); assert.deepEqual(post.included, []); }); test('normalizeResponse returns empty `included` payload when relationship is undefined', function(assert) { - env.registry.register("serializer:post", DS.JSONSerializer.extend()); + env.registry.register('serializer:post', DS.JSONSerializer.extend()); var jsonHash = { - id: "1", - title: "Rails is omakase", - comments: null + id: '1', + title: 'Rails is omakase', + comments: null, }; - var post = env.store.serializerFor("post").normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); + var post = env.store + .serializerFor('post') + .normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); assert.deepEqual(post.included, []); }); test('normalizeResponse respects `included` items (single response)', function(assert) { - env.registry.register("serializer:comment", DS.JSONSerializer); - env.registry.register("serializer:post", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - comments: { embedded: 'always' } - } - })); + env.registry.register('serializer:comment', DS.JSONSerializer); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + comments: { embedded: 'always' }, + }, + }) + ); var jsonHash = { - id: "1", - title: "Rails is omakase", - comments: [ - { id: "1", body: "comment 1" }, - { id: "2", body: "comment 2" } - ] + id: '1', + title: 'Rails is omakase', + comments: [{ id: '1', body: 'comment 1' }, { id: '2', body: 'comment 2' }], }; - var post = env.store.serializerFor("post").normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); + var post = env.store + .serializerFor('post') + .normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); assert.deepEqual(post.included, [ - { id: "1", type: "comment", attributes: { body: "comment 1" }, relationships: {} }, - { id: "2", type: "comment", attributes: { body: "comment 2" }, relationships: {} } + { id: '1', type: 'comment', attributes: { body: 'comment 1' }, relationships: {} }, + { id: '2', type: 'comment', attributes: { body: 'comment 2' }, relationships: {} }, ]); }); test('normalizeResponse respects `included` items (array response)', function(assert) { - env.registry.register("serializer:comment", DS.JSONSerializer); - env.registry.register("serializer:post", DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { - attrs: { - comments: { embedded: 'always' } - } - })); - - var payload = [{ - id: "1", - title: "Rails is omakase", - comments: [ - { id: "1", body: "comment 1" } - ] - }, { - id: "2", - title: "Post 2", - comments: [ - { id: "2", body: "comment 2" }, - { id: "3", body: "comment 3" } - ] - }]; - - var post = env.store.serializerFor("post").normalizeResponse(env.store, Post, payload, '1', 'findAll'); + env.registry.register('serializer:comment', DS.JSONSerializer); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { + attrs: { + comments: { embedded: 'always' }, + }, + }) + ); + + var payload = [ + { + id: '1', + title: 'Rails is omakase', + comments: [{ id: '1', body: 'comment 1' }], + }, + { + id: '2', + title: 'Post 2', + comments: [{ id: '2', body: 'comment 2' }, { id: '3', body: 'comment 3' }], + }, + ]; + + var post = env.store + .serializerFor('post') + .normalizeResponse(env.store, Post, payload, '1', 'findAll'); assert.deepEqual(post.included, [ - { id: "1", type: "comment", attributes: { body: "comment 1" }, relationships: {} }, - { id: "2", type: "comment", attributes: { body: "comment 2" }, relationships: {} }, - { id: "3", type: "comment", attributes: { body: "comment 3" }, relationships: {} } + { id: '1', type: 'comment', attributes: { body: 'comment 1' }, relationships: {} }, + { id: '2', type: 'comment', attributes: { body: 'comment 2' }, relationships: {} }, + { id: '3', type: 'comment', attributes: { body: 'comment 3' }, relationships: {} }, ]); }); testInDebug('normalizeResponse ignores unmapped attributes', function(assert) { - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - attrs: { - title: { serialize: false }, - notInMapping: { serialize: false } - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + title: { serialize: false }, + notInMapping: { serialize: false }, + }, + }) + ); var jsonHash = { - id: "1", + id: '1', notInMapping: 'I should be ignored', - title: "Rails is omakase" + title: 'Rails is omakase', }; assert.expectWarning(function() { - var post = env.store.serializerFor("post").normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); - assert.equal(post.data.attributes.title, "Rails is omakase"); + var post = env.store + .serializerFor('post') + .normalizeResponse(env.store, Post, jsonHash, '1', 'findRecord'); + assert.equal(post.data.attributes.title, 'Rails is omakase'); }, /There is no attribute or relationship with the name/); }); test('options are passed to transform for serialization', function(assert) { assert.expect(1); - env.registry.register('transform:custom', DS.Transform.extend({ - serialize: function(deserialized, options) { - assert.deepEqual(options, { custom: 'config' }); - } - })); + env.registry.register( + 'transform:custom', + DS.Transform.extend({ + serialize: function(deserialized, options) { + assert.deepEqual(options, { custom: 'config' }); + }, + }) + ); Post.reopen({ custom: DS.attr('custom', { - custom: 'config' - }) + custom: 'config', + }), }); let post = env.store.createRecord('post', { custom: 'value' }); @@ -907,41 +1083,48 @@ test('options are passed to transform for serialization', function(assert) { test('options are passed to transform for normalization', function(assert) { assert.expect(1); - env.registry.register('transform:custom', DS.Transform.extend({ - deserialize: function(serialized, options) { - assert.deepEqual(options, { custom: 'config' }); - } - })); + env.registry.register( + 'transform:custom', + DS.Transform.extend({ + deserialize: function(serialized, options) { + assert.deepEqual(options, { custom: 'config' }); + }, + }) + ); Post.reopen({ custom: DS.attr('custom', { - custom: 'config' - }) + custom: 'config', + }), }); serializer.normalize(Post, { - custom: 'value' + custom: 'value', }); }); test('Serializer should respect the attrs hash in links', function(assert) { - env.registry.register("serializer:post", DS.JSONSerializer.extend({ - attrs: { - title: "title_payload_key", - comments: { key: 'my_comments' } - } - })); + env.registry.register( + 'serializer:post', + DS.JSONSerializer.extend({ + attrs: { + title: 'title_payload_key', + comments: { key: 'my_comments' }, + }, + }) + ); var jsonHash = { - title_payload_key: "Rails is omakase", + title_payload_key: 'Rails is omakase', links: { - my_comments: 'posts/1/comments' - } + my_comments: 'posts/1/comments', + }, }; - var post = env.container.lookup("serializer:post").normalizeSingleResponse(env.store, Post, jsonHash); + var post = env.container + .lookup('serializer:post') + .normalizeSingleResponse(env.store, Post, jsonHash); - assert.equal(post.data.attributes.title, "Rails is omakase"); + assert.equal(post.data.attributes.title, 'Rails is omakase'); assert.equal(post.data.relationships.comments.links.related, 'posts/1/comments'); }); - diff --git a/tests/integration/serializers/rest-serializer-test.js b/tests/integration/serializers/rest-serializer-test.js index 60445918b58..25739f5e10d 100644 --- a/tests/integration/serializers/rest-serializer-test.js +++ b/tests/integration/serializers/rest-serializer-test.js @@ -6,54 +6,62 @@ import testInDebug from 'dummy/tests/helpers/test-in-debug'; import { module, test } from 'qunit'; import DS from 'ember-data'; -let HomePlanet, SuperVillain, EvilMinion, YellowMinion, DoomsdayDevice, Comment, Basket, Container, env; - -module("integration/serializer/rest - RESTSerializer", { +let HomePlanet, + SuperVillain, + EvilMinion, + YellowMinion, + DoomsdayDevice, + Comment, + Basket, + Container, + env; + +module('integration/serializer/rest - RESTSerializer', { beforeEach() { HomePlanet = DS.Model.extend({ - name: DS.attr('string'), - superVillains: DS.hasMany('super-villain', { async: false }) + name: DS.attr('string'), + superVillains: DS.hasMany('super-villain', { async: false }), }); SuperVillain = DS.Model.extend({ - firstName: DS.attr('string'), - lastName: DS.attr('string'), - homePlanet: DS.belongsTo('home-planet', { async: false }), - evilMinions: DS.hasMany('evil-minion', { async: false }) + firstName: DS.attr('string'), + lastName: DS.attr('string'), + homePlanet: DS.belongsTo('home-planet', { async: false }), + evilMinions: DS.hasMany('evil-minion', { async: false }), }); EvilMinion = DS.Model.extend({ superVillain: DS.belongsTo('super-villain', { async: false }), - name: DS.attr('string'), - doomsdayDevice: DS.belongsTo('doomsday-device', { async: false }) + name: DS.attr('string'), + doomsdayDevice: DS.belongsTo('doomsday-device', { async: false }), }); YellowMinion = EvilMinion.extend({ - eyes: DS.attr('number') + eyes: DS.attr('number'), }); DoomsdayDevice = DS.Model.extend({ - name: DS.attr('string'), - evilMinion: DS.belongsTo('evil-minion', { polymorphic: true, async: true }) + name: DS.attr('string'), + evilMinion: DS.belongsTo('evil-minion', { polymorphic: true, async: true }), }); Comment = DS.Model.extend({ body: DS.attr('string'), root: DS.attr('boolean'), - children: DS.hasMany('comment', { inverse: null, async: false }) + children: DS.hasMany('comment', { inverse: null, async: false }), }); Basket = DS.Model.extend({ type: DS.attr('string'), - size: DS.attr('number') + size: DS.attr('number'), }); Container = DS.Model.extend({ type: DS.belongsTo('basket', { async: true }), - volume: DS.attr('string') + volume: DS.attr('string'), }); env = setupStore({ - superVillain: SuperVillain, - homePlanet: HomePlanet, - evilMinion: EvilMinion, - yellowMinion: YellowMinion, + superVillain: SuperVillain, + homePlanet: HomePlanet, + evilMinion: EvilMinion, + yellowMinion: YellowMinion, doomsdayDevice: DoomsdayDevice, - comment: Comment, - basket: Basket, - container: Container + comment: Comment, + basket: Basket, + container: Container, }); env.store.modelFor('super-villain'); env.store.modelFor('home-planet'); @@ -67,10 +75,10 @@ module("integration/serializer/rest - RESTSerializer", { afterEach() { run(env.store, 'destroy'); - } + }, }); -test("modelNameFromPayloadKey returns always same modelName even for uncountable multi words keys", function(assert) { +test('modelNameFromPayloadKey returns always same modelName even for uncountable multi words keys', function(assert) { assert.expect(2); Inflector.inflector.uncountable('words'); var expectedModelName = 'multi-words'; @@ -79,25 +87,30 @@ test("modelNameFromPayloadKey returns always same modelName even for uncountable }); test('normalizeResponse should extract meta using extractMeta', function(assert) { - env.registry.register("serializer:home-planet", DS.RESTSerializer.extend({ - extractMeta(store, modelClass, payload) { - let meta = this._super(...arguments); - meta.authors.push('Tomhuda'); - return meta; - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend({ + extractMeta(store, modelClass, payload) { + let meta = this._super(...arguments); + meta.authors.push('Tomhuda'); + return meta; + }, + }) + ); var jsonHash = { meta: { authors: ['Tomster'] }, - home_planets: [{ id: "1", name: "Umber", superVillains: [1] }] + home_planets: [{ id: '1', name: 'Umber', superVillains: [1] }], }; - var json = env.container.lookup("serializer:home-planet").normalizeResponse(env.store, HomePlanet, jsonHash, null, 'findAll'); + var json = env.container + .lookup('serializer:home-planet') + .normalizeResponse(env.store, HomePlanet, jsonHash, null, 'findAll'); assert.deepEqual(json.meta.authors, ['Tomster', 'Tomhuda']); }); -test("normalizeResponse with custom modelNameFromPayloadKey", function(assert) { +test('normalizeResponse with custom modelNameFromPayloadKey', function(assert) { assert.expect(1); env.restSerializer.modelNameFromPayloadKey = function(root) { @@ -108,22 +121,32 @@ test("normalizeResponse with custom modelNameFromPayloadKey", function(assert) { env.registry.register('serializer:super-villain', DS.JSONSerializer); var jsonHash = { - home_planets: [{ - id: "1", - name: "Umber", - superVillains: [1] - }], - super_villains: [{ - id: "1", - firstName: "Tom", - lastName: "Dale", - homePlanet: "1" - }] + home_planets: [ + { + id: '1', + name: 'Umber', + superVillains: [1], + }, + ], + super_villains: [ + { + id: '1', + firstName: 'Tom', + lastName: 'Dale', + homePlanet: '1', + }, + ], }; var array; run(function() { - array = env.restSerializer.normalizeResponse(env.store, HomePlanet, jsonHash, '1', 'findRecord'); + array = env.restSerializer.normalizeResponse( + env.store, + HomePlanet, + jsonHash, + '1', + 'findRecord' + ); }); assert.deepEqual(array, { @@ -131,118 +154,134 @@ test("normalizeResponse with custom modelNameFromPayloadKey", function(assert) { id: '1', type: 'home-planet', attributes: { - name: 'Umber' + name: 'Umber', }, relationships: { superVillains: { - data: [{ id: '1', type: 'super-villain' }] - } - } + data: [{ id: '1', type: 'super-villain' }], + }, + }, }, - included: [{ - id: '1', - type: 'super-villain', - attributes: { - firstName: 'Tom', - lastName: 'Dale' + included: [ + { + id: '1', + type: 'super-villain', + attributes: { + firstName: 'Tom', + lastName: 'Dale', + }, + relationships: { + homePlanet: { + data: { id: '1', type: 'home-planet' }, + }, + }, }, - relationships: { - homePlanet: { - data: { id: '1', type: 'home-planet' } - } - } - }] + ], }); }); -testInDebug("normalizeResponse with type and custom modelNameFromPayloadKey", function(assert) { +testInDebug('normalizeResponse with type and custom modelNameFromPayloadKey', function(assert) { assert.expect(2); var homePlanetNormalizeCount = 0; env.restSerializer.modelNameFromPayloadKey = function(root) { - return "home-planet"; + return 'home-planet'; }; - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend({ - normalize() { - homePlanetNormalizeCount++; - return this._super.apply(this, arguments); - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend({ + normalize() { + homePlanetNormalizeCount++; + return this._super.apply(this, arguments); + }, + }) + ); var jsonHash = { - "my-custom-type": [{ id: "1", name: "Umber", type: "my-custom-type" }] + 'my-custom-type': [{ id: '1', name: 'Umber', type: 'my-custom-type' }], }; var array; - run(function() { array = env.restSerializer.normalizeResponse(env.store, HomePlanet, jsonHash, '1', 'findAll'); }); assert.deepEqual(array, { - data: [{ - id: '1', - type: 'home-planet', - attributes: { - name: 'Umber' + data: [ + { + id: '1', + type: 'home-planet', + attributes: { + name: 'Umber', + }, + relationships: {}, }, - relationships: {} - }], - included: [] + ], + included: [], }); - assert.equal(homePlanetNormalizeCount, 1, "homePlanet is normalized once"); + assert.equal(homePlanetNormalizeCount, 1, 'homePlanet is normalized once'); }); -testInDebug("normalizeResponse warning with custom modelNameFromPayloadKey", function(assert) { +testInDebug('normalizeResponse warning with custom modelNameFromPayloadKey', function(assert) { var homePlanet; var oldModelNameFromPayloadKey = env.restSerializer.modelNameFromPayloadKey; env.registry.register('serializer:super-villain', DS.JSONSerializer); env.registry.register('serializer:home-planet', DS.JSONSerializer); env.restSerializer.modelNameFromPayloadKey = function(root) { //return some garbage that won"t resolve in the container - return "garbage"; + return 'garbage'; }; var jsonHash = { - home_planet: { id: "1", name: "Umber", superVillains: [1] } + home_planet: { id: '1', name: 'Umber', superVillains: [1] }, }; - assert.expectWarning(bind(null, function() { - run(function() { - env.restSerializer.normalizeResponse(env.store, HomePlanet, jsonHash, '1', 'findRecord'); - }); - }), /Encountered "home_planet" in payload, but no model was found for model name "garbage"/); + assert.expectWarning( + bind(null, function() { + run(function() { + env.restSerializer.normalizeResponse(env.store, HomePlanet, jsonHash, '1', 'findRecord'); + }); + }), + /Encountered "home_planet" in payload, but no model was found for model name "garbage"/ + ); // should not warn if a model is found. env.restSerializer.modelNameFromPayloadKey = oldModelNameFromPayloadKey; jsonHash = { - home_planet: { id: "1", name: "Umber", superVillains: [1] } + home_planet: { id: '1', name: 'Umber', superVillains: [1] }, }; assert.expectNoWarning(function() { run(function() { - - homePlanet = env.restSerializer.normalizeResponse(env.store, HomePlanet, jsonHash, 1, 'findRecord'); + homePlanet = env.restSerializer.normalizeResponse( + env.store, + HomePlanet, + jsonHash, + 1, + 'findRecord' + ); }); }); - assert.equal(homePlanet.data.attributes.name, "Umber"); - assert.deepEqual(homePlanet.data.relationships.superVillains.data, [{ id: '1', type: 'super-villain' }]); + assert.equal(homePlanet.data.attributes.name, 'Umber'); + assert.deepEqual(homePlanet.data.relationships.superVillains.data, [ + { id: '1', type: 'super-villain' }, + ]); }); -testInDebug("normalizeResponse warning with custom modelNameFromPayloadKey", function(assert) { +testInDebug('normalizeResponse warning with custom modelNameFromPayloadKey', function(assert) { var homePlanets; env.registry.register('serializer:super-villain', DS.JSONSerializer); env.registry.register('serializer:home-planet', DS.JSONSerializer); env.restSerializer.modelNameFromPayloadKey = function(root) { //return some garbage that won"t resolve in the container - return "garbage"; + return 'garbage'; }; var jsonHash = { - home_planets: [{ id: "1", name: "Umber", superVillains: [1] }] + home_planets: [{ id: '1', name: 'Umber', superVillains: [1] }], }; assert.expectWarning(function() { @@ -255,120 +294,143 @@ testInDebug("normalizeResponse warning with custom modelNameFromPayloadKey", fun }; jsonHash = { - home_planets: [{ id: "1", name: "Umber", superVillains: [1] }] + home_planets: [{ id: '1', name: 'Umber', superVillains: [1] }], }; assert.expectNoWarning(function() { run(function() { - homePlanets = env.restSerializer.normalizeResponse(env.store, HomePlanet, jsonHash, null, 'findAll'); + homePlanets = env.restSerializer.normalizeResponse( + env.store, + HomePlanet, + jsonHash, + null, + 'findAll' + ); }); }); assert.equal(homePlanets.data.length, 1); - assert.equal(homePlanets.data[0].attributes.name, "Umber"); - assert.deepEqual(homePlanets.data[0].relationships.superVillains.data, [{ id: '1', type: 'super-villain' }]); + assert.equal(homePlanets.data[0].attributes.name, 'Umber'); + assert.deepEqual(homePlanets.data[0].relationships.superVillains.data, [ + { id: '1', type: 'super-villain' }, + ]); }); -test("serialize polymorphicType", function(assert) { - let tom = env.store.createRecord('yellow-minion', { name: "Alex", id: "124" }); - let ray = env.store.createRecord('doomsday-device', { evilMinion: tom, name: "DeathRay" }); +test('serialize polymorphicType', function(assert) { + let tom = env.store.createRecord('yellow-minion', { name: 'Alex', id: '124' }); + let ray = env.store.createRecord('doomsday-device', { evilMinion: tom, name: 'DeathRay' }); let json = env.restSerializer.serialize(ray._createSnapshot()); assert.deepEqual(json, { - name: "DeathRay", - evilMinionType: "yellowMinion", - evilMinion: "124" + name: 'DeathRay', + evilMinionType: 'yellowMinion', + evilMinion: '124', }); }); -test("serialize polymorphicType with decamelized modelName", function(assert) { - let tom = env.store.createRecord('yellow-minion', { name: "Alex", id: "124" }); - let ray = env.store.createRecord('doomsday-device', { evilMinion: tom, name: "DeathRay" }); +test('serialize polymorphicType with decamelized modelName', function(assert) { + let tom = env.store.createRecord('yellow-minion', { name: 'Alex', id: '124' }); + let ray = env.store.createRecord('doomsday-device', { evilMinion: tom, name: 'DeathRay' }); let json = env.restSerializer.serialize(ray._createSnapshot()); - assert.deepEqual(json["evilMinionType"], "yellowMinion"); + assert.deepEqual(json['evilMinionType'], 'yellowMinion'); }); -test("serialize polymorphic when associated object is null", function(assert) { - let ray = env.store.createRecord('doomsday-device', { name: "DeathRay" }); +test('serialize polymorphic when associated object is null', function(assert) { + let ray = env.store.createRecord('doomsday-device', { name: 'DeathRay' }); let json = env.restSerializer.serialize(ray._createSnapshot()); - assert.deepEqual(json["evilMinionType"], null); + assert.deepEqual(json['evilMinionType'], null); }); -test("normalizeResponse loads secondary records with correct serializer", function(assert) { +test('normalizeResponse loads secondary records with correct serializer', function(assert) { var superVillainNormalizeCount = 0; env.registry.register('serializer:evil-minion', DS.JSONSerializer); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend({ - normalize() { - superVillainNormalizeCount++; - return this._super.apply(this, arguments); - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend({ + normalize() { + superVillainNormalizeCount++; + return this._super.apply(this, arguments); + }, + }) + ); var jsonHash = { - evilMinion: { id: "1", name: "Tom Dale", superVillain: 1 }, - superVillains: [{ id: "1", firstName: "Yehuda", lastName: "Katz", homePlanet: "1" }] + evilMinion: { id: '1', name: 'Tom Dale', superVillain: 1 }, + superVillains: [{ id: '1', firstName: 'Yehuda', lastName: 'Katz', homePlanet: '1' }], }; run(function() { env.restSerializer.normalizeResponse(env.store, EvilMinion, jsonHash, '1', 'findRecord'); }); - assert.equal(superVillainNormalizeCount, 1, "superVillain is normalized once"); + assert.equal(superVillainNormalizeCount, 1, 'superVillain is normalized once'); }); -test("normalizeResponse returns null if payload contains null", function(assert) { +test('normalizeResponse returns null if payload contains null', function(assert) { assert.expect(1); var jsonHash = { - evilMinion: null + evilMinion: null, }; var value; run(function() { - value = env.restSerializer.normalizeResponse(env.store, EvilMinion, jsonHash, null, 'findRecord'); + value = env.restSerializer.normalizeResponse( + env.store, + EvilMinion, + jsonHash, + null, + 'findRecord' + ); }); - assert.deepEqual(value, { data: null, included: [] }, "returned value is null"); + assert.deepEqual(value, { data: null, included: [] }, 'returned value is null'); }); -test("normalizeResponse loads secondary records with correct serializer", function(assert) { +test('normalizeResponse loads secondary records with correct serializer', function(assert) { var superVillainNormalizeCount = 0; env.registry.register('serializer:evil-minion', DS.JSONSerializer); - env.registry.register('serializer:super-villain', DS.RESTSerializer.extend({ - normalize() { - superVillainNormalizeCount++; - return this._super.apply(this, arguments); - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend({ + normalize() { + superVillainNormalizeCount++; + return this._super.apply(this, arguments); + }, + }) + ); var jsonHash = { - evilMinions: [{ id: "1", name: "Tom Dale", superVillain: 1 }], - superVillains: [{ id: "1", firstName: "Yehuda", lastName: "Katz", homePlanet: "1" }] + evilMinions: [{ id: '1', name: 'Tom Dale', superVillain: 1 }], + superVillains: [{ id: '1', firstName: 'Yehuda', lastName: 'Katz', homePlanet: '1' }], }; run(function() { env.restSerializer.normalizeResponse(env.store, EvilMinion, jsonHash, null, 'findAll'); }); - assert.equal(superVillainNormalizeCount, 1, "superVillain is normalized once"); + assert.equal(superVillainNormalizeCount, 1, 'superVillain is normalized once'); }); test('normalize should allow for different levels of normalization', function(assert) { - env.registry.register('serializer:application', DS.RESTSerializer.extend({ - attrs: { - superVillain: 'is_super_villain' - }, - keyForAttribute(attr) { - return decamelize(attr); - } - })); + env.registry.register( + 'serializer:application', + DS.RESTSerializer.extend({ + attrs: { + superVillain: 'is_super_villain', + }, + keyForAttribute(attr) { + return decamelize(attr); + }, + }) + ); var jsonHash = { - evilMinions: [{ id: "1", name: "Tom Dale", is_super_villain: 1 }] + evilMinions: [{ id: '1', name: 'Tom Dale', is_super_villain: 1 }], }; var array; @@ -380,17 +442,20 @@ test('normalize should allow for different levels of normalization', function(as }); test('normalize should allow for different levels of normalization - attributes', function(assert) { - env.registry.register('serializer:application', DS.RESTSerializer.extend({ - attrs: { - name: 'full_name' - }, - keyForAttribute(attr) { - return decamelize(attr); - } - })); + env.registry.register( + 'serializer:application', + DS.RESTSerializer.extend({ + attrs: { + name: 'full_name', + }, + keyForAttribute(attr) { + return decamelize(attr); + }, + }) + ); var jsonHash = { - evilMinions: [{ id: "1", full_name: "Tom Dale" }] + evilMinions: [{ id: '1', full_name: 'Tom Dale' }], }; var array; @@ -401,29 +466,29 @@ test('normalize should allow for different levels of normalization - attributes' assert.equal(array.data[0].attributes.name, 'Tom Dale'); }); -test("serializeIntoHash", function(assert) { - let league = env.store.createRecord('home-planet', { name: "Umber", id: "123" }); +test('serializeIntoHash', function(assert) { + let league = env.store.createRecord('home-planet', { name: 'Umber', id: '123' }); let json = {}; env.restSerializer.serializeIntoHash(json, HomePlanet, league._createSnapshot()); assert.deepEqual(json, { homePlanet: { - name: "Umber" - } + name: 'Umber', + }, }); }); -test("serializeIntoHash with decamelized modelName", function(assert) { - let league = env.store.createRecord('home-planet', { name: "Umber", id: "123" }); +test('serializeIntoHash with decamelized modelName', function(assert) { + let league = env.store.createRecord('home-planet', { name: 'Umber', id: '123' }); let json = {}; env.restSerializer.serializeIntoHash(json, HomePlanet, league._createSnapshot()); assert.deepEqual(json, { homePlanet: { - name: "Umber" - } + name: 'Umber', + }, }); }); @@ -431,9 +496,16 @@ test('serializeBelongsTo with async polymorphic', function(assert) { let json = {}; let expected = { evilMinion: '1', evilMinionType: 'evilMinion' }; let evilMinion = env.store.createRecord('evil-minion', { id: 1, name: 'Tomster' }); - let doomsdayDevice = env.store.createRecord('doomsday-device', { id: 2, name: 'Yehuda', evilMinion: evilMinion }); + let doomsdayDevice = env.store.createRecord('doomsday-device', { + id: 2, + name: 'Yehuda', + evilMinion: evilMinion, + }); - env.restSerializer.serializeBelongsTo(doomsdayDevice._createSnapshot(), json, { key: 'evilMinion', options: { polymorphic: true, async: true } }); + env.restSerializer.serializeBelongsTo(doomsdayDevice._createSnapshot(), json, { + key: 'evilMinion', + options: { polymorphic: true, async: true }, + }); assert.deepEqual(json, expected, 'returned JSON is correct'); }); @@ -447,9 +519,16 @@ test('keyForPolymorphicType can be used to overwrite how the type of a polymorph }; let evilMinion = env.store.createRecord('evil-minion', { id: 1, name: 'Tomster' }); - let doomsdayDevice = env.store.createRecord('doomsday-device', { id: 2, name: 'Yehuda', evilMinion: evilMinion }); + let doomsdayDevice = env.store.createRecord('doomsday-device', { + id: 2, + name: 'Yehuda', + evilMinion: evilMinion, + }); - env.restSerializer.serializeBelongsTo(doomsdayDevice._createSnapshot(), json, { key: 'evilMinion', options: { polymorphic: true, async: true } }); + env.restSerializer.serializeBelongsTo(doomsdayDevice._createSnapshot(), json, { + key: 'evilMinion', + options: { polymorphic: true, async: true }, + }); assert.deepEqual(json, expected, 'returned JSON is correct'); }); @@ -459,8 +538,8 @@ test('keyForPolymorphicType can be used to overwrite how the type of a polymorph doomsdayDevice: { id: '1', evilMinion: '2', - typeForEvilMinion: 'evilMinion' - } + typeForEvilMinion: 'evilMinion', + }, }; var expected = { @@ -472,32 +551,41 @@ test('keyForPolymorphicType can be used to overwrite how the type of a polymorph evilMinion: { data: { type: 'evil-minion', - id: '2' - } - } - } + id: '2', + }, + }, + }, }, - included: [] + included: [], }; env.restSerializer.keyForPolymorphicType = function() { return 'typeForEvilMinion'; }; - var normalized = env.restSerializer.normalizeResponse(env.store, DoomsdayDevice, json, null, 'findRecord'); + var normalized = env.restSerializer.normalizeResponse( + env.store, + DoomsdayDevice, + json, + null, + 'findRecord' + ); assert.deepEqual(normalized, expected, 'normalized JSON is correct'); }); test('serializeIntoHash uses payloadKeyFromModelName to normalize the payload root key', function(assert) { - let league = env.store.createRecord('home-planet', { name: "Umber", id: "123" }); + let league = env.store.createRecord('home-planet', { name: 'Umber', id: '123' }); let json = {}; - env.registry.register('serializer:home-planet', DS.RESTSerializer.extend({ - payloadKeyFromModelName(modelName) { - return dasherize(modelName); - } - })); + env.registry.register( + 'serializer:home-planet', + DS.RESTSerializer.extend({ + payloadKeyFromModelName(modelName) { + return dasherize(modelName); + }, + }) + ); let serializer = env.store.serializerFor('home-planet'); @@ -505,8 +593,8 @@ test('serializeIntoHash uses payloadKeyFromModelName to normalize the payload ro assert.deepEqual(json, { 'home-planet': { - name: "Umber" - } + name: 'Umber', + }, }); }); @@ -518,10 +606,10 @@ test('normalizeResponse with async polymorphic belongsTo, using { - return deathRay.get('evilMinion'); - }).then((evilMinion) => { - assert.equal(evilMinion.get('eyes'), 3); - }); + store + .findRecord('doomsday-device', 1) + .then(deathRay => { + return deathRay.get('evilMinion'); + }) + .then(evilMinion => { + assert.equal(evilMinion.get('eyes'), 3); + }); }); }); @@ -551,13 +642,15 @@ test('normalizeResponse with async polymorphic belongsTo', function(assert) { var store = env.store; env.adapter.findRecord = () => { return { - doomsdayDevices: [{ - id: 1, - name: "DeathRay", - links: { - evilMinion: '/doomsday-device/1/evil-minion' - } - }] + doomsdayDevices: [ + { + id: 1, + name: 'DeathRay', + links: { + evilMinion: '/doomsday-device/1/evil-minion', + }, + }, + ], }; }; @@ -567,63 +660,75 @@ test('normalizeResponse with async polymorphic belongsTo', function(assert) { id: 1, type: 'yellowMinion', name: 'Alex', - eyes: 3 - } + eyes: 3, + }, }; }; run(function() { - store.findRecord('doomsday-device', 1).then((deathRay) => { - return deathRay.get('evilMinion'); - }).then((evilMinion) => { - assert.equal(evilMinion.get('eyes'), 3); - }); + store + .findRecord('doomsday-device', 1) + .then(deathRay => { + return deathRay.get('evilMinion'); + }) + .then(evilMinion => { + assert.equal(evilMinion.get('eyes'), 3); + }); }); }); test('normalizeResponse with async polymorphic hasMany', function(assert) { - SuperVillain.reopen({ evilMinions: DS.hasMany('evil-minion', { async: true, polymorphic: true }) }); + SuperVillain.reopen({ + evilMinions: DS.hasMany('evil-minion', { async: true, polymorphic: true }), + }); env.registry.register('serializer:application', DS.RESTSerializer.extend()); var store = env.store; env.adapter.findRecord = () => { return { - superVillains: [{ - id: "1", - firstName: "Yehuda", - lastName: "Katz", - links: { - evilMinions: '/super-villain/1/evil-minions' - } - }] + superVillains: [ + { + id: '1', + firstName: 'Yehuda', + lastName: 'Katz', + links: { + evilMinions: '/super-villain/1/evil-minions', + }, + }, + ], }; }; env.adapter.findHasMany = () => { return { - evilMinion: [{ - id: 1, - type: 'yellowMinion', - name: 'Alex', - eyes: 3 - }] + evilMinion: [ + { + id: 1, + type: 'yellowMinion', + name: 'Alex', + eyes: 3, + }, + ], }; }; run(function() { - store.findRecord('super-villain', 1).then((superVillain) => { - return superVillain.get('evilMinions'); - }).then((evilMinions) => { - assert.ok(evilMinions.get('firstObject') instanceof YellowMinion); - assert.equal(evilMinions.get('firstObject.eyes'), 3); - }); + store + .findRecord('super-villain', 1) + .then(superVillain => { + return superVillain.get('evilMinions'); + }) + .then(evilMinions => { + assert.ok(evilMinions.get('firstObject') instanceof YellowMinion); + assert.equal(evilMinions.get('firstObject.eyes'), 3); + }); }); }); -test("normalizeResponse can load secondary records of the same type without affecting the query count", function(assert) { +test('normalizeResponse can load secondary records of the same type without affecting the query count', function(assert) { var jsonHash = { - comments: [{ id: "1", body: "Parent Comment", root: true, children: [2, 3] }], + comments: [{ id: '1', body: 'Parent Comment', root: true, children: [2, 3] }], _comments: [ - { id: "2", body: "Child Comment 1", root: false }, - { id: "3", body: "Child Comment 2", root: false } - ] + { id: '2', body: 'Child Comment 1', root: false }, + { id: '3', body: 'Child Comment 2', root: false }, + ], }; var array; env.registry.register('serializer:comment', DS.JSONSerializer); @@ -633,39 +738,39 @@ test("normalizeResponse can load secondary records of the same type without affe }); assert.deepEqual(array, { - "data": { - "id": "1", - "type": "comment", - "attributes": { - "body": "Parent Comment", - "root": true + data: { + id: '1', + type: 'comment', + attributes: { + body: 'Parent Comment', + root: true, + }, + relationships: { + children: { + data: [{ id: '2', type: 'comment' }, { id: '3', type: 'comment' }], + }, }, - "relationships": { - "children": { - "data": [ - { "id": "2", "type": "comment" }, - { "id": "3", "type": "comment" } - ] - } - } }, - "included": [{ - "id": "2", - "type": "comment", - "attributes": { - "body": "Child Comment 1", - "root": false + included: [ + { + id: '2', + type: 'comment', + attributes: { + body: 'Child Comment 1', + root: false, + }, + relationships: {}, }, - "relationships": {} - }, { - "id": "3", - "type": "comment", - "attributes": { - "body": "Child Comment 2", - "root": false + { + id: '3', + type: 'comment', + attributes: { + body: 'Child Comment 2', + root: false, + }, + relationships: {}, }, - "relationships": {} - }] + ], }); }); @@ -673,12 +778,14 @@ test("don't polymorphically deserialize base on the type key in payload when a t env.registry.register('serializer:application', DS.RESTSerializer.extend()); run(function() { - env.store.push(env.restSerializer.normalizeArrayResponse(env.store, Basket, { - basket: [ - { type: 'bamboo', size: 10, id: '1' }, - { type: 'yellowMinion', size: 10, id: '65536' } - ] - })); + env.store.push( + env.restSerializer.normalizeArrayResponse(env.store, Basket, { + basket: [ + { type: 'bamboo', size: 10, id: '1' }, + { type: 'yellowMinion', size: 10, id: '65536' }, + ], + }) + ); }); const normalRecord = env.store.peekRecord('basket', '1'); @@ -696,9 +803,16 @@ test("don't polymorphically deserialize base on the type key in payload when a t env.registry.register('serializer:application', DS.RESTSerializer.extend()); run(function() { - env.store.push(env.restSerializer.normalizeSingleResponse(env.store, Basket, { - basket: { type: 'yellowMinion', size: 10, id: '65536' } - }, '65536')); + env.store.push( + env.restSerializer.normalizeSingleResponse( + env.store, + Basket, + { + basket: { type: 'yellowMinion', size: 10, id: '65536' }, + }, + '65536' + ) + ); }); const clashingRecord = env.store.peekRecord('basket', '65536'); @@ -707,49 +821,55 @@ test("don't polymorphically deserialize base on the type key in payload when a t assert.strictEqual(clashingRecord.get('size'), 10); }); - test("don't polymorphically deserialize based on the type key in payload when a relationship exists named type", function(assert) { env.registry.register('serializer:application', DS.RESTSerializer.extend()); env.adapter.findRecord = () => { return { containers: [{ id: 42, volume: '10 liters', type: 1 }], - baskets: [{ id: 1, size: 4 }] + baskets: [{ id: 1, size: 4 }], }; }; run(function() { - env.store.findRecord('container', 42).then((container) => { - assert.strictEqual(container.get('volume'), '10 liters'); - return container.get('type'); - }).then((basket) => { - assert.ok(basket instanceof Basket); - assert.equal(basket.get('size'), 4); - }); + env.store + .findRecord('container', 42) + .then(container => { + assert.strictEqual(container.get('volume'), '10 liters'); + return container.get('type'); + }) + .then(basket => { + assert.ok(basket instanceof Basket); + assert.equal(basket.get('size'), 4); + }); }); - }); test('Serializer should respect the attrs hash in links', function(assert) { - env.registry.register("serializer:super-villain", DS.RESTSerializer.extend({ - attrs: { - evilMinions: { key: 'my_minions' } - } - })); + env.registry.register( + 'serializer:super-villain', + DS.RESTSerializer.extend({ + attrs: { + evilMinions: { key: 'my_minions' }, + }, + }) + ); var jsonHash = { - "super-villains": [ + 'super-villains': [ { firstName: 'Tom', lastName: 'Dale', links: { - my_minions: 'me/minions' - } - } - ] + my_minions: 'me/minions', + }, + }, + ], }; - var documentHash = env.container.lookup("serializer:super-villain").normalizeSingleResponse(env.store, SuperVillain, jsonHash); + var documentHash = env.container + .lookup('serializer:super-villain') + .normalizeSingleResponse(env.store, SuperVillain, jsonHash); assert.equal(documentHash.data.relationships.evilMinions.links.related, 'me/minions'); }); @@ -757,19 +877,21 @@ test('Serializer should respect the attrs hash in links', function(assert) { // https://github.com/emberjs/data/issues/3805 test('normalizes sideloaded single record so that it sideloads correctly - belongsTo - GH-3805', function(assert) { env.registry.register('serializer:evil-minion', DS.JSONSerializer); - env.registry.register("serializer:doomsday-device", DS.RESTSerializer.extend()); + env.registry.register('serializer:doomsday-device', DS.RESTSerializer.extend()); let payload = { doomsdayDevice: { id: 1, - evilMinion: 2 + evilMinion: 2, }, evilMinion: { id: 2, - doomsdayDevice: 1 - } + doomsdayDevice: 1, + }, }; - let document = env.store.serializerFor('doomsday-device').normalizeSingleResponse(env.store, DoomsdayDevice, payload); + let document = env.store + .serializerFor('doomsday-device') + .normalizeSingleResponse(env.store, DoomsdayDevice, payload); assert.equal(document.data.relationships.evilMinion.data.id, 2); assert.equal(document.included.length, 1); assert.deepEqual(document.included[0], { @@ -780,29 +902,31 @@ test('normalizes sideloaded single record so that it sideloads correctly - belon doomsdayDevice: { data: { id: '1', - type: 'doomsday-device' - } - } - } + type: 'doomsday-device', + }, + }, + }, }); }); // https://github.com/emberjs/data/issues/3805 test('normalizes sideloaded single record so that it sideloads correctly - hasMany - GH-3805', function(assert) { env.registry.register('serializer:super-villain', DS.JSONSerializer); - env.registry.register("serializer:home-planet", DS.RESTSerializer.extend()); + env.registry.register('serializer:home-planet', DS.RESTSerializer.extend()); let payload = { homePlanet: { id: 1, - superVillains: [2] + superVillains: [2], }, superVillain: { id: 2, - homePlanet: 1 - } + homePlanet: 1, + }, }; - let document = env.store.serializerFor('home-planet').normalizeSingleResponse(env.store, HomePlanet, payload); + let document = env.store + .serializerFor('home-planet') + .normalizeSingleResponse(env.store, HomePlanet, payload); assert.equal(document.data.relationships.superVillains.data.length, 1); assert.equal(document.data.relationships.superVillains.data[0].id, 2); @@ -815,9 +939,9 @@ test('normalizes sideloaded single record so that it sideloads correctly - hasMa homePlanet: { data: { id: '1', - type: 'home-planet' - } - } - } + type: 'home-planet', + }, + }, + }, }); }); diff --git a/tests/integration/setup-container-test.js b/tests/integration/setup-container-test.js index eb61d686a0b..fcf890a972b 100644 --- a/tests/integration/setup-container-test.js +++ b/tests/integration/setup-container-test.js @@ -15,7 +15,7 @@ let container, registry, application; initialization and dependency injection API. */ -module("integration/setup-container - Setting up a container", { +module('integration/setup-container - Setting up a container', { beforeEach() { application = run(() => Application.create()); @@ -35,19 +35,22 @@ module("integration/setup-container - Setting up a container", { afterEach() { run(() => application.destroy()); - } + }, }); -test("The store should be registered into a container.", function(assert) { - assert.ok(container.lookup('service:store') instanceof Store, "the custom store is instantiated"); +test('The store should be registered into a container.', function(assert) { + assert.ok(container.lookup('service:store') instanceof Store, 'the custom store is instantiated'); }); -test("The store should be registered into the container as a service.", function(assert) { - assert.ok(container.lookup('service:store') instanceof Store, "the store as a service is registered"); +test('The store should be registered into the container as a service.', function(assert) { + assert.ok( + container.lookup('service:store') instanceof Store, + 'the store as a service is registered' + ); }); -test("If a store is instantiated, it should be made available to each controller.", function(assert) { +test('If a store is instantiated, it should be made available to each controller.', function(assert) { registry.register('controller:foo', EmberObject.extend({})); let fooController = container.lookup('controller:foo'); - assert.ok(fooController.get('store') instanceof Store, "the store was injected"); + assert.ok(fooController.get('store') instanceof Store, 'the store was injected'); }); diff --git a/tests/integration/snapshot-test.js b/tests/integration/snapshot-test.js index f9e79980a00..5513e86c5e8 100644 --- a/tests/integration/snapshot-test.js +++ b/tests/integration/snapshot-test.js @@ -5,25 +5,25 @@ import setupStore from 'dummy/tests/helpers/store'; import { module, test } from 'qunit'; import DS from 'ember-data'; -const { Model, attr, hasMany,belongsTo, Snapshot } = DS; +const { Model, attr, hasMany, belongsTo, Snapshot } = DS; let env, Post, Comment; -module("integration/snapshot - Snapshot", { +module('integration/snapshot - Snapshot', { beforeEach() { Post = Model.extend({ author: attr(), title: attr(), - comments: hasMany({ async: true }) + comments: hasMany({ async: true }), }); Comment = Model.extend({ body: attr(), - post: belongsTo({ async: true }) + post: belongsTo({ async: true }), }); env = setupStore({ post: Post, - comment: Comment + comment: Comment, }); }, @@ -31,25 +31,25 @@ module("integration/snapshot - Snapshot", { run(() => { env.store.destroy(); }); - } + }, }); test('snapshot.attributes() includes defaultValues when appropriate', function(assert) { const Address = Model.extend({ street: attr(), country: attr({ defaultValue: 'USA' }), - state: attr({ defaultValue: () => 'CA' }) + state: attr({ defaultValue: () => 'CA' }), }); let { store } = setupStore({ - address: Address + address: Address, }); let newAddress = store.createRecord('address', {}); let snapshot = newAddress._createSnapshot(); let expected = { - country: "USA", - state: "CA", - street: undefined + country: 'USA', + state: 'CA', + street: undefined, }; assert.ok(snapshot instanceof Snapshot, 'snapshot is an instance of Snapshot'); @@ -58,7 +58,7 @@ test('snapshot.attributes() includes defaultValues when appropriate', function(a run(() => store.destroy()); }); -test("record._createSnapshot() returns a snapshot", function(assert) { +test('record._createSnapshot() returns a snapshot', function(assert) { assert.expect(1); run(() => { @@ -67,9 +67,9 @@ test("record._createSnapshot() returns a snapshot", function(assert) { type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -78,7 +78,7 @@ test("record._createSnapshot() returns a snapshot", function(assert) { }); }); -test("snapshot.id, snapshot.type and snapshot.modelName returns correctly", function(assert) { +test('snapshot.id, snapshot.type and snapshot.modelName returns correctly', function(assert) { assert.expect(3); run(() => { @@ -87,9 +87,9 @@ test("snapshot.id, snapshot.type and snapshot.modelName returns correctly", func type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -105,7 +105,7 @@ test('snapshot.type loads the class lazily', function(assert) { let postClassLoaded = false; let modelFactoryFor = env.store._modelFactoryFor; - env.store._modelFactoryFor = (name) => { + env.store._modelFactoryFor = name => { if (name === 'post') { postClassLoaded = true; } @@ -118,9 +118,9 @@ test('snapshot.type loads the class lazily', function(assert) { type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let postInternalModel = env.store._internalModelForId('post', 1); let snapshot = postInternalModel.createSnapshot(); @@ -141,9 +141,9 @@ test('an initial findRecord call has no record for internal-model when a snapsho type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); }; @@ -153,21 +153,23 @@ test('an initial findRecord call has no record for internal-model when a snapsho test('snapshots for un-materialized internal-models generate attributes lazily', function(assert) { assert.expect(2); - run(() => env.store._push({ - data: { - type: 'post', - id: '1', - attributes: { - title: 'Hello World' - } - } - })); + run(() => + env.store._push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World', + }, + }, + }) + ); let postInternalModel = env.store._internalModelForId('post', 1); let snapshot = postInternalModel.createSnapshot(); let expected = { author: undefined, - title: 'Hello World' + title: 'Hello World', }; assert.equal(snapshot.__attributes, null, 'attributes were not populated initially'); @@ -178,27 +180,29 @@ test('snapshots for un-materialized internal-models generate attributes lazily', test('snapshots for materialized internal-models generate attributes greedily', function(assert) { assert.expect(1); - run(() => env.store.push({ - data: { - type: 'post', - id: '1', - attributes: { - title: 'Hello World' - } - } - })); + run(() => + env.store.push({ + data: { + type: 'post', + id: '1', + attributes: { + title: 'Hello World', + }, + }, + }) + ); let postInternalModel = env.store._internalModelForId('post', 1); let snapshot = postInternalModel.createSnapshot(); let expected = { author: undefined, - title: 'Hello World' + title: 'Hello World', }; assert.deepEqual(snapshot.__attributes, expected, 'attributes were populated initially'); }); -test("snapshot.attr() does not change when record changes", function(assert) { +test('snapshot.attr() does not change when record changes', function(assert) { assert.expect(2); run(() => { @@ -207,9 +211,9 @@ test("snapshot.attr() does not change when record changes", function(assert) { type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -220,7 +224,7 @@ test("snapshot.attr() does not change when record changes", function(assert) { }); }); -test("snapshot.attr() throws an error attribute not found", function(assert) { +test('snapshot.attr() throws an error attribute not found', function(assert) { assert.expect(1); run(() => { @@ -229,20 +233,24 @@ test("snapshot.attr() throws an error attribute not found", function(assert) { type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); - assert.throws(() => { - snapshot.attr('unknown'); - }, /has no attribute named 'unknown' defined/, 'attr throws error'); + assert.throws( + () => { + snapshot.attr('unknown'); + }, + /has no attribute named 'unknown' defined/, + 'attr throws error' + ); }); }); -test("snapshot.attributes() returns a copy of all attributes for the current snapshot", function(assert) { +test('snapshot.attributes() returns a copy of all attributes for the current snapshot', function(assert) { assert.expect(1); run(() => { @@ -251,20 +259,24 @@ test("snapshot.attributes() returns a copy of all attributes for the current sna type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); let attributes = snapshot.attributes(); - assert.deepEqual(attributes, { author: undefined, title: 'Hello World' }, 'attributes are returned correctly'); + assert.deepEqual( + attributes, + { author: undefined, title: 'Hello World' }, + 'attributes are returned correctly' + ); }); }); -test("snapshot.changedAttributes() returns a copy of all changed attributes for the current snapshot", function(assert) { +test('snapshot.changedAttributes() returns a copy of all changed attributes for the current snapshot', function(assert) { assert.expect(1); run(() => { @@ -273,9 +285,9 @@ test("snapshot.changedAttributes() returns a copy of all changed attributes for type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); post.set('title', 'Hello World!'); @@ -283,11 +295,15 @@ test("snapshot.changedAttributes() returns a copy of all changed attributes for let changes = snapshot.changedAttributes(); - assert.deepEqual(changes.title, ['Hello World', 'Hello World!'], 'changed attributes are returned correctly'); + assert.deepEqual( + changes.title, + ['Hello World', 'Hello World!'], + 'changed attributes are returned correctly' + ); }); }); -test("snapshot.belongsTo() returns undefined if relationship is undefined", function(assert) { +test('snapshot.belongsTo() returns undefined if relationship is undefined', function(assert) { assert.expect(1); run(() => { @@ -296,9 +312,9 @@ test("snapshot.belongsTo() returns undefined if relationship is undefined", func type: 'comment', id: '1', attributes: { - body: 'This is comment' - } - } + body: 'This is comment', + }, + }, }); let comment = env.store.peekRecord('comment', 1); let snapshot = comment._createSnapshot(); @@ -308,29 +324,32 @@ test("snapshot.belongsTo() returns undefined if relationship is undefined", func }); }); -test("snapshot.belongsTo() returns null if relationship is unset", function(assert) { +test('snapshot.belongsTo() returns null if relationship is unset', function(assert) { assert.expect(1); run(() => { env.store.push({ - data: [{ - type: 'post', - id: '1', - attributes: { - title: 'Hello World' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'This is comment' + data: [ + { + type: 'post', + id: '1', + attributes: { + title: 'Hello World', + }, }, - relationships: { - post: { - data: null - } - } - }] + { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment', + }, + relationships: { + post: { + data: null, + }, + }, + }, + ], }); let comment = env.store.peekRecord('comment', 2); let snapshot = comment._createSnapshot(); @@ -340,29 +359,32 @@ test("snapshot.belongsTo() returns null if relationship is unset", function(asse }); }); -test("snapshot.belongsTo() returns a snapshot if relationship is set", function(assert) { +test('snapshot.belongsTo() returns a snapshot if relationship is set', function(assert) { assert.expect(3); run(() => { env.store.push({ - data: [{ - type: 'post', - id: '1', - attributes: { - title: 'Hello World' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'This is comment' + data: [ + { + type: 'post', + id: '1', + attributes: { + title: 'Hello World', + }, }, - relationships: { - post: { - data: { type: 'post', id: '1' } - } - } - }] + { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment', + }, + relationships: { + post: { + data: { type: 'post', id: '1' }, + }, + }, + }, + ], }); let comment = env.store.peekRecord('comment', 2); let snapshot = comment._createSnapshot(); @@ -374,29 +396,32 @@ test("snapshot.belongsTo() returns a snapshot if relationship is set", function( }); }); -test("snapshot.belongsTo() returns null if relationship is deleted", function(assert) { +test('snapshot.belongsTo() returns null if relationship is deleted', function(assert) { assert.expect(1); run(() => { env.store.push({ - data: [{ - type: 'post', - id: '1', - attributes: { - title: 'Hello World' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'This is comment' + data: [ + { + type: 'post', + id: '1', + attributes: { + title: 'Hello World', + }, }, - relationships: { - post: { - data: { type: 'post', id: '1' } - } - } - }] + { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment', + }, + relationships: { + post: { + data: { type: 'post', id: '1' }, + }, + }, + }, + ], }); let post = env.store.peekRecord('post', 1); let comment = env.store.peekRecord('comment', 2); @@ -410,7 +435,7 @@ test("snapshot.belongsTo() returns null if relationship is deleted", function(as }); }); -test("snapshot.belongsTo() returns undefined if relationship is a link", function(assert) { +test('snapshot.belongsTo() returns undefined if relationship is a link', function(assert) { assert.expect(1); run(() => { @@ -419,16 +444,16 @@ test("snapshot.belongsTo() returns undefined if relationship is a link", functio type: 'comment', id: '2', attributes: { - body: 'This is comment' + body: 'This is comment', }, relationships: { post: { links: { - related: 'post' - } - } - } - } + related: 'post', + }, + }, + }, + }, }); let comment = env.store.peekRecord('comment', 2); let snapshot = comment._createSnapshot(); @@ -447,20 +472,24 @@ test("snapshot.belongsTo() throws error if relation doesn't exist", function(ass type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); - assert.throws(() => { - snapshot.belongsTo('unknown'); - }, /has no belongsTo relationship named 'unknown'/, 'throws error'); + assert.throws( + () => { + snapshot.belongsTo('unknown'); + }, + /has no belongsTo relationship named 'unknown'/, + 'throws error' + ); }); }); -test("snapshot.belongsTo() returns a snapshot if relationship link has been fetched", function(assert) { +test('snapshot.belongsTo() returns a snapshot if relationship link has been fetched', function(assert) { assert.expect(2); env.adapter.findBelongsTo = function(store, snapshot, link, relationship) { @@ -473,16 +502,16 @@ test("snapshot.belongsTo() returns a snapshot if relationship link has been fetc type: 'comment', id: '2', attributes: { - body: 'This is comment' + body: 'This is comment', }, relationships: { post: { links: { - related: 'post' - } - } - } - } + related: 'post', + }, + }, + }, + }, }); let comment = env.store.peekRecord('comment', 2); @@ -496,24 +525,27 @@ test("snapshot.belongsTo() returns a snapshot if relationship link has been fetc }); }); -test("snapshot.belongsTo() and snapshot.hasMany() returns correctly when adding an object to a hasMany relationship", function(assert) { +test('snapshot.belongsTo() and snapshot.hasMany() returns correctly when adding an object to a hasMany relationship', function(assert) { assert.expect(4); return run(() => { env.store.push({ - data: [{ - type: 'post', - id: '1', - attributes: { - title: 'Hello World' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'This is comment' - } - }] + data: [ + { + type: 'post', + id: '1', + attributes: { + title: 'Hello World', + }, + }, + { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment', + }, + }, + ], }); let post = env.store.peekRecord('post', 1); let comment = env.store.peekRecord('comment', 2); @@ -527,33 +559,46 @@ test("snapshot.belongsTo() and snapshot.hasMany() returns correctly when adding let hasManyRelationship = postSnapshot.hasMany('comments'); let belongsToRelationship = commentSnapshot.belongsTo('post'); - assert.ok(hasManyRelationship instanceof Array, 'hasMany relationship is an instance of Array'); + assert.ok( + hasManyRelationship instanceof Array, + 'hasMany relationship is an instance of Array' + ); assert.equal(hasManyRelationship.length, 1, 'hasMany relationship contains related object'); - assert.ok(belongsToRelationship instanceof Snapshot, 'belongsTo relationship is an instance of Snapshot'); - assert.equal(belongsToRelationship.attr('title'), 'Hello World', 'belongsTo relationship contains related object'); + assert.ok( + belongsToRelationship instanceof Snapshot, + 'belongsTo relationship is an instance of Snapshot' + ); + assert.equal( + belongsToRelationship.attr('title'), + 'Hello World', + 'belongsTo relationship contains related object' + ); }); }); }); -test("snapshot.belongsTo() and snapshot.hasMany() returns correctly when setting an object to a belongsTo relationship", function(assert) { +test('snapshot.belongsTo() and snapshot.hasMany() returns correctly when setting an object to a belongsTo relationship', function(assert) { assert.expect(4); run(() => { env.store.push({ - data: [{ - type: 'post', - id: '1', - attributes: { - title: 'Hello World' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'This is comment' - } - }] + data: [ + { + type: 'post', + id: '1', + attributes: { + title: 'Hello World', + }, + }, + { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment', + }, + }, + ], }); let post = env.store.peekRecord('post', 1); let comment = env.store.peekRecord('comment', 2); @@ -569,34 +614,44 @@ test("snapshot.belongsTo() and snapshot.hasMany() returns correctly when setting assert.ok(hasManyRelationship instanceof Array, 'hasMany relationship is an instance of Array'); assert.equal(hasManyRelationship.length, 1, 'hasMany relationship contains related object'); - assert.ok(belongsToRelationship instanceof Snapshot, 'belongsTo relationship is an instance of Snapshot'); - assert.equal(belongsToRelationship.attr('title'), 'Hello World', 'belongsTo relationship contains related object'); + assert.ok( + belongsToRelationship instanceof Snapshot, + 'belongsTo relationship is an instance of Snapshot' + ); + assert.equal( + belongsToRelationship.attr('title'), + 'Hello World', + 'belongsTo relationship contains related object' + ); }); }); -test("snapshot.belongsTo() returns ID if option.id is set", function(assert) { +test('snapshot.belongsTo() returns ID if option.id is set', function(assert) { assert.expect(1); run(() => { env.store.push({ - data: [{ - type: 'post', - id: '1', - attributes: { - title: 'Hello World' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'This is comment' + data: [ + { + type: 'post', + id: '1', + attributes: { + title: 'Hello World', + }, }, - relationships: { - post: { - data: { type: 'post', id: '1' } - } - } - }] + { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment', + }, + relationships: { + post: { + data: { type: 'post', id: '1' }, + }, + }, + }, + ], }); let comment = env.store.peekRecord('comment', 2); let snapshot = comment._createSnapshot(); @@ -606,29 +661,32 @@ test("snapshot.belongsTo() returns ID if option.id is set", function(assert) { }); }); -test("snapshot.belongsTo() returns null if option.id is set but relationship was deleted", function(assert) { +test('snapshot.belongsTo() returns null if option.id is set but relationship was deleted', function(assert) { assert.expect(1); run(() => { env.store.push({ - data: [{ - type: 'post', - id: '1', - attributes: { - title: 'Hello World' - } - }, { - type: 'comment', - id: '2', - attributes: { - body: 'This is comment' + data: [ + { + type: 'post', + id: '1', + attributes: { + title: 'Hello World', + }, }, - relationships: { - post: { - data: { type: 'post', id: '1' } - } - } - }] + { + type: 'comment', + id: '2', + attributes: { + body: 'This is comment', + }, + relationships: { + post: { + data: { type: 'post', id: '1' }, + }, + }, + }, + ], }); let post = env.store.peekRecord('post', 1); let comment = env.store.peekRecord('comment', 2); @@ -642,7 +700,7 @@ test("snapshot.belongsTo() returns null if option.id is set but relationship was }); }); -test("snapshot.hasMany() returns undefined if relationship is undefined", function(assert) { +test('snapshot.hasMany() returns undefined if relationship is undefined', function(assert) { assert.expect(1); run(() => { @@ -651,9 +709,9 @@ test("snapshot.hasMany() returns undefined if relationship is undefined", functi type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -663,7 +721,7 @@ test("snapshot.hasMany() returns undefined if relationship is undefined", functi }); }); -test("snapshot.hasMany() returns empty array if relationship is empty", function(assert) { +test('snapshot.hasMany() returns empty array if relationship is empty', function(assert) { assert.expect(2); run(() => { @@ -672,14 +730,14 @@ test("snapshot.hasMany() returns empty array if relationship is empty", function type: 'post', id: '1', attributes: { - title: 'Hello World' + title: 'Hello World', }, relationships: { comments: { - data: [] - } - } - } + data: [], + }, + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -690,38 +748,39 @@ test("snapshot.hasMany() returns empty array if relationship is empty", function }); }); -test("snapshot.hasMany() returns array of snapshots if relationship is set", function(assert) { +test('snapshot.hasMany() returns array of snapshots if relationship is set', function(assert) { assert.expect(5); run(() => { 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' + data: [ + { + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment', + }, }, - relationships: { - comments: { - data: [ - { type: 'comment', id: '1' }, - { type: 'comment', id: '2' } - ] - } - } - }] + { + 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' }], + }, + }, + }, + ], }); let post = env.store.peekRecord('post', 3); let snapshot = post._createSnapshot(); @@ -735,42 +794,47 @@ test("snapshot.hasMany() returns array of snapshots if relationship is set", fun assert.ok(relationship1 instanceof Snapshot, 'relationship item is an instance of Snapshot'); assert.equal(relationship1.id, '1', 'relationship item id is correct'); - assert.equal(relationship1.attr('body'), 'This is the first comment', 'relationship item body is correct'); + assert.equal( + relationship1.attr('body'), + 'This is the first comment', + 'relationship item body is correct' + ); }); }); -test("snapshot.hasMany() returns empty array if relationship records are deleted", function(assert) { +test('snapshot.hasMany() returns empty array if relationship records are deleted', function(assert) { assert.expect(2); run(() => { 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' + data: [ + { + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment', + }, }, - relationships: { - comments: { - data: [ - { type: 'comment', id: '1' }, - { type: 'comment', id: '2' } - ] - } - } - }] + { + 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' }], + }, + }, + }, + ], }); let comment1 = env.store.peekRecord('comment', 1); let comment2 = env.store.peekRecord('comment', 2); @@ -787,7 +851,7 @@ test("snapshot.hasMany() returns empty array if relationship records are deleted }); }); -test("snapshot.hasMany() returns array of IDs if option.ids is set", function(assert) { +test('snapshot.hasMany() returns array of IDs if option.ids is set', function(assert) { assert.expect(1); run(() => { @@ -796,17 +860,14 @@ test("snapshot.hasMany() returns array of IDs if option.ids is set", function(as type: 'post', id: '1', attributes: { - title: 'Hello World' + title: 'Hello World', }, relationships: { comments: { - data: [ - { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + data: [{ type: 'comment', id: '2' }, { type: 'comment', id: '3' }], + }, + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -816,38 +877,39 @@ test("snapshot.hasMany() returns array of IDs if option.ids is set", function(as }); }); -test("snapshot.hasMany() returns empty array of IDs if option.ids is set but relationship records were deleted", function(assert) { +test('snapshot.hasMany() returns empty array of IDs if option.ids is set but relationship records were deleted', function(assert) { assert.expect(2); run(() => { 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' + data: [ + { + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment', + }, }, - relationships: { - comments: { - data: [ - { type: 'comment', id: '1' }, - { type: 'comment', id: '2' } - ] - } - } - }] + { + 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' }], + }, + }, + }, + ], }); let comment1 = env.store.peekRecord('comment', 1); let comment2 = env.store.peekRecord('comment', 2); @@ -864,7 +926,7 @@ test("snapshot.hasMany() returns empty array of IDs if option.ids is set but rel }); }); -test("snapshot.hasMany() returns undefined if relationship is a link", function(assert) { +test('snapshot.hasMany() returns undefined if relationship is a link', function(assert) { assert.expect(1); run(() => { @@ -873,16 +935,16 @@ test("snapshot.hasMany() returns undefined if relationship is a link", function( type: 'post', id: '1', attributes: { - title: 'Hello World' + title: 'Hello World', }, relationships: { comments: { links: { - related: 'comments' - } - } - } - } + related: 'comments', + }, + }, + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -892,11 +954,11 @@ test("snapshot.hasMany() returns undefined if relationship is a link", function( }); }); -test("snapshot.hasMany() returns array of snapshots if relationship link has been fetched", function(assert) { +test('snapshot.hasMany() returns array of snapshots if relationship link has been fetched', function(assert) { assert.expect(2); env.adapter.findHasMany = function(store, snapshot, link, relationship) { - return resolve({ data: [{ id: 2, type: 'comment', attributes: { body: 'This is comment' } }]}); + return resolve({ data: [{ id: 2, type: 'comment', attributes: { body: 'This is comment' } }] }); }; return run(() => { @@ -905,16 +967,16 @@ test("snapshot.hasMany() returns array of snapshots if relationship link has bee type: 'post', id: '1', attributes: { - title: 'Hello World' + title: 'Hello World', }, relationships: { comments: { links: { - related: 'comments' - } - } - } - } + related: 'comments', + }, + }, + }, + }, }); let post = env.store.peekRecord('post', 1); @@ -938,58 +1000,67 @@ test("snapshot.hasMany() throws error if relation doesn't exist", function(asser type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); - assert.throws(() => { - snapshot.hasMany('unknown'); - }, /has no hasMany relationship named 'unknown'/, 'throws error'); + assert.throws( + () => { + snapshot.hasMany('unknown'); + }, + /has no hasMany relationship named 'unknown'/, + 'throws error' + ); }); }); -test("snapshot.hasMany() respects the order of items in the relationship", function(assert) { +test('snapshot.hasMany() respects the order of items in the relationship', function(assert) { assert.expect(3); run(() => { 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' + data: [ + { + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment', + }, }, - relationships: { - comments: { - data: [ - { type: 'comment', id: '1' }, - { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - }] + { + 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' }, + ], + }, + }, + }, + ], }); let comment3 = env.store.peekRecord('comment', 3); let post = env.store.peekRecord('post', 4); @@ -1006,7 +1077,7 @@ test("snapshot.hasMany() respects the order of items in the relationship", funct }); }); -test("snapshot.eachAttribute() proxies to record", function(assert) { +test('snapshot.eachAttribute() proxies to record', function(assert) { assert.expect(1); run(() => { @@ -1015,9 +1086,9 @@ test("snapshot.eachAttribute() proxies to record", function(assert) { type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -1028,7 +1099,7 @@ test("snapshot.eachAttribute() proxies to record", function(assert) { }); }); -test("snapshot.eachRelationship() proxies to record", function(assert) { +test('snapshot.eachRelationship() proxies to record', function(assert) { assert.expect(2); let getRelationships = function(snapshot) { @@ -1039,19 +1110,22 @@ test("snapshot.eachRelationship() proxies to record", function(assert) { run(() => { env.store.push({ - data: [{ - type: 'comment', - id: '1', - attributes: { - body: 'This is the first comment' - } - }, { - type: 'post', - id: '2', - attributes: { - title: 'Hello World' - } - }] + data: [ + { + type: 'comment', + id: '1', + attributes: { + body: 'This is the first comment', + }, + }, + { + type: 'post', + id: '2', + attributes: { + title: 'Hello World', + }, + }, + ], }); let comment = env.store.peekRecord('comment', 1); let post = env.store.peekRecord('post', 2); @@ -1061,11 +1135,15 @@ test("snapshot.eachRelationship() proxies to record", function(assert) { assert.deepEqual(getRelationships(snapshot), ['post'], 'relationships are iterated correctly'); snapshot = post._createSnapshot(); - assert.deepEqual(getRelationships(snapshot), ['comments'], 'relationships are iterated correctly'); + assert.deepEqual( + getRelationships(snapshot), + ['comments'], + 'relationships are iterated correctly' + ); }); }); -test("snapshot.belongsTo() does not trigger a call to store._scheduleFetch", function(assert) { +test('snapshot.belongsTo() does not trigger a call to store._scheduleFetch', function(assert) { assert.expect(0); env.store._scheduleFetch = function() { @@ -1078,14 +1156,14 @@ test("snapshot.belongsTo() does not trigger a call to store._scheduleFetch", fun type: 'comment', id: '1', attributes: { - body: 'This is the first comment' + body: 'This is the first comment', }, relationships: { post: { - data: { type: 'post', id: '2' } - } - } - } + data: { type: 'post', id: '2' }, + }, + }, + }, }); let comment = env.store.peekRecord('comment', 1); let snapshot = comment._createSnapshot(); @@ -1094,7 +1172,7 @@ test("snapshot.belongsTo() does not trigger a call to store._scheduleFetch", fun }); }); -test("snapshot.hasMany() does not trigger a call to store._scheduleFetch", function(assert) { +test('snapshot.hasMany() does not trigger a call to store._scheduleFetch', function(assert) { assert.expect(0); env.store._scheduleFetch = function() { @@ -1107,17 +1185,14 @@ test("snapshot.hasMany() does not trigger a call to store._scheduleFetch", funct type: 'post', id: '1', attributes: { - title: 'Hello World' + title: 'Hello World', }, relationships: { comments: { - data: [ - { type: 'comment', id: '2' }, - { type: 'comment', id: '3' } - ] - } - } - } + data: [{ type: 'comment', id: '2' }, { type: 'comment', id: '3' }], + }, + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -1126,7 +1201,7 @@ test("snapshot.hasMany() does not trigger a call to store._scheduleFetch", funct }); }); -test("snapshot.serialize() serializes itself", function(assert) { +test('snapshot.serialize() serializes itself', function(assert) { assert.expect(2); run(() => { @@ -1135,9 +1210,9 @@ test("snapshot.serialize() serializes itself", function(assert) { type: 'post', id: '1', attributes: { - title: 'Hello World' - } - } + title: 'Hello World', + }, + }, }); let post = env.store.peekRecord('post', 1); let snapshot = post._createSnapshot(); @@ -1148,10 +1223,10 @@ test("snapshot.serialize() serializes itself", function(assert) { data: { attributes: { author: undefined, - title: 'Hello World' + title: 'Hello World', }, - type: 'posts' - } + type: 'posts', + }, }; assert.deepEqual(snapshot.serialize(), expected, 'shapshot serializes correctly'); expected.data.id = '1'; diff --git a/tests/integration/store-test.js b/tests/integration/store-test.js index 50799070505..207b653e201 100644 --- a/tests/integration/store-test.js +++ b/tests/integration/store-test.js @@ -1,7 +1,4 @@ -import RSVP, { - Promise as EmberPromise, - resolve -} from 'rsvp'; +import RSVP, { Promise as EmberPromise, resolve } from 'rsvp'; import { run, next } from '@ember/runloop'; import setupStore from 'dummy/tests/helpers/store'; @@ -15,30 +12,30 @@ let store, env; const Person = DS.Model.extend({ name: DS.attr('string'), - cars: DS.hasMany('car', { async: false }) + cars: DS.hasMany('car', { async: false }), }); Person.reopenClass({ toString() { - return 'Person' - } + return 'Person'; + }, }); const Car = DS.Model.extend({ make: DS.attr('string'), model: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); Car.reopenClass({ toString() { return 'Car'; - } + }, }); function initializeStore(adapter) { env = setupStore({ - adapter: adapter + adapter: adapter, }); store = env.store; @@ -46,14 +43,14 @@ function initializeStore(adapter) { env.registry.register('model:person', Person); } -module("integration/store - destroy", { +module('integration/store - destroy', { beforeEach() { initializeStore(DS.Adapter.extend()); }, afterEach() { store = null; env = null; - } + }, }); function tap(obj, methodName, callback) { @@ -85,18 +82,18 @@ test("destroying record during find doesn't cause error", function(assert) { reject(); }); }); - } + }, }); initializeStore(TestAdapter); - let type = "car"; + let type = 'car'; let id = 1; return run(() => store.findRecord(type, id).then(done, done)); }); -test("find calls do not resolve when the store is destroyed", function(assert) { +test('find calls do not resolve when the store is destroyed', function(assert) { assert.expect(0); let done = assert.async(); @@ -104,17 +101,16 @@ test("find calls do not resolve when the store is destroyed", function(assert) { findRecord(store, type, id, snapshot) { store.destroy(); resolve(null); - } + }, }); initializeStore(TestAdapter); - - let type = "car"; + let type = 'car'; let id = 1; store.push = function() { - assert("The test should have destroyed the store by now", store.get("isDestroyed")); + assert('The test should have destroyed the store by now', store.get('isDestroyed')); throw new Error("We shouldn't be pushing data into the store when it is destroyed"); }; @@ -124,37 +120,38 @@ test("find calls do not resolve when the store is destroyed", function(assert) { setTimeout(() => done(), 500); }); -test("destroying the store correctly cleans everything up", function(assert) { +test('destroying the store correctly cleans everything up', function(assert) { let car, person; env.adapter.shouldBackgroundReloadRecord = () => false; run(() => { store.push({ - data: [{ - type: 'car', - id: '1', - attributes: { - make: 'BMC', - model: 'Mini' + data: [ + { + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini', + }, + relationships: { + person: { + data: { type: 'person', id: '1' }, + }, + }, }, - relationships: { - person: { - data: { type: 'person', id: '1' } - } - } - }, { - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + cars: { + data: [{ type: 'car', id: '1' }], + }, + }, }, - relationships: { - cars: { - data: [ - { type: 'car', id: '1' } - ] - } - } - }] + ], }); car = store.peekRecord('car', 1); person = store.peekRecord('person', 1); @@ -170,35 +167,63 @@ test("destroying the store correctly cleans everything up", function(assert) { { id: 2, type: 'person', - attributes: { name: 'Yehuda' } - } - ] + attributes: { name: 'Yehuda' }, + }, + ], }; }; - let adapterPopulatedPeople =run(() => { - return adapterPopulatedPeople = store.query('person', { - someCrazy: 'query' - }); + let adapterPopulatedPeople = run(() => { + return (adapterPopulatedPeople = store.query('person', { + someCrazy: 'query', + })); }); let adapterPopulatedPeopleWillDestroy = tap(adapterPopulatedPeople.get('content'), 'willDestroy'); run(() => store.findRecord('person', 2)); - assert.equal(personWillDestroy.called.length, 0, 'expected person.willDestroy to not have been called'); + assert.equal( + personWillDestroy.called.length, + 0, + 'expected person.willDestroy to not have been called' + ); assert.equal(carWillDestroy.called.length, 0, 'expected car.willDestroy to not have been called'); - assert.equal(carsWillDestroy.called.length, 0, 'expected cars.willDestroy to not have been called'); - assert.equal(adapterPopulatedPeopleWillDestroy.called.length, 0, 'expected adapterPopulatedPeople.willDestroy to not have been called'); + assert.equal( + carsWillDestroy.called.length, + 0, + 'expected cars.willDestroy to not have been called' + ); + assert.equal( + adapterPopulatedPeopleWillDestroy.called.length, + 0, + 'expected adapterPopulatedPeople.willDestroy to not have been called' + ); assert.equal(car.get('person'), person, "expected car's person to be the correct person"); - assert.equal(person.get('cars.firstObject'), car, " expected persons cars's firstRecord to be the correct car"); + assert.equal( + person.get('cars.firstObject'), + car, + " expected persons cars's firstRecord to be the correct car" + ); run(store, 'destroy'); - assert.equal(personWillDestroy.called.length, 1, 'expected person to have recieved willDestroy once'); + assert.equal( + personWillDestroy.called.length, + 1, + 'expected person to have recieved willDestroy once' + ); assert.equal(carWillDestroy.called.length, 1, 'expected car to recieve willDestroy once'); - assert.equal(carsWillDestroy.called.length, 1, 'expected person.cars to recieve willDestroy once'); - assert.equal(adapterPopulatedPeopleWillDestroy.called.length, 1, 'expected adapterPopulatedPeople to recieve willDestroy once'); + assert.equal( + carsWillDestroy.called.length, + 1, + 'expected person.cars to recieve willDestroy once' + ); + assert.equal( + adapterPopulatedPeopleWillDestroy.called.length, + 1, + 'expected adapterPopulatedPeople to recieve willDestroy once' + ); }); function ajaxResponse(value) { @@ -207,20 +232,22 @@ function ajaxResponse(value) { }; } -module("integration/store - findRecord"); +module('integration/store - findRecord'); -test("store#findRecord fetches record from server when cached record is not present", function(assert) { +test('store#findRecord fetches record from server when cached record is not present', function(assert) { assert.expect(2); initializeStore(DS.RESTAdapter.extend()); env.registry.register('serializer:application', DS.RESTSerializer); ajaxResponse({ - cars: [{ - id: 20, - make: 'BMC', - model: 'Mini' - }] + cars: [ + { + id: 20, + make: 'BMC', + model: 'Mini', + }, + ], }); let cachedRecordIsPresent = store.hasRecordForId('car', 20); @@ -233,7 +260,7 @@ test("store#findRecord fetches record from server when cached record is not pres }); }); -test("store#findRecord returns cached record immediately and reloads record in the background", function(assert) { +test('store#findRecord returns cached record immediately and reloads record in the background', function(assert) { assert.expect(2); initializeStore(DS.RESTAdapter.extend()); @@ -245,18 +272,20 @@ test("store#findRecord returns cached record immediately and reloads record in t id: '1', attributes: { make: 'BMC', - model: 'Mini' - } - } + model: 'Mini', + }, + }, }); }); ajaxResponse({ - cars: [{ - id: 1, - make: 'BMC', - model: 'Princess' - }] + cars: [ + { + id: 1, + make: 'BMC', + model: 'Princess', + }, + ], }); run(() => { @@ -271,13 +300,13 @@ test("store#findRecord returns cached record immediately and reloads record in t }); }); -test("store#findRecord { reload: true } ignores cached record and reloads record from server", function(assert) { +test('store#findRecord { reload: true } ignores cached record and reloads record from server', function(assert) { assert.expect(2); const testAdapter = DS.RESTAdapter.extend({ shouldReloadRecord(store, type, id, snapshot) { assert.ok(false, 'shouldReloadRecord should not be called when { reload: true }'); - } + }, }); initializeStore(testAdapter); @@ -289,18 +318,20 @@ test("store#findRecord { reload: true } ignores cached record and reloads record id: '1', attributes: { make: 'BMC', - model: 'Mini' - } - } + model: 'Mini', + }, + }, }); }); ajaxResponse({ - cars: [{ - id: 1, - make: 'BMC', - model: 'Princess' - }] + cars: [ + { + id: 1, + make: 'BMC', + model: 'Princess', + }, + ], }); let cachedCar = store.peekRecord('car', 1); @@ -308,13 +339,16 @@ test("store#findRecord { reload: true } ignores cached record and reloads record return run(() => { return store.findRecord('car', 1, { reload: true }).then(car => { - assert.equal(car.get('model'), 'Princess', 'cached record ignored, record reloaded via server'); + assert.equal( + car.get('model'), + 'Princess', + 'cached record ignored, record reloaded via server' + ); }); }); }); - -test("store#findRecord { reload: true } ignores cached record and reloads record from server even after previous findRecord", function(assert) { +test('store#findRecord { reload: true } ignores cached record and reloads record from server even after previous findRecord', function(assert) { assert.expect(5); let calls = 0; @@ -330,11 +364,11 @@ test("store#findRecord { reload: true } ignores cached record and reloads record id: '1', attributes: { make: 'BMC', - model: calls === 1 ? 'Mini' : 'Princess' - } - } + model: calls === 1 ? 'Mini' : 'Princess', + }, + }, }); - } + }, }); initializeStore(testAdapter); @@ -354,17 +388,20 @@ test("store#findRecord { reload: true } ignores cached record and reloads record assert.equal(car.get('model'), 'Princess', 'cached record ignored, record reloaded via server'); }); -test("store#findRecord { backgroundReload: false } returns cached record and does not reload in the background", function(assert) { +test('store#findRecord { backgroundReload: false } returns cached record and does not reload in the background', function(assert) { assert.expect(2); let testAdapter = DS.RESTAdapter.extend({ shouldBackgroundReloadRecord() { - assert.ok(false, 'shouldBackgroundReloadRecord should not be called when { backgroundReload: false }'); + assert.ok( + false, + 'shouldBackgroundReloadRecord should not be called when { backgroundReload: false }' + ); }, findRecord() { assert.ok(false, 'findRecord() should not be called when { backgroundReload: false }'); - } + }, }); initializeStore(testAdapter); @@ -376,14 +413,14 @@ test("store#findRecord { backgroundReload: false } returns cached record and doe id: '1', attributes: { make: 'BMC', - model: 'Mini' - } - } + model: 'Mini', + }, + }, }); }); run(() => { - store.findRecord('car', 1, { backgroundReload: false }).then((car) => { + store.findRecord('car', 1, { backgroundReload: false }).then(car => { assert.equal(car.get('model'), 'Mini', 'cached car record is returned'); }); }); @@ -394,13 +431,16 @@ test("store#findRecord { backgroundReload: false } returns cached record and doe }); }); -test("store#findRecord { backgroundReload: true } returns cached record and reloads record in background", function(assert) { +test('store#findRecord { backgroundReload: true } returns cached record and reloads record in background', function(assert) { assert.expect(2); let testAdapter = DS.RESTAdapter.extend({ shouldBackgroundReloadRecord() { - assert.ok(false, 'shouldBackgroundReloadRecord should not be called when { backgroundReload: true }'); - } + assert.ok( + false, + 'shouldBackgroundReloadRecord should not be called when { backgroundReload: true }' + ); + }, }); initializeStore(testAdapter); @@ -412,22 +452,24 @@ test("store#findRecord { backgroundReload: true } returns cached record and relo id: '1', attributes: { make: 'BMC', - model: 'Mini' - } - } + model: 'Mini', + }, + }, }); }); ajaxResponse({ - cars: [{ - id: 1, - make: 'BMC', - model: 'Princess' - }] + cars: [ + { + id: 1, + make: 'BMC', + model: 'Princess', + }, + ], }); run(() => { - store.findRecord('car', 1, { backgroundReload: true }).then((car) => { + store.findRecord('car', 1, { backgroundReload: true }).then(car => { assert.equal(car.get('model'), 'Mini', 'cached car record is returned'); }); }); @@ -438,7 +480,7 @@ test("store#findRecord { backgroundReload: true } returns cached record and relo }); }); -test("store#findRecord { backgroundReload: false } is ignored if adapter.shouldReloadRecord is true", function(assert) { +test('store#findRecord { backgroundReload: false } is ignored if adapter.shouldReloadRecord is true', function(assert) { assert.expect(2); let testAdapter = DS.RESTAdapter.extend({ @@ -447,8 +489,11 @@ test("store#findRecord { backgroundReload: false } is ignored if adapter.shouldR }, shouldBackgroundReloadRecord() { - assert.ok(false, 'shouldBackgroundReloadRecord should not be called when adapter.shouldReloadRecord = true'); - } + assert.ok( + false, + 'shouldBackgroundReloadRecord should not be called when adapter.shouldReloadRecord = true' + ); + }, }); initializeStore(testAdapter); @@ -460,18 +505,20 @@ test("store#findRecord { backgroundReload: false } is ignored if adapter.shouldR id: '1', attributes: { make: 'BMC', - model: 'Mini' - } - } + model: 'Mini', + }, + }, }); }); ajaxResponse({ - cars: [{ - id: 1, - make: 'BMC', - model: 'Princess' - }] + cars: [ + { + id: 1, + make: 'BMC', + model: 'Princess', + }, + ], }); run(() => { @@ -480,47 +527,56 @@ test("store#findRecord { backgroundReload: false } is ignored if adapter.shouldR }); run(() => { - store.findRecord('car', 1, { backgroundReload: false }).then((car) => { - assert.equal(car.get('model'), 'Princess', 'Car record is reloaded immediately (not in the background)'); + store.findRecord('car', 1, { backgroundReload: false }).then(car => { + assert.equal( + car.get('model'), + 'Princess', + 'Car record is reloaded immediately (not in the background)' + ); }); }); }); -testInDebug('store#findRecord call with `id` of type different than non-empty string or number should trigger an assertion', assert => { - const badValues = ['', undefined, null, NaN, false]; - assert.expect(badValues.length); +testInDebug( + 'store#findRecord call with `id` of type different than non-empty string or number should trigger an assertion', + assert => { + const badValues = ['', undefined, null, NaN, false]; + assert.expect(badValues.length); - initializeStore(DS.RESTAdapter.extend()); + initializeStore(DS.RESTAdapter.extend()); - run(() => { - badValues.map(item => { - assert.expectAssertion(() => { - store.findRecord('car', item); - }, '`id` passed to `findRecord()` has to be non-empty string or number'); + run(() => { + badValues.map(item => { + assert.expectAssertion(() => { + store.findRecord('car', item); + }, '`id` passed to `findRecord()` has to be non-empty string or number'); + }); }); - }); -}); + } +); -module("integration/store - findAll", { +module('integration/store - findAll', { beforeEach() { initializeStore(DS.RESTAdapter.extend()); - } + }, }); -test("Using store#findAll with no records triggers a query", function(assert) { +test('Using store#findAll with no records triggers a query', function(assert) { assert.expect(2); ajaxResponse({ - cars: [{ - id: 1, - make: 'BMC', - model: 'Mini' - }, - { - id: 2, - make: 'BMCW', - model: 'Isetta' - }] + cars: [ + { + id: 1, + make: 'BMC', + model: 'Mini', + }, + { + id: 2, + make: 'BMCW', + model: 'Isetta', + }, + ], }); let cars = store.peekAll('car'); @@ -533,7 +589,7 @@ test("Using store#findAll with no records triggers a query", function(assert) { }); }); -test("Using store#findAll with existing records performs a query in the background, updating existing records and returning new ones", function(assert) { +test('Using store#findAll with existing records performs a query in the background, updating existing records and returning new ones', function(assert) { assert.expect(4); run(() => { @@ -543,23 +599,25 @@ test("Using store#findAll with existing records performs a query in the backgrou id: '1', attributes: { make: 'BMC', - model: 'Mini' - } - } + model: 'Mini', + }, + }, }); }); ajaxResponse({ - cars: [{ - id: 1, - make: 'BMC', - model: 'New Mini' - }, - { - id: 2, - make: 'BMCW', - model: 'Isetta' - }] + cars: [ + { + id: 1, + make: 'BMC', + model: 'New Mini', + }, + { + id: 2, + make: 'BMCW', + model: 'Isetta', + }, + ], }); let cars = store.peekAll('car'); @@ -581,17 +639,20 @@ test("Using store#findAll with existing records performs a query in the backgrou return waiter; }); -test("store#findAll { backgroundReload: false } skips shouldBackgroundReloadAll, returns cached records & does not reload in the background", function(assert) { +test('store#findAll { backgroundReload: false } skips shouldBackgroundReloadAll, returns cached records & does not reload in the background', function(assert) { assert.expect(4); let testAdapter = DS.RESTAdapter.extend({ shouldBackgroundReloadAll() { - assert.ok(false, 'shouldBackgroundReloadAll should not be called when { backgroundReload: false }'); + assert.ok( + false, + 'shouldBackgroundReloadAll should not be called when { backgroundReload: false }' + ); }, findAll() { assert.ok(false, 'findAll() should not be called when { backgroundReload: true }'); - } + }, }); initializeStore(testAdapter); @@ -603,14 +664,14 @@ test("store#findAll { backgroundReload: false } skips shouldBackgroundReloadAll, id: '1', attributes: { make: 'BMC', - model: 'Mini' - } - } + model: 'Mini', + }, + }, }); }); run(() => { - store.findAll('car', { backgroundReload: false }).then((cars) => { + store.findAll('car', { backgroundReload: false }).then(cars => { assert.equal(cars.get('length'), 1, 'single cached car record is returned'); assert.equal(cars.get('firstObject.model'), 'Mini', 'correct cached car record is returned'); }); @@ -619,17 +680,24 @@ test("store#findAll { backgroundReload: false } skips shouldBackgroundReloadAll, run(() => { let cars = store.peekAll('car'); assert.equal(cars.get('length'), 1, 'single cached car record is returned again'); - assert.equal(cars.get('firstObject.model'), 'Mini', 'correct cached car record is returned again'); + assert.equal( + cars.get('firstObject.model'), + 'Mini', + 'correct cached car record is returned again' + ); }); }); -test("store#findAll { backgroundReload: true } skips shouldBackgroundReloadAll, returns cached records, & reloads in background", function(assert) { +test('store#findAll { backgroundReload: true } skips shouldBackgroundReloadAll, returns cached records, & reloads in background', function(assert) { assert.expect(5); let testAdapter = DS.RESTAdapter.extend({ shouldBackgroundReloadAll() { - assert.ok(false, 'shouldBackgroundReloadAll should not be called when { backgroundReload: true }'); - } + assert.ok( + false, + 'shouldBackgroundReloadAll should not be called when { backgroundReload: true }' + ); + }, }); initializeStore(testAdapter); @@ -641,27 +709,29 @@ test("store#findAll { backgroundReload: true } skips shouldBackgroundReloadAll, id: '1', attributes: { make: 'BMC', - model: 'Mini' - } - } + model: 'Mini', + }, + }, }); }); ajaxResponse({ - cars: [{ - id: 1, - make: 'BMC', - model: 'New Mini' - }, - { - id: 2, - make: 'BMCW', - model: 'Isetta' - }] + cars: [ + { + id: 1, + make: 'BMC', + model: 'New Mini', + }, + { + id: 2, + make: 'BMCW', + model: 'Isetta', + }, + ], }); run(() => { - store.findAll('car', { backgroundReload: true }).then((cars) => { + store.findAll('car', { backgroundReload: true }).then(cars => { assert.equal(cars.get('length'), 1, 'single cached car record is returned'); assert.equal(cars.get('firstObject.model'), 'Mini', 'correct cached car record is returned'); }); @@ -675,7 +745,7 @@ test("store#findAll { backgroundReload: true } skips shouldBackgroundReloadAll, }); }); -test("store#findAll { backgroundReload: false } is ignored if adapter.shouldReloadAll is true", function(assert) { +test('store#findAll { backgroundReload: false } is ignored if adapter.shouldReloadAll is true', function(assert) { assert.expect(5); let testAdapter = DS.RESTAdapter.extend({ @@ -684,8 +754,11 @@ test("store#findAll { backgroundReload: false } is ignored if adapter.shouldRelo }, shouldBackgroundReloadAll() { - assert.ok(false, 'shouldBackgroundReloadAll should not be called when adapter.shouldReloadAll = true'); - } + assert.ok( + false, + 'shouldBackgroundReloadAll should not be called when adapter.shouldReloadAll = true' + ); + }, }); initializeStore(testAdapter); @@ -697,23 +770,25 @@ test("store#findAll { backgroundReload: false } is ignored if adapter.shouldRelo id: '1', attributes: { make: 'BMC', - model: 'Mini' - } - } + model: 'Mini', + }, + }, }); }); ajaxResponse({ - cars: [{ - id: 1, - make: 'BMC', - model: 'New Mini' - }, - { - id: 2, - make: 'BMCW', - model: 'Isetta' - }] + cars: [ + { + id: 1, + make: 'BMC', + model: 'New Mini', + }, + { + id: 2, + make: 'BMCW', + model: 'Isetta', + }, + ], }); run(() => { @@ -723,7 +798,7 @@ test("store#findAll { backgroundReload: false } is ignored if adapter.shouldRelo }); return run(() => { - return store.findAll('car', { backgroundReload: false }).then((cars) => { + return store.findAll('car', { backgroundReload: false }).then(cars => { assert.equal(cars.get('length'), 2, 'multiple car records are returned'); assert.equal(cars.get('firstObject.model'), 'New Mini', 'initial car record was updated'); assert.equal(cars.get('lastObject.model'), 'Isetta', 'second car record was loaded'); @@ -731,35 +806,40 @@ test("store#findAll { backgroundReload: false } is ignored if adapter.shouldRelo }); }); -test("store#findAll should eventually return all known records even if they are not in the adapter response", function(assert) { +test('store#findAll should eventually return all known records even if they are not in the adapter response', function(assert) { assert.expect(5); run(() => { store.push({ - data: [{ - type: 'car', - id: '1', - attributes: { - make: 'BMC', - model: 'Mini' - } - }, { - type: 'car', - id: '2', - attributes: { - make: 'BMCW', - model: 'Isetta' - } - }] + data: [ + { + type: 'car', + id: '1', + attributes: { + make: 'BMC', + model: 'Mini', + }, + }, + { + type: 'car', + id: '2', + attributes: { + make: 'BMCW', + model: 'Isetta', + }, + }, + ], }); }); ajaxResponse({ - cars: [{ - id: 1, - make: 'BMC', - model: 'New Mini' - }] + cars: [ + { + id: 1, + make: 'BMC', + model: 'New Mini', + }, + ], }); let cars = store.peekAll('car'); @@ -786,16 +866,17 @@ test("store#findAll should eventually return all known records even if they are return waiter; }); - -test("Using store#fetch on an empty record calls find", function(assert) { +test('Using store#fetch on an empty record calls find', function(assert) { assert.expect(2); ajaxResponse({ - cars: [{ - id: 20, - make: 'BMCW', - model: 'Mini' - }] + cars: [ + { + id: 20, + make: 'BMCW', + model: 'Mini', + }, + ], }); run(() => { @@ -804,16 +885,14 @@ test("Using store#fetch on an empty record calls find", function(assert) { type: 'person', id: '1', attributes: { - name: 'Tom Dale' + name: 'Tom Dale', }, relationships: { cars: { - data: [ - { type: 'car', id: '20' } - ] - } - } - } + data: [{ type: 'car', id: '20' }], + }, + }, + }, }); }); @@ -827,7 +906,7 @@ test("Using store#fetch on an empty record calls find", function(assert) { }); }); -test("Using store#adapterFor should not throw an error when looking up the application adapter", function(assert) { +test('Using store#adapterFor should not throw an error when looking up the application adapter', function(assert) { assert.expect(1); run(() => { @@ -836,8 +915,7 @@ test("Using store#adapterFor should not throw an error when looking up the appli }); }); - -test("Using store#serializerFor should not throw an error when looking up the application serializer", function(assert) { +test('Using store#serializerFor should not throw an error when looking up the application serializer', function(assert) { assert.expect(1); run(() => { @@ -846,13 +924,13 @@ test("Using store#serializerFor should not throw an error when looking up the ap }); }); -module("integration/store - deleteRecord", { +module('integration/store - deleteRecord', { beforeEach() { initializeStore(DS.RESTAdapter.extend()); - } + }, }); -test("Using store#deleteRecord should mark the model for removal", function(assert) { +test('Using store#deleteRecord should mark the model for removal', function(assert) { assert.expect(3); let person; @@ -862,9 +940,9 @@ test("Using store#deleteRecord should mark the model for removal", function(asse type: 'person', id: '1', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); person = store.peekRecord('person', 1); }); @@ -875,26 +953,32 @@ test("Using store#deleteRecord should mark the model for removal", function(asse run(() => store.deleteRecord(person)); - assert.equal(personDeleteRecord.called.length, 1, 'expected person.deleteRecord to have been called'); + assert.equal( + personDeleteRecord.called.length, + 1, + 'expected person.deleteRecord to have been called' + ); assert.ok(person.get('isDeleted'), 'expect person to be isDeleted'); }); -test("Store should accept a null value for `data`", function(assert) { +test('Store should accept a null value for `data`', function(assert) { assert.expect(0); run(() => { store.push({ - data: null + data: null, }); }); }); testInDebug('store#findRecord that returns an array should assert', assert => { - initializeStore(DS.JSONAPIAdapter.extend({ - findRecord() { - return { data: [] }; - } - })); + initializeStore( + DS.JSONAPIAdapter.extend({ + findRecord() { + return { data: [] }; + }, + }) + ); assert.expectAssertion(() => { run(() => { @@ -903,98 +987,103 @@ testInDebug('store#findRecord that returns an array should assert', assert => { }, /expected the primary data returned from a 'findRecord' response to be an object but instead it found an array/); }); -testInDebug('store#didSaveRecord should assert when the response to a save does not include the id', function(assert) { - env.adapter.createRecord = function() { - return {}; - }; +testInDebug( + 'store#didSaveRecord should assert when the response to a save does not include the id', + function(assert) { + env.adapter.createRecord = function() { + return {}; + }; - assert.expectAssertion(() => { - run(() => { - let car = store.createRecord('car'); - car.save(); - }); - }, /Your car record was saved to the server, but the response does not have an id and no id has been set client side. Records must have ids. Please update the server response to provide an id in the response or generate the id on the client side either before saving the record or while normalizing the response./); -}); + assert.expectAssertion(() => { + run(() => { + let car = store.createRecord('car'); + car.save(); + }); + }, /Your car record was saved to the server, but the response does not have an id and no id has been set client side. Records must have ids. Please update the server response to provide an id in the response or generate the id on the client side either before saving the record or while normalizing the response./); + } +); -module("integration/store - queryRecord", { +module('integration/store - queryRecord', { beforeEach() { initializeStore(DS.Adapter.extend()); - } + }, }); -testInDebug('store#queryRecord should assert when normalized payload of adapter has an array an data', function(assert) { - env.adapter.queryRecord = function() { - return { - cars: [{ id: 1 }] +testInDebug( + 'store#queryRecord should assert when normalized payload of adapter has an array an data', + function(assert) { + env.adapter.queryRecord = function() { + return { + cars: [{ id: 1 }], + }; }; - }; - env.serializer.normalizeQueryRecordResponse = function() { - return { - data: [{ id: 1, type: 'car' }] + env.serializer.normalizeQueryRecordResponse = function() { + return { + data: [{ id: 1, type: 'car' }], + }; }; - }; - assert.expectAssertion(() => { - run(() => store.queryRecord('car', {})); - }, /Expected the primary data returned by the serializer for a 'queryRecord' response to be a single object or null but instead it was an array./); -}); + assert.expectAssertion(() => { + run(() => store.queryRecord('car', {})); + }, /Expected the primary data returned by the serializer for a 'queryRecord' response to be a single object or null but instead it was an array./); + } +); test('The store should trap exceptions that are thrown from adapter#findRecord', function(assert) { - assert.expect(1) + assert.expect(1); env.adapter.findRecord = function() { throw new Error('Refusing to find record'); }; run(() => { store.findRecord('car', 1).catch(error => { - assert.equal(error.message, 'Refusing to find record') - }) + assert.equal(error.message, 'Refusing to find record'); + }); }); }); test('The store should trap exceptions that are thrown from adapter#findAll', function(assert) { - assert.expect(1) + assert.expect(1); env.adapter.findAll = function() { throw new Error('Refusing to find all records'); }; run(() => { store.findAll('car').catch(error => { - assert.equal(error.message, 'Refusing to find all records') - }) + assert.equal(error.message, 'Refusing to find all records'); + }); }); }); test('The store should trap exceptions that are thrown from adapter#query', function(assert) { - assert.expect(1) + assert.expect(1); env.adapter.query = function() { throw new Error('Refusing to query records'); }; run(() => { store.query('car', {}).catch(error => { - assert.equal(error.message, 'Refusing to query records') - }) + assert.equal(error.message, 'Refusing to query records'); + }); }); }); test('The store should trap exceptions that are thrown from adapter#queryRecord', function(assert) { - assert.expect(1) + assert.expect(1); env.adapter.queryRecord = function() { throw new Error('Refusing to query record'); }; run(() => { store.queryRecord('car', {}).catch(error => { - assert.equal(error.message, 'Refusing to query record') - }) + assert.equal(error.message, 'Refusing to query record'); + }); }); }); - test('The store should trap exceptions that are thrown from adapter#createRecord', function(assert) { - assert.expect(1) + assert.expect(1); env.adapter.createRecord = function() { throw new Error('Refusing to serialize'); }; @@ -1003,7 +1092,7 @@ test('The store should trap exceptions that are thrown from adapter#createRecord let car = store.createRecord('car'); car.save().catch(error => { - assert.equal(error.message, 'Refusing to serialize') - }) + assert.equal(error.message, 'Refusing to serialize'); + }); }); }); diff --git a/tests/integration/store/json-api-validation-test.js b/tests/integration/store/json-api-validation-test.js index 09906f695b3..4728e67f92f 100644 --- a/tests/integration/store/json-api-validation-test.js +++ b/tests/integration/store/json-api-validation-test.js @@ -8,26 +8,36 @@ import DS from 'ember-data'; var Person, store, env; function payloadError(payload, expectedError, assert) { - env.registry.register('serializer:person', DS.Serializer.extend({ - normalizeResponse(store, type, pld) { - return pld; - } - })); - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord() { - return resolve(payload); - } - })); - this.expectAssertion(function () { - run(function() { - store.findRecord('person', 1); - }); - }, expectedError, `Payload ${JSON.stringify(payload)} should throw error ${expectedError}`); + env.registry.register( + 'serializer:person', + DS.Serializer.extend({ + normalizeResponse(store, type, pld) { + return pld; + }, + }) + ); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord() { + return resolve(payload); + }, + }) + ); + this.expectAssertion( + function() { + run(function() { + store.findRecord('person', 1); + }); + }, + expectedError, + `Payload ${JSON.stringify(payload)} should throw error ${expectedError}` + ); env.registry.unregister('serializer:person'); env.registry.unregister('adapter:person'); } -module("integration/store/json-validation", { +module('integration/store/json-validation', { beforeEach() { QUnit.assert.payloadError = payloadError.bind(QUnit.assert); @@ -35,159 +45,193 @@ module("integration/store/json-validation", { updatedAt: DS.attr('string'), name: DS.attr('string'), firstName: DS.attr('string'), - lastName: DS.attr('string') + lastName: DS.attr('string'), }); env = setupStore({ - person: Person + person: Person, }); store = env.store; }, afterEach() { - QUnit.assert.payloadError = null + QUnit.assert.payloadError = null; run(store, 'destroy'); - } -}); - -testInDebug("when normalizeResponse returns undefined (or doesn't return), throws an error", function(assert) { - - env.registry.register('serializer:person', DS.Serializer.extend({ - normalizeResponse() {} - })); - - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord() { - return resolve({ data: {} }); - } - })); - - assert.expectAssertion(function () { - run(function() { - store.findRecord('person', 1); - }); - }, /Top level of a JSON API document must be an object/); + }, }); -testInDebug("when normalizeResponse returns null, throws an error", function(assert) { - - env.registry.register('serializer:person', DS.Serializer.extend({ - normalizeResponse() {return null;} - })); - - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord() { - return resolve({ data: {} }); - } - })); - - assert.expectAssertion(function () { +testInDebug( + "when normalizeResponse returns undefined (or doesn't return), throws an error", + function(assert) { + env.registry.register( + 'serializer:person', + DS.Serializer.extend({ + normalizeResponse() {}, + }) + ); + + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord() { + return resolve({ data: {} }); + }, + }) + ); + + assert.expectAssertion(function() { + run(function() { + store.findRecord('person', 1); + }); + }, /Top level of a JSON API document must be an object/); + } +); + +testInDebug('when normalizeResponse returns null, throws an error', function(assert) { + env.registry.register( + 'serializer:person', + DS.Serializer.extend({ + normalizeResponse() { + return null; + }, + }) + ); + + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord() { + return resolve({ data: {} }); + }, + }) + ); + + assert.expectAssertion(function() { run(function() { store.findRecord('person', 1); }); }, /Top level of a JSON API document must be an object/); }); - -testInDebug("when normalizeResponse returns an empty object, throws an error", function(assert) { - - env.registry.register('serializer:person', DS.Serializer.extend({ - normalizeResponse() {return {};} - })); - - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord() { - return resolve({ data: {} }); - } - })); - - assert.expectAssertion(function () { +testInDebug('when normalizeResponse returns an empty object, throws an error', function(assert) { + env.registry.register( + 'serializer:person', + DS.Serializer.extend({ + normalizeResponse() { + return {}; + }, + }) + ); + + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord() { + return resolve({ data: {} }); + }, + }) + ); + + assert.expectAssertion(function() { run(function() { store.findRecord('person', 1); }); }, /One or more of the following keys must be present/); }); -testInDebug("when normalizeResponse returns a document with both data and errors, throws an error", function(assert) { - - env.registry.register('serializer:person', DS.Serializer.extend({ - normalizeResponse() { - return { - data: [], - errors: [] - }; - } - })); - - env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord() { - return resolve({ data: {} }); - } - })); - - assert.expectAssertion(function () { - run(function() { - store.findRecord('person', 1); - }); - }, /cannot both be present/); -}); - -testInDebug("normalizeResponse 'data' cannot be undefined, a number, a string or a boolean", function(assert) { - - assert.payloadError({ data: undefined }, /data must be/); - assert.payloadError({ data: 1 }, /data must be/); - assert.payloadError({ data: 'lollerskates' }, /data must be/); - assert.payloadError({ data: true }, /data must be/); -}); - -testInDebug("normalizeResponse 'meta' cannot be an array, undefined, a number, a string or a boolean", function(assert) { - - assert.payloadError({ meta: undefined }, /meta must be an object/); - assert.payloadError({ meta: [] }, /meta must be an object/); - assert.payloadError({ meta: 1 }, /meta must be an object/); - assert.payloadError({ meta: 'lollerskates' }, /meta must be an object/); - assert.payloadError({ meta: true }, /meta must be an object/); - -}); - -testInDebug("normalizeResponse 'links' cannot be an array, undefined, a number, a string or a boolean", function(assert) { - - assert.payloadError({ data: [], links: undefined }, /links must be an object/); - assert.payloadError({ data: [], links: [] }, /links must be an object/); - assert.payloadError({ data: [], links: 1 }, /links must be an object/); - assert.payloadError({ data: [], links: 'lollerskates' }, /links must be an object/); - assert.payloadError({ data: [], links: true }, /links must be an object/); - -}); - -testInDebug("normalizeResponse 'jsonapi' cannot be an array, undefined, a number, a string or a boolean", function(assert) { - - assert.payloadError({ data: [], jsonapi: undefined }, /jsonapi must be an object/); - assert.payloadError({ data: [], jsonapi: [] }, /jsonapi must be an object/); - assert.payloadError({ data: [], jsonapi: 1 }, /jsonapi must be an object/); - assert.payloadError({ data: [], jsonapi: 'lollerskates' }, /jsonapi must be an object/); - assert.payloadError({ data: [], jsonapi: true }, /jsonapi must be an object/); - -}); - -testInDebug("normalizeResponse 'included' cannot be an object, undefined, a number, a string or a boolean", function(assert) { - - assert.payloadError({ included: undefined }, /included must be an array/); - assert.payloadError({ included: {} }, /included must be an array/); - assert.payloadError({ included: 1 }, /included must be an array/); - assert.payloadError({ included: 'lollerskates' }, /included must be an array/); - assert.payloadError({ included: true }, /included must be an array/); - -}); - -testInDebug("normalizeResponse 'errors' cannot be an object, undefined, a number, a string or a boolean", function(assert) { - - assert.payloadError({ errors: undefined }, /errors must be an array/); - assert.payloadError({ errors: {} }, /errors must be an array/); - assert.payloadError({ errors: 1 }, /errors must be an array/); - assert.payloadError({ errors: 'lollerskates' }, /errors must be an array/); - assert.payloadError({ errors: true }, /errors must be an array/); - -}); - - +testInDebug( + 'when normalizeResponse returns a document with both data and errors, throws an error', + function(assert) { + env.registry.register( + 'serializer:person', + DS.Serializer.extend({ + normalizeResponse() { + return { + data: [], + errors: [], + }; + }, + }) + ); + + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord() { + return resolve({ data: {} }); + }, + }) + ); + + assert.expectAssertion(function() { + run(function() { + store.findRecord('person', 1); + }); + }, /cannot both be present/); + } +); + +testInDebug( + "normalizeResponse 'data' cannot be undefined, a number, a string or a boolean", + function(assert) { + assert.payloadError({ data: undefined }, /data must be/); + assert.payloadError({ data: 1 }, /data must be/); + assert.payloadError({ data: 'lollerskates' }, /data must be/); + assert.payloadError({ data: true }, /data must be/); + } +); + +testInDebug( + "normalizeResponse 'meta' cannot be an array, undefined, a number, a string or a boolean", + function(assert) { + assert.payloadError({ meta: undefined }, /meta must be an object/); + assert.payloadError({ meta: [] }, /meta must be an object/); + assert.payloadError({ meta: 1 }, /meta must be an object/); + assert.payloadError({ meta: 'lollerskates' }, /meta must be an object/); + assert.payloadError({ meta: true }, /meta must be an object/); + } +); + +testInDebug( + "normalizeResponse 'links' cannot be an array, undefined, a number, a string or a boolean", + function(assert) { + assert.payloadError({ data: [], links: undefined }, /links must be an object/); + assert.payloadError({ data: [], links: [] }, /links must be an object/); + assert.payloadError({ data: [], links: 1 }, /links must be an object/); + assert.payloadError({ data: [], links: 'lollerskates' }, /links must be an object/); + assert.payloadError({ data: [], links: true }, /links must be an object/); + } +); + +testInDebug( + "normalizeResponse 'jsonapi' cannot be an array, undefined, a number, a string or a boolean", + function(assert) { + assert.payloadError({ data: [], jsonapi: undefined }, /jsonapi must be an object/); + assert.payloadError({ data: [], jsonapi: [] }, /jsonapi must be an object/); + assert.payloadError({ data: [], jsonapi: 1 }, /jsonapi must be an object/); + assert.payloadError({ data: [], jsonapi: 'lollerskates' }, /jsonapi must be an object/); + assert.payloadError({ data: [], jsonapi: true }, /jsonapi must be an object/); + } +); + +testInDebug( + "normalizeResponse 'included' cannot be an object, undefined, a number, a string or a boolean", + function(assert) { + assert.payloadError({ included: undefined }, /included must be an array/); + assert.payloadError({ included: {} }, /included must be an array/); + assert.payloadError({ included: 1 }, /included must be an array/); + assert.payloadError({ included: 'lollerskates' }, /included must be an array/); + assert.payloadError({ included: true }, /included must be an array/); + } +); + +testInDebug( + "normalizeResponse 'errors' cannot be an object, undefined, a number, a string or a boolean", + function(assert) { + assert.payloadError({ errors: undefined }, /errors must be an array/); + assert.payloadError({ errors: {} }, /errors must be an array/); + assert.payloadError({ errors: 1 }, /errors must be an array/); + assert.payloadError({ errors: 'lollerskates' }, /errors must be an array/); + assert.payloadError({ errors: true }, /errors must be an array/); + } +); diff --git a/tests/integration/store/query-record-test.js b/tests/integration/store/query-record-test.js index b83aa9bfa69..1edff1cc00f 100644 --- a/tests/integration/store/query-record-test.js +++ b/tests/integration/store/query-record-test.js @@ -9,33 +9,33 @@ import DS from 'ember-data'; var Person, store, env; -module("integration/store/query-record - Query one record with a query hash", { +module('integration/store/query-record - Query one record with a query hash', { beforeEach() { Person = DS.Model.extend({ updatedAt: DS.attr('string'), name: DS.attr('string'), firstName: DS.attr('string'), - lastName: DS.attr('string') + lastName: DS.attr('string'), }); env = setupStore({ - person: Person + person: Person, }); store = env.store; }, afterEach() { run(store, 'destroy'); - } + }, }); -testInDebug("It raises an assertion when no type is passed", function(assert) { +testInDebug('It raises an assertion when no type is passed', function(assert) { assert.expectAssertion(function() { store.queryRecord(); }, "You need to pass a model name to the store's queryRecord method"); }); -testInDebug("It raises an assertion when no query hash is passed", function(assert) { +testInDebug('It raises an assertion when no query hash is passed', function(assert) { assert.expectAssertion(function() { store.queryRecord('person'); }, "You need to pass a query hash to the store's queryRecord method"); @@ -44,28 +44,34 @@ testInDebug("It raises an assertion when no query hash is passed", function(asse test("When a record is requested, the adapter's queryRecord method should be called.", function(assert) { assert.expect(1); - env.registry.register('adapter:person', DS.Adapter.extend({ - queryRecord(store, type, query) { - assert.equal(type, Person, "the query method is called with the correct type"); - return resolve({ data: { id: 1, type: 'person', attributes: { name: "Peter Wagenet" } } }); - } - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + queryRecord(store, type, query) { + assert.equal(type, Person, 'the query method is called with the correct type'); + return resolve({ data: { id: 1, type: 'person', attributes: { name: 'Peter Wagenet' } } }); + }, + }) + ); run(function() { store.queryRecord('person', { related: 'posts' }); }); }); -test("When a record is requested, and the promise is rejected, .queryRecord() is rejected.", function(assert) { - env.registry.register('adapter:person', DS.Adapter.extend({ - queryRecord(store, type, query) { - return reject(); - } - })); +test('When a record is requested, and the promise is rejected, .queryRecord() is rejected.', function(assert) { + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + queryRecord(store, type, query) { + return reject(); + }, + }) + ); run(function() { store.queryRecord('person', {}).catch(function(reason) { - assert.ok(true, "The rejection handler was called"); + assert.ok(true, 'The rejection handler was called'); }); }); }); @@ -73,26 +79,36 @@ test("When a record is requested, and the promise is rejected, .queryRecord() is test("When a record is requested, the serializer's normalizeQueryRecordResponse method should be called.", function(assert) { assert.expect(1); - env.registry.register('serializer:person', DS.JSONAPISerializer.extend({ - normalizeQueryRecordResponse(store, primaryModelClass, payload, id, requestType) { - assert.equal(payload.data.id , '1', "the normalizeQueryRecordResponse method was called with the right payload"); - return this._super(...arguments); - } - })); - - env.registry.register('adapter:person', DS.Adapter.extend({ - queryRecord(store, type, query) { - return resolve({ - data: { - id: '1', - type: 'person', - attributes: { - name: "Peter Wagenet" - } - } - }); - } - })); + env.registry.register( + 'serializer:person', + DS.JSONAPISerializer.extend({ + normalizeQueryRecordResponse(store, primaryModelClass, payload, id, requestType) { + assert.equal( + payload.data.id, + '1', + 'the normalizeQueryRecordResponse method was called with the right payload' + ); + return this._super(...arguments); + }, + }) + ); + + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + queryRecord(store, type, query) { + return resolve({ + data: { + id: '1', + type: 'person', + attributes: { + name: 'Peter Wagenet', + }, + }, + }); + }, + }) + ); run(function() { store.queryRecord('person', { related: 'posts' }); diff --git a/tests/integration/store/query-test.js b/tests/integration/store/query-test.js index 257c07944c6..911fa49706c 100644 --- a/tests/integration/store/query-test.js +++ b/tests/integration/store/query-test.js @@ -9,12 +9,12 @@ import DS from 'ember-data'; var Person, store, env; var run = Ember.run; -module("integration/store/query", { +module('integration/store/query', { beforeEach() { Person = DS.Model.extend(); env = setupStore({ - person: Person + person: Person, }); store = env.store; @@ -22,17 +22,20 @@ module("integration/store/query", { afterEach() { run(store, 'destroy'); - } + }, }); -test("meta is proxied correctly on the PromiseArray", function(assert) { +test('meta is proxied correctly on the PromiseArray', function(assert) { let defered = RSVP.defer(); - env.registry.register('adapter:person', DS.Adapter.extend({ - query(store, type, query) { - return defered.promise; - } - })); + env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + query(store, type, query) { + return defered.promise; + }, + }) + ); let result; run(function() { diff --git a/tests/test-helper.js b/tests/test-helper.js index 360c70df4f7..0966beb4885 100644 --- a/tests/test-helper.js +++ b/tests/test-helper.js @@ -2,18 +2,12 @@ import RSVP from 'rsvp'; import Application from '@ember/application'; import resolver from './helpers/resolver'; -import { - setResolver -} from '@ember/test-helpers'; +import { setResolver } from '@ember/test-helpers'; import { start } from 'ember-qunit'; import QUnit from 'qunit'; import DS from 'ember-data'; -import { - wait, - asyncEqual, - invokeAsync -} from 'dummy/tests/helpers/async'; +import { wait, asyncEqual, invokeAsync } from 'dummy/tests/helpers/async'; import loadInitializers from 'ember-load-initializers'; setResolver(resolver); @@ -22,9 +16,9 @@ loadInitializers(Application, 'dummy'); const { assert } = QUnit; const transforms = { boolean: DS.BooleanTransform.create(), - date: DS.DateTransform.create(), - number: DS.NumberTransform.create(), - string: DS.StringTransform.create() + date: DS.DateTransform.create(), + number: DS.NumberTransform.create(), + string: DS.StringTransform.create(), }; QUnit.begin(() => { @@ -41,32 +35,33 @@ QUnit.begin(() => { DS.JSONSerializer.reopen({ transformFor(attributeType) { return this._super(attributeType, true) || transforms[attributeType]; - } + }, }); - }); assert.wait = wait; assert.asyncEqual = asyncEqual; assert.invokeAsync = invokeAsync; assert.assertClean = function(promise) { - return promise.then(this.wait(record => { - this.equal(record.get('hasDirtyAttributes'), false, 'The record is now clean'); - return record; - })); + return promise.then( + this.wait(record => { + this.equal(record.get('hasDirtyAttributes'), false, 'The record is now clean'); + return record; + }) + ); }; assert.contains = function(array, item) { this.ok(array.indexOf(item) !== -1, `array contains ${item}`); }; -assert.without = function(array, item) { +assert.without = function(array, item) { this.ok(array.indexOf(item) === -1, `array doesn't contain ${item}`); }; QUnit.config.testTimeout = 2000; QUnit.config.urlConfig.push({ id: 'enableoptionalfeatures', - label: 'Enable Opt Features' + label: 'Enable Opt Features', }); start({ setupTestIsolationValidation: true }); diff --git a/tests/unit/adapter-errors-test.js b/tests/unit/adapter-errors-test.js index 738bec5a131..aac6600afe4 100644 --- a/tests/unit/adapter-errors-test.js +++ b/tests/unit/adapter-errors-test.js @@ -107,42 +107,42 @@ test('CustomAdapterError with default message', function(assert) { const errorsHash = { name: ['is invalid', 'must be a string'], - age: ['must be a number'] + age: ['must be a number'], }; const errorsArray = [ { title: 'Invalid Attribute', detail: 'is invalid', - source: { pointer: '/data/attributes/name' } + source: { pointer: '/data/attributes/name' }, }, { title: 'Invalid Attribute', detail: 'must be a string', - source: { pointer: '/data/attributes/name' } + source: { pointer: '/data/attributes/name' }, }, { title: 'Invalid Attribute', detail: 'must be a number', - source: { pointer: '/data/attributes/age' } - } + source: { pointer: '/data/attributes/age' }, + }, ]; const errorsPrimaryHash = { - base: ['is invalid', 'error message'] + base: ['is invalid', 'error message'], }; const errorsPrimaryArray = [ { title: 'Invalid Document', detail: 'is invalid', - source: { pointer: '/data' } + source: { pointer: '/data' }, }, { title: 'Invalid Document', detail: 'error message', - source: { pointer: '/data' } - } + source: { pointer: '/data' }, + }, ]; test('errorsHashToArray', function(assert) { @@ -164,8 +164,8 @@ test('errorsArrayToHash without trailing slash', function(assert) { let result = DS.errorsArrayToHash([ { detail: 'error message', - source: { pointer: 'data/attributes/name' } - } + source: { pointer: 'data/attributes/name' }, + }, ]); assert.deepEqual(result, { name: ['error message'] }); }); diff --git a/tests/unit/adapters/build-url-mixin/build-url-test.js b/tests/unit/adapters/build-url-mixin/build-url-test.js index cc7ce50d5f5..98fdacfb172 100644 --- a/tests/unit/adapters/build-url-mixin/build-url-test.js +++ b/tests/unit/adapters/build-url-mixin/build-url-test.js @@ -5,23 +5,25 @@ import { module, test } from 'qunit'; let adapter, env; -module("unit/adapters/build-url-mixin/build-url - DS.BuildURLMixin#buildURL", { +module('unit/adapters/build-url-mixin/build-url - DS.BuildURLMixin#buildURL', { beforeEach() { const customPathForType = { pathForType(type) { - if (type === 'rootModel') { return ''; } + if (type === 'rootModel') { + return ''; + } return this._super(type); - } + }, }; const Adapter = DS.Adapter.extend(DS.BuildURLMixin, customPathForType); env = setupStore({ - adapter: Adapter + adapter: Adapter, }); adapter = env.adapter; - } + }, }); test('buildURL - works with empty paths', function(assert) { diff --git a/tests/unit/adapters/build-url-mixin/path-for-type-test.js b/tests/unit/adapters/build-url-mixin/path-for-type-test.js index 1302a3bf9ee..701bb729787 100644 --- a/tests/unit/adapters/build-url-mixin/path-for-type-test.js +++ b/tests/unit/adapters/build-url-mixin/path-for-type-test.js @@ -6,21 +6,22 @@ import { module, test } from 'qunit'; let env, adapter; -module("unit/adapters/build-url-mixin/path-for-type - DS.BuildURLMixin#pathForType", { +module('unit/adapters/build-url-mixin/path-for-type - DS.BuildURLMixin#pathForType', { beforeEach() { - // test for overriden pathForType methods which return null path values let customPathForType = { pathForType(type) { - if (type === 'rootModel') { return ''; } + if (type === 'rootModel') { + return ''; + } return this._super(type); - } + }, }; let Adapter = DS.Adapter.extend(DS.BuildURLMixin, customPathForType); env = setupStore({ - adapter: Adapter + adapter: Adapter, }); adapter = env.adapter; @@ -28,7 +29,7 @@ module("unit/adapters/build-url-mixin/path-for-type - DS.BuildURLMixin#pathForTy afterEach() { run(env.container, 'destroy'); - } + }, }); test('pathForType - works with camelized types', function(assert) { diff --git a/tests/unit/adapters/json-api-adapter/ajax-test.js b/tests/unit/adapters/json-api-adapter/ajax-test.js index 94b9036a307..8d39cf67ea7 100644 --- a/tests/unit/adapters/json-api-adapter/ajax-test.js +++ b/tests/unit/adapters/json-api-adapter/ajax-test.js @@ -7,7 +7,7 @@ import DS from 'ember-data'; let Person, Place, store, adapter, env; -module("unit/adapters/json-api-adapter/ajax - building requests", { +module('unit/adapters/json-api-adapter/ajax - building requests', { beforeEach() { Person = { modelName: 'person' }; Place = { modelName: 'place' }; @@ -21,7 +21,7 @@ module("unit/adapters/json-api-adapter/ajax - building requests", { store.destroy(); env.container.destroy(); }); - } + }, }); test('ajaxOptions() adds Accept when no other headers exist', function(assert) { @@ -32,7 +32,7 @@ test('ajaxOptions() adds Accept when no other headers exist', function(assert) { let fakeXHR = { setRequestHeader(key, value) { receivedHeaders.push([key, value]); - } + }, }; ajaxOptions.beforeSend(fakeXHR); assert.deepEqual(receivedHeaders, [['Accept', 'application/vnd.api+json']], 'headers assigned'); @@ -47,10 +47,14 @@ test('ajaxOptions() adds Accept header to existing headers', function(assert) { let fakeXHR = { setRequestHeader(key, value) { receivedHeaders.push([key, value]); - } + }, }; ajaxOptions.beforeSend(fakeXHR); - assert.deepEqual(receivedHeaders, [['Accept', 'application/vnd.api+json'], ['Other-key', 'Other Value']], 'headers assigned'); + assert.deepEqual( + receivedHeaders, + [['Accept', 'application/vnd.api+json'], ['Other-key', 'Other Value']], + 'headers assigned' + ); }); test('ajaxOptions() adds Accept header to existing computed properties headers', function(assert) { @@ -62,8 +66,12 @@ test('ajaxOptions() adds Accept header to existing computed properties headers', let fakeXHR = { setRequestHeader(key, value) { receivedHeaders.push([key, value]); - } + }, }; ajaxOptions.beforeSend(fakeXHR); - assert.deepEqual(receivedHeaders, [['Accept', 'application/vnd.api+json'], ['Other-key', 'Other Value']], 'headers assigned'); + assert.deepEqual( + receivedHeaders, + [['Accept', 'application/vnd.api+json'], ['Other-key', 'Other Value']], + 'headers assigned' + ); }); diff --git a/tests/unit/adapters/rest-adapter/ajax-test.js b/tests/unit/adapters/rest-adapter/ajax-test.js index 285707123e3..f8f82b9e53d 100644 --- a/tests/unit/adapters/rest-adapter/ajax-test.js +++ b/tests/unit/adapters/rest-adapter/ajax-test.js @@ -22,7 +22,7 @@ module('unit/adapters/rest-adapter/ajax - building requests', { store.destroy(); env.container.destroy(); }); - } + }, }); test('When an id is searched, the correct url should be generated', function(assert) { @@ -31,8 +31,12 @@ test('When an id is searched, the correct url should be generated', function(ass let count = 0; adapter.ajax = function(url, method) { - if (count === 0) { assert.equal(url, '/people/1', 'should create the correct url'); } - if (count === 1) { assert.equal(url, '/places/1', 'should create the correct url'); } + if (count === 0) { + assert.equal(url, '/people/1', 'should create the correct url'); + } + if (count === 1) { + assert.equal(url, '/places/1', 'should create the correct url'); + } count++; return resolve(); }; @@ -40,7 +44,7 @@ test('When an id is searched, the correct url should be generated', function(ass return run(() => { return EmberPromise.all([ adapter.findRecord(store, Person, 1, {}), - adapter.findRecord(store, Place, 1, {}) + adapter.findRecord(store, Place, 1, {}), ]); }); }); @@ -49,7 +53,7 @@ test(`id's should be sanatized`, function(assert) { assert.expect(1); adapter.ajax = function(url, method) { - assert.equal(url, '/people/..%2Fplace%2F1', "should create the correct url"); + assert.equal(url, '/people/..%2Fplace%2F1', 'should create the correct url'); return resolve(); }; @@ -59,7 +63,7 @@ test(`id's should be sanatized`, function(assert) { test('ajaxOptions() headers are set', function(assert) { adapter.headers = { 'Content-Type': 'application/json', - 'Other-key': 'Other Value' + 'Other-key': 'Other Value', }; let url = 'example.com'; @@ -69,13 +73,14 @@ test('ajaxOptions() headers are set', function(assert) { let fakeXHR = { setRequestHeader(key, value) { receivedHeaders.push([key, value]); - } + }, }; ajaxOptions.beforeSend(fakeXHR); - assert.deepEqual(receivedHeaders, [ - ['Content-Type', 'application/json'], - ['Other-key', 'Other Value'] - ], 'headers assigned'); + assert.deepEqual( + receivedHeaders, + [['Content-Type', 'application/json'], ['Other-key', 'Other Value']], + 'headers assigned' + ); }); test('ajaxOptions() do not serializes data when GET', function(assert) { @@ -86,11 +91,11 @@ test('ajaxOptions() do not serializes data when GET', function(assert) { assert.deepEqual(ajaxOptions, { context: adapter, data: { - key: 'value' + key: 'value', }, dataType: 'json', type: 'GET', - url: 'example.com' + url: 'example.com', }); }); @@ -105,7 +110,7 @@ test('ajaxOptions() serializes data when not GET', function(assert) { data: '{"key":"value"}', dataType: 'json', type: 'POST', - url: 'example.com' + url: 'example.com', }); }); @@ -118,6 +123,6 @@ test('ajaxOptions() empty data', function(assert) { context: adapter, dataType: 'json', type: 'POST', - url: 'example.com' + url: 'example.com', }); }); diff --git a/tests/unit/adapters/rest-adapter/detailed-message-test.js b/tests/unit/adapters/rest-adapter/detailed-message-test.js index cef3e9b4c6d..195c24b34de 100644 --- a/tests/unit/adapters/rest-adapter/detailed-message-test.js +++ b/tests/unit/adapters/rest-adapter/detailed-message-test.js @@ -6,31 +6,37 @@ import DS from 'ember-data'; let adapter, env; -module('unit/adapters/rest_adapter/detailed_message_test - DS.RESTAdapter#generatedDetailedMessage', { - beforeEach() { - env = setupStore({ adapter: DS.RESTAdapter }); - adapter = env.adapter; +module( + 'unit/adapters/rest_adapter/detailed_message_test - DS.RESTAdapter#generatedDetailedMessage', + { + beforeEach() { + env = setupStore({ adapter: DS.RESTAdapter }); + adapter = env.adapter; + }, } -}); +); test('generating a wonderfully friendly error message should work', function(assert) { assert.expect(1); let friendlyMessage = adapter.generatedDetailedMessage( 418, - { "Content-Type": "text/plain" }, + { 'Content-Type': 'text/plain' }, "I'm a little teapot, short and stout", { - url: "/teapots/testing", - method: "GET" + url: '/teapots/testing', + method: 'GET', } ); - assert.equal(friendlyMessage, [ - 'Ember Data Request GET /teapots/testing returned a 418', - 'Payload (text/plain)', - `I'm a little teapot, short and stout` - ].join('\n')); + assert.equal( + friendlyMessage, + [ + 'Ember Data Request GET /teapots/testing returned a 418', + 'Payload (text/plain)', + `I'm a little teapot, short and stout`, + ].join('\n') + ); }); test('generating a friendly error message with a missing content-type header should work', function(assert) { @@ -40,13 +46,16 @@ test('generating a friendly error message with a missing content-type header sho `I'm a little teapot, short and stout`, { url: '/teapots/testing', - method: 'GET' + method: 'GET', } ); - assert.equal(friendlyMessage, [ - 'Ember Data Request GET /teapots/testing returned a 418', - 'Payload (Empty Content-Type)', - `I'm a little teapot, short and stout` - ].join('\n')); + assert.equal( + friendlyMessage, + [ + 'Ember Data Request GET /teapots/testing returned a 418', + 'Payload (Empty Content-Type)', + `I'm a little teapot, short and stout`, + ].join('\n') + ); }); diff --git a/tests/unit/adapters/rest-adapter/group-records-for-find-many-test.js b/tests/unit/adapters/rest-adapter/group-records-for-find-many-test.js index 981005ea274..083f04929e6 100644 --- a/tests/unit/adapters/rest-adapter/group-records-for-find-many-test.js +++ b/tests/unit/adapters/rest-adapter/group-records-for-find-many-test.js @@ -10,50 +10,54 @@ let GroupsAdapter, store, requests; let maxLength; let lengths; -module('unit/adapters/rest_adapter/group_records_for_find_many_test - DS.RESTAdapter#groupRecordsForFindMany', { - beforeEach() { - maxLength = -1; - requests = []; - lengths = []; - - GroupsAdapter = DS.RESTAdapter.extend({ - - coalesceFindRequests: true, - - findRecord(store, type, id, snapshot) { - return { id }; - } - }); - - GroupsAdapter.reopen({ - ajax(url, type, options) { - requests.push({ - url, - ids: options.data.ids - }); - - let queryString = options.data.ids.map(i => { - return encodeURIComponent('ids[]') + '=' + encodeURIComponent(i); - }).join('&'); - let fullUrl = url + '?' + queryString; - - maxLength = this.get('maxURLLength'); - lengths.push(fullUrl.length); - - let testRecords = options.data.ids.map(id => ({ id })); - return EmberPromise.resolve({ 'testRecords' : testRecords }); - } - }); - - store = createStore({ - adapter: GroupsAdapter, - testRecord: DS.Model.extend() - }); - }, - afterEach() { - run(store, 'destroy'); +module( + 'unit/adapters/rest_adapter/group_records_for_find_many_test - DS.RESTAdapter#groupRecordsForFindMany', + { + beforeEach() { + maxLength = -1; + requests = []; + lengths = []; + + GroupsAdapter = DS.RESTAdapter.extend({ + coalesceFindRequests: true, + + findRecord(store, type, id, snapshot) { + return { id }; + }, + }); + + GroupsAdapter.reopen({ + ajax(url, type, options) { + requests.push({ + url, + ids: options.data.ids, + }); + + let queryString = options.data.ids + .map(i => { + return encodeURIComponent('ids[]') + '=' + encodeURIComponent(i); + }) + .join('&'); + let fullUrl = url + '?' + queryString; + + maxLength = this.get('maxURLLength'); + lengths.push(fullUrl.length); + + let testRecords = options.data.ids.map(id => ({ id })); + return EmberPromise.resolve({ testRecords: testRecords }); + }, + }); + + store = createStore({ + adapter: GroupsAdapter, + testRecord: DS.Model.extend(), + }); + }, + afterEach() { + run(store, 'destroy'); + }, } -}); +); test('groupRecordsForFindMany - findMany', function(assert) { let wait = []; @@ -82,7 +86,7 @@ test('groupRecordsForFindMany works for encodeURIComponent-ified ids', function( }); test('_stripIDFromURL works with id being encoded - #4190', function(assert) { - let record = store.createRecord('testRecord', { id: "id:123" }); + let record = store.createRecord('testRecord', { id: 'id:123' }); let adapter = store.adapterFor('testRecord'); let snapshot = record._internalModel.createSnapshot(); let strippedUrl = adapter._stripIDFromURL(store, snapshot); diff --git a/tests/unit/debug-test.js b/tests/unit/debug-test.js index fe44fb27660..937ced7dbf9 100644 --- a/tests/unit/debug-test.js +++ b/tests/unit/debug-test.js @@ -11,25 +11,25 @@ module('Debug'); test('_debugInfo groups the attributes and relationships correctly', function(assert) { const MaritalStatus = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const Post = DS.Model.extend({ - title: DS.attr('string') + title: DS.attr('string'), }); const User = DS.Model.extend({ name: DS.attr('string'), isDrugAddict: DS.attr('boolean'), maritalStatus: DS.belongsTo('marital-status', { async: false }), - posts: DS.hasMany('post', { async: false }) + posts: DS.hasMany('post', { async: false }), }); let store = createStore({ adapter: TestAdapter.extend(), maritalStatus: MaritalStatus, post: Post, - user: User + user: User, }); let record = store.createRecord('user'); @@ -44,32 +44,33 @@ test('_debugInfo groups the attributes and relationships correctly', function(as test('_debugInfo supports arbitray relationship types', function(assert) { const MaritalStatus = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const Post = DS.Model.extend({ - title: DS.attr('string') + title: DS.attr('string'), }); const User = DS.Model.extend({ name: DS.attr('string'), isDrugAddict: DS.attr('boolean'), maritalStatus: DS.belongsTo('marital-status', { async: false }), - posts: computed(() => [1, 2, 3] ) - .readOnly().meta({ - options: { inverse: null }, - isRelationship: true, - kind: 'customRelationship', - name: 'posts', - type: 'post' - }) + posts: computed(() => [1, 2, 3]) + .readOnly() + .meta({ + options: { inverse: null }, + isRelationship: true, + kind: 'customRelationship', + name: 'posts', + type: 'post', + }), }); let store = createStore({ adapter: TestAdapter.extend(), maritalStatus: MaritalStatus, post: Post, - user: User + user: User, }); let record = store.createRecord('user'); @@ -81,26 +82,18 @@ test('_debugInfo supports arbitray relationship types', function(assert) { groups: [ { name: 'Attributes', - properties: [ - 'id', - 'name', - 'isDrugAddict' - ], - expand: true + properties: ['id', 'name', 'isDrugAddict'], + expand: true, }, { name: 'maritalStatus', - properties: [ - 'maritalStatus' - ], - expand: true + properties: ['maritalStatus'], + expand: true, }, { name: 'posts', - properties: [ - 'posts' - ], - expand: true + properties: ['posts'], + expand: true, }, { name: 'Flags', @@ -111,13 +104,10 @@ test('_debugInfo supports arbitray relationship types', function(assert) { 'isDeleted', 'isError', 'isNew', - 'isValid' - ] - } + 'isValid', + ], + }, ], - expensiveProperties: [ - 'maritalStatus', - 'posts' - ] - }) + expensiveProperties: ['maritalStatus', 'posts'], + }); }); diff --git a/tests/unit/diff-array-test.js b/tests/unit/diff-array-test.js index a226a2ffd07..791c710fc56 100644 --- a/tests/unit/diff-array-test.js +++ b/tests/unit/diff-array-test.js @@ -2,21 +2,20 @@ import { module, test } from 'qunit'; import { diffArray } from 'ember-data/-private'; -module('unit/diff-array Diff Array tests', { -}); - -const a = "aaa"; -const b = "bbb"; -const c = "ccc"; -const d = "ddd"; -const e = "eee"; -const f = "fff"; -const g = "ggg"; -const h = "hhh"; -const w = "www"; -const x = "xxx"; -const y = "yyy"; -const z = "zzz"; +module('unit/diff-array Diff Array tests', {}); + +const a = 'aaa'; +const b = 'bbb'; +const c = 'ccc'; +const d = 'ddd'; +const e = 'eee'; +const f = 'fff'; +const g = 'ggg'; +const h = 'hhh'; +const w = 'www'; +const x = 'xxx'; +const y = 'yyy'; +const z = 'zzz'; test('diff array returns no change given two empty arrays', function(assert) { const result = diffArray([], []); @@ -33,7 +32,7 @@ test('diff array returns no change given two identical arrays length 1', functio }); test('diff array returns no change given two identical arrays length 3', function(assert) { - const result = diffArray([a,b,c], [a,b,c]); + const result = diffArray([a, b, c], [a, b, c]); assert.strictEqual(result.firstChangeIndex, null); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 0); @@ -47,35 +46,35 @@ test('diff array returns correctly given one appended item with old length 0', f }); test('diff array returns correctly given one appended item with old length 1', function(assert) { - const result = diffArray([a], [a,b]); + const result = diffArray([a], [a, b]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 0); }); test('diff array returns correctly given one appended item with old length 2', function(assert) { - const result = diffArray([a,b], [a,b,c]); + const result = diffArray([a, b], [a, b, c]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 0); }); test('diff array returns correctly given 3 appended items with old length 0', function(assert) { - const result = diffArray([], [a,b,c]); + const result = diffArray([], [a, b, c]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 0); }); test('diff array returns correctly given 3 appended items with old length 1', function(assert) { - const result = diffArray([a], [a,b,c,d]); + const result = diffArray([a], [a, b, c, d]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 0); }); test('diff array returns correctly given 3 appended items with old length 2', function(assert) { - const result = diffArray([a,b], [a,b,c,d,e]); + const result = diffArray([a, b], [a, b, c, d, e]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 0); @@ -89,119 +88,119 @@ test('diff array returns correctly given one item removed from end with old leng }); test('diff array returns correctly given one item removed from end with old length 2', function(assert) { - const result = diffArray([a,b], [a]); + const result = diffArray([a, b], [a]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given one item removed from end with old length 3', function(assert) { - const result = diffArray([a,b,c], [a,b]); + const result = diffArray([a, b, c], [a, b]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given 3 items removed from end with old length 3', function(assert) { - const result = diffArray([a,b,c], []); + const result = diffArray([a, b, c], []); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items removed from end with old length 4', function(assert) { - const result = diffArray([a,b,c,d], [a]); + const result = diffArray([a, b, c, d], [a]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items removed from end with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [a,b]); + const result = diffArray([a, b, c, d, e], [a, b]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given one item removed from beginning with old length 2', function(assert) { - const result = diffArray([a,b], [b]); + const result = diffArray([a, b], [b]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given one item removed from beginning with old length 3', function(assert) { - const result = diffArray([a,b,c], [b,c]); + const result = diffArray([a, b, c], [b, c]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given 3 items removed from beginning with old length 4', function(assert) { - const result = diffArray([a,b,c,d], [d]); + const result = diffArray([a, b, c, d], [d]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items removed from beginning with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [d,e]); + const result = diffArray([a, b, c, d, e], [d, e]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given one item removed from middle with old length 3', function(assert) { - const result = diffArray([a,b,c], [a,c]); + const result = diffArray([a, b, c], [a, c]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given one item removed from middle with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [a,b,d,e]); + const result = diffArray([a, b, c, d, e], [a, b, d, e]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given 3 items removed from middle with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [a,e]); + const result = diffArray([a, b, c, d, e], [a, e]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items removed from middle with old length 7', function(assert) { - const result = diffArray([a,b,c,d,e,f,g], [a,b,f,g]); + const result = diffArray([a, b, c, d, e, f, g], [a, b, f, g]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 0); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given one item added to middle with old length 2', function(assert) { - const result = diffArray([a,c], [a,b,c]); + const result = diffArray([a, c], [a, b, c]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 0); }); test('diff array returns correctly given one item added to middle with old length 4', function(assert) { - const result = diffArray([a,b,d,e], [a,b,c,d,e]); + const result = diffArray([a, b, d, e], [a, b, c, d, e]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 0); }); test('diff array returns correctly given 3 items added to middle with old length 2', function(assert) { - const result = diffArray([a,e], [a,b,c,d,e]); + const result = diffArray([a, e], [a, b, c, d, e]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 0); }); test('diff array returns correctly given 3 items added to middle with old length 4', function(assert) { - const result = diffArray([a,b,f,g], [a,b,c,d,e,f,g]); + const result = diffArray([a, b, f, g], [a, b, c, d, e, f, g]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 0); @@ -215,273 +214,273 @@ test('diff array returns correctly given complete replacement with length 1', fu }); test('diff array returns correctly given complete replacement with length 3', function(assert) { - const result = diffArray([a,b,c], [x,y,z]); + const result = diffArray([a, b, c], [x, y, z]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given complete replacement with longer length', function(assert) { - const result = diffArray([a,b], [x,y,z]); + const result = diffArray([a, b], [x, y, z]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 2); }); test('diff array returns correctly given one item replaced in middle with old length 3', function(assert) { - const result = diffArray([a,b,c], [a,x,c]); + const result = diffArray([a, b, c], [a, x, c]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given one item replaced in middle with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [a,b,x,d,e]); + const result = diffArray([a, b, c, d, e], [a, b, x, d, e]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given 3 items replaced in middle with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [a,x,y,z,e]); + const result = diffArray([a, b, c, d, e], [a, x, y, z, e]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items replaced in middle with old length 7', function(assert) { - const result = diffArray([a,b,c,d,e,f,g], [a,b,x,y,z,f,g]); + const result = diffArray([a, b, c, d, e, f, g], [a, b, x, y, z, f, g]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given one item replaced at beginning with old length 2', function(assert) { - const result = diffArray([a,b], [x,b]); + const result = diffArray([a, b], [x, b]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given one item replaced at beginning with old length 3', function(assert) { - const result = diffArray([a,b,c], [x,b,c]); + const result = diffArray([a, b, c], [x, b, c]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given 3 items replaced at beginning with old length 4', function(assert) { - const result = diffArray([a,b,c,d], [x,y,z,d]); + const result = diffArray([a, b, c, d], [x, y, z, d]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items replaced at beginning with old length 6', function(assert) { - const result = diffArray([a,b,c,d,e,f], [x,y,z,d,e,f]); + const result = diffArray([a, b, c, d, e, f], [x, y, z, d, e, f]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given one item replaced at end with old length 2', function(assert) { - const result = diffArray([a,b], [a,x]); + const result = diffArray([a, b], [a, x]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given one item replaced at end with old length 3', function(assert) { - const result = diffArray([a,b,c], [a,b,x]); + const result = diffArray([a, b, c], [a, b, x]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given 3 items replaced at end with old length 4', function(assert) { - const result = diffArray([a,b,c,d], [a,x,y,z]); + const result = diffArray([a, b, c, d], [a, x, y, z]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items replaced at end with old length 6', function(assert) { - const result = diffArray([a,b,c,d,e,f], [a,b,c,x,y,z]); + const result = diffArray([a, b, c, d, e, f], [a, b, c, x, y, z]); assert.equal(result.firstChangeIndex, 3); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given one item replaced with two in middle with old length 3', function(assert) { - const result = diffArray([a,b,c], [a,x,y,c]); + const result = diffArray([a, b, c], [a, x, y, c]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 2); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given one item replaced with two in middle with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [a,b,x,y,d,e]); + const result = diffArray([a, b, c, d, e], [a, b, x, y, d, e]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 2); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given 3 items replaced with 4 in middle with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [a,w,x,y,z,e]); + const result = diffArray([a, b, c, d, e], [a, w, x, y, z, e]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 4); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items replaced with 4 in middle with old length 7', function(assert) { - const result = diffArray([a,b,c,d,e,f,g], [a,b,w,x,y,z,f,g]); + const result = diffArray([a, b, c, d, e, f, g], [a, b, w, x, y, z, f, g]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 4); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given one item replaced with two at beginning with old length 2', function(assert) { - const result = diffArray([a,b], [x,y,b]); + const result = diffArray([a, b], [x, y, b]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 2); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given one item replaced with two at beginning with old length 3', function(assert) { - const result = diffArray([a,b,c], [x,y,b,c]); + const result = diffArray([a, b, c], [x, y, b, c]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 2); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given 3 items replaced with 4 at beginning with old length 4', function(assert) { - const result = diffArray([a,b,c,d], [w,x,y,z,d]); + const result = diffArray([a, b, c, d], [w, x, y, z, d]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 4); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items replaced with 4 at beginning with old length 6', function(assert) { - const result = diffArray([a,b,c,d,e,f], [w,x,y,z,d,e,f]); + const result = diffArray([a, b, c, d, e, f], [w, x, y, z, d, e, f]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 4); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given one item replaced with two at end with old length 2', function(assert) { - const result = diffArray([a,b], [a,x,y]); + const result = diffArray([a, b], [a, x, y]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 2); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given one item replaced with two at end with old length 3', function(assert) { - const result = diffArray([a,b,c], [a,b,x,y]); + const result = diffArray([a, b, c], [a, b, x, y]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 2); assert.equal(result.removedCount, 1); }); test('diff array returns correctly given 3 items replaced with 4 at end with old length 4', function(assert) { - const result = diffArray([a,b,c,d], [a,w,x,y,z]); + const result = diffArray([a, b, c, d], [a, w, x, y, z]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 4); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given 3 items replaced with 4 at end with old length 6', function(assert) { - const result = diffArray([a,b,c,d,e,f], [a,b,c,w,x,y,z]); + const result = diffArray([a, b, c, d, e, f], [a, b, c, w, x, y, z]); assert.equal(result.firstChangeIndex, 3); assert.equal(result.addedCount, 4); assert.equal(result.removedCount, 3); }); test('diff array returns correctly given two items replaced with one in middle with old length 4', function(assert) { - const result = diffArray([a,b,c,d], [a,x,d]); + const result = diffArray([a, b, c, d], [a, x, d]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 2); }); test('diff array returns correctly given two items replaced with one in middle with old length 6', function(assert) { - const result = diffArray([a,b,c,d,e,f], [a,b,x,e,f]); + const result = diffArray([a, b, c, d, e, f], [a, b, x, e, f]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 2); }); test('diff array returns correctly given 4 items replaced with 3 in middle with old length 6', function(assert) { - const result = diffArray([a,b,c,d,e,f], [a,x,y,z,f]); + const result = diffArray([a, b, c, d, e, f], [a, x, y, z, f]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 4); }); test('diff array returns correctly given 4 items replaced with 3 in middle with old length 8', function(assert) { - const result = diffArray([a,b,c,d,e,f,g,h], [a,b,x,y,z,g,h]); + const result = diffArray([a, b, c, d, e, f, g, h], [a, b, x, y, z, g, h]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 4); }); test('diff array returns correctly given two items replaced with one at beginning with old length 3', function(assert) { - const result = diffArray([a,b,c], [x,c]); + const result = diffArray([a, b, c], [x, c]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 2); }); test('diff array returns correctly given two items replaced with one at beginning with old length 4', function(assert) { - const result = diffArray([a,b,c,d], [x,c,d]); + const result = diffArray([a, b, c, d], [x, c, d]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 2); }); test('diff array returns correctly given 4 items replaced with 3 at beginning with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [x,y,z,e]); + const result = diffArray([a, b, c, d, e], [x, y, z, e]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 4); }); test('diff array returns correctly given 4 items replaced with 3 at beginning with old length 6', function(assert) { - const result = diffArray([a,b,c,d,e,f], [x,y,z,e,f]); + const result = diffArray([a, b, c, d, e, f], [x, y, z, e, f]); assert.equal(result.firstChangeIndex, 0); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 4); }); test('diff array returns correctly given two items replaced with one at end with old length 3', function(assert) { - const result = diffArray([a,b,c], [a,x]); + const result = diffArray([a, b, c], [a, x]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 2); }); test('diff array returns correctly given two items replaced with one at end with old length 4', function(assert) { - const result = diffArray([a,b,c,d], [a,b,x]); + const result = diffArray([a, b, c, d], [a, b, x]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 1); assert.equal(result.removedCount, 2); }); test('diff array returns correctly given 4 items replaced with 3 at end with old length 5', function(assert) { - const result = diffArray([a,b,c,d,e], [a,x,y,z]); + const result = diffArray([a, b, c, d, e], [a, x, y, z]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 4); }); test('diff array returns correctly given 4 items replaced with 3 at end with old length 6', function(assert) { - const result = diffArray([a,b,c,d,e,f], [a,b,x,y,z]); + const result = diffArray([a, b, c, d, e, f], [a, b, x, y, z]); assert.equal(result.firstChangeIndex, 2); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 4); }); test('diff array returns correctly given non-contiguous insertion', function(assert) { - const result = diffArray([a,c,e], [a,b,c,d,e]); + const result = diffArray([a, c, e], [a, b, c, d, e]); assert.equal(result.firstChangeIndex, 1); assert.equal(result.addedCount, 3); assert.equal(result.removedCount, 1); diff --git a/tests/unit/many-array-test.js b/tests/unit/many-array-test.js index d0f8b141c74..c80465b2853 100644 --- a/tests/unit/many-array-test.js +++ b/tests/unit/many-array-test.js @@ -14,29 +14,29 @@ module('unit/many_array - DS.ManyArray', { beforeEach() { Post = DS.Model.extend({ title: attr('string'), - tags: hasMany('tag', { async: false }) + tags: hasMany('tag', { async: false }), }); Post.reopenClass({ toString() { return 'Post'; - } + }, }); Tag = DS.Model.extend({ name: attr('string'), - post: belongsTo('post', { async: false }) + post: belongsTo('post', { async: false }), }); Tag.reopenClass({ toString() { return 'Tag'; - } + }, }); env = setupStore({ post: Post, - tag: Tag + tag: Tag, }); store = env.store; @@ -44,7 +44,7 @@ module('unit/many_array - DS.ManyArray', { afterEach() { run(store, 'destroy'); - } + }, }); test('manyArray.save() calls save() on all records', function(assert) { @@ -54,7 +54,7 @@ test('manyArray.save() calls save() on all records', function(assert) { save() { assert.ok(true, 'record.save() was called'); return resolve(); - } + }, }); return run(() => { @@ -64,38 +64,39 @@ test('manyArray.save() calls save() on all records', function(assert) { type: 'tag', id: '1', attributes: { - name: 'Ember.js' - } + name: 'Ember.js', + }, }, { type: 'tag', id: '2', attributes: { - name: 'Tomster' - } + name: 'Tomster', + }, }, { type: 'post', id: '3', attributes: { - title: 'A framework for creating ambitious web applications' + title: 'A framework for creating ambitious web applications', }, relationships: { tags: { - data: [ - { type: 'tag', id: '1' }, - { type: 'tag', id: '2' } - ] - } - } - }] + data: [{ type: 'tag', id: '1' }, { type: 'tag', id: '2' }], + }, + }, + }, + ], }); let post = store.peekRecord('post', 3); - return post.get('tags').save().then(() => { - assert.ok(true, 'manyArray.save() promise resolved'); - }); + return post + .get('tags') + .save() + .then(() => { + assert.ok(true, 'manyArray.save() promise resolved'); + }); }); }); @@ -111,7 +112,7 @@ test('manyArray trigger arrayContentChange functions with the correct values', f // override DS.ManyArray temp (cleanup occures in afterTest); - DS.ManyArray.proto().arrayContentWillChange = function(startIdx, removeAmt, addAmt) { + DS.ManyArray.proto().arrayContentWillChange = function(startIdx, removeAmt, addAmt) { willChangeStartIdx = startIdx; willChangeRemoveAmt = removeAmt; willChangeAddAmt = addAmt; @@ -135,31 +136,29 @@ test('manyArray trigger arrayContentChange functions with the correct values', f type: 'tag', id: '1', attributes: { - name: 'Ember.js' - } + name: 'Ember.js', + }, }, { type: 'tag', id: '2', attributes: { - name: 'Tomster' - } + name: 'Tomster', + }, }, { type: 'post', id: '3', attributes: { - title: 'A framework for creating ambitious web applications' + title: 'A framework for creating ambitious web applications', }, relationships: { tags: { - data: [ - { type: 'tag', id: '1' } - ] - } - } - } - ] + data: [{ type: 'tag', id: '1' }], + }, + }, + }, + ], }); store.peekRecord('post', 3).get('tags'); @@ -169,17 +168,14 @@ test('manyArray trigger arrayContentChange functions with the correct values', f type: 'post', id: '3', attributes: { - title: 'A framework for creating ambitious web applications' + title: 'A framework for creating ambitious web applications', }, relationships: { tags: { - data: [ - { type: 'tag', id: '1' }, - { type: 'tag', id: '2' } - ] - } - } - } + data: [{ type: 'tag', id: '1' }, { type: 'tag', id: '2' }], + }, + }, + }, }); }); } finally { diff --git a/tests/unit/model-test.js b/tests/unit/model-test.js index 59e8f2896e6..9a8c00c256c 100644 --- a/tests/unit/model-test.js +++ b/tests/unit/model-test.js @@ -17,19 +17,19 @@ module('unit/model - DS.Model', { Person = DS.Model.extend({ name: DS.attr('string'), isDrugAddict: DS.attr('boolean'), - isArchived: DS.attr() + isArchived: DS.attr(), }); env = setupStore({ adapter: DS.JSONAPIAdapter, - person: Person + person: Person, }); store = env.store; }, afterEach() { run(() => store.destroy()); - } + }, }); test('can have a property set on it', function(assert) { @@ -53,18 +53,26 @@ test('setting a property on a record that has not changed does not cause it to b id: '1', attributes: { name: 'Peter', - isDrugAddict: true - } - } + isDrugAddict: true, + }, + }, }); return store.findRecord('person', 1).then(person => { - assert.equal(person.get('hasDirtyAttributes'), false, 'precond - person record should not be dirty'); + assert.equal( + person.get('hasDirtyAttributes'), + false, + 'precond - person record should not be dirty' + ); - person.set('name', "Peter"); + person.set('name', 'Peter'); person.set('isDrugAddict', true); - assert.equal(person.get('hasDirtyAttributes'), false, 'record does not become dirty after setting property to old value'); + assert.equal( + person.get('hasDirtyAttributes'), + false, + 'record does not become dirty after setting property to old value' + ); }); }); }); @@ -80,17 +88,29 @@ test('resetting a property on a record cause it to become clean again', function id: '1', attributes: { name: 'Peter', - isDrugAddict: true - } - } + isDrugAddict: true, + }, + }, }); return store.findRecord('person', 1).then(person => { - assert.equal(person.get('hasDirtyAttributes'), false, 'precond - person record should not be dirty'); + assert.equal( + person.get('hasDirtyAttributes'), + false, + 'precond - person record should not be dirty' + ); person.set('isDrugAddict', false); - assert.equal(person.get('hasDirtyAttributes'), true, 'record becomes dirty after setting property to a new value'); + assert.equal( + person.get('hasDirtyAttributes'), + true, + 'record becomes dirty after setting property to a new value' + ); person.set('isDrugAddict', true); - assert.equal(person.get('hasDirtyAttributes'), false, 'record becomes clean after resetting property to the old value'); + assert.equal( + person.get('hasDirtyAttributes'), + false, + 'record becomes clean after resetting property to the old value' + ); }); }); }); @@ -108,15 +128,15 @@ test('resetting a property to the current in-flight value causes it to become cl type: 'person', id: '1', attributes: { - name: 'Tom' - } - } + name: 'Tom', + }, + }, }); let person = store.peekRecord('person', 1); - person.set('name', "Thomas"); + person.set('name', 'Thomas'); - let saving = person.save() + let saving = person.save(); assert.equal(person.get('name'), 'Thomas'); @@ -143,21 +163,41 @@ test('a record becomes clean again only if all changed properties are reset', fu id: '1', attributes: { name: 'Peter', - isDrugAddict: true - } - } + isDrugAddict: true, + }, + }, }); - return store.findRecord('person', 1).then(person => { - assert.equal(person.get('hasDirtyAttributes'), false, 'precond - person record should not be dirty'); + return store.findRecord('person', 1).then(person => { + assert.equal( + person.get('hasDirtyAttributes'), + false, + 'precond - person record should not be dirty' + ); person.set('isDrugAddict', false); - assert.equal(person.get('hasDirtyAttributes'), true, 'record becomes dirty after setting one property to a new value'); + assert.equal( + person.get('hasDirtyAttributes'), + true, + 'record becomes dirty after setting one property to a new value' + ); person.set('name', 'Mark'); - assert.equal(person.get('hasDirtyAttributes'), true, 'record stays dirty after setting another property to a new value'); + assert.equal( + person.get('hasDirtyAttributes'), + true, + 'record stays dirty after setting another property to a new value' + ); person.set('isDrugAddict', true); - assert.equal(person.get('hasDirtyAttributes'), true, 'record stays dirty after resetting only one property to the old value'); + assert.equal( + person.get('hasDirtyAttributes'), + true, + 'record stays dirty after resetting only one property to the old value' + ); person.set('name', 'Peter'); - assert.equal(person.get('hasDirtyAttributes'), false, "record becomes clean after resetting both properties to the old value"); + assert.equal( + person.get('hasDirtyAttributes'), + false, + 'record becomes clean after resetting both properties to the old value' + ); }); }); }); @@ -177,16 +217,24 @@ test('an invalid record becomes clean again if changed property is reset', funct id: '1', attributes: { name: 'Peter', - isDrugAddict: true - } - } + isDrugAddict: true, + }, + }, }); let person = store.peekRecord('person', 1); - assert.equal(person.get('hasDirtyAttributes'), false, 'precond - person record should not be dirty'); + assert.equal( + person.get('hasDirtyAttributes'), + false, + 'precond - person record should not be dirty' + ); person.set('name', 'Wolf'); - assert.equal(person.get('hasDirtyAttributes'), true, 'record becomes dirty after setting one property to a new value'); + assert.equal( + person.get('hasDirtyAttributes'), + true, + 'record becomes dirty after setting one property to a new value' + ); return person.save().catch(() => { assert.equal(person.get('isValid'), false, 'record is not valid'); @@ -194,8 +242,16 @@ test('an invalid record becomes clean again if changed property is reset', funct person.set('name', 'Peter'); - assert.equal(person.get('isValid'), true, 'record is valid after resetting attribute to old value'); - assert.equal(person.get('hasDirtyAttributes'), false, "record becomes clean after resetting property to the old value"); + assert.equal( + person.get('isValid'), + true, + 'record is valid after resetting attribute to old value' + ); + assert.equal( + person.get('hasDirtyAttributes'), + false, + 'record becomes clean after resetting property to the old value' + ); }); }); }); @@ -215,17 +271,25 @@ test('an invalid record stays dirty if only invalid property is reset', function id: '1', attributes: { name: 'Peter', - isDrugAddict: true - } - } + isDrugAddict: true, + }, + }, }); let person = store.peekRecord('person', 1); - assert.equal(person.get('hasDirtyAttributes'), false, 'precond - person record should not be dirty'); + assert.equal( + person.get('hasDirtyAttributes'), + false, + 'precond - person record should not be dirty' + ); person.set('name', 'Wolf'); person.set('isDrugAddict', false); - assert.equal(person.get('hasDirtyAttributes'), true, 'record becomes dirty after setting one property to a new value'); + assert.equal( + person.get('hasDirtyAttributes'), + true, + 'record becomes dirty after setting one property to a new value' + ); return person.save().catch(() => { assert.equal(person.get('isValid'), false, 'record is not valid'); @@ -233,8 +297,12 @@ test('an invalid record stays dirty if only invalid property is reset', function person.set('name', 'Peter'); - assert.equal(person.get('isValid'), true, 'record is valid after resetting invalid attribute to old value'); - assert.equal(person.get('hasDirtyAttributes'), true, "record still has dirty attributes"); + assert.equal( + person.get('isValid'), + true, + 'record is valid after resetting invalid attribute to old value' + ); + assert.equal(person.get('hasDirtyAttributes'), true, 'record still has dirty attributes'); }); }); }); @@ -247,8 +315,8 @@ test('a record reports its unique id via the `id` property', function(assert) { store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); return store.findRecord('person', 1).then(record => { @@ -261,12 +329,14 @@ test("a record's id is included in its toString representation", function(assert assert.expect(1); env.adapter.shouldBackgroundReloadRecord = () => false; - let person = run(() => store.push({ - data: { - type: 'person', - id: '1' - } - })); + let person = run(() => + store.push({ + data: { + type: 'person', + id: '1', + }, + }) + ); assert.equal( person.toString(), @@ -278,11 +348,11 @@ test("a record's id is included in its toString representation", function(assert testInDebug('trying to set an `id` attribute should raise', function(assert) { Person = DS.Model.extend({ id: DS.attr('number'), - name: DS.attr('string') + name: DS.attr('string'), }); const store = createStore({ - person: Person + person: Person, }); assert.expectAssertion(() => { @@ -292,9 +362,9 @@ testInDebug('trying to set an `id` attribute should raise', function(assert) { type: 'person', id: '1', attributes: { - name: 'Scumdale' - } - } + name: 'Scumdale', + }, + }, }); store.findRecord('person', 1); }); @@ -314,12 +384,16 @@ test(`a collision of a record's id with object function's name`, function(assert store.push({ data: { type: 'person', - id: 'watch' - } + id: 'watch', + }, }); return store.findRecord('person', 'watch').then(record => { - assert.equal(get(record, 'id'), 'watch', 'record is successfully created and could be found by its id'); + assert.equal( + get(record, 'id'), + 'watch', + 'record is successfully created and could be found by its id' + ); }); }); } finally { @@ -335,11 +409,15 @@ test('it should use `_internalModel` and not `internalModel` to store its intern data: { type: 'person', id: 1, - attributes: {} - } + attributes: {}, + }, }); - assert.equal(store.peekRecord('person', 1).get('internalModel'), undefined, `doesn't shadow internalModel key`); + assert.equal( + store.peekRecord('person', 1).get('internalModel'), + undefined, + `doesn't shadow internalModel key` + ); }); }); @@ -347,14 +425,14 @@ test('it should cache attributes', function(assert) { assert.expect(2); const Post = DS.Model.extend({ - updatedAt: DS.attr('string') + updatedAt: DS.attr('string'), }); const store = createStore({ adapter: DS.JSONAPIAdapter.extend({ - shouldBackgroundReloadRecord: () => false + shouldBackgroundReloadRecord: () => false, }), - post: Post + post: Post, }); let dateString = 'Sat, 31 Dec 2011 00:08:16 GMT'; @@ -364,32 +442,39 @@ test('it should cache attributes', function(assert) { store.push({ data: { type: 'post', - id: '1' - } + id: '1', + }, }); - return store.findRecord('post', '1').then(record => { - record.set('updatedAt', date); - - assert.deepEqual(date, get(record, 'updatedAt'), 'setting a date returns the same date'); - assert.strictEqual(get(record, 'updatedAt'), get(record, 'updatedAt'), 'second get still returns the same object'); - }).finally(() => { - run(store, 'destroy'); - }); + return store + .findRecord('post', '1') + .then(record => { + record.set('updatedAt', date); + + assert.deepEqual(date, get(record, 'updatedAt'), 'setting a date returns the same date'); + assert.strictEqual( + get(record, 'updatedAt'), + get(record, 'updatedAt'), + 'second get still returns the same object' + ); + }) + .finally(() => { + run(store, 'destroy'); + }); }); }); -test("changedAttributes() return correct values", function(assert) { +test('changedAttributes() return correct values', function(assert) { assert.expect(4); const Mascot = DS.Model.extend({ name: DS.attr('string'), likes: DS.attr('string'), - isMascot: DS.attr('boolean') + isMascot: DS.attr('boolean'), }); let store = createStore({ - mascot: Mascot + mascot: Mascot, }); let mascot = run(() => { @@ -399,9 +484,9 @@ test("changedAttributes() return correct values", function(assert) { id: '1', attributes: { likes: 'JavaScript', - isMascot: true - } - } + isMascot: true, + }, + }, }); return store.peekRecord('mascot', 1); @@ -409,9 +494,9 @@ test("changedAttributes() return correct values", function(assert) { assert.equal(Object.keys(mascot.changedAttributes()).length, 0, 'there are no initial changes'); run(() => { - mascot.set('name', 'Tomster'); // new value + mascot.set('name', 'Tomster'); // new value mascot.set('likes', 'Ember.js'); // changed value - mascot.set('isMascot', true); // same value + mascot.set('isMascot', true); // same value }); let changedAttributes = mascot.changedAttributes(); @@ -421,7 +506,11 @@ test("changedAttributes() return correct values", function(assert) { run(() => mascot.rollbackAttributes()); - assert.equal(Object.keys(mascot.changedAttributes()).length, 0, 'after rollback attributes there are no changes'); + assert.equal( + Object.keys(mascot.changedAttributes()).length, + 0, + 'after rollback attributes there are no changes' + ); }); function toObj(obj) { @@ -441,29 +530,29 @@ test('changedAttributes() works while the record is being saved', function(asser createRecord(store, model, snapshot) { assert.deepEqual(toObj(cat.changedAttributes()), { name: [undefined, 'Argon'], - likes: [undefined, 'Cheese'] + likes: [undefined, 'Cheese'], }); return { data: { id: 1, type: 'mascot' } }; - } + }, }); const Mascot = DS.Model.extend({ name: DS.attr('string'), likes: DS.attr('string'), - isMascot: DS.attr('boolean') + isMascot: DS.attr('boolean'), }); let store = createStore({ mascot: Mascot, - adapter: Adapter + adapter: Adapter, }); return run(() => { cat = store.createRecord('mascot'); cat.setProperties({ name: 'Argon', - likes: 'Cheese' + likes: 'Cheese', }); return cat.save(); @@ -477,22 +566,22 @@ test('changedAttributes() works while the record is being updated', function(ass updateRecord(store, model, snapshot) { assert.deepEqual(toObj(cat.changedAttributes()), { name: ['Argon', 'Helia'], - likes: ['Cheese', 'Mussels'] + likes: ['Cheese', 'Mussels'], }); return { data: { id: '1', type: 'mascot' } }; - } + }, }); const Mascot = DS.Model.extend({ name: DS.attr('string'), likes: DS.attr('string'), - isMascot: DS.attr('boolean') + isMascot: DS.attr('boolean'), }); let store = createStore({ mascot: Mascot, - adapter: Adapter + adapter: Adapter, }); return run(() => { @@ -502,41 +591,41 @@ test('changedAttributes() works while the record is being updated', function(ass id: '1', attributes: { name: 'Argon', - likes: 'Cheese' - } - } + likes: 'Cheese', + }, + }, }); cat = store.peekRecord('mascot', 1); cat.setProperties({ name: 'Helia', - likes: 'Mussels' + likes: 'Mussels', }); return cat.save(); }); }); -test("a DS.Model does not require an attribute type", function(assert) { +test('a DS.Model does not require an attribute type', function(assert) { const Tag = DS.Model.extend({ - name: DS.attr() + name: DS.attr(), }); let store = createStore({ - tag: Tag + tag: Tag, }); - let tag = store.createRecord('tag', { name: "test" }); + let tag = store.createRecord('tag', { name: 'test' }); assert.equal(get(tag, 'name'), 'test', 'the value is persisted'); }); test('a DS.Model can have a defaultValue without an attribute type', function(assert) { const Tag = DS.Model.extend({ - name: DS.attr({ defaultValue: "unknown" }) + name: DS.attr({ defaultValue: 'unknown' }), }); let store = createStore({ - tag: Tag + tag: Tag, }); let tag = store.createRecord('tag'); @@ -549,25 +638,32 @@ testInDebug('Calling attr() throws a warning', function(assert) { let person = store.createRecord('person', { id: 1, name: 'TomHuda' }); - assert.throws(() => { - person.attr(); - }, /The `attr` method is not available on DS.Model, a DS.Snapshot was probably expected/, 'attr() throws a warning'); + assert.throws( + () => { + person.attr(); + }, + /The `attr` method is not available on DS.Model, a DS.Snapshot was probably expected/, + 'attr() throws a warning' + ); }); test('supports pushedData in root.deleted.uncommitted', function(assert) { let hash = { data: { type: 'person', - id: '1' - } + id: '1', + }, }; run(() => { let record = store.push(hash); record.deleteRecord(); store.push(hash); - assert.equal(get(record, 'currentState.stateName'), 'root.deleted.uncommitted', - 'record accepts pushedData is in root.deleted.uncommitted state'); + assert.equal( + get(record, 'currentState.stateName'), + 'root.deleted.uncommitted', + 'record accepts pushedData is in root.deleted.uncommitted state' + ); }); }); @@ -579,24 +675,31 @@ test('supports canonical updates via pushedData in root.deleted.saved', function return Ember.RSVP.resolve(); }; - let record = run(() => store.push({ - data: { - type: 'person', - id: '1', - attributes: { - isArchived: false - } - } - })); + let record = run(() => + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + isArchived: false, + }, + }, + }) + ); run(() => { record.destroyRecord().then(() => { let currentState = record._internalModel.currentState; - assert.ok(currentState.stateName === 'root.deleted.saved', - 'record is in a persisted deleted state'); + assert.ok( + currentState.stateName === 'root.deleted.saved', + 'record is in a persisted deleted state' + ); assert.equal(get(record, 'isDeleted'), true); - assert.ok(store.peekRecord('person', '1') !== null, 'the deleted person is not removed from store (no unload called)'); + assert.ok( + store.peekRecord('person', '1') !== null, + 'the deleted person is not removed from store (no unload called)' + ); }); }); @@ -606,21 +709,25 @@ test('supports canonical updates via pushedData in root.deleted.saved', function type: 'person', id: '1', attributes: { - isArchived: true - } - } + isArchived: true, + }, + }, }); let currentState = record._internalModel.currentState; - assert.ok(currentState.stateName === 'root.deleted.saved', - 'record is still in a persisted deleted state'); + assert.ok( + currentState.stateName === 'root.deleted.saved', + 'record is still in a persisted deleted state' + ); assert.ok(get(record, 'isDeleted') === true, 'The record is still deleted'); - assert.ok(get(record, 'isArchived') === true, 'The record reflects the update to canonical state'); + assert.ok( + get(record, 'isArchived') === true, + 'The record reflects the update to canonical state' + ); }); }); - test('Does not support dirtying in root.deleted.saved', function(assert) { let { adapter } = env; @@ -629,24 +736,31 @@ test('Does not support dirtying in root.deleted.saved', function(assert) { return Ember.RSVP.resolve(); }; - let record = run(() => store.push({ - data: { - type: 'person', - id: '1', - attributes: { - isArchived: false - } - } - })); + let record = run(() => + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + isArchived: false, + }, + }, + }) + ); run(() => { record.destroyRecord().then(() => { let currentState = record._internalModel.currentState; - assert.ok(currentState.stateName === 'root.deleted.saved', - 'record is in a persisted deleted state'); + assert.ok( + currentState.stateName === 'root.deleted.saved', + 'record is in a persisted deleted state' + ); assert.equal(get(record, 'isDeleted'), true); - assert.ok(store.peekRecord('person', '1') !== null, 'the deleted person is not removed from store (no unload called)'); + assert.ok( + store.peekRecord('person', '1') !== null, + 'the deleted person is not removed from store (no unload called)' + ); }); }); @@ -657,8 +771,10 @@ test('Does not support dirtying in root.deleted.saved', function(assert) { let currentState = record._internalModel.currentState; - assert.ok(currentState.stateName === 'root.deleted.saved', - 'record is still in a persisted deleted state'); + assert.ok( + currentState.stateName === 'root.deleted.saved', + 'record is still in a persisted deleted state' + ); assert.ok(get(record, 'isDeleted') === true, 'The record is still deleted'); assert.ok(get(record, 'isArchived') === false, 'The record reflects canonical state'); }); @@ -668,25 +784,28 @@ test('currentState is accessible when the record is created', function(assert) { let hash = { data: { type: 'person', - id: '1' - } + id: '1', + }, }; run(() => { let record = store.push(hash); - assert.equal(get(record, 'currentState.stateName'), 'root.loaded.saved', - 'records pushed into the store start in the loaded state'); + assert.equal( + get(record, 'currentState.stateName'), + 'root.loaded.saved', + 'records pushed into the store start in the loaded state' + ); }); }); module('unit/model - DS.Model updating', { beforeEach() { Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); env = setupStore({ - person: Person + person: Person, }); store = env.store; @@ -697,30 +816,31 @@ module('unit/model - DS.Model updating', { type: 'person', id: '1', attributes: { - name: 'Scumbag Dale' - } + name: 'Scumbag Dale', + }, }, { type: 'person', id: '2', attributes: { - name: 'Scumbag Katz' - } + name: 'Scumbag Katz', + }, }, { type: 'person', id: '3', attributes: { - name: 'Scumbag Bryn' - } - }] + name: 'Scumbag Bryn', + }, + }, + ], }); }); }, afterEach() { run(store, 'destroy'); - } + }, }); test('a DS.Model can update its attributes', function(assert) { @@ -737,11 +857,11 @@ test('a DS.Model can update its attributes', function(assert) { test('a DS.Model can have a defaultValue', function(assert) { const Tag = DS.Model.extend({ - name: DS.attr('string', { defaultValue: 'unknown' }) + name: DS.attr('string', { defaultValue: 'unknown' }), }); let store = createStore({ - tag: Tag + tag: Tag, }); let tag = store.createRecord('tag'); @@ -761,15 +881,15 @@ test(`a DS.model can define 'setUnknownProperty'`, function(assert) { if (key === 'title') { this.set('name', value); } - } + }, }); let store = createStore({ - tag: Tag + tag: Tag, }); let tag = run(() => { - tag = store.createRecord('tag', { name: "old" }); + tag = store.createRecord('tag', { name: 'old' }); set(tag, 'title', 'new'); return tag; @@ -783,12 +903,12 @@ test('a defaultValue for an attribute can be a function', function(assert) { createdAt: DS.attr('string', { defaultValue() { return 'le default value'; - } - }) + }, + }), }); let store = createStore({ - tag: Tag + tag: Tag, }); let tag = store.createRecord('tag'); @@ -804,12 +924,12 @@ test('a defaultValue function gets the record, options, and key', function(asser assert.deepEqual(record, tag, 'the record is passed in properly'); assert.equal(key, 'createdAt', 'the attribute being defaulted is passed in properly'); return 'le default value'; - } - }) + }, + }), }); let store = createStore({ - tag: Tag + tag: Tag, }); let tag = store.createRecord('tag'); @@ -819,11 +939,11 @@ test('a defaultValue function gets the record, options, and key', function(asser testInDebug('a complex object defaultValue is deprecated', function(assert) { const Tag = DS.Model.extend({ - tagInfo: DS.attr({ defaultValue: [] }) + tagInfo: DS.attr({ defaultValue: [] }), }); let store = createStore({ - tag: Tag + tag: Tag, }); let tag = store.createRecord('tag'); @@ -835,11 +955,11 @@ testInDebug('a complex object defaultValue is deprecated', function(assert) { test('setting a property to undefined on a newly created record should not impact the current state', function(assert) { const Tag = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ - tag: Tag + tag: Tag, }); let tag = run(() => { @@ -851,7 +971,6 @@ test('setting a property to undefined on a newly created record should not impac return tag; }); - assert.equal(get(tag, 'currentState.stateName'), 'root.loaded.created.uncommitted'); tag = store.createRecord('tag', { name: undefined }); @@ -873,7 +992,11 @@ test('setting a property back to its original value removes the property from th set(person, 'name', 'Niceguy Dale'); - assert.equal(dataSource._attributes.name, 'Niceguy Dale', 'the `_attributes` hash contains the changed value'); + assert.equal( + dataSource._attributes.name, + 'Niceguy Dale', + 'the `_attributes` hash contains the changed value' + ); set(person, 'name', 'Scumbag Dale'); @@ -882,13 +1005,13 @@ test('setting a property back to its original value removes the property from th }); }); -module("unit/model - with a simple Person model", { +module('unit/model - with a simple Person model', { beforeEach() { Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); store = createStore({ - person: Person + person: Person, }); run(() => { @@ -898,29 +1021,30 @@ module("unit/model - with a simple Person model", { type: 'person', id: '1', attributes: { - name: 'Scumbag Dale' - } + name: 'Scumbag Dale', + }, }, { type: 'person', id: '2', attributes: { - name: 'Scumbag Katz' - } + name: 'Scumbag Katz', + }, }, { type: 'person', id: '3', attributes: { - name: 'Scumbag Bryn' - } - }] + name: 'Scumbag Bryn', + }, + }, + ], }); }); }, afterEach() { run(store, 'destroy'); - } + }, }); test('can ask if record with a given id is loaded', function(assert) { @@ -930,9 +1054,11 @@ test('can ask if record with a given id is loaded', function(assert) { assert.equal(store.hasRecordForId('person', 4), false, 'should not have person with id 4'); }); -test("a listener can be added to a record", function(assert) { +test('a listener can be added to a record', function(assert) { let count = 0; - let F = function() { count++; }; + let F = function() { + count++; + }; let record = store.createRecord('person'); @@ -948,19 +1074,23 @@ test("a listener can be added to a record", function(assert) { test('when an event is triggered on a record the method with the same name is invoked with arguments', function(assert) { let count = 0; - let F = function() { count++; }; + let F = function() { + count++; + }; let record = store.createRecord('person'); record.eventNamedMethod = F; run(() => record.trigger('eventNamedMethod')); - assert.equal(count, 1, "the corresponding method was called"); + assert.equal(count, 1, 'the corresponding method was called'); }); test('when a method is invoked from an event with the same name the arguments are passed through', function(assert) { let eventMethodArgs = null; - let F = function() { eventMethodArgs = arguments; }; + let F = function() { + eventMethodArgs = arguments; + }; let record = store.createRecord('person'); record.eventThatTriggersMethod = F; @@ -973,7 +1103,7 @@ test('when a method is invoked from an event with the same name the arguments ar function converts(assert, type, provided, expected, options = {}) { const Model = DS.Model.extend({ - name: DS.attr(type, options) + name: DS.attr(type, options), }); let registry, container; @@ -986,7 +1116,7 @@ function converts(assert, type, provided, expected, options = {}) { } let testStore = createStore({ - model: Model + model: Model, }); getOwner(testStore).register('serializer:model', DS.JSONSerializer); @@ -996,7 +1126,11 @@ function converts(assert, type, provided, expected, options = {}) { let record = testStore.peekRecord('model', 1); - assert.deepEqual(get(record, 'name'), expected, type + ' coerces ' + provided + ' to ' + expected); + assert.deepEqual( + get(record, 'name'), + expected, + type + ' coerces ' + provided + ' to ' + expected + ); }); // See: Github issue #421 @@ -1007,7 +1141,7 @@ function converts(assert, type, provided, expected, options = {}) { function convertsFromServer(assert, type, provided, expected) { const Model = DS.Model.extend({ - name: DS.attr(type) + name: DS.attr(type), }); let registry, container; @@ -1021,19 +1155,27 @@ function convertsFromServer(assert, type, provided, expected) { let testStore = createStore({ model: Model, adapter: DS.Adapter.extend({ - shouldBackgroundReloadRecord() { return false; } - }) + shouldBackgroundReloadRecord() { + return false; + }, + }), }); getOwner(testStore).register('serializer:model', DS.JSONSerializer); return run(() => { - testStore.push(testStore.normalize('model', { - id: '1', - name: provided - })); + testStore.push( + testStore.normalize('model', { + id: '1', + name: provided, + }) + ); return testStore.findRecord('model', 1).then(record => { - assert.deepEqual(get(record, 'name'), expected, type + ' coerces ' + provided + ' to ' + expected); + assert.deepEqual( + get(record, 'name'), + expected, + type + ' coerces ' + provided + ' to ' + expected + ); }); }); } @@ -1054,7 +1196,7 @@ test('a DS.Model can describe Number attributes', function(assert) { converts(assert, 'number', '0', 0); converts(assert, 'number', 1, 1); converts(assert, 'number', 0, 0); - converts(assert, 'number', "", null); + converts(assert, 'number', '', null); converts(assert, 'number', null, null); converts(assert, 'number', true, 1); converts(assert, 'number', false, 0); @@ -1062,7 +1204,7 @@ test('a DS.Model can describe Number attributes', function(assert) { test('a DS.Model can describe Boolean attributes', function(assert) { converts(assert, 'boolean', '1', true); - converts(assert, 'boolean', "", false); + converts(assert, 'boolean', '', false); converts(assert, 'boolean', 1, true); converts(assert, 'boolean', 0, false); @@ -1086,22 +1228,24 @@ test('a DS.Model can describe Date attributes', function(assert) { let date = new Date(dateString); const Person = DS.Model.extend({ - updatedAt: DS.attr('date') + updatedAt: DS.attr('date'), }); let store = createStore({ person: Person, adapter: DS.Adapter.extend({ - shouldBackgroundReloadRecord() { return false; } - }) + shouldBackgroundReloadRecord() { + return false; + }, + }), }); return run(() => { store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); return store.findRecord('person', 1).then(record => { @@ -1117,13 +1261,13 @@ test('a DS.Model can describe Date attributes', function(assert) { function convertsWhenSet(assert, type, provided, expected) { let testStore = createStore({ model: DS.Model.extend({ - name: DS.attr(type) + name: DS.attr(type), }), adapter: DS.Adapter.extend({ shouldBackgroundReloadRecord() { return false; - } - }) + }, + }), }); getOwner(testStore).register('serializer:model', DS.JSONSerializer); @@ -1131,13 +1275,17 @@ function convertsWhenSet(assert, type, provided, expected) { testStore.push({ data: { type: 'model', - id: '2' - } + id: '2', + }, }); return testStore.findRecord('model', 2).then(record => { set(record, 'name', provided); - assert.deepEqual(record.serialize().name, expected, type + ' saves ' + provided + ' as ' + expected); + assert.deepEqual( + record.serialize().name, + expected, + type + ' saves ' + provided + ' as ' + expected + ); }); }); } @@ -1146,7 +1294,7 @@ testInDebug(`don't allow setting`, function(assert) { const Person = DS.Model.extend(); let store = createStore({ - person: Person + person: Person, }); let record = store.createRecord('person'); @@ -1168,17 +1316,21 @@ test('ensure model exits loading state, materializes data and fulfills promise o data: { id: 1, type: 'person', - attributes: { name: 'John' } - } + attributes: { name: 'John' }, + }, }); - } + }, }), - person: Person + person: Person, }); return run(() => { return store.findRecord('person', 1).then(person => { - assert.equal(get(person, 'currentState.stateName'), 'root.loaded.saved', 'model is in loaded state'); + assert.equal( + get(person, 'currentState.stateName'), + 'root.loaded.saved', + 'model is in loaded state' + ); assert.equal(get(person, 'isLoaded'), true, 'model is loaded'); }); }); @@ -1186,7 +1338,7 @@ test('ensure model exits loading state, materializes data and fulfills promise o test('A DS.Model can be JSONified', function(assert) { const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ person: Person }); @@ -1198,7 +1350,7 @@ test('A DS.Model can be JSONified', function(assert) { testInDebug('A subclass of DS.Model can not use the `data` property', function(assert) { const Person = DS.Model.extend({ data: DS.attr('string'), - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ person: Person }); @@ -1211,7 +1363,7 @@ testInDebug('A subclass of DS.Model can not use the `data` property', function(a testInDebug('A subclass of DS.Model can not use the `store` property', function(assert) { const Retailer = DS.Model.extend({ store: DS.attr(), - name: DS.attr() + name: DS.attr(), }); let store = createStore({ retailer: Retailer }); @@ -1223,9 +1375,7 @@ testInDebug('A subclass of DS.Model can not use the `store` property', function( testInDebug('A subclass of DS.Model can not use reserved properties', function(assert) { assert.expect(3); - [ - 'currentState', 'data', 'store' - ].forEach(reservedProperty => { + ['currentState', 'data', 'store'].forEach(reservedProperty => { let invalidExtendObject = {}; invalidExtendObject[reservedProperty] = DS.attr(); const Post = DS.Model.extend(invalidExtendObject); @@ -1240,7 +1390,7 @@ testInDebug('A subclass of DS.Model can not use reserved properties', function(a test('Pushing a record into the store should transition it to the loaded state', function(assert) { const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ person: Person }); @@ -1254,32 +1404,38 @@ test('Pushing a record into the store should transition it to the loaded state', type: 'person', id: '1', attributes: { - name: 'TomHuda' - } - } + name: 'TomHuda', + }, + }, }); assert.equal(person.get('isNew'), false, 'push should put records into the loaded state'); }); }); -testInDebug('A subclass of DS.Model throws an error when calling create() directly', function(assert) { - assert.throws(() => { - Person.create(); - }, /You should not call `create` on a model/, 'Throws an error when calling create() on model'); +testInDebug('A subclass of DS.Model throws an error when calling create() directly', function( + assert +) { + assert.throws( + () => { + Person.create(); + }, + /You should not call `create` on a model/, + 'Throws an error when calling create() on model' + ); }); test('toJSON looks up the JSONSerializer using the store instead of using JSONSerializer.create', function(assert) { const Person = DS.Model.extend({ - posts: DS.hasMany('post', { async: false }) + posts: DS.hasMany('post', { async: false }), }); const Post = DS.Model.extend({ - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); let env = setupStore({ person: Person, - post: Post + post: Post, }); let { store } = env; @@ -1292,8 +1448,8 @@ test('toJSON looks up the JSONSerializer using the store instead of using JSONSe return store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); }); @@ -1306,7 +1462,7 @@ test('toJSON looks up the JSONSerializer using the store instead of using JSONSe } assert.ok(!errorThrown, 'error not thrown due to missing store'); - assert.deepEqual(json, { data: { type: 'people' }}); + assert.deepEqual(json, { data: { type: 'people' } }); }); test('internalModel is ready by `init`', function(assert) { @@ -1321,7 +1477,7 @@ test('internalModel is ready by `init`', function(assert) { this.set('name', 'my-name-set-in-init'); }, - nameDidChange: observer('name', () => nameDidChange++) + nameDidChange: observer('name', () => nameDidChange++), }); let { store } = setupStore({ person: Person }); @@ -1340,11 +1496,11 @@ test('accessing attributes in the initializer should not throw an error', functi init() { this._super(...arguments); assert.ok(!this.get('name')); - } + }, }); let { store } = setupStore({ - person: Person + person: Person, }); store.createRecord('person'); @@ -1354,11 +1510,11 @@ test('setting the id after model creation should correctly update the id', funct assert.expect(2); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let { store } = setupStore({ - person: Person + person: Person, }); let person = store.createRecord('person'); @@ -1372,101 +1528,112 @@ test('setting the id after model creation should correctly update the id', funct }); }); -testRecordData('updating the id with store.setRecordId should correctly when the id property is watched', function(assert) { - assert.expect(2); - - const Person = DS.Model.extend({ - name: DS.attr('string'), - idComputed: computed('id', function() {}) - }); +testRecordData( + 'updating the id with store.setRecordId should correctly when the id property is watched', + function(assert) { + assert.expect(2); - let { store } = setupStore({ - person: Person - }); + const Person = DS.Model.extend({ + name: DS.attr('string'), + idComputed: computed('id', function() {}), + }); - run(() => { - let person = store.createRecord('person'); - person.get('idComputed'); + let { store } = setupStore({ + person: Person, + }); - assert.equal(person.get('id'), null, 'initial created model id should be null'); + run(() => { + let person = store.createRecord('person'); + person.get('idComputed'); - store.setRecordId('person', 'john', person._internalModel.clientId); + assert.equal(person.get('id'), null, 'initial created model id should be null'); - assert.equal(person.id, 'john', 'new id should be correctly set.'); - }); -}); + store.setRecordId('person', 'john', person._internalModel.clientId); -skipRecordData('updating the id with store.updateId should correctly when the id property is watched', function(assert) { - assert.expect(2); + assert.equal(person.id, 'john', 'new id should be correctly set.'); + }); + } +); - const Person = DS.Model.extend({ - name: DS.attr('string'), - idComputed: computed('id', function() {}) - }); +skipRecordData( + 'updating the id with store.updateId should correctly when the id property is watched', + function(assert) { + assert.expect(2); - let { store } = setupStore({ - person: Person - }); + const Person = DS.Model.extend({ + name: DS.attr('string'), + idComputed: computed('id', function() {}), + }); - run(() => { - let person = store.createRecord('person'); - person.get('idComputed'); + let { store } = setupStore({ + person: Person, + }); - assert.equal(person.get('id'), null, 'initial created model id should be null'); + run(() => { + let person = store.createRecord('person'); + person.get('idComputed'); - store.updateId(person._internalModel, { id: 'john' }); - assert.equal(person.id, 'john', 'new id should be correctly set.'); - }); -}); + assert.equal(person.get('id'), null, 'initial created model id should be null'); -testRecordData('accessing the model id without the get function should work when id is watched', function(assert) { - assert.expect(2); + store.updateId(person._internalModel, { id: 'john' }); + assert.equal(person.id, 'john', 'new id should be correctly set.'); + }); + } +); - const Person = DS.Model.extend({ - name: DS.attr('string'), - idComputed: computed('id', function() {}) - }); +testRecordData( + 'accessing the model id without the get function should work when id is watched', + function(assert) { + assert.expect(2); - let { store } = setupStore({ - person: Person - }); + const Person = DS.Model.extend({ + name: DS.attr('string'), + idComputed: computed('id', function() {}), + }); - run(() => { - let person = store.createRecord('person'); - person.get('idComputed'); + let { store } = setupStore({ + person: Person, + }); - assert.equal(person.get('id'), null, 'initial created model id should be null'); + run(() => { + let person = store.createRecord('person'); + person.get('idComputed'); - store.setRecordId('person', 'john', person._internalModel.clientId); + assert.equal(person.get('id'), null, 'initial created model id should be null'); - assert.equal(person.id, 'john', 'new id should be correctly set.'); - }); -}); + store.setRecordId('person', 'john', person._internalModel.clientId); -skipRecordData('accessing the model id without the get function should work when id is watched', function(assert) { - assert.expect(2); + assert.equal(person.id, 'john', 'new id should be correctly set.'); + }); + } +); - const Person = DS.Model.extend({ - name: DS.attr('string'), - idComputed: computed('id', function() {}) - }); +skipRecordData( + 'accessing the model id without the get function should work when id is watched', + function(assert) { + assert.expect(2); - let { store } = setupStore({ - person: Person - }); + const Person = DS.Model.extend({ + name: DS.attr('string'), + idComputed: computed('id', function() {}), + }); - run(() => { - let person = store.createRecord('person'); - person.get('idComputed'); + let { store } = setupStore({ + person: Person, + }); - assert.equal(person.get('id'), null, 'initial created model id should be null'); + run(() => { + let person = store.createRecord('person'); + person.get('idComputed'); - store.updateId(person._internalModel, { id: 'john' }); + assert.equal(person.get('id'), null, 'initial created model id should be null'); - assert.equal(person.id, 'john', 'new id should be correctly set.'); - }); -}); + store.updateId(person._internalModel, { id: 'john' }); + assert.equal(person.id, 'john', 'new id should be correctly set.'); + }); + } +); test('ID mutation (complicated)', function(assert) { assert.expect(5); @@ -1474,11 +1641,11 @@ test('ID mutation (complicated)', function(assert) { const Person = DS.Model.extend({ name: DS.attr('string'), idComputed: Ember.computed('id', function() {}), - idDidChange: Ember.observer('id', () => idChange++) + idDidChange: Ember.observer('id', () => idChange++), }); let { store } = setupStore({ - person: Person.extend() + person: Person.extend(), }); run(() => { diff --git a/tests/unit/model/errors-test.js b/tests/unit/model/errors-test.js index d81f7dc7de4..0cffcb12fd0 100644 --- a/tests/unit/model/errors-test.js +++ b/tests/unit/model/errors-test.js @@ -9,11 +9,14 @@ let errors; module('unit/model/errors', { beforeEach() { errors = DS.Errors.create(); - } + }, }); function updateErrors(func, assert) { - assert.expectWarning(func, 'Interacting with a record errors object will no longer change the record state.'); + assert.expectWarning( + func, + 'Interacting with a record errors object will no longer change the record state.' + ); } AssertPrototype.becameInvalid = function becameInvalid(eventName) { @@ -67,11 +70,11 @@ testInDebug('get error', function(assert) { assert.deepEqual(errors.toArray(), [ { attribute: 'firstName', message: 'error' }, { attribute: 'firstName', message: 'error2' }, - { attribute: 'lastName', message: 'error3' } + { attribute: 'lastName', message: 'error3' }, ]); assert.deepEqual(errors.get('firstName'), [ { attribute: 'firstName', message: 'error' }, - { attribute: 'firstName', message: 'error2' } + { attribute: 'firstName', message: 'error2' }, ]); assert.deepEqual(errors.get('messages'), ['error', 'error2', 'error3']); }); diff --git a/tests/unit/model/init-properties-test.js b/tests/unit/model/init-properties-test.js index 5651f87679b..5cbc74d852c 100644 --- a/tests/unit/model/init-properties-test.js +++ b/tests/unit/model/init-properties-test.js @@ -11,11 +11,11 @@ function setupModels(testState) { let types; const Comment = Model.extend({ text: attr(), - post: belongsTo('post', { async: false, inverse: 'comments' }) + post: belongsTo('post', { async: false, inverse: 'comments' }), }); const Author = Model.extend({ name: attr(), - post: belongsTo('post', { async: false, inverse: 'author' }) + post: belongsTo('post', { async: false, inverse: 'author' }), }); const Post = Model.extend({ title: attr(), @@ -24,19 +24,19 @@ function setupModels(testState) { init() { this._super(...arguments); testState(types, this); - } + }, }); types = { Author, Comment, - Post + Post, }; return setupStore({ adapter: JSONAPIAdapter.extend(), post: Post, comment: Comment, - author: Author + author: Author, }); } @@ -49,9 +49,18 @@ test('createRecord(properties) makes properties available during record init', f function testState(types, record) { assert.ok(get(record, 'title') === 'My Post', 'Attrs are available as expected'); - assert.ok(get(record, 'randomProp') === 'An unknown prop', 'Unknown properties are available as expected'); - assert.ok(get(record, 'author') instanceof types.Author, 'belongsTo relationships are available as expected'); - assert.ok(get(record, 'comments.firstObject') instanceof types.Comment, 'hasMany relationships are available as expected'); + assert.ok( + get(record, 'randomProp') === 'An unknown prop', + 'Unknown properties are available as expected' + ); + assert.ok( + get(record, 'author') instanceof types.Author, + 'belongsTo relationships are available as expected' + ); + assert.ok( + get(record, 'comments.firstObject') instanceof types.Comment, + 'hasMany relationships are available as expected' + ); } let { store } = setupModels(testState); @@ -62,18 +71,18 @@ test('createRecord(properties) makes properties available during record init', f type: 'comment', id: '1', attributes: { - text: 'Hello darkness my old friend' - } - } + text: 'Hello darkness my old friend', + }, + }, }); author = store.push({ data: { type: 'author', id: '1', attributes: { - name: '@runspired' - } - } + name: '@runspired', + }, + }, }); }); @@ -82,7 +91,7 @@ test('createRecord(properties) makes properties available during record init', f title: 'My Post', randomProp: 'An unknown prop', comments: [comment], - author + author, }); }); }); @@ -92,45 +101,53 @@ test('store.push() makes properties available during record init', function(asse function testState(types, record) { assert.ok(get(record, 'title') === 'My Post', 'Attrs are available as expected'); - assert.ok(get(record, 'author') instanceof types.Author, 'belongsTo relationships are available as expected'); - assert.ok(get(record, 'comments.firstObject') instanceof types.Comment, 'hasMany relationships are available as expected'); + assert.ok( + get(record, 'author') instanceof types.Author, + 'belongsTo relationships are available as expected' + ); + assert.ok( + get(record, 'comments.firstObject') instanceof types.Comment, + 'hasMany relationships are available as expected' + ); } let { store } = setupModels(testState); - run(() => store.push({ - data: { - type: 'post', - id: '1', - attributes: { - title: 'My Post' - }, - relationships: { - comments: { - data: [{ type: 'comment', id: '1' }] - }, - author: { - data: { type: 'author', id: '1' } - } - } - }, - included: [ - { - type: 'comment', + run(() => + store.push({ + data: { + type: 'post', id: '1', attributes: { - text: 'Hello darkness my old friend' - } + title: 'My Post', + }, + relationships: { + comments: { + data: [{ type: 'comment', id: '1' }], + }, + author: { + data: { type: 'author', id: '1' }, + }, + }, }, - { - type: 'author', - id: '1', - attributes: { - name: '@runspired' - } - } - ] - })); + included: [ + { + type: 'comment', + id: '1', + attributes: { + text: 'Hello darkness my old friend', + }, + }, + { + type: 'author', + id: '1', + attributes: { + name: '@runspired', + }, + }, + ], + }) + ); }); test('store.findRecord(type, id) makes properties available during record init', function(assert) { @@ -138,8 +155,14 @@ test('store.findRecord(type, id) makes properties available during record init', function testState(types, record) { assert.ok(get(record, 'title') === 'My Post', 'Attrs are available as expected'); - assert.ok(get(record, 'author') instanceof types.Author, 'belongsTo relationships are available as expected'); - assert.ok(get(record, 'comments.firstObject') instanceof types.Comment, 'hasMany relationships are available as expected'); + assert.ok( + get(record, 'author') instanceof types.Author, + 'belongsTo relationships are available as expected' + ); + assert.ok( + get(record, 'comments.firstObject') instanceof types.Comment, + 'hasMany relationships are available as expected' + ); } let { adapter, store } = setupModels(testState); @@ -150,33 +173,33 @@ test('store.findRecord(type, id) makes properties available during record init', type: 'post', id: '1', attributes: { - title: 'My Post' + title: 'My Post', }, relationships: { comments: { - data: [{ type: 'comment', id: '1' }] + data: [{ type: 'comment', id: '1' }], }, author: { - data: { type: 'author', id: '1' } - } - } + data: { type: 'author', id: '1' }, + }, + }, }, included: [ { type: 'comment', id: '1', attributes: { - text: 'Hello darkness my old friend' - } + text: 'Hello darkness my old friend', + }, }, { type: 'author', id: '1', attributes: { - name: '@runspired' - } - } - ] + name: '@runspired', + }, + }, + ], }); }; @@ -188,8 +211,14 @@ test('store.queryRecord(type, query) makes properties available during record in function testState(types, record) { assert.ok(get(record, 'title') === 'My Post', 'Attrs are available as expected'); - assert.ok(get(record, 'author') instanceof types.Author, 'belongsTo relationships are available as expected'); - assert.ok(get(record, 'comments.firstObject') instanceof types.Comment, 'hasMany relationships are available as expected'); + assert.ok( + get(record, 'author') instanceof types.Author, + 'belongsTo relationships are available as expected' + ); + assert.ok( + get(record, 'comments.firstObject') instanceof types.Comment, + 'hasMany relationships are available as expected' + ); } let { adapter, store } = setupModels(testState); @@ -200,33 +229,33 @@ test('store.queryRecord(type, query) makes properties available during record in type: 'post', id: '1', attributes: { - title: 'My Post' + title: 'My Post', }, relationships: { comments: { - data: [{ type: 'comment', id: '1' }] + data: [{ type: 'comment', id: '1' }], }, author: { - data: { type: 'author', id: '1' } - } - } + data: { type: 'author', id: '1' }, + }, + }, }, included: [ { type: 'comment', id: '1', attributes: { - text: 'Hello darkness my old friend' - } + text: 'Hello darkness my old friend', + }, }, { type: 'author', id: '1', attributes: { - name: '@runspired' - } - } - ] + name: '@runspired', + }, + }, + ], }); }; diff --git a/tests/unit/model/lifecycle-callbacks-test.js b/tests/unit/model/lifecycle-callbacks-test.js index c007aac027a..5693aeb1a5b 100644 --- a/tests/unit/model/lifecycle-callbacks-test.js +++ b/tests/unit/model/lifecycle-callbacks-test.js @@ -16,18 +16,18 @@ test('a record receives a didLoad callback when it has finished loading', functi name: DS.attr(), didLoad() { assert.ok('The didLoad callback was called'); - } + }, }); const Adapter = DS.Adapter.extend({ findRecord(store, type, id, snapshot) { return { data: { id: 1, type: 'person', attributes: { name: 'Foo' } } }; - } + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); return run(() => { @@ -45,19 +45,19 @@ test(`TEMPORARY: a record receives a didLoad callback once it materializes if it name: DS.attr(), didLoad() { didLoadCalled++; - } + }, }); let store = createStore({ - person: Person + person: Person, }); run(() => { store._pushInternalModel({ id: 1, type: 'person' }); - assert.equal(didLoadCalled, 0, "didLoad was not called"); + assert.equal(didLoadCalled, 0, 'didLoad was not called'); }); run(() => store.peekRecord('person', 1)); - assert.equal(didLoadCalled, 1, "didLoad was called"); + assert.equal(didLoadCalled, 1, 'didLoad was called'); }); test('a record receives a didUpdate callback when it has finished updating', function(assert) { @@ -73,7 +73,7 @@ test('a record receives a didUpdate callback when it has finished updating', fun callCount++; assert.equal(get(this, 'isSaving'), false, 'record should be saving'); assert.equal(get(this, 'hasDirtyAttributes'), false, 'record should not be dirty'); - } + }, }); const Adapter = DS.Adapter.extend({ @@ -85,12 +85,12 @@ test('a record receives a didUpdate callback when it has finished updating', fun assert.equal(callCount, 0, 'didUpdate callback was not called until didSaveRecord is called'); return resolve(); - } + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); let asyncPerson = run(() => store.findRecord('person', 1)); @@ -98,14 +98,16 @@ test('a record receives a didUpdate callback when it has finished updating', fun assert.equal(callCount, 0, 'precond - didUpdate callback was not called yet'); return run(() => { - return asyncPerson.then(person => { - return run(() => { - person.set('bar', "Bar"); - return person.save(); + return asyncPerson + .then(person => { + return run(() => { + person.set('bar', 'Bar'); + return person.save(); + }); + }) + .then(() => { + assert.equal(callCount, 1, 'didUpdate called after update'); }); - }).then(() => { - assert.equal(callCount, 1, 'didUpdate called after update'); - }); }); }); @@ -119,7 +121,7 @@ test('a record receives a didCreate callback when it has finished updating', fun callCount++; assert.equal(get(this, 'isSaving'), false, 'record should not be saving'); assert.equal(get(this, 'hasDirtyAttributes'), false, 'record should not be dirty'); - } + }, }); const Adapter = DS.Adapter.extend({ @@ -127,12 +129,12 @@ test('a record receives a didCreate callback when it has finished updating', fun assert.equal(callCount, 0, 'didCreate callback was not called until didSaveRecord is called'); return resolve(); - } + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); assert.equal(callCount, 0, 'precond - didCreate callback was not called yet'); @@ -159,7 +161,7 @@ test('a record receives a didDelete callback when it has finished deleting', fun assert.equal(get(this, 'isSaving'), false, 'record should not be saving'); assert.equal(get(this, 'hasDirtyAttributes'), false, 'record should not be dirty'); - } + }, }); const Adapter = DS.Adapter.extend({ @@ -171,26 +173,28 @@ test('a record receives a didDelete callback when it has finished deleting', fun assert.equal(callCount, 0, 'didDelete callback was not called until didSaveRecord is called'); return resolve(); - } + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); let asyncPerson = run(() => store.findRecord('person', 1)); assert.equal(callCount, 0, 'precond - didDelete callback was not called yet'); return run(() => { - return asyncPerson.then(person => { - return run(() => { - person.deleteRecord(); - return person.save(); + return asyncPerson + .then(person => { + return run(() => { + person.deleteRecord(); + return person.save(); + }); + }) + .then(() => { + assert.equal(callCount, 1, 'didDelete called after delete'); }); - }).then(() => { - assert.equal(callCount, 1, 'didDelete called after delete'); - }); }); }); @@ -207,12 +211,12 @@ test('an uncommited record also receives a didDelete callback when it is deleted callCount++; assert.equal(get(this, 'isSaving'), false, 'record should not be saving'); assert.equal(get(this, 'hasDirtyAttributes'), false, 'record should not be dirty'); - } + }, }); let store = createStore({ adapter: DS.Adapter.extend(), - person: Person + person: Person, }); let person = store.createRecord('person', { name: 'Tomster' }); @@ -238,7 +242,7 @@ test('a record receives a becameInvalid callback when it became invalid', functi assert.equal(get(this, 'isSaving'), false, 'record should not be saving'); assert.equal(get(this, 'hasDirtyAttributes'), true, 'record should be dirty'); - } + }, }); const Adapter = DS.Adapter.extend({ @@ -247,23 +251,29 @@ test('a record receives a becameInvalid callback when it became invalid', functi }, updateRecord(store, type, snapshot) { - assert.equal(callCount, 0, 'becameInvalid callback was not called until recordWasInvalid is called'); - - return reject(new DS.InvalidError([ - { - title: 'Invalid Attribute', - detail: 'error', - source: { - pointer: '/data/attributes/bar' - } - } - ])); - } + assert.equal( + callCount, + 0, + 'becameInvalid callback was not called until recordWasInvalid is called' + ); + + return reject( + new DS.InvalidError([ + { + title: 'Invalid Attribute', + detail: 'error', + source: { + pointer: '/data/attributes/bar', + }, + }, + ]) + ); + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); let asyncPerson = run(() => store.findRecord('person', 1)); @@ -289,11 +299,11 @@ test('a record receives a becameInvalid callback when it became invalid', functi test('an ID of 0 is allowed', function(assert) { const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ - person: Person + person: Person, }); run(() => { @@ -302,11 +312,18 @@ test('an ID of 0 is allowed', function(assert) { type: 'person', id: '0', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); }); - assert.equal(store.peekAll('person').objectAt(0).get('name'), 'Tom Dale', 'found record with id 0'); + assert.equal( + store + .peekAll('person') + .objectAt(0) + .get('name'), + 'Tom Dale', + 'found record with id 0' + ); }); diff --git a/tests/unit/model/merge-test.js b/tests/unit/model/merge-test.js index 680db2281bd..f75315f2cc3 100644 --- a/tests/unit/model/merge-test.js +++ b/tests/unit/model/merge-test.js @@ -12,9 +12,9 @@ module('unit/model/merge - Merging', { beforeEach() { Person = DS.Model.extend({ name: DS.attr(), - city: DS.attr() + city: DS.attr(), }); - } + }, }); test('When a record is in flight, changes can be made', function(assert) { @@ -23,12 +23,12 @@ test('When a record is in flight, changes can be made', function(assert) { const Adapter = DS.Adapter.extend({ createRecord(store, type, snapshot) { return { data: { id: 1, type: 'person', attributes: { name: 'Tom Dale' } } }; - } + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); let person = store.createRecord('person', { name: 'Tom Dale' }); @@ -56,7 +56,7 @@ test('Make sure snapshot is created at save time not at flush time', function(as assert.equal(snapshot.attr('name'), 'Thomas Dale'); return resolve(); - } + }, }); let store = createStore({ adapter: Adapter, person: Person }); @@ -68,9 +68,9 @@ test('Make sure snapshot is created at save time not at flush time', function(as type: 'person', id: '1', attributes: { - name: "Tom" - } - } + name: 'Tom', + }, + }, }); person.set('name', 'Thomas Dale'); }); @@ -86,26 +86,32 @@ test('Make sure snapshot is created at save time not at flush time', function(as return promise.then(person => { assert.equal(person.get('hasDirtyAttributes'), true, 'The person is still dirty'); - assert.equal(person.get('name'), "Tomasz Dale", 'The local changes apply'); + assert.equal(person.get('name'), 'Tomasz Dale', 'The local changes apply'); }); }); }); -test("When a record is in flight, pushes are applied underneath the in flight changes", function(assert) { +test('When a record is in flight, pushes are applied underneath the in flight changes', function(assert) { assert.expect(6); const Adapter = DS.Adapter.extend({ updateRecord(store, type, snapshot) { // Make sure saving isn't resolved synchronously - return new EmberPromise(resolve => { - run.next(null, resolve, { data: { id: 1, type: 'person', attributes: { name: 'Senor Thomas Dale, Esq.', city: 'Portland' } } }); + return new EmberPromise(resolve => { + run.next(null, resolve, { + data: { + id: 1, + type: 'person', + attributes: { name: 'Senor Thomas Dale, Esq.', city: 'Portland' }, + }, + }); }); - } + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); let person; @@ -115,9 +121,9 @@ test("When a record is in flight, pushes are applied underneath the in flight ch type: 'person', id: '1', attributes: { - name: "Tom" - } - } + name: 'Tom', + }, + }, }); person.set('name', 'Thomas Dale'); }); @@ -134,10 +140,10 @@ test("When a record is in flight, pushes are applied underneath the in flight ch type: 'person', id: '1', attributes: { - name: "Tommy Dale", - city: "PDX" - } - } + name: 'Tommy Dale', + city: 'PDX', + }, + }, }); assert.equal(person.get('name'), 'Tomasz Dale', 'the local changes applied on top'); @@ -146,7 +152,11 @@ test("When a record is in flight, pushes are applied underneath the in flight ch return promise.then(person => { assert.equal(person.get('hasDirtyAttributes'), true, 'The person is still dirty'); assert.equal(person.get('name'), 'Tomasz Dale', 'The local changes apply'); - assert.equal(person.get('city'), 'Portland', 'The updates from the server apply on top of the previous pushes'); + assert.equal( + person.get('city'), + 'Portland', + 'The updates from the server apply on top of the previous pushes' + ); }); }); }); @@ -154,7 +164,7 @@ test("When a record is in flight, pushes are applied underneath the in flight ch test('When a record is dirty, pushes are overridden by local changes', function(assert) { let store = createStore({ adapter: DS.Adapter, - person: Person + person: Person, }); let person; @@ -165,9 +175,9 @@ test('When a record is dirty, pushes are overridden by local changes', function( id: '1', attributes: { name: 'Tom Dale', - city: 'San Francisco' - } - } + city: 'San Francisco', + }, + }, }); person.set('name', 'Tomasz Dale'); }); @@ -182,22 +192,26 @@ test('When a record is dirty, pushes are overridden by local changes', function( type: 'person', id: '1', attributes: { - name: "Thomas Dale", - city: "Portland" - } - } + name: 'Thomas Dale', + city: 'Portland', + }, + }, }); }); assert.equal(person.get('hasDirtyAttributes'), true, 'the local changes are reapplied'); assert.equal(person.get('name'), 'Tomasz Dale', 'the local changes are reapplied'); - assert.equal(person.get('city'), 'Portland', 'if there are no local changes, the new data applied'); + assert.equal( + person.get('city'), + 'Portland', + 'if there are no local changes, the new data applied' + ); }); test('When a record is invalid, pushes are overridden by local changes', function(assert) { let store = createStore({ adapter: DS.Adapter, - person: Person + person: Person, }); let person; @@ -208,9 +222,9 @@ test('When a record is invalid, pushes are overridden by local changes', functio id: '1', attributes: { name: 'Brendan McLoughlin', - city: 'Boston' - } - } + city: 'Boston', + }, + }, }); person.set('name', 'Brondan McLoughlin'); person.send('becameInvalid'); @@ -228,9 +242,9 @@ test('When a record is invalid, pushes are overridden by local changes', functio id: '1', attributes: { name: 'bmac', - city: 'Prague' - } - } + city: 'Prague', + }, + }, }); }); @@ -246,12 +260,12 @@ test('A record with no changes can still be saved', function(assert) { const Adapter = DS.Adapter.extend({ updateRecord(store, type, snapshot) { return { data: { id: 1, type: 'person', attributes: { name: 'Thomas Dale' } } }; - } + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); let person = run(() => { return store.push({ @@ -259,9 +273,9 @@ test('A record with no changes can still be saved', function(assert) { type: 'person', id: '1', attributeS: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); }); @@ -277,13 +291,15 @@ test('A dirty record can be reloaded', function(assert) { const Adapter = DS.Adapter.extend({ findRecord(store, type, id, snapshot) { - return { data: { id: 1, type: 'person', attributes: { name: 'Thomas Dale', city: 'Portland' } } }; - } + return { + data: { id: 1, type: 'person', attributes: { name: 'Thomas Dale', city: 'Portland' } }, + }; + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); let person; @@ -294,9 +310,9 @@ test('A dirty record can be reloaded', function(assert) { type: 'person', id: '1', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); person.set('name', 'Tomasz Dale'); }); @@ -304,8 +320,8 @@ test('A dirty record can be reloaded', function(assert) { return run(() => { return person.reload().then(() => { assert.equal(person.get('hasDirtyAttributes'), true, 'the person is dirty'); - assert.equal(person.get('name'), "Tomasz Dale", 'the local changes remain'); - assert.equal(person.get('city'), "Portland", 'the new changes apply'); + assert.equal(person.get('name'), 'Tomasz Dale', 'the local changes remain'); + assert.equal(person.get('city'), 'Portland', 'the new changes apply'); }); }); }); diff --git a/tests/unit/model/relationships-test.js b/tests/unit/model/relationships-test.js index d1d1ecf609d..74a5a06546d 100644 --- a/tests/unit/model/relationships-test.js +++ b/tests/unit/model/relationships-test.js @@ -14,16 +14,16 @@ module('unit/model/relationships - DS.Model', { Person = DS.Model.extend({ occupations: DS.hasMany('occupation', { async: false }), people: DS.hasMany('person', { inverse: 'parent', async: false }), - parent: DS.belongsTo('person', { inverse: 'people', async: false }) + parent: DS.belongsTo('person', { inverse: 'people', async: false }), }); store = createStore({ occupation: Occupation, - person: Person + person: Person, }); Person = store.modelFor('person'); - } + }, }); test('exposes a hash of the relationships on a model', function(assert) { @@ -38,23 +38,25 @@ test('exposes a hash of the relationships on a model', function(assert) { return { kind: desc.kind, name: desc.name, - options: desc.options + options: desc.options, }; }); } assert.deepEqual(extractDetails('person'), [ - { name: "people", kind: "hasMany", options: { async: false, inverse: 'parent'} }, - { name: "parent", kind: "belongsTo", options: { async: false, inverse: 'people' } } + { name: 'people', kind: 'hasMany', options: { async: false, inverse: 'parent' } }, + { name: 'parent', kind: 'belongsTo', options: { async: false, inverse: 'people' } }, ]); assert.deepEqual(extractDetails('occupation'), [ - { name: "occupations", kind: "hasMany", options: { async: false } } + { name: 'occupations', kind: 'hasMany', options: { async: false } }, ]); }); test('relationshipNames a hash of the relationships on a model with type as a key', function(assert) { - assert.deepEqual(get(Person, 'relationshipNames'), - { hasMany: ['occupations', 'people'], belongsTo: ["parent"] }); + assert.deepEqual(get(Person, 'relationshipNames'), { + hasMany: ['occupations', 'people'], + belongsTo: ['parent'], + }); }); test('eachRelatedType() iterates over relations without duplication', function(assert) { diff --git a/tests/unit/model/relationships/belongs-to-test.js b/tests/unit/model/relationships/belongs-to-test.js index 9a6601b15f2..062734ebe3c 100644 --- a/tests/unit/model/relationships/belongs-to-test.js +++ b/tests/unit/model/relationships/belongs-to-test.js @@ -14,12 +14,12 @@ test('belongsTo lazily loads relationships as needed', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -29,36 +29,41 @@ test('belongsTo lazily loads relationships as needed', function(assert) { run(() => { 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' + data: [ + { + type: 'tag', + id: '5', + attributes: { + name: 'friendly', + }, }, - relationships: { - tag: { - data: { type: 'tag', id: '5' } - } - } - }] + { + 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' }, + }, + }, + }, + ], }); }); @@ -69,8 +74,16 @@ test('belongsTo lazily loads relationships as needed', function(assert) { assert.equal(get(person, 'tag') instanceof Tag, true, 'the tag property should return a tag'); assert.equal(get(person, 'tag.name'), 'friendly', 'the tag shuld have name'); - assert.strictEqual(get(person, 'tag'), get(person, 'tag'), 'the returned object is always the same'); - assert.asyncEqual(get(person, 'tag'), store.findRecord('tag', 5), 'relationship object is the same as object retrieved directly'); + assert.strictEqual( + get(person, 'tag'), + get(person, 'tag'), + 'the returned object is always the same' + ); + assert.asyncEqual( + get(person, 'tag'), + store.findRecord('tag', 5), + 'relationship object is the same as object retrieved directly' + ); }); }); }); @@ -80,13 +93,13 @@ test('belongsTo does not notify when it is initially reified', function(assert) const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); Tag.toString = () => 'Tag'; const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); Person.toString = () => 'Person'; @@ -97,27 +110,30 @@ test('belongsTo does not notify when it is initially reified', function(assert) run(() => { store.push({ - data: [{ - type: 'tag', - id: 1, - attributes: { - name: 'whatever' - } - }, { - type: 'person', - id: 2, - attributes: { - name: 'David J. Hamilton' + data: [ + { + type: 'tag', + id: 1, + attributes: { + name: 'whatever', + }, }, - relationships: { - tag: { - data: { - type: 'tag', - id: '1' - } - } - } - }] + { + type: 'person', + id: 2, + attributes: { + name: 'David J. Hamilton', + }, + relationships: { + tag: { + data: { + type: 'tag', + id: '1', + }, + }, + }, + }, + ], }); }); @@ -125,7 +141,7 @@ test('belongsTo does not notify when it is initially reified', function(assert) let person = store.peekRecord('person', 2); person.addObserver('tag', () => { assert.ok(false, 'observer is not called'); - }) + }); assert.equal(person.get('tag.name'), 'whatever', 'relationship is correct'); }); @@ -135,12 +151,12 @@ test('async belongsTo relationships work when the data hash has not been loaded' assert.expect(5); const Tag = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: true }) + tag: DS.belongsTo('tag', { async: true }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -150,7 +166,14 @@ test('async belongsTo relationships work when the data hash has not been loaded' if (type === Person) { assert.equal(id, 1, 'id should be 1'); - return { data: { id: 1, type: 'person', attributes: { name: 'Tom Dale' }, relationships: { tag: { data: { id: 2, type: 'tag' } } } } }; + return { + data: { + id: 1, + type: 'person', + attributes: { name: 'Tom Dale' }, + relationships: { tag: { data: { id: 2, type: 'tag' } } }, + }, + }; } else if (type === Tag) { assert.equal(id, 2, 'id should be 2'); @@ -159,16 +182,19 @@ test('async belongsTo relationships work when the data hash has not been loaded' }; return run(() => { - return store.findRecord('person', 1).then(person => { - assert.equal(get(person, 'name'), 'Tom Dale', 'The person is now populated'); - - return run(() => { - return get(person, 'tag'); + return store + .findRecord('person', 1) + .then(person => { + assert.equal(get(person, 'name'), 'Tom Dale', 'The person is now populated'); + + return run(() => { + return get(person, 'tag'); + }); + }) + .then(tag => { + assert.equal(get(tag, 'name'), 'friendly', 'Tom Dale is now friendly'); + assert.equal(get(tag, 'isLoaded'), true, 'Tom Dale is now loaded'); }); - }).then(tag => { - assert.equal(get(tag, 'name'), 'friendly', 'Tom Dale is now friendly'); - assert.equal(get(tag, 'isLoaded'), true, 'Tom Dale is now loaded'); - }); }); }); @@ -176,12 +202,12 @@ test('async belongsTo relationships work when the data hash has already been loa assert.expect(3); const Tag = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: true }) + tag: DS.belongsTo('tag', { async: true }), }); var env = setupStore({ tag: Tag, person: Person }); @@ -189,24 +215,27 @@ test('async belongsTo relationships work when the data hash has already been loa run(() => { store.push({ - data: [{ - type: 'tag', - id: '2', - attributes: { - name: 'friendly' - } - }, { - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' + data: [ + { + type: 'tag', + id: '2', + attributes: { + name: 'friendly', + }, }, - relationships: { - tag: { - data: { type: 'tag', id: '2' } - } - } - }] + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + tag: { + data: { type: 'tag', id: '2' }, + }, + }, + }, + ], }); }); @@ -231,17 +260,18 @@ test('when response to saving a belongsTo is a success but includes changes that run(() => { store.push({ data: [ - { type: 'user', + { + type: 'user', id: '1', relationships: { tag: { - data: { type: 'tag', id: '1' } - } - } + data: { type: 'tag', id: '1' }, + }, + }, }, { type: 'tag', id: '1' }, - { type: 'tag', id: '2' } - ] + { type: 'tag', id: '2' }, + ], }); }); @@ -258,11 +288,11 @@ test('when response to saving a belongsTo is a success but includes changes that tag: { data: { id: '1', - type: 'tag' - } - } - } - } + type: 'tag', + }, + }, + }, + }, }; }; @@ -278,12 +308,12 @@ test('calling createRecord and passing in an undefined value for a relationship const Tag = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -294,7 +324,11 @@ test('calling createRecord and passing in an undefined value for a relationship return run(() => { return store.findRecord('person', '1').then(person => { - assert.strictEqual(person.get('tag'), null, 'undefined values should return null relationships'); + assert.strictEqual( + person.get('tag'), + null, + 'undefined values should return null relationships' + ); }); }); }); @@ -302,12 +336,12 @@ test('calling createRecord and passing in an undefined value for a relationship test('When finding a hasMany relationship the inverse belongsTo relationship is available immediately', function(assert) { const Occupation = DS.Model.extend({ description: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - occupations: DS.hasMany('occupation', { async: true }) + occupations: DS.hasMany('occupation', { async: true }), }); let env = setupStore({ occupation: Occupation, person: Person }); @@ -316,10 +350,12 @@ test('When finding a hasMany relationship the inverse belongsTo relationship is env.adapter.findMany = function(store, type, ids, snapshots) { assert.equal(snapshots[0].belongsTo('person').id, '1'); - return { data: [ - { id: 5, type: 'occupation', attributes: { description: "fifth" } }, - { id: 2, type: 'occupation', attributes: { description: "second" } } - ]}; + return { + data: [ + { id: 5, type: 'occupation', attributes: { description: 'fifth' } }, + { id: 2, type: 'occupation', attributes: { description: 'second' } }, + ], + }; }; env.adapter.coalesceFindRequests = true; @@ -330,32 +366,44 @@ test('When finding a hasMany relationship the inverse belongsTo relationship is type: 'person', id: '1', attributes: { - name: 'Tom Dale' + name: 'Tom Dale', }, relationships: { occupations: { - data: [ - { type: 'occupation', id: '5' }, - { type: 'occupation', id: '2' } - ] - } - } - } + data: [{ type: 'occupation', id: '5' }, { type: 'occupation', id: '2' }], + }, + }, + }, }); }); return run(() => { - return store.findRecord('person', 1).then(person => { - assert.equal(get(person, 'isLoaded'), true, 'isLoaded should be true'); - assert.equal(get(person, 'name'), 'Tom Dale', 'the person is still Tom Dale'); - - return get(person, 'occupations'); - }).then(occupations => { - assert.equal(get(occupations, 'length'), 2, 'the list of occupations should have the correct length'); - - assert.equal(get(occupations.objectAt(0), 'description'), 'fifth', 'the occupation is the fifth'); - assert.equal(get(occupations.objectAt(0), 'isLoaded'), true, 'the occupation is now loaded'); - }); + return store + .findRecord('person', 1) + .then(person => { + assert.equal(get(person, 'isLoaded'), true, 'isLoaded should be true'); + assert.equal(get(person, 'name'), 'Tom Dale', 'the person is still Tom Dale'); + + return get(person, 'occupations'); + }) + .then(occupations => { + assert.equal( + get(occupations, 'length'), + 2, + 'the list of occupations should have the correct length' + ); + + assert.equal( + get(occupations.objectAt(0), 'description'), + 'fifth', + 'the occupation is the fifth' + ); + assert.equal( + get(occupations.objectAt(0), 'isLoaded'), + true, + 'the occupation is now loaded' + ); + }); }); }); @@ -364,12 +412,12 @@ test('When finding a belongsTo relationship the inverse belongsTo relationship i const Occupation = DS.Model.extend({ description: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - occupation: DS.belongsTo('occupation', { async: true }) + occupation: DS.belongsTo('occupation', { async: true }), }); let env = setupStore({ occupation: Occupation, person: Person }); @@ -386,14 +434,14 @@ test('When finding a belongsTo relationship the inverse belongsTo relationship i type: 'person', id: '1', attributes: { - name: 'Tom Dale' + name: 'Tom Dale', }, relationships: { occupation: { - data: { type: 'occupation', id: '5' } - } - } - } + data: { type: 'occupation', id: '5' }, + }, + }, + }, }); }); @@ -405,12 +453,12 @@ test('belongsTo supports relationships to models with id 0', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -420,36 +468,41 @@ test('belongsTo supports relationships to models with id 0', function(assert) { run(() => { 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' + data: [ + { + type: 'tag', + id: '0', + attributes: { + name: 'friendly', + }, }, - relationships: { - tag: { - data: { type: 'tag', id: '0' } - } - } - }] + { + 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' }, + }, + }, + }, + ], }); }); @@ -458,22 +511,30 @@ test('belongsTo supports relationships to models with id 0', function(assert) { assert.equal(get(person, 'name'), 'Tom Dale', 'precond - retrieves person record from store'); assert.equal(get(person, 'tag') instanceof Tag, true, 'the tag property should return a tag'); - assert.equal(get(person, 'tag.name'), "friendly", 'the tag should have name'); - - assert.strictEqual(get(person, 'tag'), get(person, 'tag'), 'the returned object is always the same'); - assert.asyncEqual(get(person, 'tag'), store.findRecord('tag', 0), 'relationship object is the same as object retrieved directly'); + assert.equal(get(person, 'tag.name'), 'friendly', 'the tag should have name'); + + assert.strictEqual( + get(person, 'tag'), + get(person, 'tag'), + 'the returned object is always the same' + ); + assert.asyncEqual( + get(person, 'tag'), + store.findRecord('tag', 0), + 'relationship object is the same as object retrieved directly' + ); }); }); }); testInDebug('belongsTo gives a warning when provided with a serialize option', function(assert) { const Hobby = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const Person = DS.Model.extend({ name: DS.attr('string'), - hobby: DS.belongsTo('hobby', { serialize: true, async: true }) + hobby: DS.belongsTo('hobby', { serialize: true, async: true }), }); let env = setupStore({ hobby: Hobby, person: Person }); @@ -483,35 +544,39 @@ testInDebug('belongsTo gives a warning when provided with a serialize option', f run(() => { 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' + data: [ + { + type: 'hobby', + id: '1', + attributes: { + name: 'fishing', + }, }, - relationships: { - hobby: { - data: { type: 'hobby', id: '1' } - } - } - }] + { + type: 'hobby', + id: '2', + attributes: { + name: 'coding', + }, + }, + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + hobby: { + data: { type: 'hobby', id: '1' }, + }, + }, + }, + ], }); }); return run(() => { - return store.findRecord('person', 1).then(person =>{ + return store.findRecord('person', 1).then(person => { assert.expectWarning(() => { get(person, 'hobby'); }, /You provided a serialize option on the "hobby" property in the "person" class, this belongs in the serializer. See DS.Serializer and it's implementations/); @@ -519,14 +584,14 @@ testInDebug('belongsTo gives a warning when provided with a serialize option', f }); }); -testInDebug("belongsTo gives a warning when provided with an embedded option", function(assert) { +testInDebug('belongsTo gives a warning when provided with an embedded option', function(assert) { const Hobby = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const Person = DS.Model.extend({ name: DS.attr('string'), - hobby: DS.belongsTo('hobby', { embedded: true, async: true }) + hobby: DS.belongsTo('hobby', { embedded: true, async: true }), }); let env = setupStore({ hobby: Hobby, person: Person }); @@ -536,30 +601,34 @@ testInDebug("belongsTo gives a warning when provided with an embedded option", f run(() => { 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' + data: [ + { + type: 'hobby', + id: '1', + attributes: { + name: 'fishing', + }, }, - relationships: { - hobby: { - data: { type: 'hobby', id: '1' } - } - } - }] + { + type: 'hobby', + id: '2', + attributes: { + name: 'coding', + }, + }, + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + hobby: { + data: { type: 'hobby', id: '1' }, + }, + }, + }, + ], }); }); @@ -575,16 +644,16 @@ testInDebug("belongsTo gives a warning when provided with an embedded option", f test('DS.belongsTo should be async by default', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag') + tag: DS.belongsTo('tag'), }); let env = setupStore({ tag: Tag, person: Person }); - let { store } = env; + let { store } = env; let person = store.createRecord('person'); assert.ok(person.get('tag') instanceof DS.PromiseObject, 'tag should be an async relationship'); diff --git a/tests/unit/model/relationships/has-many-test.js b/tests/unit/model/relationships/has-many-test.js index 8feb6fb13aa..7f050c6fbbc 100644 --- a/tests/unit/model/relationships/has-many-test.js +++ b/tests/unit/model/relationships/has-many-test.js @@ -13,7 +13,7 @@ let env; module('unit/model/relationships - DS.hasMany', { beforeEach() { env = setupStore(); - } + }, }); test('hasMany handles pre-loaded relationships', function(assert) { @@ -21,18 +21,18 @@ test('hasMany handles pre-loaded relationships', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Pet = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), tags: DS.hasMany('tag', { async: false }), - pets: DS.hasMany('pet', { async: false }) + pets: DS.hasMany('pet', { async: false }), }); env.registry.register('model:tag', Tag); @@ -52,165 +52,197 @@ test('hasMany handles pre-loaded relationships', function(assert) { run(() => { 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' + data: [ + { + type: 'tag', + id: '5', + attributes: { + name: 'friendly', + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '5' } - ] - } - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Yehuda Katz' + { + type: 'tag', + id: '2', + attributes: { + name: 'smarmy', + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '12' } - ] - } - } - }] + { + 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' }], + }, + }, + }, + ], }); }); return run(() => { - return store.findRecord('person', 1).then(person => { - assert.equal(get(person, 'name'), 'Tom Dale', 'precond - retrieves person record from store'); - - let tags = get(person, 'tags'); - assert.equal(get(tags, 'length'), 1, 'the list of tags should have the correct length'); - assert.equal(get(tags.objectAt(0), 'name'), 'friendly', 'the first tag should be a Tag'); - - run(() => { - store.push({ - data: { - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' + return store + .findRecord('person', 1) + .then(person => { + assert.equal( + get(person, 'name'), + 'Tom Dale', + 'precond - retrieves person record from store' + ); + + let tags = get(person, 'tags'); + assert.equal(get(tags, 'length'), 1, 'the list of tags should have the correct length'); + assert.equal(get(tags.objectAt(0), 'name'), 'friendly', 'the first tag should be a Tag'); + + run(() => { + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + tags: { + data: [{ type: 'tag', id: '5' }, { type: 'tag', id: '2' }], + }, + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '5' }, - { type: 'tag', id: '2' } - ] - } - } - } + }); }); - }); - assert.equal(tags, get(person, 'tags'), 'a relationship returns the same object every time'); - assert.equal(get(get(person, 'tags'), 'length'), 2, 'the length is updated after new data is loaded'); - - assert.strictEqual(get(person, 'tags').objectAt(0), get(person, 'tags').objectAt(0), 'the returned object is always the same'); - assert.equal(get(person, 'tags').objectAt(0), store.peekRecord('tag', 5), 'relationship objects are the same as objects retrieved directly'); - - run(() => { - store.push({ - data: { - type: 'person', - id: '3', - attributes: { - name: 'KSelden' - } - } + assert.equal( + tags, + get(person, 'tags'), + 'a relationship returns the same object every time' + ); + assert.equal( + get(get(person, 'tags'), 'length'), + 2, + 'the length is updated after new data is loaded' + ); + + assert.strictEqual( + get(person, 'tags').objectAt(0), + get(person, 'tags').objectAt(0), + 'the returned object is always the same' + ); + assert.equal( + get(person, 'tags').objectAt(0), + store.peekRecord('tag', 5), + 'relationship objects are the same as objects retrieved directly' + ); + + run(() => { + store.push({ + data: { + type: 'person', + id: '3', + attributes: { + name: 'KSelden', + }, + }, + }); }); - }); - return store.findRecord('person', 3); - }).then(kselden => { - assert.equal(get(get(kselden, 'tags'), 'length'), 0, 'a relationship that has not been supplied returns an empty array'); - - run(() => { - store.push({ - data: { - type: 'person', - id: '4', - attributes: { - name: 'Cyvid Hamluck' + return store.findRecord('person', 3); + }) + .then(kselden => { + assert.equal( + get(get(kselden, 'tags'), 'length'), + 0, + 'a relationship that has not been supplied returns an empty array' + ); + + run(() => { + store.push({ + data: { + type: 'person', + id: '4', + attributes: { + name: 'Cyvid Hamluck', + }, + relationships: { + pets: { + data: [{ type: 'pet', id: '4' }], + }, + }, }, - relationships: { - pets: { - data: [ - { type: 'pet', id: '4' } - ] - } - } - } + }); }); - }); - return store.findRecord('person', 4); - }).then(cyvid => { - assert.equal(get(cyvid, 'name'), 'Cyvid Hamluck', 'precond - retrieves person record from store'); - - let pets = get(cyvid, 'pets'); - assert.equal(get(pets, 'length'), 1, 'the list of pets should have the correct length'); - assert.equal(get(pets.objectAt(0), 'name'), 'fluffy', 'the first pet should be correct'); - - run(() => { - store.push({ - data: { - type: 'person', - id: '4', - attributes: { - name: 'Cyvid Hamluck' + return store.findRecord('person', 4); + }) + .then(cyvid => { + assert.equal( + get(cyvid, 'name'), + 'Cyvid Hamluck', + 'precond - retrieves person record from store' + ); + + let pets = get(cyvid, 'pets'); + assert.equal(get(pets, 'length'), 1, 'the list of pets should have the correct length'); + assert.equal(get(pets.objectAt(0), 'name'), 'fluffy', 'the first pet should be correct'); + + run(() => { + store.push({ + data: { + type: 'person', + id: '4', + attributes: { + name: 'Cyvid Hamluck', + }, + relationships: { + pets: { + data: [{ type: 'pet', id: '4' }, { type: 'pet', id: '12' }], + }, + }, }, - relationships: { - pets: { - data: [ - { type: 'pet', id: '4' }, - { type: 'pet', id: '12' } - ] - } - } - } + }); }); - }); - assert.equal(pets, get(cyvid, 'pets'), 'a relationship returns the same object every time'); - assert.equal(get(get(cyvid, 'pets'), 'length'), 2, 'the length is updated after new data is loaded'); - }); + assert.equal(pets, get(cyvid, 'pets'), 'a relationship returns the same object every time'); + assert.equal( + get(get(cyvid, 'pets'), 'length'), + 2, + 'the length is updated after new data is loaded' + ); + }); }); }); @@ -219,13 +251,13 @@ test('hasMany does not notify when it is initially reified', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); Tag.toString = () => 'Tag'; const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); Person.toString = () => 'Person'; @@ -236,27 +268,32 @@ test('hasMany does not notify when it is initially reified', function(assert) { run(() => { store.push({ - data: [{ - type: 'tag', - id: 1, - attributes: { - name: 'whatever' + data: [ + { + type: 'tag', + id: 1, + attributes: { + name: 'whatever', + }, + relationships: { + people: { + data: [ + { + id: 2, + type: 'person', + }, + ], + }, + }, }, - relationships: { - people: { - data: [{ - id: 2, - type: 'person' - }] - } - } - }, { - type: 'person', - id: 2, - attributes: { - name: 'David J. Hamilton' - } - }] + { + type: 'person', + id: 2, + attributes: { + name: 'David J. Hamilton', + }, + }, + ], }); }); @@ -269,11 +306,7 @@ test('hasMany does not notify when it is initially reified', function(assert) { assert.ok(false, 'observer is not called'); }); - assert.equal( - tag.get('people').mapBy('name'), - 'David J. Hamilton', - 'relationship is correct' - ); + assert.equal(tag.get('people').mapBy('name'), 'David J. Hamilton', 'relationship is correct'); }); }); @@ -282,12 +315,12 @@ test('hasMany can be initially reified with null', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -301,14 +334,14 @@ test('hasMany can be initially reified with null', function(assert) { type: 'tag', id: 1, attributes: { - name: 'whatever' + name: 'whatever', }, relationships: { people: { - data: null - } - } - } + data: null, + }, + }, + }, }); }); @@ -324,12 +357,12 @@ test('hasMany with explicit initial null works even when the inverse was set to const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -344,34 +377,36 @@ test('hasMany with explicit initial null works even when the inverse was set to type: 'person', id: 1, attributes: { - name: 'David J. Hamilton' + name: 'David J. Hamilton', }, relationships: { tag: { data: { type: 'tag', - id: 1 - } - } - } + id: 1, + }, + }, + }, }, included: [ { type: 'tag', id: 1, attributes: { - name: 'whatever' + name: 'whatever', }, relationships: { people: { - data: [{ - type: 'person', - id: 1 - }] - } - } - } - ] + data: [ + { + type: 'person', + id: 1, + }, + ], + }, + }, + }, + ], }); // now we push in data for that record which says it has no relationships @@ -380,14 +415,14 @@ test('hasMany with explicit initial null works even when the inverse was set to type: 'tag', id: 1, attributes: { - name: 'whatever' + name: 'whatever', }, relationships: { people: { - data: null - } - } - } + data: null, + }, + }, + }, }); }); @@ -405,24 +440,24 @@ test('hasMany with duplicates from payload', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); Tag.reopenClass({ toString() { return 'tag'; - } + }, }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); Person.reopenClass({ toString() { return 'person'; - } + }, }); let env = setupStore({ tag: Tag, person: Person }); @@ -435,40 +470,40 @@ test('hasMany with duplicates from payload', function(assert) { type: 'person', id: 1, attributes: { - name: 'David J. Hamilton' + name: 'David J. Hamilton', }, relationships: { tag: { data: { type: 'tag', - id: 1 - } - } - } + id: 1, + }, + }, + }, }, included: [ { type: 'tag', id: 1, attributes: { - name: 'whatever' + name: 'whatever', }, relationships: { people: { data: [ { type: 'person', - id: 1 + id: 1, }, { type: 'person', - id: 1 - } - ] - } - } - } - ] + id: 1, + }, + ], + }, + }, + }, + ], }); }); @@ -483,24 +518,24 @@ test('many2many loads both sides #5140', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); Tag.reopenClass({ toString() { return 'tag'; - } + }, }); const Person = DS.Model.extend({ name: DS.attr('string'), - tags: DS.hasMany('tags', { async: false }) + tags: DS.hasMany('tags', { async: false }), }); Person.reopenClass({ toString() { return 'person'; - } + }, }); let env = setupStore({ tag: Tag, person: Person }); @@ -514,87 +549,91 @@ test('many2many loads both sides #5140', function(assert) { type: 'person', id: 1, attributes: { - name: 'David J. Hamilton' + name: 'David J. Hamilton', }, relationships: { - tags: [{ - data: { - type: 'tag', - id: 1 - } - }, - { - data: { - type: 'tag', - id: 2 - } - }] - } + tags: [ + { + data: { + type: 'tag', + id: 1, + }, + }, + { + data: { + type: 'tag', + id: 2, + }, + }, + ], + }, }, { type: 'person', id: 2, attributes: { - name: 'Gerald Dempsey Posey' + name: 'Gerald Dempsey Posey', }, relationships: { - tags: [{ - data: { - type: 'tag', - id: 1 - } - }, - { - data: { - type: 'tag', - id: 2 - } - }] - } + tags: [ + { + data: { + type: 'tag', + id: 1, + }, + }, + { + data: { + type: 'tag', + id: 2, + }, + }, + ], + }, }, { type: 'tag', id: 1, attributes: { - name: 'whatever' + name: 'whatever', }, relationships: { people: { data: [ { type: 'person', - id: 1 + id: 1, }, { type: 'person', - id: 2 - } - ] - } - } + id: 2, + }, + ], + }, + }, }, { type: 'tag', id: 2, attributes: { - name: 'nothing' + name: 'nothing', }, relationships: { people: { data: [ { type: 'person', - id: 1 + id: 1, }, { type: 'person', - id: 2 - } - ] - } - } - } - ] + id: 2, + }, + ], + }, + }, + }, + ], }); }); @@ -613,12 +652,12 @@ test('hasMany with explicit null works even when the inverse was set to not null const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person', { async: false }) + people: DS.hasMany('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -633,34 +672,36 @@ test('hasMany with explicit null works even when the inverse was set to not null type: 'person', id: 1, attributes: { - name: 'David J. Hamilton' + name: 'David J. Hamilton', }, relationships: { tag: { data: { type: 'tag', - id: 1 - } - } - } + id: 1, + }, + }, + }, }, included: [ { type: 'tag', id: 1, attributes: { - name: 'whatever' + name: 'whatever', }, relationships: { people: { - data: [{ - type: 'person', - id: 1 - }] - } - } - } - ] + data: [ + { + type: 'person', + id: 1, + }, + ], + }, + }, + }, + ], }); }); @@ -678,14 +719,14 @@ test('hasMany with explicit null works even when the inverse was set to not null type: 'tag', id: 1, attributes: { - name: 'whatever' + name: 'whatever', }, relationships: { people: { - data: null - } - } - } + data: null, + }, + }, + }, }); }); @@ -693,7 +734,7 @@ test('hasMany with explicit null works even when the inverse was set to not null let person = store.peekRecord('person', 1); let tag = store.peekRecord('tag', 1); - assert.equal(person.get('tag'), null,'relationship is now empty'); + assert.equal(person.get('tag'), null, 'relationship is now empty'); assert.equal(tag.get('people.length'), 0, 'relationship is correct'); }); }); @@ -703,7 +744,7 @@ test('hasMany tolerates reflexive self-relationships', function(assert) { const Person = DS.Model.extend({ name: DS.attr(), - trueFriends: DS.hasMany('person', { async: false }) + trueFriends: DS.hasMany('person', { async: false }), }); let env = setupStore({ person: Person }); @@ -715,17 +756,19 @@ test('hasMany tolerates reflexive self-relationships', function(assert) { id: '1', type: 'person', attributes: { - name: 'Edward II' + name: 'Edward II', }, relationships: { trueFriends: { - data: [{ - id: '1', - type: 'person' - }] - } - } - } + data: [ + { + id: '1', + type: 'person', + }, + ], + }, + }, + }, }); }); @@ -742,18 +785,18 @@ test('hasMany lazily loads async relationships', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Pet = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), tags: DS.hasMany('tag', { async: true }), - pets: DS.hasMany('pet', { async: false }) + pets: DS.hasMany('pet', { async: false }), }); env.registry.register('model:tag', Tag); @@ -773,89 +816,117 @@ test('hasMany lazily loads async relationships', function(assert) { run(() => { 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' + data: [ + { + type: 'tag', + id: '5', + attributes: { + name: 'friendly', + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '5' } - ] - } - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Yehuda Katz' + { + type: 'tag', + id: '2', + attributes: { + name: 'smarmy', + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '12' } - ] - } - } - }] + { + 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' }], + }, + }, + }, + ], }); }); - return run(() =>{ + return run(() => { let wycats; - store.findRecord('person', 2).then(function(person) { - wycats = person; - - assert.equal(get(wycats, 'name'), 'Yehuda Katz', 'precond - retrieves person record from store'); - - return hash({ - wycats, - tags: wycats.get('tags') + store + .findRecord('person', 2) + .then(function(person) { + wycats = person; + + assert.equal( + get(wycats, 'name'), + 'Yehuda Katz', + 'precond - retrieves person record from store' + ); + + return hash({ + wycats, + tags: wycats.get('tags'), + }); + }) + .then(records => { + assert.equal( + get(records.tags, 'length'), + 1, + 'the list of tags should have the correct length' + ); + assert.equal( + get(records.tags.objectAt(0), 'name'), + 'oohlala', + 'the first tag should be a Tag' + ); + + assert.strictEqual( + records.tags.objectAt(0), + records.tags.objectAt(0), + 'the returned object is always the same' + ); + assert.equal( + records.tags.objectAt(0), + store.peekRecord('tag', 12), + 'relationship objects are the same as objects retrieved directly' + ); + + return get(wycats, 'tags'); + }) + .then(tags => { + let newTag = store.createRecord('tag'); + tags.pushObject(newTag); }); - }).then(records => { - assert.equal(get(records.tags, 'length'), 1, 'the list of tags should have the correct length'); - assert.equal(get(records.tags.objectAt(0), 'name'), 'oohlala', 'the first tag should be a Tag'); - - assert.strictEqual(records.tags.objectAt(0), records.tags.objectAt(0), 'the returned object is always the same'); - assert.equal(records.tags.objectAt(0), store.peekRecord('tag', 12), 'relationship objects are the same as objects retrieved directly'); - - return get(wycats, 'tags'); - }).then(tags => { - let newTag = store.createRecord('tag'); - tags.pushObject(newTag); - }); }); }); @@ -863,63 +934,78 @@ test('should be able to retrieve the type for a hasMany relationship without spe const Tag = DS.Model.extend({}); const Person = DS.Model.extend({ - tags: DS.hasMany('tag', { async: false }) - + tags: DS.hasMany('tag', { async: false }), }); let env = setupStore({ tag: Tag, - person: Person + person: Person, }); - assert.equal(env.store.modelFor('person').typeForRelationship('tags', env.store), Tag, 'returns the relationship type'); + assert.equal( + env.store.modelFor('person').typeForRelationship('tags', env.store), + Tag, + 'returns the relationship type' + ); }); test('should be able to retrieve the type for a hasMany relationship specified using a string from its metadata', function(assert) { const Tag = DS.Model.extend({}); const Person = DS.Model.extend({ - tags: DS.hasMany('tag', { async: false }) + tags: DS.hasMany('tag', { async: false }), }); let env = setupStore({ tag: Tag, - person: Person + person: Person, }); - assert.equal(env.store.modelFor('person').typeForRelationship('tags', env.store), Tag, 'returns the relationship type'); + assert.equal( + env.store.modelFor('person').typeForRelationship('tags', env.store), + Tag, + 'returns the relationship type' + ); }); test('should be able to retrieve the type for a belongsTo relationship without specifying a type from its metadata', function(assert) { const Tag = DS.Model.extend({}); const Person = DS.Model.extend({ - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let env = setupStore({ tag: Tag, - person: Person + person: Person, }); - assert.equal(env.store.modelFor('person').typeForRelationship('tag', env.store), Tag, 'returns the relationship type'); + assert.equal( + env.store.modelFor('person').typeForRelationship('tag', env.store), + Tag, + 'returns the relationship type' + ); }); test('should be able to retrieve the type for a belongsTo relationship specified using a string from its metadata', function(assert) { const Tag = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const Person = DS.Model.extend({ - tags: DS.belongsTo('tag', { async: false }) + tags: DS.belongsTo('tag', { async: false }), }); let env = setupStore({ tag: Tag, - person: Person + person: Person, }); - assert.equal(env.store.modelFor('person').typeForRelationship('tags', env.store), Tag, 'returns the relationship type'); + assert.equal( + env.store.modelFor('person').typeForRelationship('tags', env.store), + Tag, + 'returns the relationship type' + ); }); test('relationships work when declared with a string path', function(assert) { @@ -927,61 +1013,67 @@ test('relationships work when declared with a string path', function(assert) { const Person = DS.Model.extend({ name: DS.attr('string'), - tags: DS.hasMany('tag', { async: false }) + tags: DS.hasMany('tag', { async: false }), }); const Tag = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let env = setupStore({ person: Person, - tag: Tag + tag: Tag, }); env.adapter.shouldBackgroundReloadRecord = () => false; run(() => { 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' + data: [ + { + type: 'tag', + id: '5', + attributes: { + name: 'friendly', + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '5' }, - { type: 'tag', id: '2' } - ] - } - } - }] + { + 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' }], + }, + }, + }, + ], }); }); return run(() => { return env.store.findRecord('person', 1).then(person => { assert.equal(get(person, 'name'), 'Tom Dale', 'precond - retrieves person record from store'); - assert.equal(get(person, 'tags.length'), 2, 'the list of tags should have the correct length'); + assert.equal( + get(person, 'tags.length'), + 2, + 'the list of tags should have the correct length' + ); }); }); }); @@ -991,12 +1083,12 @@ test('hasMany relationships work when the data hash has not been loaded', functi const Tag = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tags: DS.hasMany('tag', { async: true }) + tags: DS.hasMany('tag', { async: true }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -1007,10 +1099,12 @@ test('hasMany relationships work when the data hash has not been loaded', functi assert.equal(type, Tag, 'type should be Tag'); assert.deepEqual(ids, ['5', '2'], 'ids should be 5 and 2'); - return { data: [ - { id: 5, type: 'tag', attributes: { name: 'friendly' } }, - { id: 2, type: 'tag', attributes: { name: 'smarmy' } } - ]}; + return { + data: [ + { id: 5, type: 'tag', attributes: { name: 'friendly' } }, + { id: 2, type: 'tag', attributes: { name: 'smarmy' } }, + ], + }; }; env.adapter.findRecord = function(store, type, id, snapshot) { @@ -1024,23 +1118,26 @@ test('hasMany relationships work when the data hash has not been loaded', functi attributes: { name: 'Tom Dale' }, relationships: { tags: { - data: [{ id: 5, type: 'tag'}, { id: 2, type: 'tag'}] - } - } - } + data: [{ id: 5, type: 'tag' }, { id: 2, type: 'tag' }], + }, + }, + }, }; }; return run(() => { - return store.findRecord('person', 1).then(person => { - assert.equal(get(person, 'name'), 'Tom Dale', 'The person is now populated'); - - return run(() => person.get('tags')); - }).then(tags => { - assert.equal(get(tags, 'length'), 2, 'the tags object still exists'); - assert.equal(get(tags.objectAt(0), 'name'), 'friendly', 'Tom Dale is now friendly'); - assert.equal(get(tags.objectAt(0), 'isLoaded'), true, 'Tom Dale is now loaded'); - }); + return store + .findRecord('person', 1) + .then(person => { + assert.equal(get(person, 'name'), 'Tom Dale', 'The person is now populated'); + + return run(() => person.get('tags')); + }) + .then(tags => { + assert.equal(get(tags, 'length'), 2, 'the tags object still exists'); + assert.equal(get(tags.objectAt(0), 'name'), 'friendly', 'Tom Dale is now friendly'); + assert.equal(get(tags.objectAt(0), 'isLoaded'), true, 'Tom Dale is now loaded'); + }); }); }); @@ -1049,17 +1146,17 @@ test('it is possible to add a new item to a relationship', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.belongsTo('person', { async: false }) + people: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tags: DS.hasMany('tag', { async: false }) + tags: DS.hasMany('tag', { async: false }), }); let env = setupStore({ tag: Tag, - person: Person + person: Person, }); env.adapter.shouldBackgroundReloadRecord = () => false; @@ -1067,31 +1164,32 @@ test('it is possible to add a new item to a relationship', function(assert) { run(() => { store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + tags: { + data: [{ type: 'tag', id: '1' }], + }, + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '1' } - ] - } - } - }, { - type: 'tag', - id: '1', - attributes: { - name: 'ember' - } - }] + { + type: 'tag', + id: '1', + attributes: { + name: 'ember', + }, + }, + ], }); }); return run(() => { - return store.findRecord('person', 1).then(person =>{ + return store.findRecord('person', 1).then(person => { let tag = get(person, 'tags').objectAt(0); assert.equal(get(tag, 'name'), 'ember', 'precond - relationships work'); @@ -1109,17 +1207,17 @@ test('new items added to a hasMany relationship are not cleared by a delete', fu const Person = DS.Model.extend({ name: DS.attr('string'), - pets: DS.hasMany('pet', { async: false, inverse: null }) + pets: DS.hasMany('pet', { async: false, inverse: null }), }); const Pet = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false, inverse: null }) + person: DS.belongsTo('person', { async: false, inverse: null }), }); let env = setupStore({ person: Person, - pet: Pet + pet: Pet, }); env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.deleteRecord = () => { @@ -1134,39 +1232,37 @@ test('new items added to a hasMany relationship are not cleared by a delete', fu type: 'person', id: '1', attributes: { - name: 'Chris Thoburn' + name: 'Chris Thoburn', }, relationships: { pets: { - data: [ - { type: 'pet', id: '1' } - ] - } - } + data: [{ type: 'pet', id: '1' }], + }, + }, }, included: [ { type: 'pet', id: '1', attributes: { - name: 'Shenanigans' - } + name: 'Shenanigans', + }, }, { type: 'pet', id: '2', attributes: { - name: 'Rambunctious' - } + name: 'Rambunctious', + }, }, { type: 'pet', id: '3', attributes: { - name: 'Rebel' - } - } - ] + name: 'Rebel', + }, + }, + ], }); }); @@ -1178,22 +1274,33 @@ test('new items added to a hasMany relationship are not cleared by a delete', fu const rebel = store.peekRecord('pet', '3'); assert.equal(get(shen, 'name'), 'Shenanigans', 'precond - relationships work'); - assert.deepEqual(pets.map(p => get(p, 'id')), ['1'], 'precond - relationship has the correct pets to start'); + assert.deepEqual( + pets.map(p => get(p, 'id')), + ['1'], + 'precond - relationship has the correct pets to start' + ); run(() => { pets.pushObjects([rambo, rebel]); }); - assert.deepEqual(pets.map(p => get(p, 'id')), ['1', '2', '3'], 'precond2 - relationship now has the correct three pets'); + assert.deepEqual( + pets.map(p => get(p, 'id')), + ['1', '2', '3'], + 'precond2 - relationship now has the correct three pets' + ); run(() => { - return shen.destroyRecord({}) - .then(() => { - shen.unloadRecord(); - }); + return shen.destroyRecord({}).then(() => { + shen.unloadRecord(); + }); }); - assert.deepEqual(pets.map(p => get(p, 'id')), ['2', '3'], 'relationship now has the correct two pets'); + assert.deepEqual( + pets.map(p => get(p, 'id')), + ['2', '3'], + 'relationship now has the correct two pets' + ); }); test('new items added to an async hasMany relationship are not cleared by a delete', function(assert) { @@ -1201,17 +1308,17 @@ test('new items added to an async hasMany relationship are not cleared by a dele const Person = DS.Model.extend({ name: DS.attr('string'), - pets: DS.hasMany('pet', { async: true, inverse: null }) + pets: DS.hasMany('pet', { async: true, inverse: null }), }); const Pet = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false, inverse: null }) + person: DS.belongsTo('person', { async: false, inverse: null }), }); let env = setupStore({ person: Person, - pet: Pet + pet: Pet, }); env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.deleteRecord = () => { @@ -1226,39 +1333,37 @@ test('new items added to an async hasMany relationship are not cleared by a dele type: 'person', id: '1', attributes: { - name: 'Chris Thoburn' + name: 'Chris Thoburn', }, relationships: { pets: { - data: [ - { type: 'pet', id: '1' } - ] - } - } + data: [{ type: 'pet', id: '1' }], + }, + }, }, included: [ { type: 'pet', id: '1', attributes: { - name: 'Shenanigans' - } + name: 'Shenanigans', + }, }, { type: 'pet', id: '2', attributes: { - name: 'Rambunctious' - } + name: 'Rambunctious', + }, }, { type: 'pet', id: '3', attributes: { - name: 'Rebel' - } - } - ] + name: 'Rebel', + }, + }, + ], }); }); @@ -1266,27 +1371,38 @@ test('new items added to an async hasMany relationship are not cleared by a dele const person = store.peekRecord('person', '1'); const petsProxy = run(() => person.get('pets')); - return petsProxy.then((pets) => { + return petsProxy.then(pets => { const shen = pets.objectAt(0); const rambo = store.peekRecord('pet', '2'); const rebel = store.peekRecord('pet', '3'); assert.equal(get(shen, 'name'), 'Shenanigans', 'precond - relationships work'); - assert.deepEqual(pets.map(p => get(p, 'id')), ['1'], 'precond - relationship has the correct pet to start'); + assert.deepEqual( + pets.map(p => get(p, 'id')), + ['1'], + 'precond - relationship has the correct pet to start' + ); assert.equal(get(petsProxy, 'length'), 1, 'precond - proxy has only one pet to start'); pets.pushObjects([rambo, rebel]); - assert.deepEqual(pets.map(p => get(p, 'id')), ['1', '2', '3'], 'precond2 - relationship now has the correct three pets'); + assert.deepEqual( + pets.map(p => get(p, 'id')), + ['1', '2', '3'], + 'precond2 - relationship now has the correct three pets' + ); assert.equal(get(petsProxy, 'length'), 3, 'precond2 - proxy now reflects three pets'); - return shen.destroyRecord({}) - .then(() => { - shen.unloadRecord(); + return shen.destroyRecord({}).then(() => { + shen.unloadRecord(); - assert.deepEqual(pets.map(p => get(p, 'id')), ['2', '3'], 'relationship now has the correct two pets'); - assert.equal(get(petsProxy, 'length'), 2, 'proxy now reflects two pets'); - }); + assert.deepEqual( + pets.map(p => get(p, 'id')), + ['2', '3'], + 'relationship now has the correct two pets' + ); + assert.equal(get(petsProxy, 'length'), 2, 'proxy now reflects two pets'); + }); }); }); }); @@ -1296,16 +1412,16 @@ test('new items added to a belongsTo relationship are not cleared by a delete', const Person = DS.Model.extend({ name: DS.attr('string'), - dog: DS.belongsTo('dog', { async: false, inverse: null }) + dog: DS.belongsTo('dog', { async: false, inverse: null }), }); const Dog = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let env = setupStore({ person: Person, - dog: Dog + dog: Dog, }); env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.deleteRecord = () => { @@ -1320,30 +1436,30 @@ test('new items added to a belongsTo relationship are not cleared by a delete', type: 'person', id: '1', attributes: { - name: 'Chris Thoburn' + name: 'Chris Thoburn', }, relationships: { dog: { - data: { type: 'dog', id: '1' } - } - } + data: { type: 'dog', id: '1' }, + }, + }, }, included: [ { type: 'dog', id: '1', attributes: { - name: 'Shenanigans' - } + name: 'Shenanigans', + }, }, { type: 'dog', id: '2', attributes: { - name: 'Rambunctious' - } - } - ] + name: 'Rambunctious', + }, + }, + ], }); }); @@ -1363,13 +1479,12 @@ test('new items added to a belongsTo relationship are not cleared by a delete', assert.equal(dog, rambo, 'precond2 - relationship was updated'); return run(() => { - return shen.destroyRecord({}) - .then(() => { - shen.unloadRecord(); + return shen.destroyRecord({}).then(() => { + shen.unloadRecord(); - dog = person.get('dog'); - assert.equal(dog, rambo, 'The currentState of the belongsTo was preserved after the delete'); - }); + dog = person.get('dog'); + assert.equal(dog, rambo, 'The currentState of the belongsTo was preserved after the delete'); + }); }); }); @@ -1378,16 +1493,16 @@ test('new items added to an async belongsTo relationship are not cleared by a de const Person = DS.Model.extend({ name: DS.attr('string'), - dog: DS.belongsTo('dog', { async: true, inverse: null }) + dog: DS.belongsTo('dog', { async: true, inverse: null }), }); const Dog = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let env = setupStore({ person: Person, - dog: Dog + dog: Dog, }); env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.deleteRecord = () => { @@ -1402,30 +1517,30 @@ test('new items added to an async belongsTo relationship are not cleared by a de type: 'person', id: '1', attributes: { - name: 'Chris Thoburn' + name: 'Chris Thoburn', }, relationships: { dog: { - data: { type: 'dog', id: '1' } - } - } + data: { type: 'dog', id: '1' }, + }, + }, }, included: [ { type: 'dog', id: '1', attributes: { - name: 'Shenanigans' - } + name: 'Shenanigans', + }, }, { type: 'dog', id: '2', attributes: { - name: 'Rambunctious' - } - } - ] + name: 'Rambunctious', + }, + }, + ], }); }); @@ -1434,7 +1549,7 @@ test('new items added to an async belongsTo relationship are not cleared by a de const shen = store.peekRecord('dog', '1'); const rambo = store.peekRecord('dog', '2'); - return person.get('dog').then((dog) => { + return person.get('dog').then(dog => { assert.ok(dog === shen, 'precond - the belongsTo points to the correct dog'); assert.equal(get(dog, 'name'), 'Shenanigans', 'precond - relationships work'); @@ -1444,13 +1559,15 @@ test('new items added to an async belongsTo relationship are not cleared by a de assert.ok(dog === rambo, 'precond2 - relationship was updated'); - return shen.destroyRecord({}) - .then(() => { - shen.unloadRecord(); + return shen.destroyRecord({}).then(() => { + shen.unloadRecord(); - dog = person.get('dog.content'); - assert.ok(dog === rambo, 'The currentState of the belongsTo was preserved after the delete'); - }); + dog = person.get('dog.content'); + assert.ok( + dog === rambo, + 'The currentState of the belongsTo was preserved after the delete' + ); + }); }); }); }); @@ -1460,16 +1577,16 @@ test('deleting an item that is the current state of a belongsTo clears currentSt const Person = DS.Model.extend({ name: DS.attr('string'), - dog: DS.belongsTo('dog', { async: false, inverse: null }) + dog: DS.belongsTo('dog', { async: false, inverse: null }), }); const Dog = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let env = setupStore({ person: Person, - dog: Dog + dog: Dog, }); env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.deleteRecord = () => { @@ -1484,30 +1601,30 @@ test('deleting an item that is the current state of a belongsTo clears currentSt type: 'person', id: '1', attributes: { - name: 'Chris Thoburn' + name: 'Chris Thoburn', }, relationships: { dog: { - data: { type: 'dog', id: '1' } - } - } + data: { type: 'dog', id: '1' }, + }, + }, }, included: [ { type: 'dog', id: '1', attributes: { - name: 'Shenanigans' - } + name: 'Shenanigans', + }, }, { type: 'dog', id: '2', attributes: { - name: 'Rambunctious' - } - } - ] + name: 'Rambunctious', + }, + }, + ], }); }); @@ -1527,41 +1644,40 @@ test('deleting an item that is the current state of a belongsTo clears currentSt assert.equal(dog, rambo, 'precond2 - relationship was updated'); return run(() => { - return rambo.destroyRecord({}) - .then(() => { - rambo.unloadRecord(); + return rambo.destroyRecord({}).then(() => { + rambo.unloadRecord(); - dog = person.get('dog'); - assert.equal(dog, null, 'The current state of the belongsTo was clearer'); - }); + dog = person.get('dog'); + assert.equal(dog, null, 'The current state of the belongsTo was clearer'); + }); }); }); test('hasMany.firstObject.unloadRecord should not break that hasMany', function(assert) { const Person = DS.Model.extend({ cars: DS.hasMany('car', { async: false }), - name: DS.attr() + name: DS.attr(), }); Person.reopenClass({ toString() { return 'person'; - } + }, }); const Car = DS.Model.extend({ - name: DS.attr() + name: DS.attr(), }); Car.reopenClass({ toString() { return 'car'; - } + }, }); let env = setupStore({ person: Person, - car: Car + car: Car, }); run(() => { @@ -1571,21 +1687,18 @@ test('hasMany.firstObject.unloadRecord should not break that hasMany', function( type: 'person', id: 1, attributes: { - name: 'marvin' + name: 'marvin', }, relationships: { cars: { - data: [ - { type: 'car', id: 1 }, - { type: 'car', id: 2 } - ] - } - } + data: [{ type: 'car', id: 1 }, { type: 'car', id: 2 }], + }, + }, }, { type: 'car', id: 1, attributes: { name: 'a' } }, - { type: 'car', id: 2, attributes: { name: 'b' } } - ] - }) + { type: 'car', id: 2, attributes: { name: 'b' } }, + ], + }); }); let person = env.store.peekRecord('person', 1); @@ -1616,17 +1729,17 @@ test('[ASSERTS KNOWN LIMITATION STILL EXISTS] returning new hasMany relationship const Person = DS.Model.extend({ name: DS.attr('string'), - pets: DS.hasMany('pet', { async: false, inverse: null }) + pets: DS.hasMany('pet', { async: false, inverse: null }), }); const Pet = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false, inverse: null }) + person: DS.belongsTo('person', { async: false, inverse: null }), }); let env = setupStore({ person: Person, - pet: Pet + pet: Pet, }); env.adapter.shouldBackgroundReloadRecord = () => false; env.adapter.deleteRecord = () => { @@ -1637,17 +1750,15 @@ test('[ASSERTS KNOWN LIMITATION STILL EXISTS] returning new hasMany relationship type: 'person', id: '1', attributes: { - name: 'Chris Thoburn' + name: 'Chris Thoburn', }, relationships: { pets: { - data: [ - { type: 'pet', id: '2' } - ] - } - } - } - ] + data: [{ type: 'pet', id: '2' }], + }, + }, + }, + ], }); }; @@ -1659,40 +1770,37 @@ test('[ASSERTS KNOWN LIMITATION STILL EXISTS] returning new hasMany relationship type: 'person', id: '1', attributes: { - name: 'Chris Thoburn' + name: 'Chris Thoburn', }, relationships: { pets: { - data: [ - { type: 'pet', id: '1' }, - { type: 'pet', id: '2' } - ] - } - } + data: [{ type: 'pet', id: '1' }, { type: 'pet', id: '2' }], + }, + }, }, included: [ { type: 'pet', id: '1', attributes: { - name: 'Shenanigans' - } + name: 'Shenanigans', + }, }, { type: 'pet', id: '2', attributes: { - name: 'Rambunctious' - } + name: 'Rambunctious', + }, }, { type: 'pet', id: '3', attributes: { - name: 'Rebel' - } - } - ] + name: 'Rebel', + }, + }, + ], }); }); @@ -1703,22 +1811,33 @@ test('[ASSERTS KNOWN LIMITATION STILL EXISTS] returning new hasMany relationship const rebel = store.peekRecord('pet', '3'); assert.equal(get(shen, 'name'), 'Shenanigans', 'precond - relationships work'); - assert.deepEqual(pets.map(p => get(p, 'id')), ['1', '2'], 'precond - relationship has the correct pets to start'); + assert.deepEqual( + pets.map(p => get(p, 'id')), + ['1', '2'], + 'precond - relationship has the correct pets to start' + ); run(() => { pets.pushObjects([rebel]); }); - assert.deepEqual(pets.map(p => get(p, 'id')), ['1', '2', '3'], 'precond2 - relationship now has the correct three pets'); + assert.deepEqual( + pets.map(p => get(p, 'id')), + ['1', '2', '3'], + 'precond2 - relationship now has the correct three pets' + ); return run(() => { - return shen.destroyRecord({}) - .then(() => { - shen.unloadRecord(); - - // were ember-data to now preserve local edits during a relationship push, this would be '2' - assert.deepEqual(pets.map(p => get(p, 'id')), ['2'], 'relationship now has only one pet, we lost the local change'); - }); + return shen.destroyRecord({}).then(() => { + shen.unloadRecord(); + + // were ember-data to now preserve local edits during a relationship push, this would be '2' + assert.deepEqual( + pets.map(p => get(p, 'id')), + ['2'], + 'relationship now has only one pet, we lost the local change' + ); + }); }); }); @@ -1727,12 +1846,12 @@ test('possible to replace items in a relationship using setObjects w/ Ember Enum const Tag = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tags: DS.hasMany('tag', { async: false }) + tags: DS.hasMany('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -1740,45 +1859,46 @@ test('possible to replace items in a relationship using setObjects w/ Ember Enum run(() => { store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + tags: { + data: [{ type: 'tag', id: '1' }], + }, + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '1' } - ] - } - } - }, { - type: 'person', - id: '2', - attributes: { - name: 'Sylvain Mina' + { + type: 'person', + id: '2', + attributes: { + name: 'Sylvain Mina', + }, + relationships: { + tags: { + data: [{ type: 'tag', id: '2' }], + }, + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '2' } - ] - } - } - }, { - type: 'tag', - id: '1', - attributes: { - name: 'ember' - } - }, { - type: 'tag', - id: '2', - attributes: { - name: 'ember-data' - } - }] + { + type: 'tag', + id: '1', + attributes: { + name: 'ember', + }, + }, + { + type: 'tag', + id: '2', + attributes: { + name: 'ember-data', + }, + }, + ], }); }); @@ -1801,12 +1921,12 @@ test('it is possible to remove an item from a relationship', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tags: DS.hasMany('tag', { async: false }) + tags: DS.hasMany('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -1816,26 +1936,27 @@ test('it is possible to remove an item from a relationship', function(assert) { run(() => { store.push({ - data: [{ - type: 'person', - id: '1', - attributes: { - name: 'Tom Dale' + data: [ + { + type: 'person', + id: '1', + attributes: { + name: 'Tom Dale', + }, + relationships: { + tags: { + data: [{ type: 'tag', id: '1' }], + }, + }, }, - relationships: { - tags: { - data: [ - { type: 'tag', id: '1' } - ] - } - } - }, { - type: 'tag', - id: '1', - attributes: { - name: 'ember' - } - }] + { + type: 'tag', + id: '1', + attributes: { + name: 'ember', + }, + }, + ], }); }); @@ -1855,12 +1976,12 @@ test('it is possible to remove an item from a relationship', function(assert) { test('it is possible to add an item to a relationship, remove it, then add it again', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tags: DS.hasMany('tag', { async: false }) + tags: DS.hasMany('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -1890,15 +2011,15 @@ test('it is possible to add an item to a relationship, remove it, then add it ag assert.equal(tags.objectAt(2), tag3); }); -test("DS.hasMany is async by default", function(assert) { +test('DS.hasMany is async by default', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person') + people: DS.hasMany('person'), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let { store } = setupStore({ tag: Tag, person: Person }); @@ -1910,12 +2031,12 @@ test("DS.hasMany is async by default", function(assert) { test('DS.hasMany is stable', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person') + people: DS.hasMany('person'), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let { store } = setupStore({ tag: Tag, person: Person }); @@ -1931,20 +2052,18 @@ test('DS.hasMany is stable', function(assert) { assert.equal(people, notifiedPeople); - return EmberPromise.all([ - people - ]); + return EmberPromise.all([people]); }); test('DS.hasMany proxy is destroyed', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - people: DS.hasMany('person') + people: DS.hasMany('person'), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let { store } = setupStore({ tag: Tag, person: Person }); @@ -1964,12 +2083,28 @@ test('DS.hasMany proxy is destroyed', function(assert) { // prior to RecordData, this was coupled to the destroy // of the relationship, which was async and possibly could // be cancelled were an unload to be aborted. - assert.equal(peopleProxy.isDestroying, isRecordDataBuild, 'peopleProxy is not destroying sync after unloadRecord'); - assert.equal(peopleProxy.isDestroyed, false, 'peopleProxy is NOT YET destroyed sync after unloadRecord'); + assert.equal( + peopleProxy.isDestroying, + isRecordDataBuild, + 'peopleProxy is not destroying sync after unloadRecord' + ); + assert.equal( + peopleProxy.isDestroyed, + false, + 'peopleProxy is NOT YET destroyed sync after unloadRecord' + ); }); - assert.equal(peopleProxy.isDestroying, true, 'peopleProxy is destroying after the run post unloadRecord'); - assert.equal(peopleProxy.isDestroyed, true, 'peopleProxy is destroyed after the run post unloadRecord'); + assert.equal( + peopleProxy.isDestroying, + true, + 'peopleProxy is destroying after the run post unloadRecord' + ); + assert.equal( + peopleProxy.isDestroyed, + true, + 'peopleProxy is destroyed after the run post unloadRecord' + ); }); }); @@ -1980,12 +2115,12 @@ test('DS.ManyArray is lazy', function(assert) { people: DS.hasMany('person'), peopleDidChange: observer('people', function() { peopleDidChange++; - }) + }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tag: DS.belongsTo('tag', { async: false }) + tag: DS.belongsTo('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -1996,18 +2131,34 @@ test('DS.ManyArray is lazy', function(assert) { //assert.ok(!hasManyRelationship._manyArray); run(() => { - assert.equal(peopleDidChange, 0, 'expect people hasMany to not emit a change event (before access)'); + assert.equal( + peopleDidChange, + 0, + 'expect people hasMany to not emit a change event (before access)' + ); tag.get('people'); - assert.equal(peopleDidChange, 0, 'expect people hasMany to not emit a change event (sync after access)'); + assert.equal( + peopleDidChange, + 0, + 'expect people hasMany to not emit a change event (sync after access)' + ); }); - assert.equal(peopleDidChange, 0, 'expect people hasMany to not emit a change event (after access, but after the current run loop)'); + assert.equal( + peopleDidChange, + 0, + 'expect people hasMany to not emit a change event (after access, but after the current run loop)' + ); //assert.ok(hasManyRelationship._manyArray instanceof DS.ManyArray); let person = env.store.createRecord('person'); run(() => { - assert.equal(peopleDidChange, 0, 'expect people hasMany to not emit a change event (before access)'); + assert.equal( + peopleDidChange, + 0, + 'expect people hasMany to not emit a change event (before access)' + ); tag.get('people').addObject(person); assert.equal(peopleDidChange, 1, 'expect people hasMany to have changed exactly once'); }); @@ -2018,12 +2169,12 @@ test('fetch hasMany loads full relationship after a parent and child have been l const Tag = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: true, inverse: 'tags' }) + person: DS.belongsTo('person', { async: true, inverse: 'tags' }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tags: DS.hasMany('tag', { async: true, inverse: 'person' }) + tags: DS.hasMany('tag', { async: true, inverse: 'person' }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -2032,11 +2183,13 @@ test('fetch hasMany loads full relationship after a parent and child have been l env.adapter.findHasMany = function(store, snapshot, url, relationship) { assert.equal(relationship.key, 'tags', 'relationship should be tags'); - return { data: [ - { id: 1, type: 'tag', attributes: { name: 'first' } }, - { id: 2, type: 'tag', attributes: { name: 'second' } }, - { id: 3, type: 'tag', attributes: { name: 'third' } } - ]}; + return { + data: [ + { id: 1, type: 'tag', attributes: { name: 'first' } }, + { id: 2, type: 'tag', attributes: { name: 'second' } }, + { id: 3, type: 'tag', attributes: { name: 'third' } }, + ], + }; }; env.adapter.findRecord = function(store, type, id, snapshot) { @@ -2047,9 +2200,9 @@ test('fetch hasMany loads full relationship after a parent and child have been l type: 'person', attributes: { name: 'Watson' }, relationships: { - tags: { links: { related: 'person/1/tags'} } - } - } + tags: { links: { related: 'person/1/tags' } }, + }, + }, }; } else if (type === Tag) { return { @@ -2059,13 +2212,13 @@ test('fetch hasMany loads full relationship after a parent and child have been l attributes: { name: 'second' }, relationships: { person: { - data: { id: 1, type: 'person'} - } - } - } + data: { id: 1, type: 'person' }, + }, + }, + }, }; } else { - assert.true(false, 'wrong type') + assert.true(false, 'wrong type'); } }; @@ -2077,9 +2230,11 @@ test('fetch hasMany loads full relationship after a parent and child have been l return store.findRecord('tag', 2).then(tag => { assert.equal(get(tag, 'name'), 'second', 'The tag is now loaded'); - return run(() => person.get('tags').then(tags => { - assert.equal(get(tags, 'length'), 3, 'the tags are all loaded'); - })); + return run(() => + person.get('tags').then(tags => { + assert.equal(get(tags, 'length'), 3, 'the tags are all loaded'); + }) + ); }); }); }); @@ -2088,10 +2243,10 @@ test('fetch hasMany loads full relationship after a parent and child have been l testInDebug('throws assertion if of not set with an array', function(assert) { const Person = DS.Model.extend(); const Tag = DS.Model.extend({ - people: DS.hasMany('person') + people: DS.hasMany('person'), }); - let { store }= setupStore({ tag: Tag, person: Person }); + let { store } = setupStore({ tag: Tag, person: Person }); let tag = store.createRecord('tag'); let person = store.createRecord('person'); @@ -2105,7 +2260,7 @@ testInDebug('throws assertion if of not set with an array', function(assert) { testInDebug('checks if passed array only contains instances of DS.Model', function(assert) { const Person = DS.Model.extend(); const Tag = DS.Model.extend({ - people: DS.hasMany('person') + people: DS.hasMany('person'), }); let env = setupStore({ tag: Tag, person: Person }); @@ -2114,8 +2269,8 @@ testInDebug('checks if passed array only contains instances of DS.Model', functi return { data: { type: 'person', - id: 1 - } + id: 1, + }, }; }; diff --git a/tests/unit/model/relationships/record-array-test.js b/tests/unit/model/relationships/record-array-test.js index 7cdf36da71c..e9711270821 100644 --- a/tests/unit/model/relationships/record-array-test.js +++ b/tests/unit/model/relationships/record-array-test.js @@ -11,7 +11,7 @@ module('unit/model/relationships - RecordArray'); test('updating the content of a RecordArray updates its content', function(assert) { let Tag = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let env = setupStore({ tag: Tag }); @@ -21,30 +21,34 @@ test('updating the content of a RecordArray updates its content', function(asser run(() => { internalModels = store._push({ - data: [{ - type: 'tag', - id: '5', - attributes: { - name: 'friendly' - } - }, { - type: 'tag', - id: '2', - attributes: { - name: 'smarmy' - } - }, { - type: 'tag', - id: '12', - attributes: { - name: 'oohlala' - } - }] + data: [ + { + type: 'tag', + id: '5', + attributes: { + name: 'friendly', + }, + }, + { + type: 'tag', + id: '2', + attributes: { + name: 'smarmy', + }, + }, + { + type: 'tag', + id: '12', + attributes: { + name: 'oohlala', + }, + }, + ], }); tags = DS.RecordArray.create({ content: A(internalModels.slice(0, 2)), store: store, - modelName: 'tag' + modelName: 'tag', }); }); @@ -62,12 +66,12 @@ test('can create child record from a hasMany relationship', function(assert) { const Tag = DS.Model.extend({ name: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); const Person = DS.Model.extend({ name: DS.attr('string'), - tags: DS.hasMany('tag', { async: false }) + tags: DS.hasMany('tag', { async: false }), }); let env = setupStore({ tag: Tag, person: Person }); @@ -81,9 +85,9 @@ test('can create child record from a hasMany relationship', function(assert) { type: 'person', id: '1', attributes: { - name: 'Tom Dale' - } - } + name: 'Tom Dale', + }, + }, }); }); @@ -93,7 +97,13 @@ test('can create child record from a hasMany relationship', function(assert) { assert.equal(get(person, 'name'), 'Tom Dale', 'precond - retrieves person record from store'); assert.equal(get(person, 'tags.length'), 1, 'tag is added to the parent record'); - assert.equal(get(person, 'tags').objectAt(0).get('name'), 'cool', 'tag values are passed along'); + assert.equal( + get(person, 'tags') + .objectAt(0) + .get('name'), + 'cool', + 'tag values are passed along' + ); }); }); }); diff --git a/tests/unit/model/rollback-attributes-test.js b/tests/unit/model/rollback-attributes-test.js index 5d25c7e7f51..9cd25a23988 100644 --- a/tests/unit/model/rollback-attributes-test.js +++ b/tests/unit/model/rollback-attributes-test.js @@ -18,13 +18,17 @@ module('unit/model/rollbackAttributes - model.rollbackAttributes()', { rolledBackCount: 0, rolledBack() { this.incrementProperty('rolledBackCount'); - } + }, + }); + Person.reopenClass({ + toString() { + return 'Person'; + }, }); - Person.reopenClass({ toString() { return 'Person'; } }); env = setupStore({ person: Person }); store = env.store; - } + }, }); test('changes to attributes can be rolled back', function(assert) { @@ -34,22 +38,22 @@ test('changes to attributes can be rolled back', function(assert) { type: 'person', id: '1', attributes: { - firstName: "Tom", - lastName: "Dale" - } - } + firstName: 'Tom', + lastName: 'Dale', + }, + }, }); person = store.peekRecord('person', 1); - person.set('firstName', "Thomas"); + person.set('firstName', 'Thomas'); return person; }); - assert.equal(person.get('firstName'), "Thomas"); + assert.equal(person.get('firstName'), 'Thomas'); assert.equal(person.get('rolledBackCount'), 0); run(() => person.rollbackAttributes()); - assert.equal(person.get('firstName'), "Tom"); + assert.equal(person.get('firstName'), 'Tom'); assert.equal(person.get('hasDirtyAttributes'), false); assert.equal(person.get('rolledBackCount'), 1); }); @@ -61,17 +65,17 @@ test('changes to unassigned attributes can be rolled back', function(assert) { type: 'person', id: '1', attributes: { - lastName: 'Dale' - } - } + lastName: 'Dale', + }, + }, }); person = store.peekRecord('person', 1); - person.set('firstName', "Thomas"); + person.set('firstName', 'Thomas'); return person; }); - assert.equal(person.get('firstName'), "Thomas"); + assert.equal(person.get('firstName'), 'Thomas'); assert.equal(person.get('rolledBackCount'), 0); run(() => person.rollbackAttributes()); @@ -93,14 +97,14 @@ test('changes to attributes made after a record is in-flight only rolls back the type: 'person', id: '1', attributes: { - firstName: "Tom", - lastName: "Dale" - } - } + firstName: 'Tom', + lastName: 'Dale', + }, + }, }); let person = store.peekRecord('person', 1); - person.set('firstName', "Thomas"); + person.set('firstName', 'Thomas'); return person; }); @@ -108,17 +112,17 @@ test('changes to attributes made after a record is in-flight only rolls back the return run(() => { let saving = person.save(); - assert.equal(person.get('firstName'), "Thomas"); + assert.equal(person.get('firstName'), 'Thomas'); - person.set('lastName', "Dolly"); + person.set('lastName', 'Dolly'); - assert.equal(person.get('lastName'), "Dolly"); + assert.equal(person.get('lastName'), 'Dolly'); assert.equal(person.get('rolledBackCount'), 0); person.rollbackAttributes(); - assert.equal(person.get('firstName'), "Thomas"); - assert.equal(person.get('lastName'), "Dale"); + assert.equal(person.get('firstName'), 'Thomas'); + assert.equal(person.get('lastName'), 'Dale'); assert.equal(person.get('isSaving'), true); return saving.then(() => { @@ -139,31 +143,31 @@ test("a record's changes can be made if it fails to save", function(assert) { type: 'person', id: '1', attributes: { - firstName: "Tom", - lastName: "Dale" - } - } + firstName: 'Tom', + lastName: 'Dale', + }, + }, }); let person = store.peekRecord('person', 1); - person.set('firstName', "Thomas"); + person.set('firstName', 'Thomas'); return person; }); - assert.deepEqual(person.changedAttributes().firstName, ["Tom", "Thomas"]); + assert.deepEqual(person.changedAttributes().firstName, ['Tom', 'Thomas']); run(function() { person.save().then(null, function() { assert.equal(person.get('isError'), true); - assert.deepEqual(person.changedAttributes().firstName, ["Tom", "Thomas"]); + assert.deepEqual(person.changedAttributes().firstName, ['Tom', 'Thomas']); assert.equal(person.get('rolledBackCount'), 0); run(function() { person.rollbackAttributes(); }); - assert.equal(person.get('firstName'), "Tom"); + assert.equal(person.get('firstName'), 'Tom'); assert.equal(person.get('isError'), false); assert.equal(Object.keys(person.changedAttributes()).length, 0); assert.equal(person.get('rolledBackCount'), 1); @@ -185,10 +189,10 @@ test(`a deleted record's attributes can be rollbacked if it fails to save, recor type: 'person', id: '1', attributes: { - firstName: "Tom", - lastName: "Dale" - } - } + firstName: 'Tom', + lastName: 'Dale', + }, + }, }); person = store.peekRecord('person', 1); people = store.peekAll('person'); @@ -196,24 +200,39 @@ test(`a deleted record's attributes can be rollbacked if it fails to save, recor run(() => person.deleteRecord()); - assert.equal(people.get('length'), 1, 'a deleted record appears in record array until it is saved'); - assert.equal(people.objectAt(0), person, 'a deleted record appears in record array until it is saved'); + assert.equal( + people.get('length'), + 1, + 'a deleted record appears in record array until it is saved' + ); + assert.equal( + people.objectAt(0), + person, + 'a deleted record appears in record array until it is saved' + ); return run(() => { - return person.save().catch(() => { - assert.equal(person.get('isError'), true); - assert.equal(person.get('isDeleted'), true); - assert.equal(person.get('rolledBackCount'), 0); - - run(() => person.rollbackAttributes()); - - assert.equal(person.get('isDeleted'), false); - assert.equal(person.get('isError'), false); - assert.equal(person.get('hasDirtyAttributes'), false, 'must be not dirty'); - assert.equal(person.get('rolledBackCount'), 1); - }).then(() => { - assert.equal(people.get('length'), 1, 'the underlying record array is updated accordingly in an asynchronous way'); - }); + return person + .save() + .catch(() => { + assert.equal(person.get('isError'), true); + assert.equal(person.get('isDeleted'), true); + assert.equal(person.get('rolledBackCount'), 0); + + run(() => person.rollbackAttributes()); + + assert.equal(person.get('isDeleted'), false); + assert.equal(person.get('isError'), false); + assert.equal(person.get('hasDirtyAttributes'), false, 'must be not dirty'); + assert.equal(person.get('rolledBackCount'), 1); + }) + .then(() => { + assert.equal( + people.get('length'), + 1, + 'the underlying record array is updated accordingly in an asynchronous way' + ); + }); }); }); @@ -236,14 +255,14 @@ test(`invalid new record's attributes can be rollbacked`, function(assert) { let error = new DS.InvalidError([ { detail: 'is invalid', - source: { pointer: 'data/attributes/name' } - } + source: { pointer: 'data/attributes/name' }, + }, ]); let adapter = DS.RESTAdapter.extend({ ajax(url, type, hash) { return reject(error); - } + }, }); env = setupStore({ person: Person, adapter: adapter }); @@ -269,12 +288,11 @@ test(`invalid new record's attributes can be rollbacked`, function(assert) { }); test(`invalid record's attributes can be rollbacked after multiple failed calls - #3677`, function(assert) { - let adapter = DS.RESTAdapter.extend({ ajax(url, type, hash) { let error = new DS.InvalidError(); return reject(error); - } + }, }); env = setupStore({ person: Person, adapter: adapter }); @@ -286,9 +304,9 @@ test(`invalid record's attributes can be rollbacked after multiple failed calls type: 'person', id: 1, attributes: { - firstName: 'original name' - } - } + firstName: 'original name', + }, + }, }); person.set('firstName', 'updated name'); @@ -297,18 +315,25 @@ test(`invalid record's attributes can be rollbacked after multiple failed calls return run(() => { assert.equal(person.get('firstName'), 'updated name', 'precondition: firstName is changed'); - return person.save().catch(() => { - assert.equal(person.get('hasDirtyAttributes'), true, 'has dirty attributes'); - assert.equal(person.get('firstName'), 'updated name', 'firstName is still changed'); - - return person.save(); - }).catch(() => { - run(() => person.rollbackAttributes()); - - assert.equal(person.get('hasDirtyAttributes'), false, 'has no dirty attributes'); - assert.equal(person.get('firstName'), 'original name', 'after rollbackAttributes() firstName has the original value'); - assert.equal(person.get('rolledBackCount'), 1); - }); + return person + .save() + .catch(() => { + assert.equal(person.get('hasDirtyAttributes'), true, 'has dirty attributes'); + assert.equal(person.get('firstName'), 'updated name', 'firstName is still changed'); + + return person.save(); + }) + .catch(() => { + run(() => person.rollbackAttributes()); + + assert.equal(person.get('hasDirtyAttributes'), false, 'has no dirty attributes'); + assert.equal( + person.get('firstName'), + 'original name', + 'after rollbackAttributes() firstName has the original value' + ); + assert.equal(person.get('rolledBackCount'), 1); + }); }); }); @@ -319,22 +344,34 @@ test(`deleted record's attributes can be rollbacked`, function(assert) { store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); person = store.peekRecord('person', 1); people = store.peekAll('person'); person.deleteRecord(); }); - assert.equal(people.get('length'), 1, 'a deleted record appears in the record array until it is saved'); - assert.equal(people.objectAt(0), person, 'a deleted record appears in the record array until it is saved'); + assert.equal( + people.get('length'), + 1, + 'a deleted record appears in the record array until it is saved' + ); + assert.equal( + people.objectAt(0), + person, + 'a deleted record appears in the record array until it is saved' + ); assert.equal(person.get('isDeleted'), true, 'must be deleted'); run(() => person.rollbackAttributes()); - assert.equal(people.get('length'), 1, 'the rollbacked record should appear again in the record array'); + assert.equal( + people.get('length'), + 1, + 'the rollbacked record should appear again in the record array' + ); assert.equal(person.get('isDeleted'), false, 'must not be deleted'); assert.equal(person.get('hasDirtyAttributes'), false, 'must not be dirty'); }); @@ -346,20 +383,20 @@ test("invalid record's attributes can be rollbacked", function(assert) { rolledBackCount: 0, rolledBack() { this.incrementProperty('rolledBackCount'); - } + }, }); let error = new DS.InvalidError([ { detail: 'is invalid', - source: { pointer: 'data/attributes/name' } - } + source: { pointer: 'data/attributes/name' }, + }, ]); let adapter = DS.RESTAdapter.extend({ ajax(url, type, hash) { return reject(error); - } + }, }); env = setupStore({ dog: Dog, adapter: adapter }); @@ -370,12 +407,12 @@ test("invalid record's attributes can be rollbacked", function(assert) { type: 'dog', id: '1', attributes: { - name: "Pluto" - } - } + name: 'Pluto', + }, + }, }); dog = env.store.peekRecord('dog', 1); - dog.set('name', "is a dwarf planet"); + dog.set('name', 'is a dwarf planet'); }); return run(() => { @@ -383,19 +420,24 @@ test("invalid record's attributes can be rollbacked", function(assert) { assert.ok(true, 'errors.name did change'); }); - dog.get('errors').addArrayObserver({}, { - willChange() { - assert.ok(true, 'errors will change'); - }, - didChange() { - assert.ok(true, 'errors did change'); + dog.get('errors').addArrayObserver( + {}, + { + willChange() { + assert.ok(true, 'errors will change'); + }, + didChange() { + assert.ok(true, 'errors did change'); + }, } - }); + ); return dog.save().catch(reason => { assert.equal(reason, error); - run(() => { dog.rollbackAttributes() }); + run(() => { + dog.rollbackAttributes(); + }); assert.equal(dog.get('hasDirtyAttributes'), false, 'must not be dirty'); assert.equal(dog.get('name'), 'Pluto'); @@ -410,20 +452,20 @@ test(`invalid record's attributes rolled back to correct state after set`, funct assert.expect(14); const Dog = DS.Model.extend({ name: DS.attr(), - breed: DS.attr() + breed: DS.attr(), }); let error = new DS.InvalidError([ { detail: 'is invalid', - source: { pointer: 'data/attributes/name' } - } + source: { pointer: 'data/attributes/name' }, + }, ]); let adapter = DS.RESTAdapter.extend({ ajax(url, type, hash) { return reject(error); - } + }, }); env = setupStore({ dog: Dog, adapter: adapter }); @@ -434,13 +476,13 @@ test(`invalid record's attributes rolled back to correct state after set`, funct type: 'dog', id: '1', attributes: { - name: "Pluto", - breed: "Disney" - } - } + name: 'Pluto', + breed: 'Disney', + }, + }, }); dog = env.store.peekRecord('dog', 1); - dog.set('name', "is a dwarf planet"); + dog.set('name', 'is a dwarf planet'); dog.set('breed', 'planet'); }); @@ -474,20 +516,20 @@ test(`invalid record's attributes rolled back to correct state after set`, funct test(`when destroying a record setup the record state to invalid, the record's attributes can be rollbacked`, function(assert) { const Dog = DS.Model.extend({ - name: DS.attr() + name: DS.attr(), }); let error = new DS.InvalidError([ { detail: 'is invalid', - source: { pointer: 'data/attributes/name' } - } + source: { pointer: 'data/attributes/name' }, + }, ]); let adapter = DS.RESTAdapter.extend({ ajax(url, type, hash) { return reject(error); - } + }, }); env = setupStore({ dog: Dog, adapter: adapter }); @@ -497,15 +539,15 @@ test(`when destroying a record setup the record state to invalid, the record's a type: 'dog', id: '1', attributes: { - name: "Pluto" - } - } + name: 'Pluto', + }, + }, }); return env.store.peekRecord('dog', 1); }); return run(() => { - return dog.destroyRecord().catch(reason => { + return dog.destroyRecord().catch(reason => { assert.equal(reason, error); assert.equal(dog.get('isError'), false, 'must not be error'); @@ -519,6 +561,6 @@ test(`when destroying a record setup the record state to invalid, the record's a assert.equal(dog.get('isDeleted'), false, 'must not be deleted after `rollbackAttributes`'); assert.equal(dog.get('isValid'), true, 'must be valid after `rollbackAttributes`'); assert.ok(dog.get('errors.length') === 0, 'must not have errors'); - }) + }); }); }); diff --git a/tests/unit/modules-test.js b/tests/unit/modules-test.js index e25b06233dc..9f92525aa3f 100644 --- a/tests/unit/modules-test.js +++ b/tests/unit/modules-test.js @@ -18,12 +18,7 @@ import JSONAPISerializer from 'ember-data/serializers/json-api'; import RESTSerializer from 'ember-data/serializers/rest'; import EmbeddedRecordsMixin from 'ember-data/serializers/embedded-records-mixin'; -import { - AdapterError, - InvalidError, - TimeoutError, - AbortError -} from 'ember-data/adapters/errors'; +import { AdapterError, InvalidError, TimeoutError, AbortError } from 'ember-data/adapters/errors'; module('unit/modules - public modules'); diff --git a/tests/unit/private-test.js b/tests/unit/private-test.js index b2f1c2f3515..95b1b7e0431 100644 --- a/tests/unit/private-test.js +++ b/tests/unit/private-test.js @@ -1,8 +1,5 @@ import { module, test } from 'qunit'; -import { - InternalModel, - RootState -} from 'ember-data/-private'; +import { InternalModel, RootState } from 'ember-data/-private'; module('-private'); diff --git a/tests/unit/promise-proxies-test.js b/tests/unit/promise-proxies-test.js index 1e5ab5fee69..26930f9b6bc 100644 --- a/tests/unit/promise-proxies-test.js +++ b/tests/unit/promise-proxies-test.js @@ -15,7 +15,7 @@ test('.reload should NOT leak the internal promise, rather return another promis content.reload = () => EmberPromise.resolve(content); let array = DS.PromiseManyArray.create({ - content + content, }); let reloaded = array.reload(); @@ -34,7 +34,7 @@ test('.reload should be stable', function(assert) { let promise = EmberPromise.resolve(content); let array = DS.PromiseManyArray.create({ - promise + promise, }); assert.equal(array.get('isRejected'), false, 'should NOT be rejected'); @@ -72,12 +72,12 @@ test('.reload should be stable', function(assert) { test('.set to new promise should be like reload', function(assert) { assert.expect(18); - let content = A([1,2,3]); + let content = A([1, 2, 3]); let promise = EmberPromise.resolve(content); let array = DS.PromiseManyArray.create({ - promise + promise, }); assert.equal(array.get('isRejected'), false, 'should NOT be rejected'); @@ -110,4 +110,3 @@ test('.set to new promise should be like reload', function(assert) { }); }); }); - diff --git a/tests/unit/record-arrays/adapter-populated-record-array-test.js b/tests/unit/record-arrays/adapter-populated-record-array-test.js index 3c0b4001236..a9db12d8068 100644 --- a/tests/unit/record-arrays/adapter-populated-record-array-test.js +++ b/tests/unit/record-arrays/adapter-populated-record-array-test.js @@ -3,7 +3,7 @@ import RSVP from 'rsvp'; import { run } from '@ember/runloop'; import DS from 'ember-data'; import { module, test } from 'qunit'; -const { AdapterPopulatedRecordArray , RecordArrayManager } = DS; +const { AdapterPopulatedRecordArray, RecordArrayManager } = DS; module('unit/record-arrays/adapter-populated-record-array - DS.AdapterPopulatedRecordArray'); @@ -14,7 +14,7 @@ function internalModelFor(record) { }, getRecord() { return record; - } + }, }; record._internalModel = _internalModel; @@ -42,7 +42,7 @@ test('custom initial state', function(assert) { content, store, query: 'some-query', - links: 'foo' + links: 'foo', }); assert.equal(recordArray.get('isLoaded'), true); assert.equal(recordArray.get('isUpdating'), false); @@ -56,9 +56,13 @@ test('custom initial state', function(assert) { test('#replace() throws error', function(assert) { let recordArray = AdapterPopulatedRecordArray.create({ modelName: 'recordType' }); - assert.throws(() => { - recordArray.replace(); - }, Error('The result of a server query (on recordType) is immutable.'), 'throws error'); + assert.throws( + () => { + recordArray.replace(); + }, + Error('The result of a server query (on recordType) is immutable.'), + 'throws error' + ); }); test('#update uses _update enabling query specific behavior', function(assert) { @@ -73,13 +77,13 @@ test('#update uses _update enabling query specific behavior', function(assert) { assert.equal(array, recordArray); return deferred.promise; - } + }, }; let recordArray = AdapterPopulatedRecordArray.create({ modelName: 'recordType', store, - query: 'some-query' + query: 'some-query', }); assert.equal(recordArray.get('isUpdating'), false, 'should not yet be updating'); @@ -110,7 +114,7 @@ test('#_setInternalModels', function(assert) { let recordArray = AdapterPopulatedRecordArray.create({ query: 'some-query', - manager: new RecordArrayManager({}) + manager: new RecordArrayManager({}), }); let model1 = internalModelFor({ id: 1 }); @@ -130,17 +134,22 @@ test('#_setInternalModels', function(assert) { let meta = { bar: 2 }; run(() => { - assert.equal(recordArray._setInternalModels([model1, model2], { - links, - meta - }), undefined, '_setInternalModels should have no return value'); + assert.equal( + recordArray._setInternalModels([model1, model2], { + links, + meta, + }), + undefined, + '_setInternalModels should have no return value' + ); assert.equal(didAddRecord, 2, 'two records should have been added'); - assert.deepEqual(recordArray.toArray(), [ - model1, - model2 - ].map(x => x.getRecord()), 'should now contain the loaded records'); + assert.deepEqual( + recordArray.toArray(), + [model1, model2].map(x => x.getRecord()), + 'should now contain the loaded records' + ); assert.equal(didLoad, 0, 'didLoad event should not have fired'); assert.equal(recordArray.get('links').foo, 1); @@ -167,7 +176,7 @@ test('change events when receiving a new query payload', function(assert) { let recordArray = AdapterPopulatedRecordArray.create({ query: 'some-query', - manager: new RecordArrayManager({}) + manager: new RecordArrayManager({}), }); let model1 = internalModelFor({ id: '1', name: 'Scumbag Dale' }); @@ -177,10 +186,7 @@ test('change events when receiving a new query payload', function(assert) { model2._recordArrays = { add, delete: del }; run(() => { - recordArray._setInternalModels([ - model1, - model2 - ], {}); + recordArray._setInternalModels([model1, model2], {}); }); assert.equal(didAddRecord, 2, 'expected 2 didAddRecords'); @@ -198,9 +204,9 @@ test('change events when receiving a new query payload', function(assert) { // first time invoked assert.equal(array, recordArray, 'should be same record array as above'); - assert.equal(startIdx, 0, 'expected startIdx'); + assert.equal(startIdx, 0, 'expected startIdx'); assert.equal(removeAmt, 2, 'expcted removeAmt'); - assert.equal(addAmt, 2, 'expected addAmt'); + assert.equal(addAmt, 2, 'expected addAmt'); }); assert.equal(recordArray.get('isLoaded'), true, 'should be considered loaded'); @@ -221,10 +227,7 @@ test('change events when receiving a new query payload', function(assert) { run(() => { // re-query - recordArray._setInternalModels([ - model3, - model4 - ], {}); + recordArray._setInternalModels([model3, model4], {}); }); assert.equal(didAddRecord, 2, 'expected 2 didAddRecords'); @@ -245,9 +248,9 @@ test('change events when receiving a new query payload', function(assert) { // first time invoked assert.equal(array, recordArray, 'should be same recordArray as above'); - assert.equal(startIdx, 0, 'expected startIdx'); + assert.equal(startIdx, 0, 'expected startIdx'); assert.equal(removeAmt, 2, 'expcted removeAmt'); - assert.equal(addAmt, 1, 'expected addAmt'); + assert.equal(addAmt, 1, 'expected addAmt'); }); // re-query @@ -257,14 +260,12 @@ test('change events when receiving a new query payload', function(assert) { assert.equal(arrayDidChange, 0, 'record array should not yet have omitted a change event'); assert.equal(contentDidChange, 0, 'recordArray.content should not have changed'); - let model5 = internalModelFor({ id: '3', name: 'Scumbag Penner' }) + let model5 = internalModelFor({ id: '3', name: 'Scumbag Penner' }); model5._recordArrays = { add, delete: del }; run(() => { - recordArray._setInternalModels([ - model5 - ], {}); + recordArray._setInternalModels([model5], {}); }); assert.equal(didAddRecord, 1, 'expected 0 didAddRecord'); diff --git a/tests/unit/record-arrays/record-array-test.js b/tests/unit/record-arrays/record-array-test.js index 51fbaeb5f10..4a26f37b6ab 100644 --- a/tests/unit/record-arrays/record-array-test.js +++ b/tests/unit/record-arrays/record-array-test.js @@ -27,7 +27,7 @@ test('custom initial state', function(assert) { isLoaded: true, isUpdating: true, content, - store + store, }); assert.equal(get(recordArray, 'isLoaded'), true); assert.equal(get(recordArray, 'isUpdating'), false); // cannot set as default value: @@ -39,21 +39,39 @@ test('custom initial state', function(assert) { test('#replace() throws error', function(assert) { let recordArray = RecordArray.create({ modelName: 'recordType' }); - assert.throws(() => { - recordArray.replace(); - }, Error('The result of a server query (for all recordType types) is immutable. To modify contents, use toArray()'), 'throws error'); + assert.throws( + () => { + recordArray.replace(); + }, + Error( + 'The result of a server query (for all recordType types) is immutable. To modify contents, use toArray()' + ), + 'throws error' + ); }); test('#objectAtContent', function(assert) { let content = A([ - { getRecord() { return 'foo'; }}, - { getRecord() { return 'bar'; }}, - { getRecord() { return 'baz'; }} + { + getRecord() { + return 'foo'; + }, + }, + { + getRecord() { + return 'bar'; + }, + }, + { + getRecord() { + return 'baz'; + }, + }, ]); let recordArray = RecordArray.create({ modelName: 'recordType', - content + content, }); assert.equal(get(recordArray, 'length'), 3); @@ -73,12 +91,12 @@ test('#update', function(assert) { assert.equal(modelName, 'recordType'); assert.equal(options.reload, true, 'options should contain reload: true'); return deferred.promise; - } + }, }; let recordArray = RecordArray.create({ modelName: 'recordType', - store + store, }); assert.equal(get(recordArray, 'isUpdating'), false, 'should not yet be updating'); @@ -99,7 +117,6 @@ test('#update', function(assert) { }); }); - test('#update while updating', function(assert) { let findAllCalled = 0; let deferred = RSVP.defer(); @@ -107,12 +124,12 @@ test('#update while updating', function(assert) { findAll(modelName, options) { findAllCalled++; return deferred.promise; - } + }, }; let recordArray = RecordArray.create({ modelName: { modelName: 'recordType' }, - store + store, }); assert.equal(get(recordArray, 'isUpdating'), false, 'should not be updating'); @@ -141,18 +158,41 @@ test('#update while updating', function(assert) { test('#_pushInternalModels', function(assert) { let content = A(); let recordArray = RecordArray.create({ - content + content, }); - let model1 = { id: 1, getRecord() { return 'model-1'; } }; - let model2 = { id: 2, getRecord() { return 'model-2'; } }; - let model3 = { id: 3, getRecord() { return 'model-3'; } }; + let model1 = { + id: 1, + getRecord() { + return 'model-1'; + }, + }; + let model2 = { + id: 2, + getRecord() { + return 'model-2'; + }, + }; + let model3 = { + id: 3, + getRecord() { + return 'model-3'; + }, + }; - assert.equal(recordArray._pushInternalModels([model1]), undefined, '_pushInternalModels has no return value'); + assert.equal( + recordArray._pushInternalModels([model1]), + undefined, + '_pushInternalModels has no return value' + ); assert.deepEqual(content, [model1], 'now contains model1'); recordArray._pushInternalModels([model1]); - assert.deepEqual(content, [model1, model1], 'allows duplicates, because record-array-manager via internalModel._recordArrays ensures no duplicates, this layer should not double check'); + assert.deepEqual( + content, + [model1, model1], + 'allows duplicates, because record-array-manager via internalModel._recordArrays ensures no duplicates, this layer should not double check' + ); recordArray._removeInternalModels([model1]); recordArray._pushInternalModels([model1]); @@ -165,31 +205,66 @@ test('#_pushInternalModels', function(assert) { test('#_removeInternalModels', function(assert) { let content = A(); let recordArray = RecordArray.create({ - content + content, }); - let model1 = { id: 1, getRecord() { return 'model-1'; } }; - let model2 = { id: 2, getRecord() { return 'model-2'; } }; - let model3 = { id: 3, getRecord() { return 'model-3'; } }; + let model1 = { + id: 1, + getRecord() { + return 'model-1'; + }, + }; + let model2 = { + id: 2, + getRecord() { + return 'model-2'; + }, + }; + let model3 = { + id: 3, + getRecord() { + return 'model-3'; + }, + }; assert.equal(content.length, 0); - assert.equal(recordArray._removeInternalModels([model1]), undefined, '_removeInternalModels has no return value'); + assert.equal( + recordArray._removeInternalModels([model1]), + undefined, + '_removeInternalModels has no return value' + ); assert.deepEqual(content, [], 'now contains no models'); recordArray._pushInternalModels([model1, model2]); assert.deepEqual(content, [model1, model2], 'now contains model1, model2,'); - assert.equal(recordArray._removeInternalModels([model1]), undefined, '_removeInternalModels has no return value'); + assert.equal( + recordArray._removeInternalModels([model1]), + undefined, + '_removeInternalModels has no return value' + ); assert.deepEqual(content, [model2], 'now only contains model2'); - assert.equal(recordArray._removeInternalModels([model2]), undefined, '_removeInternalModels has no return value'); + assert.equal( + recordArray._removeInternalModels([model2]), + undefined, + '_removeInternalModels has no return value' + ); assert.deepEqual(content, [], 'now contains no models'); - recordArray._pushInternalModels([model1, model2, model3]) + recordArray._pushInternalModels([model1, model2, model3]); - assert.equal(recordArray._removeInternalModels([model1, model3]), undefined, '_removeInternalModels has no return value'); + assert.equal( + recordArray._removeInternalModels([model1, model3]), + undefined, + '_removeInternalModels has no return value' + ); assert.deepEqual(content, [model2], 'now contains model2'); - assert.equal(recordArray._removeInternalModels([model2]), undefined, '_removeInternalModels has no return value'); + assert.equal( + recordArray._removeInternalModels([model2]), + undefined, + '_removeInternalModels has no return value' + ); assert.deepEqual(content, [], 'now contains no models'); }); @@ -203,7 +278,9 @@ class FakeInternalModel { return this.__recordArrays; } - getRecord() { return this._record; } + getRecord() { + return this._record; + } createSnapshot() { return this._record; @@ -215,15 +292,22 @@ function internalModelFor(record) { } test('#save', function(assert) { - let model1 = { save() { model1Saved++; return this;} }; - let model2 = { save() { model2Saved++; return this;} }; - let content = A([ - internalModelFor(model1), - internalModelFor(model2) - ]); + let model1 = { + save() { + model1Saved++; + return this; + }, + }; + let model2 = { + save() { + model2Saved++; + return this; + }, + }; + let content = A([internalModelFor(model1), internalModelFor(model2)]); let recordArray = RecordArray.create({ - content + content, }); let model1Saved = 0; @@ -244,8 +328,8 @@ test('#save', function(assert) { test('#destroy', function(assert) { let didUnregisterRecordArray = 0; - let didDissociatieFromOwnRecords = 0; - let model1 = { }; + let didDissociatieFromOwnRecords = 0; + let model1 = {}; let internalModel1 = internalModelFor(model1); // TODO: this will be removed once we fix ownership related memory leaks. @@ -253,7 +337,7 @@ test('#destroy', function(assert) { delete(array) { didDissociatieFromOwnRecords++; assert.equal(array, recordArray); - } + }, }; // end TODO: @@ -263,8 +347,8 @@ test('#destroy', function(assert) { unregisterRecordArray(_recordArray) { didUnregisterRecordArray++; assert.equal(recordArray, _recordArray); - } - } + }, + }, }); assert.equal(get(recordArray, 'isDestroyed'), false, 'should not be destroyed'); @@ -272,13 +356,29 @@ test('#destroy', function(assert) { run(() => { assert.equal(get(recordArray, 'length'), 1, 'before destroy, length should be 1'); - assert.equal(didUnregisterRecordArray, 0, 'before destroy, we should not yet have unregisterd the record array'); - assert.equal(didDissociatieFromOwnRecords, 0, 'before destroy, we should not yet have dissociated from own record array'); + assert.equal( + didUnregisterRecordArray, + 0, + 'before destroy, we should not yet have unregisterd the record array' + ); + assert.equal( + didDissociatieFromOwnRecords, + 0, + 'before destroy, we should not yet have dissociated from own record array' + ); recordArray.destroy(); }); - assert.equal(didUnregisterRecordArray, 1, 'after destroy we should have unregistered the record array'); - assert.equal(didDissociatieFromOwnRecords, 1, 'after destroy, we should have dissociated from own record array'); + assert.equal( + didUnregisterRecordArray, + 1, + 'after destroy we should have unregistered the record array' + ); + assert.equal( + didDissociatieFromOwnRecords, + 1, + 'after destroy, we should have dissociated from own record array' + ); recordArray.destroy(); assert.strictEqual(get(recordArray, 'content'), null); @@ -288,35 +388,33 @@ test('#destroy', function(assert) { test('#_createSnapshot', function(assert) { let model1 = { - id: 1 + id: 1, }; let model2 = { - id: 2 + id: 2, }; - let content = A([ - internalModelFor(model1), - internalModelFor(model2) - ]); + let content = A([internalModelFor(model1), internalModelFor(model2)]); let recordArray = RecordArray.create({ - content + content, }); let snapshot = recordArray._createSnapshot(); let snapshots = snapshot.snapshots(); - assert.deepEqual(snapshots, [ - model1, - model2 - ], 'record array snapshot should contain the internalModel.createSnapshot result'); + assert.deepEqual( + snapshots, + [model1, model2], + 'record array snapshot should contain the internalModel.createSnapshot result' + ); }); test('#destroy', function(assert) { let didUnregisterRecordArray = 0; - let didDissociatieFromOwnRecords = 0; - let model1 = { }; + let didDissociatieFromOwnRecords = 0; + let model1 = {}; let internalModel1 = internalModelFor(model1); // TODO: this will be removed once we fix ownership related memory leaks. @@ -324,7 +422,7 @@ test('#destroy', function(assert) { delete(array) { didDissociatieFromOwnRecords++; assert.equal(array, recordArray); - } + }, }; // end TODO: @@ -334,8 +432,8 @@ test('#destroy', function(assert) { unregisterRecordArray(_recordArray) { didUnregisterRecordArray++; assert.equal(recordArray, _recordArray); - } - } + }, + }, }); assert.equal(get(recordArray, 'isDestroyed'), false, 'should not be destroyed'); @@ -343,17 +441,32 @@ test('#destroy', function(assert) { run(() => { assert.equal(get(recordArray, 'length'), 1, 'before destroy, length should be 1'); - assert.equal(didUnregisterRecordArray, 0, 'before destroy, we should not yet have unregisterd the record array'); - assert.equal(didDissociatieFromOwnRecords, 0, 'before destroy, we should not yet have dissociated from own record array'); + assert.equal( + didUnregisterRecordArray, + 0, + 'before destroy, we should not yet have unregisterd the record array' + ); + assert.equal( + didDissociatieFromOwnRecords, + 0, + 'before destroy, we should not yet have dissociated from own record array' + ); recordArray.destroy(); }); - assert.equal(didUnregisterRecordArray, 1, 'after destroy we should have unregistered the record array'); - assert.equal(didDissociatieFromOwnRecords, 1, 'after destroy, we should have dissociated from own record array'); + assert.equal( + didUnregisterRecordArray, + 1, + 'after destroy we should have unregistered the record array' + ); + assert.equal( + didDissociatieFromOwnRecords, + 1, + 'after destroy, we should have dissociated from own record array' + ); recordArray.destroy(); assert.strictEqual(get(recordArray, 'content'), null); assert.equal(get(recordArray, 'length'), 0, 'after destroy we should have no length'); assert.equal(get(recordArray, 'isDestroyed'), true, 'should be destroyed'); }); - diff --git a/tests/unit/states-test.js b/tests/unit/states-test.js index c655068d54b..dd01674ee90 100644 --- a/tests/unit/states-test.js +++ b/tests/unit/states-test.js @@ -9,15 +9,23 @@ let rootState, stateName; module('unit/states - Flags for record states', { beforeEach() { rootState = DS.RootState; - } + }, }); assert.flagIsTrue = function flagIsTrue(flag) { - this.equal(get(rootState, stateName + '.' + flag), true, stateName + '.' + flag + ' should be true'); + this.equal( + get(rootState, stateName + '.' + flag), + true, + stateName + '.' + flag + ' should be true' + ); }; assert.flagIsFalse = function flagIsFalse(flag) { - this.equal(get(rootState, stateName + '.' + flag), false, stateName + '.' + flag + ' should be false'); + this.equal( + get(rootState, stateName + '.' + flag), + false, + stateName + '.' + flag + ' should be false' + ); }; test('the empty state', function(assert) { diff --git a/tests/unit/store/adapter-interop-test.js b/tests/unit/store/adapter-interop-test.js index e2bd5b86b9d..576faf6cfaf 100644 --- a/tests/unit/store/adapter-interop-test.js +++ b/tests/unit/store/adapter-interop-test.js @@ -1,9 +1,5 @@ import { A } from '@ember/array'; -import { - resolve, - all, - Promise as EmberPromise -} from 'rsvp'; +import { resolve, all, Promise as EmberPromise } from 'rsvp'; import { set, get } from '@ember/object'; import { run } from '@ember/runloop'; import { createStore } from 'dummy/tests/helpers/store'; @@ -23,9 +19,11 @@ module('unit/store/adapter-interop - DS.Store working with a DS.Adapter', { afterEach() { run(() => { - if (store) { store.destroy(); } + if (store) { + store.destroy(); + } }); - } + }, }); test('Adapter can be set as a factory', function(assert) { @@ -44,7 +42,7 @@ testInDebug('Adapter can not be set as an instance', function(assert) { assert.expect(1); store = DS.Store.create({ - adapter: DS.Adapter.create() + adapter: DS.Adapter.create(), }); assert.expectAssertion(() => store.get('defaultAdapter')); }); @@ -55,26 +53,34 @@ test('Calling Store#find invokes its adapter#find', function(assert) { let currentStore; const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { - assert.ok(true, "Adapter#find was called"); - assert.equal(store, currentStore, "Adapter#find was called with the right store"); - assert.equal(type, store.modelFor('test'), "Adapter#find was called with the type passed into Store#find"); - assert.equal(id, 1, "Adapter#find was called with the id passed into Store#find"); - assert.equal(snapshot.id, '1', "Adapter#find was called with the record created from Store#find"); + assert.ok(true, 'Adapter#find was called'); + assert.equal(store, currentStore, 'Adapter#find was called with the right store'); + assert.equal( + type, + store.modelFor('test'), + 'Adapter#find was called with the type passed into Store#find' + ); + assert.equal(id, 1, 'Adapter#find was called with the id passed into Store#find'); + assert.equal( + snapshot.id, + '1', + 'Adapter#find was called with the record created from Store#find' + ); return resolve({ data: { id: 1, - type: 'test' - } + type: 'test', + }, }); - } + }, }); const Type = DS.Model.extend(); currentStore = createStore({ adapter: Adapter, - test: Type + test: Type, }); return run(() => currentStore.findRecord('test', 1)); @@ -89,23 +95,20 @@ test('Calling Store#findRecord multiple times coalesces the calls into a adapter }, findMany(store, type, ids, snapshots) { assert.ok(true, 'Adapter#findMany was called'); - assert.deepEqual(ids, ['1','2'], 'Correct ids were passed in to findMany'); + assert.deepEqual(ids, ['1', '2'], 'Correct ids were passed in to findMany'); return resolve({ data: [{ id: 1, type: 'test' }, { id: 2, type: 'test' }] }); }, - coalesceFindRequests: true + coalesceFindRequests: true, }); const Type = DS.Model.extend(); let store = createStore({ adapter: Adapter, - test: Type + test: Type, }); return run(() => { - return all([ - store.findRecord('test', 1), - store.findRecord('test', 2) - ]); + return all([store.findRecord('test', 1), store.findRecord('test', 2)]); }); }); @@ -114,17 +117,17 @@ test('Returning a promise from `findRecord` asynchronously loads data', function const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { - return resolve({ data: { id: 1, type: 'test', attributes: { name: "Scumbag Dale" } } }); - } + return resolve({ data: { id: 1, type: 'test', attributes: { name: 'Scumbag Dale' } } }); + }, }); const Type = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ adapter: Adapter, - test: Type + test: Type, }); return run(() => { @@ -141,38 +144,45 @@ test('IDs provided as numbers are coerced to strings', function(assert) { findRecord(store, type, id, snapshot) { assert.equal(typeof id, 'string', 'id has been normalized to a string'); return resolve({ data: { id, type: 'test', attributes: { name: 'Scumbag Sylvain' } } }); - } + }, }); const Type = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ adapter: Adapter, - test: Type + test: Type, }); return run(() => { - return store.findRecord('test', 1).then(object => { - assert.equal(typeof object.get('id'), 'string', 'id was coerced to a string'); - run(() => { - store.push({ - data: { - type: 'test', - id: '2', - attributes: { - name: 'Scumbag Sam Saffron' - } - } + return store + .findRecord('test', 1) + .then(object => { + assert.equal(typeof object.get('id'), 'string', 'id was coerced to a string'); + run(() => { + store.push({ + data: { + type: 'test', + id: '2', + attributes: { + name: 'Scumbag Sam Saffron', + }, + }, + }); }); - }); - return store.findRecord('test', 2); - }).then(object => { - assert.ok(object, 'object was found'); - assert.equal(typeof object.get('id'), 'string', 'id is a string despite being supplied and searched for as a number'); - }); + return store.findRecord('test', 2); + }) + .then(object => { + assert.ok(object, 'object was found'); + assert.equal( + typeof object.get('id'), + 'string', + 'id is a string despite being supplied and searched for as a number' + ); + }); }); }); @@ -180,7 +190,7 @@ test('can load data for the same record if it is not dirty', function(assert) { assert.expect(3); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ @@ -188,8 +198,8 @@ test('can load data for the same record if it is not dirty', function(assert) { adapter: DS.Adapter.extend({ shouldBackgroundReloadRecord() { return false; - } - }) + }, + }), }); return run(() => { @@ -198,9 +208,9 @@ test('can load data for the same record if it is not dirty', function(assert) { type: 'person', id: '1', attributes: { - name: "Tom Dale" - } - } + name: 'Tom Dale', + }, + }, }); return store.findRecord('person', 1).then(tom => { @@ -212,9 +222,9 @@ test('can load data for the same record if it is not dirty', function(assert) { type: 'person', id: '1', attributes: { - name: 'Captain Underpants' - } - } + name: 'Captain Underpants', + }, + }, }); assert.equal(get(tom, 'name'), 'Captain Underpants', 'updated record with new date'); }); @@ -227,7 +237,7 @@ test('loadMany takes an optional Object and passes it on to the Adapter', functi let passedQuery = { page: 1 }; const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const Adapter = TestAdapter.extend({ @@ -235,12 +245,12 @@ test('loadMany takes an optional Object and passes it on to the Adapter', functi assert.equal(type, store.modelFor('person'), 'The type was Person'); assert.equal(query, passedQuery, 'The query was passed in'); return resolve({ data: [] }); - } + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); run(() => store.query('person', passedQuery)); @@ -250,13 +260,13 @@ test('Find with query calls the correct normalizeResponse', function(assert) { let passedQuery = { page: 1 }; const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const Adapter = TestAdapter.extend({ query(store, type, query) { return resolve([]); - } + }, }); let callCount = 0; @@ -265,12 +275,12 @@ test('Find with query calls the correct normalizeResponse', function(assert) { normalizeQueryResponse() { callCount++; return this._super(...arguments); - } + }, }); let env = setupStore({ adapter: Adapter, - person: Person + person: Person, }); let { store } = env; @@ -283,11 +293,11 @@ test('Find with query calls the correct normalizeResponse', function(assert) { test('peekAll(type) returns a record array of all records of a specific type', function(assert) { const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ - person: Person + person: Person, }); run(() => { @@ -296,9 +306,9 @@ test('peekAll(type) returns a record array of all records of a specific type', f type: 'person', id: '1', attributes: { - name: "Tom Dale" - } - } + name: 'Tom Dale', + }, + }, }); }); @@ -313,24 +323,32 @@ test('peekAll(type) returns a record array of all records of a specific type', f type: 'person', id: '2', attributes: { - name: 'Yehuda Katz' - } - } + name: 'Yehuda Katz', + }, + }, }); }); assert.equal(get(results, 'length'), 2, 'record array should have the new object'); - assert.equal(get(results.objectAt(1), 'name'), 'Yehuda Katz', 'record has the correct information'); - - assert.strictEqual(results, store.peekAll('person'), 'subsequent calls to peekAll return the same recordArray)'); + assert.equal( + get(results.objectAt(1), 'name'), + 'Yehuda Katz', + 'record has the correct information' + ); + + assert.strictEqual( + results, + store.peekAll('person'), + 'subsequent calls to peekAll return the same recordArray)' + ); }); test('a new record of a particular type is created via store.createRecord(type)', function(assert) { const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ - person: Person + person: Person, }); let person = store.createRecord('person'); @@ -341,38 +359,45 @@ test('a new record of a particular type is created via store.createRecord(type)' run(() => set(person, 'name', 'Braaahm Dale')); - assert.equal(get(person, 'name'), 'Braaahm Dale', 'Even if no hash is supplied, `set` still worked'); + assert.equal( + get(person, 'name'), + 'Braaahm Dale', + 'Even if no hash is supplied, `set` still worked' + ); }); -testInDebug("a new record with a specific id can't be created if this id is already used in the store", function(assert) { - const Person = DS.Model.extend({ - name: DS.attr('string') - }); - - Person.reopenClass({ - toString() { - return 'Person'; - } - }); +testInDebug( + "a new record with a specific id can't be created if this id is already used in the store", + function(assert) { + const Person = DS.Model.extend({ + name: DS.attr('string'), + }); - let store = createStore({ - person: Person - }); + Person.reopenClass({ + toString() { + return 'Person'; + }, + }); - store.createRecord('person', { id: 5 }); + let store = createStore({ + person: Person, + }); - assert.expectAssertion(() => { store.createRecord('person', { id: 5 }); - }, /The id 5 has already been used with another record for modelClass 'person'/); -}); + + assert.expectAssertion(() => { + store.createRecord('person', { id: 5 }); + }, /The id 5 has already been used with another record for modelClass 'person'/); + } +); test('an initial data hash can be provided via store.createRecord(type, hash)', function(assert) { const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ - person: Person + person: Person, }); let person = store.createRecord('person', { name: 'Brohuda Katz' }); @@ -384,18 +409,18 @@ test('an initial data hash can be provided via store.createRecord(type, hash)', assert.equal(get(person, 'name'), 'Brohuda Katz', 'The initial data hash is provided'); }); -test("if an id is supplied in the initial data hash, it can be looked up using `store.find`", function(assert) { +test('if an id is supplied in the initial data hash, it can be looked up using `store.find`', function(assert) { assert.expect(1); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ person: Person, adapter: DS.Adapter.extend({ - shouldBackgroundReloadRecord: () => false - }) + shouldBackgroundReloadRecord: () => false, + }), }); return run(() => { @@ -407,23 +432,23 @@ test("if an id is supplied in the initial data hash, it can be looked up using ` }); }); -test("initial values of attributes can be passed in as the third argument to find", function(assert) { +test('initial values of attributes can be passed in as the third argument to find', function(assert) { assert.expect(1); const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { assert.equal(snapshot.attr('name'), 'Test', 'Preloaded attribtue set'); return { data: { id: '1', type: 'test', attributes: { name: 'Test' } } }; - } + }, }); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let store = createStore({ adapter: Adapter, - test: Person + test: Person, }); return run(() => store.findRecord('test', 1, { preload: { name: 'Test' } })); @@ -436,18 +461,18 @@ test('initial values of belongsTo can be passed in as the third argument to find findRecord(store, type, id, snapshot) { assert.equal(snapshot.belongsTo('friend').attr('name'), 'Tom', 'Preloaded belongsTo set'); return { data: { id, type: 'person' } }; - } + }, }); let env = setupStore({ - adapter: Adapter + adapter: Adapter, }); let { store } = env; const Person = DS.Model.extend({ name: DS.attr('string'), - friend: DS.belongsTo('person', { inverse: null, async: true }) + friend: DS.belongsTo('person', { inverse: null, async: true }), }); env.registry.register('model:person', Person); @@ -458,9 +483,9 @@ test('initial values of belongsTo can be passed in as the third argument to find type: 'person', id: '2', attributes: { - name: 'Tom' - } - } + name: 'Tom', + }, + }, }); let tom = store.peekRecord('person', 2); @@ -474,27 +499,29 @@ test('initial values of belongsTo can be passed in as the third argument to find const Adapter = TestAdapter.extend({ findRecord(store, type, id, snapshot) { return { data: { id, type: 'person' } }; - } + }, }); let env = setupStore({ - adapter: Adapter - + adapter: Adapter, }); let { store } = env; const Person = DS.Model.extend({ name: DS.attr('string'), - friend: DS.belongsTo('person', { async: true, inverse: null }) + friend: DS.belongsTo('person', { async: true, inverse: null }), }); env.registry.register('model:person', Person); return run(() => { return store.findRecord('person', 1, { preload: { friend: 2 } }).then(() => { - return store.peekRecord('person', 1).get('friend').then(friend => { - assert.equal(friend.get('id'), '2', 'Preloaded belongsTo set'); - }); + return store + .peekRecord('person', 1) + .get('friend') + .then(friend => { + assert.equal(friend.get('id'), '2', 'Preloaded belongsTo set'); + }); }); }); }); @@ -506,18 +533,18 @@ test('initial values of hasMany can be passed in as the third argument to find a findRecord(store, type, id, snapshot) { assert.equal(snapshot.hasMany('friends')[0].attr('name'), 'Tom', 'Preloaded hasMany set'); return { data: { id, type: 'person' } }; - } + }, }); let env = setupStore({ - adapter: Adapter + adapter: Adapter, }); let { store } = env; const Person = DS.Model.extend({ name: DS.attr('string'), - friends: DS.hasMany('person', { inverse: null, async: true }) + friends: DS.hasMany('person', { inverse: null, async: true }), }); env.registry.register('model:person', Person); @@ -528,9 +555,9 @@ test('initial values of hasMany can be passed in as the third argument to find a type: 'person', id: '2', attributes: { - name: 'Tom' - } - } + name: 'Tom', + }, + }, }); let tom = store.peekRecord('person', 2); @@ -545,17 +572,17 @@ test('initial values of hasMany can be passed in as the third argument to find a findRecord(store, type, id, snapshot) { assert.equal(snapshot.hasMany('friends')[0].id, '2', 'Preloaded hasMany set'); return { data: { id, type: 'person' } }; - } + }, }); let env = setupStore({ - adapter: Adapter + adapter: Adapter, }); let { store } = env; const Person = DS.Model.extend({ name: DS.attr('string'), - friends: DS.hasMany('person', { async: true, inverse: null }) + friends: DS.hasMany('person', { async: true, inverse: null }), }); env.registry.register('model:person', Person); @@ -570,18 +597,18 @@ test('initial empty values of hasMany can be passed in as the third argument to findRecord(store, type, id, snapshot) { assert.equal(snapshot.hasMany('friends').length, 0, 'Preloaded hasMany set'); return { data: { id, type: 'person' } }; - } + }, }); let env = setupStore({ - adapter: Adapter + adapter: Adapter, }); let { store } = env; const Person = DS.Model.extend({ name: DS.attr('string'), - friends: DS.hasMany('person', { inverse: null, async: true }) + friends: DS.hasMany('person', { inverse: null, async: true }), }); env.registry.register('model:person', Person); @@ -598,17 +625,17 @@ test('initial values of hasMany can be passed in as the third argument to find a findRecord(store, type, id, snapshot) { assert.equal(snapshot.hasMany('friends').length, 0, 'Preloaded hasMany set'); return { data: { id, type: 'person' } }; - } + }, }); let env = setupStore({ - adapter: Adapter + adapter: Adapter, }); let { store } = env; const Person = DS.Model.extend({ name: DS.attr('string'), - friends: DS.hasMany('person', { async: true, inverse: null }) + friends: DS.hasMany('person', { async: true, inverse: null }), }); env.registry.register('model:person', Person); @@ -620,7 +647,7 @@ test('records should have their ids updated when the adapter returns the id data assert.expect(2); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); let idCounter = 1; @@ -631,16 +658,16 @@ test('records should have their ids updated when the adapter returns the id data id: idCounter++, type: 'person', attributes: { - name: snapshot.attr('name') - } - } + name: snapshot.attr('name'), + }, + }, }; - } + }, }); let store = createStore({ adapter: Adapter, - person: Person + person: Person, }); let people = store.peekAll('person'); @@ -648,10 +675,7 @@ test('records should have their ids updated when the adapter returns the id data let yehuda = store.createRecord('person', { name: 'Yehuda Katz' }); return run(() => { - return all([ - tom.save(), - yehuda.save() - ]).then(() => { + return all([tom.save(), yehuda.save()]).then(() => { people.forEach((person, index) => { assert.equal(person.get('id'), index + 1, `The record's id should be correct.`); }); @@ -665,10 +689,10 @@ test('store.fetchMany should always return a promise', function(assert) { const Person = DS.Model.extend(); let store = createStore({ adapter: TestAdapter.extend(), - person: Person + person: Person, }); - store.createRecord('person') + store.createRecord('person'); let records = []; let results = run(() => store._scheduleFetchMany(records)); @@ -697,20 +721,20 @@ test('store._scheduleFetchMany should not resolve until all the records are reso }, findMany(store, type, ids, snapshots) { - let records = ids.map(id => ( { id, type: type.modelName }) ); + let records = ids.map(id => ({ id, type: type.modelName })); return new EmberPromise(resolve => { run.later(() => { - resolve({data: records }); + resolve({ data: records }); }, 15); }); - } + }, }); let store = createStore({ adapter: adapter, test: Person, - phone: Phone + phone: Phone, }); store.createRecord('test'); @@ -718,7 +742,7 @@ test('store._scheduleFetchMany should not resolve until all the records are reso let internalModels = [ store._internalModelForId('test', 10), store._internalModelForId('phone', 20), - store._internalModelForId('phone', 21) + store._internalModelForId('phone', 21), ]; return run(() => { @@ -737,10 +761,7 @@ test('the store calls adapter.findMany according to groupings returned by adapte const Adapter = TestAdapter.extend({ groupRecordsForFindMany(store, snapshots) { - return [ - [snapshots[0]], - [snapshots[1], snapshots[2]] - ]; + return [[snapshots[0]], [snapshots[1], snapshots[2]]]; }, findRecord(store, type, id, snapshot) { @@ -754,23 +775,23 @@ test('the store calls adapter.findMany according to groupings returned by adapte assert.deepEqual(ids, ['20', '21'], 'The second group is passed to findMany'); return { data: records }; - } + }, }); let store = createStore({ adapter: Adapter, - test: Person + test: Person, }); let internalModels = [ store._internalModelForId('test', 10), store._internalModelForId('test', 20), - store._internalModelForId('test', 21) + store._internalModelForId('test', 21), ]; return run(() => { return store._scheduleFetchMany(internalModels).then(() => { - let ids = internalModels.map(x => x.id ) + let ids = internalModels.map(x => x.id); assert.deepEqual(ids, ['10', '20', '21'], 'The promise fulfills with the records'); }); }); @@ -784,10 +805,7 @@ test('the promise returned by `_scheduleFetch`, when it resolves, does not depen const Person = DS.Model.extend(); const Adapter = TestAdapter.extend({ groupRecordsForFindMany(store, snapshots) { - return [ - [snapshots[0]], - [snapshots[1]] - ]; + return [[snapshots[0]], [snapshots[1]]]; }, findRecord(store, type, id, snapshot) { @@ -797,18 +815,18 @@ test('the promise returned by `_scheduleFetch`, when it resolves, does not depen if (id === 'igor') { resolve({ data: record }); } else { - run.later(function () { + run.later(function() { davidResolved = true; resolve({ data: record }); }, 5); } }); - } + }, }); let store = createStore({ adapter: Adapter, - test: Person + test: Person, }); return run(() => { @@ -816,13 +834,17 @@ test('the promise returned by `_scheduleFetch`, when it resolves, does not depen let igor = store.findRecord('test', 'igor'); let wait = []; - wait.push(igor.then(() => { - assert.equal(davidResolved, false, 'Igor did not need to wait for David'); - })); + wait.push( + igor.then(() => { + assert.equal(davidResolved, false, 'Igor did not need to wait for David'); + }) + ); - wait.push(david.then(() => { - assert.equal(davidResolved, true, 'David resolved'); - })); + wait.push( + david.then(() => { + assert.equal(davidResolved, true, 'David resolved'); + }) + ); return all(wait); }); @@ -836,10 +858,7 @@ test('the promise returned by `_scheduleFetch`, when it rejects, does not depend const Person = DS.Model.extend(); const Adapter = TestAdapter.extend({ groupRecordsForFindMany(store, snapshots) { - return [ - [snapshots[0]], - [snapshots[1]] - ]; + return [[snapshots[0]], [snapshots[1]]]; }, findRecord(store, type, id, snapshot) { @@ -855,12 +874,12 @@ test('the promise returned by `_scheduleFetch`, when it rejects, does not depend }, 5); } }); - } + }, }); let store = createStore({ adapter: Adapter, - test: Person + test: Person, }); return run(() => { @@ -868,48 +887,55 @@ test('the promise returned by `_scheduleFetch`, when it rejects, does not depend let igor = store.findRecord('test', 'igor'); let wait = []; - wait.push(igor.catch(() => { - assert.equal(davidResolved, false, 'Igor did not need to wait for David'); - })); + wait.push( + igor.catch(() => { + assert.equal(davidResolved, false, 'Igor did not need to wait for David'); + }) + ); - wait.push(david.then(() => { - assert.equal(davidResolved, true, 'David resolved'); - })); + wait.push( + david.then(() => { + assert.equal(davidResolved, true, 'David resolved'); + }) + ); return EmberPromise.all(wait); }); }); -testInDebug('store._fetchRecord reject records that were not found, even when those requests were coalesced with records that were found', function(assert) { - assert.expect(3); +testInDebug( + 'store._fetchRecord reject records that were not found, even when those requests were coalesced with records that were found', + function(assert) { + assert.expect(3); - const Person = DS.Model.extend(); + const Person = DS.Model.extend(); - const Adapter = TestAdapter.extend({ - findMany(store, type, ids, snapshots) { - let records = ids.map((id) => ({ id, type: 'test' })); - return { data: [records[0]] }; - } - }); + const Adapter = TestAdapter.extend({ + findMany(store, type, ids, snapshots) { + let records = ids.map(id => ({ id, type: 'test' })); + return { data: [records[0]] }; + }, + }); - let store = createStore({ - adapter: Adapter, - test: Person - }); + let store = createStore({ + adapter: Adapter, + test: Person, + }); - let wait = []; - assert.expectWarning(() => { - run(() => { - let david = store.findRecord('test', 'david'); - let igor = store.findRecord('test', 'igor'); + let wait = []; + assert.expectWarning(() => { + run(() => { + let david = store.findRecord('test', 'david'); + let igor = store.findRecord('test', 'igor'); - wait.push(david.then(() => assert.ok(true, 'David resolved'))); - wait.push(igor.catch(() => assert.ok(true, 'Igor rejected'))); - }); - }, /expected to find records with the following ids/); + wait.push(david.then(() => assert.ok(true, 'David resolved'))); + wait.push(igor.catch(() => assert.ok(true, 'Igor rejected'))); + }); + }, /expected to find records with the following ids/); - return EmberPromise.all(wait); -}); + return EmberPromise.all(wait); + } +); testInDebug('store._fetchRecord warns when records are missing', function(assert) { const Person = DS.Model.extend(); @@ -918,13 +944,13 @@ testInDebug('store._fetchRecord warns when records are missing', function(assert findMany(store, type, ids, snapshots) { let records = ids.map(id => ({ id, type: 'test' })).filter(({ id }) => id === 'david'); - return {data: [records[0]] }; - } + return { data: [records[0]] }; + }, }); let store = createStore({ adapter: Adapter, - test: Person + test: Person, }); let wait = []; @@ -933,15 +959,23 @@ testInDebug('store._fetchRecord warns when records are missing', function(assert assert.expectWarning(() => { run(() => { wait.push(store.findRecord('test', 'david')); - wait.push(store.findRecord('test', 'igor').catch(e => { - igorDidReject = true; - assert.equal(e.message, `Expected: '' to be present in the adapter provided payload, but it was not found.`); - })); + wait.push( + store.findRecord('test', 'igor').catch(e => { + igorDidReject = true; + assert.equal( + e.message, + `Expected: '' to be present in the adapter provided payload, but it was not found.` + ); + }) + ); }); }, /expected to find records with the following ids in the adapter response but they were missing/); return EmberPromise.all(wait).then(() => { - assert.ok(igorDidReject, 'expected rejection that could not be found in the payload, but no such rejection occured'); + assert.ok( + igorDidReject, + 'expected rejection that could not be found in the payload, but no such rejection occured' + ); }); }); @@ -949,7 +983,7 @@ test('store should not call shouldReloadRecord when the record is not in the sto assert.expect(1); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ @@ -960,12 +994,12 @@ test('store should not call shouldReloadRecord when the record is not in the sto findRecord() { assert.ok(true, 'find is always called when the record is not in the store'); return { data: { id: 1, type: 'person' } }; - } + }, }); let store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); return run(() => store.findRecord('person', 1)); @@ -975,7 +1009,7 @@ test('store should not reload record when shouldReloadRecord returns false', fun assert.expect(1); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ @@ -988,20 +1022,20 @@ test('store should not reload record when shouldReloadRecord returns false', fun }, findRecord() { assert.ok(false, 'find should not be called when shouldReloadRecord returns false'); - } + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); return run(() => { store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); return store.findRecord('person', 1); @@ -1012,7 +1046,7 @@ test('store should reload record when shouldReloadRecord returns true', function assert.expect(3); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ @@ -1023,20 +1057,20 @@ test('store should reload record when shouldReloadRecord returns true', function findRecord() { assert.ok(true, 'find should not be called when shouldReloadRecord returns false'); return { data: { id: 1, type: 'person', attributes: { name: 'Tom' } } }; - } + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); return run(() => { store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); return store.findRecord('person', 1).then(record => { @@ -1049,7 +1083,7 @@ test('store should not call shouldBackgroundReloadRecord when the store is alrea assert.expect(2); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ @@ -1057,25 +1091,28 @@ test('store should not call shouldBackgroundReloadRecord when the store is alrea return true; }, shouldBackgroundReloadRecord(store, type, id, snapshot) { - assert.ok(false, 'shouldBackgroundReloadRecord is not called when shouldReloadRecord returns true'); + assert.ok( + false, + 'shouldBackgroundReloadRecord is not called when shouldReloadRecord returns true' + ); }, findRecord() { assert.ok(true, 'find should be called'); return { data: { id: 1, type: 'person', attributes: { name: 'Tom' } } }; - } + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); return run(() => { store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); return store.findRecord('person', 1).then(record => { @@ -1088,31 +1125,34 @@ test('store should not reload a record when `shouldBackgroundReloadRecord` is fa assert.expect(2); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ shouldBackgroundReloadRecord(store, type, id, snapshot) { - assert.ok(true, 'shouldBackgroundReloadRecord is called when record is loaded form the cache'); + assert.ok( + true, + 'shouldBackgroundReloadRecord is called when record is loaded form the cache' + ); return false; }, findRecord() { assert.ok(false, 'find should not be called'); return { data: { id: 1, type: 'person', attributes: { name: 'Tom' } } }; - } + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); return run(() => { store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); return store.findRecord('person', 1).then(record => { @@ -1121,36 +1161,38 @@ test('store should not reload a record when `shouldBackgroundReloadRecord` is fa }); }); - test('store should reload the record in the background when `shouldBackgroundReloadRecord` is true', function(assert) { assert.expect(4); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ shouldBackgroundReloadRecord(store, type, id, snapshot) { - assert.ok(true, 'shouldBackgroundReloadRecord is called when record is loaded form the cache'); + assert.ok( + true, + 'shouldBackgroundReloadRecord is called when record is loaded form the cache' + ); return true; }, findRecord() { assert.ok(true, 'find should not be called'); return { data: { id: 1, type: 'person', attributes: { name: 'Tom' } } }; - } + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); let done = run(() => { store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); return store.findRecord('person', 1).then(record => { @@ -1167,7 +1209,7 @@ test('store should not reload record array when shouldReloadAll returns false', assert.expect(1); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ @@ -1180,12 +1222,12 @@ test('store should not reload record array when shouldReloadAll returns false', }, findAll() { assert.ok(false, 'findAll should not be called when shouldReloadAll returns false'); - } + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); return run(() => store.findAll('person')); @@ -1195,7 +1237,7 @@ test('store should reload all records when shouldReloadAll returns true', functi assert.expect(3); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ @@ -1205,13 +1247,13 @@ test('store should reload all records when shouldReloadAll returns true', functi }, findAll() { assert.ok(true, 'findAll should be called when shouldReloadAll returns true'); - return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }]}; - } + return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }] }; + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); return run(() => { @@ -1225,7 +1267,7 @@ test('store should not call shouldBackgroundReloadAll when the store is already assert.expect(2); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ @@ -1233,17 +1275,20 @@ test('store should not call shouldBackgroundReloadAll when the store is already return true; }, shouldBackgroundReloadAll(store, type, id, snapshot) { - assert.ok(false, 'shouldBackgroundReloadRecord is not called when shouldReloadRecord returns true'); + assert.ok( + false, + 'shouldBackgroundReloadRecord is not called when shouldReloadRecord returns true' + ); }, findAll() { assert.ok(true, 'find should be called'); - return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }]}; - } + return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }] }; + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); return run(() => { @@ -1257,7 +1302,7 @@ test('store should not reload all records when `shouldBackgroundReloadAll` is fa assert.expect(3); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ @@ -1272,12 +1317,12 @@ test('store should not reload all records when `shouldBackgroundReloadAll` is fa findAll() { assert.ok(false, 'findAll should not be called'); return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }] }; - } + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); return run(() => { @@ -1287,12 +1332,11 @@ test('store should not reload all records when `shouldBackgroundReloadAll` is fa }); }); - test('store should reload all records in the background when `shouldBackgroundReloadAll` is true', function(assert) { assert.expect(5); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); const TestAdapter = DS.Adapter.extend({ @@ -1307,12 +1351,12 @@ test('store should reload all records in the background when `shouldBackgroundRe findAll() { assert.ok(true, 'find should not be called'); return { data: [{ id: 1, type: 'person', attributes: { name: 'Tom' } }] }; - } + }, }); store = createStore({ adapter: TestAdapter, - person: Person + person: Person, }); let done = run(() => { @@ -1330,11 +1374,11 @@ testInDebug('store should assert of the user tries to call store.filter', functi assert.expect(1); const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); store = createStore({ - person: Person + person: Person, }); assert.expectAssertion(() => { @@ -1342,13 +1386,13 @@ testInDebug('store should assert of the user tries to call store.filter', functi }, /The filter API has been moved to a plugin/); }); -testInDebug("Calling adapterFor with a model class should assert", function(assert) { +testInDebug('Calling adapterFor with a model class should assert', function(assert) { const Person = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); store = createStore({ - person: Person + person: Person, }); assert.expectAssertion(() => { diff --git a/tests/unit/store/asserts-test.js b/tests/unit/store/asserts-test.js index 279bd62dbc2..4263f541fc2 100644 --- a/tests/unit/store/asserts-test.js +++ b/tests/unit/store/asserts-test.js @@ -19,14 +19,14 @@ const MODEL_NAME_METHODS = [ '_modelFactoryFor', 'normalize', 'adapterFor', - 'serializerFor' + 'serializerFor', ]; testInDebug('Calling Store methods with no modelName asserts', function(assert) { assert.expect(MODEL_NAME_METHODS.length); let store = createStore(); - MODEL_NAME_METHODS.forEach(methodName =>{ + MODEL_NAME_METHODS.forEach(methodName => { assert.expectAssertion(() => { store[methodName](null); }, new RegExp(`You need to pass a model name to the store's ${methodName} method`)); diff --git a/tests/unit/store/create-record-test.js b/tests/unit/store/create-record-test.js index 1c87e24d29f..e2bd5e79459 100644 --- a/tests/unit/store/create-record-test.js +++ b/tests/unit/store/create-record-test.js @@ -12,40 +12,40 @@ let store, Record, Storage; module('unit/store/createRecord - Store creating records', { beforeEach() { Record = DS.Model.extend({ - title: DS.attr('string') + title: DS.attr('string'), }); Storage = DS.Model.extend({ name: DS.attr('name'), - records: DS.hasMany('record', { async: false }) + records: DS.hasMany('record', { async: false }), }); store = createStore({ adapter: DS.Adapter.extend(), record: Record, - storage: Storage + storage: Storage, }); - } + }, }); test(`doesn't modify passed in properties hash`, function(assert) { const Post = Model.extend({ title: attr(), author: belongsTo('author', { async: false, inverse: 'post' }), - comments: hasMany('comment', { async: false, inverse: 'post' }) + comments: hasMany('comment', { async: false, inverse: 'post' }), }); const Comment = Model.extend({ text: attr(), - post: belongsTo('post', { async: false, inverse: 'comments' }) + post: belongsTo('post', { async: false, inverse: 'comments' }), }); const Author = Model.extend({ name: attr(), - post: belongsTo('post', { async: false, inverse: 'author' }) + post: belongsTo('post', { async: false, inverse: 'author' }), }); let env = setupStore({ post: Post, comment: Comment, - author: Author + author: Author, }); let store = env.store; let comment, author; @@ -56,18 +56,18 @@ test(`doesn't modify passed in properties hash`, function(assert) { type: 'comment', id: '1', attributes: { - text: 'Hello darkness my old friend' - } - } + text: 'Hello darkness my old friend', + }, + }, }); author = store.push({ data: { type: 'author', id: '1', attributes: { - name: '@runspired' - } - } + name: '@runspired', + }, + }, }); }); @@ -75,13 +75,13 @@ test(`doesn't modify passed in properties hash`, function(assert) { title: 'My Post', randomProp: 'An unknown prop', comments: [comment], - author + author, }; let propertiesClone = { title: 'My Post', randomProp: 'An unknown prop', comments: [comment], - author + author, }; store.createRecord('post', properties); @@ -99,17 +99,17 @@ test('allow passing relationships as well as attributes', function(assert) { type: 'record', id: '1', attributes: { - title: "it's a beautiful day" - } + title: "it's a beautiful day", + }, }, { type: 'record', id: '2', attributes: { - title: "it's a beautiful day" - } - } - ] + title: "it's a beautiful day", + }, + }, + ], }); records = store.peekAll('record'); @@ -117,19 +117,27 @@ test('allow passing relationships as well as attributes', function(assert) { }); assert.equal(storage.get('name'), 'Great store', 'The attribute is well defined'); - assert.equal(storage.get('records').findBy('id', '1'), A(records).findBy('id', '1'), 'Defined relationships are allowed in createRecord'); - assert.equal(storage.get('records').findBy('id', '2'), A(records).findBy('id', '2'), 'Defined relationships are allowed in createRecord'); + assert.equal( + storage.get('records').findBy('id', '1'), + A(records).findBy('id', '1'), + 'Defined relationships are allowed in createRecord' + ); + assert.equal( + storage.get('records').findBy('id', '2'), + A(records).findBy('id', '2'), + 'Defined relationships are allowed in createRecord' + ); }); module('unit/store/createRecord - Store with models by dash', { beforeEach() { let env = setupStore({ someThing: DS.Model.extend({ - foo: DS.attr('string') - }) + foo: DS.attr('string'), + }), }); store = env.store; - } + }, }); test('creating a record by dasherize string finds the model', function(assert) { diff --git a/tests/unit/store/finders-test.js b/tests/unit/store/finders-test.js index 9ee8ee9b859..58d167c207f 100644 --- a/tests/unit/store/finders-test.js +++ b/tests/unit/store/finders-test.js @@ -12,11 +12,11 @@ module('unit/store/finders', { updatedAt: DS.attr('string'), name: DS.attr('string'), firstName: DS.attr('string'), - lastName: DS.attr('string') + lastName: DS.attr('string'), }); this.Dog = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); this.env = setupStore({ person: this.Person, dog: this.Dog }); @@ -26,7 +26,7 @@ module('unit/store/finders', { afterEach() { run(this.env.container, 'destroy'); - } + }, }); test('findRecord does not load a serializer until the adapter promise resolves', function(assert) { @@ -34,13 +34,16 @@ test('findRecord does not load a serializer until the adapter promise resolves', let deferedFind = defer(); - this.env.registry.register('adapter:person', DS.Adapter.extend({ - findRecord: () => deferedFind.promise - })); + this.env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findRecord: () => deferedFind.promise, + }) + ); let serializerLoaded = false; let serializerFor = this.store.serializerFor; - this.store.serializerFor = (modelName) => { + this.store.serializerFor = modelName => { if (modelName === 'person') { serializerLoaded = true; } @@ -51,7 +54,9 @@ test('findRecord does not load a serializer until the adapter promise resolves', assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve({ data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } } }); + deferedFind.resolve({ + data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } }, + }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -63,13 +68,16 @@ test('findMany does not load a serializer until the adapter promise resolves', f let deferedFind = defer(); - this.env.registry.register('adapter:person', DS.Adapter.extend({ - findMany: () => deferedFind.promise - })); + this.env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findMany: () => deferedFind.promise, + }) + ); let serializerLoaded = false; let serializerFor = this.store.serializerFor; - this.store.serializerFor = (modelName) => { + this.store.serializerFor = modelName => { if (modelName === 'person') { serializerLoaded = true; } @@ -77,13 +85,18 @@ test('findMany does not load a serializer until the adapter promise resolves', f }; let storePromise = run(() => { - this.store.findRecord('person', 1) + this.store.findRecord('person', 1); return this.store.findRecord('person', 2); }); assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve({ data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }, { id: 2, type: 'person', attributes: { name: 'Louis Joseph' } }] }); + deferedFind.resolve({ + data: [ + { id: 1, type: 'person', attributes: { name: 'John Churchill' } }, + { id: 2, type: 'person', attributes: { name: 'Louis Joseph' } }, + ], + }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -95,17 +108,20 @@ test('findHasMany does not load a serializer until the adapter promise resolves' let deferedFind = defer(); - this.env.registry.register('adapter:person', DS.Adapter.extend({ - findHasMany: () => deferedFind.promise - })); + this.env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findHasMany: () => deferedFind.promise, + }) + ); this.Person.reopen({ - dogs: DS.hasMany('dog', { async: true }) + dogs: DS.hasMany('dog', { async: true }), }); let serializerLoaded = false; let serializerFor = this.store.serializerFor; - this.store.serializerFor = (modelName) => { + this.store.serializerFor = modelName => { if (modelName === 'dog') { serializerLoaded = true; } @@ -118,16 +134,16 @@ test('findHasMany does not load a serializer until the adapter promise resolves' type: 'person', id: '1', attributes: { - name: 'John Churchill' + name: 'John Churchill', }, relationships: { dogs: { links: { - related: 'http://exmaple.com/person/1/dogs' - } - } - } - } + related: 'http://exmaple.com/person/1/dogs', + }, + }, + }, + }, }); return this.store.peekRecord('person', 1).get('dogs'); @@ -135,7 +151,12 @@ test('findHasMany does not load a serializer until the adapter promise resolves' assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve({ data: [{ id: 1, type: 'dog', attributes: { name: 'Scooby' } }, { id: 2, type: 'dog', attributes: { name: 'Scrappy' } }] }); + deferedFind.resolve({ + data: [ + { id: 1, type: 'dog', attributes: { name: 'Scooby' } }, + { id: 2, type: 'dog', attributes: { name: 'Scrappy' } }, + ], + }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -147,17 +168,20 @@ test('findBelongsTo does not load a serializer until the adapter promise resolve let deferedFind = defer(); - this.env.registry.register('adapter:person', DS.Adapter.extend({ - findBelongsTo: () => deferedFind.promise - })); + this.env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findBelongsTo: () => deferedFind.promise, + }) + ); this.Person.reopen({ - favoriteDog: DS.belongsTo('dog', { async: true }) + favoriteDog: DS.belongsTo('dog', { async: true }), }); let serializerLoaded = false; let serializerFor = this.store.serializerFor; - this.store.serializerFor = (modelName) => { + this.store.serializerFor = modelName => { if (modelName === 'dog') { serializerLoaded = true; } @@ -170,16 +194,16 @@ test('findBelongsTo does not load a serializer until the adapter promise resolve type: 'person', id: '1', attributes: { - name: 'John Churchill' + name: 'John Churchill', }, relationships: { favoriteDog: { links: { - related: 'http://exmaple.com/person/1/favorite-dog' - } - } - } - } + related: 'http://exmaple.com/person/1/favorite-dog', + }, + }, + }, + }, }); return this.store.peekRecord('person', 1).get('favoriteDog'); @@ -199,13 +223,16 @@ test('findAll does not load a serializer until the adapter promise resolves', fu let deferedFind = defer(); - this.env.registry.register('adapter:person', DS.Adapter.extend({ - findAll: () => deferedFind.promise - })); + this.env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + findAll: () => deferedFind.promise, + }) + ); let serializerLoaded = false; let serializerFor = this.store.serializerFor; - this.store.serializerFor = (modelName) => { + this.store.serializerFor = modelName => { if (modelName === 'person') { serializerLoaded = true; } @@ -216,7 +243,9 @@ test('findAll does not load a serializer until the adapter promise resolves', fu assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve({ data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }] }); + deferedFind.resolve({ + data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }], + }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -228,13 +257,16 @@ test('query does not load a serializer until the adapter promise resolves', func let deferedFind = defer(); - this.env.registry.register('adapter:person', DS.Adapter.extend({ - query: () => deferedFind.promise - })); + this.env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + query: () => deferedFind.promise, + }) + ); let serializerLoaded = false; let serializerFor = this.store.serializerFor; - this.store.serializerFor = (modelName) => { + this.store.serializerFor = modelName => { if (modelName === 'person') { serializerLoaded = true; } @@ -245,7 +277,9 @@ test('query does not load a serializer until the adapter promise resolves', func assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve({ data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }] }); + deferedFind.resolve({ + data: [{ id: 1, type: 'person', attributes: { name: 'John Churchill' } }], + }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); @@ -257,27 +291,33 @@ test('queryRecord does not load a serializer until the adapter promise resolves' let deferedFind = defer(); - this.env.registry.register('adapter:person', DS.Adapter.extend({ - queryRecord: () => deferedFind.promise - })); + this.env.registry.register( + 'adapter:person', + DS.Adapter.extend({ + queryRecord: () => deferedFind.promise, + }) + ); let serializerLoaded = false; let serializerFor = this.store.serializerFor; - this.store.serializerFor = (modelName) => { + this.store.serializerFor = modelName => { if (modelName === 'person') { serializerLoaded = true; } return serializerFor.call(this.store, modelName); }; - let storePromise = run(() => this.store.queryRecord('person', { first_duke_of_marlborough: true })); + let storePromise = run(() => + this.store.queryRecord('person', { first_duke_of_marlborough: true }) + ); assert.equal(false, serializerLoaded, 'serializer is not eagerly loaded'); return run(() => { - deferedFind.resolve({ data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } } }); + deferedFind.resolve({ + data: { id: 1, type: 'person', attributes: { name: 'John Churchill' } }, + }); return storePromise.then(() => { assert.equal(true, serializerLoaded, 'serializer is loaded'); }); }); }); - diff --git a/tests/unit/store/has-model-for-test.js b/tests/unit/store/has-model-for-test.js index 0fa53f5a2cd..47f648a2ba3 100644 --- a/tests/unit/store/has-model-for-test.js +++ b/tests/unit/store/has-model-for-test.js @@ -8,13 +8,13 @@ module('unit/store/has-model-For', { beforeEach() { store = createStore({ adapter: DS.Adapter.extend(), - 'one-foo': DS.Model.extend({}), - 'two-foo': DS.Model.extend({}) + 'one-foo': DS.Model.extend({}), + 'two-foo': DS.Model.extend({}), }); - } + }, }); test(`hasModelFor correctly normalizes`, function(assert) { assert.equal(store._hasModelFor('oneFoo'), true); - assert.equal(store._hasModelFor('twoFoo'). true); + assert.equal(store._hasModelFor('twoFoo').true); }); diff --git a/tests/unit/store/has-record-for-id-test.js b/tests/unit/store/has-record-for-id-test.js index 3aab6feb164..4fb93fc8e15 100644 --- a/tests/unit/store/has-record-for-id-test.js +++ b/tests/unit/store/has-record-for-id-test.js @@ -10,55 +10,53 @@ const { attr, hasMany, belongsTo } = DS; module('unit/store/hasRecordForId - Store hasRecordForId', { beforeEach() { - Person = DS.Model.extend({ firstName: attr('string'), lastName: attr('string'), - phoneNumbers: hasMany('phone-number', { async: false }) + phoneNumbers: hasMany('phone-number', { async: false }), }); PhoneNumber = DS.Model.extend({ number: attr('string'), - person: belongsTo('person', { async: false }) + person: belongsTo('person', { async: false }), }); env = setupStore({ person: Person, - 'phone-number': PhoneNumber + 'phone-number': PhoneNumber, }); store = env.store; - }, afterEach() { run(store, 'destroy'); - } + }, }); test('hasRecordForId should return false for records in the empty state ', function(assert) { - run(() => { store.push({ data: { type: 'person', id: '1', attributes: { - firstName: "Yehuda", - lastName: "Katz" + firstName: 'Yehuda', + lastName: 'Katz', }, relationships: { phoneNumbers: { - data: [ - { type: 'phone-number', id: '1' } - ] - } - } - } + data: [{ type: 'phone-number', id: '1' }], + }, + }, + }, }); - assert.equal(false, store.hasRecordForId('phone-number', 1), 'hasRecordForId only returns true for loaded records'); - + assert.equal( + false, + store.hasRecordForId('phone-number', 1), + 'hasRecordForId only returns true for loaded records' + ); }); }); @@ -69,19 +67,21 @@ test('hasRecordForId should return true for records in the loaded state ', funct type: 'person', id: '1', attributes: { - firstName: "Yehuda", - lastName: "Katz" + firstName: 'Yehuda', + lastName: 'Katz', }, relationships: { phoneNumbers: { - data: [ - { type: 'phone-number', id: '1' } - ] - } - } - } + data: [{ type: 'phone-number', id: '1' }], + }, + }, + }, }); - assert.equal(true, store.hasRecordForId('person', 1), 'hasRecordForId returns true for records loaded into the store'); + assert.equal( + true, + store.hasRecordForId('person', 1), + 'hasRecordForId returns true for records loaded into the store' + ); }); }); diff --git a/tests/unit/store/lookup-test.js b/tests/unit/store/lookup-test.js index 86a210d279e..ac96f6ff363 100644 --- a/tests/unit/store/lookup-test.js +++ b/tests/unit/store/lookup-test.js @@ -13,7 +13,7 @@ function resetStore() { } env = setupStore({ adapter: '-rest', - person: Person + person: Person, }); env.registry.unregister('adapter:application'); @@ -54,29 +54,29 @@ module('unit/store/lookup - Managed Instance lookups', { afterEach() { run(store, 'destroy'); - } + }, }); -test('when the adapter does not exist for a type, the fallback is returned', (assert) => { +test('when the adapter does not exist for a type, the fallback is returned', assert => { let personAdapter = lookupAdapter('person'); assert.strictEqual(personAdapter, applicationAdapter); }); -test('when the adapter for a type exists, returns that instead of the fallback', (assert) => { +test('when the adapter for a type exists, returns that instead of the fallback', assert => { registerAdapter('person', DS.Adapter.extend()); let personAdapter = lookupAdapter('person'); assert.ok(personAdapter !== applicationAdapter); }); -test('when the serializer does not exist for a type, the fallback is returned', (assert) => { +test('when the serializer does not exist for a type, the fallback is returned', assert => { let personSerializer = lookupSerializer('person'); assert.strictEqual(personSerializer, applicationSerializer); }); -test('when the serializer does exist for a type, the serializer is returned', (assert) => { +test('when the serializer does exist for a type, the serializer is returned', assert => { registerSerializer('person', DS.Serializer.extend()); let personSerializer = lookupSerializer('person'); @@ -84,7 +84,7 @@ test('when the serializer does exist for a type, the serializer is returned', (a assert.ok(personSerializer !== applicationSerializer); }); -test('adapter lookup order', (assert) => { +test('adapter lookup order', assert => { assert.expect(3); resetStore(); @@ -97,17 +97,24 @@ test('adapter lookup order', (assert) => { registerAdapter('application', DS.RESTSerializer.extend()); personAdapter = lookupAdapter('person'); - assert.strictEqual(personAdapter, lookupAdapter('application'), 'looks up application adapter before RESTAdapter if it exists'); + assert.strictEqual( + personAdapter, + lookupAdapter('application'), + 'looks up application adapter before RESTAdapter if it exists' + ); resetStore(); registerAdapter('application', DS.RESTSerializer.extend()); registerAdapter('person', DS.RESTSerializer.extend({ customThingy: true })); - assert.ok(lookupAdapter('person').get('customThingy'), 'looks up type serializer before application'); + assert.ok( + lookupAdapter('person').get('customThingy'), + 'looks up type serializer before application' + ); }); -test('serializer lookup order', (assert) => { +test('serializer lookup order', assert => { resetStore(); let personSerializer = lookupSerializer('person'); @@ -118,23 +125,40 @@ test('serializer lookup order', (assert) => { registerSerializer('application', DS.RESTSerializer.extend()); personSerializer = lookupSerializer('person'); - assert.strictEqual(personSerializer, lookupSerializer('application'), 'looks up application before default'); + assert.strictEqual( + personSerializer, + lookupSerializer('application'), + 'looks up application before default' + ); resetStore(); - registerAdapter('person', DS.Adapter.extend({ - defaultSerializer: '-rest' - })); + registerAdapter( + 'person', + DS.Adapter.extend({ + defaultSerializer: '-rest', + }) + ); personSerializer = lookupSerializer('person'); - assert.strictEqual(personSerializer, lookupSerializer('-rest'), 'uses defaultSerializer on adapterFor("model") if application not defined'); + assert.strictEqual( + personSerializer, + lookupSerializer('-rest'), + 'uses defaultSerializer on adapterFor("model") if application not defined' + ); resetStore(); - registerAdapter('person', DS.Adapter.extend({ - defaultSerializer: '-rest' - })); + registerAdapter( + 'person', + DS.Adapter.extend({ + defaultSerializer: '-rest', + }) + ); registerSerializer('application', DS.RESTSerializer.extend()); registerSerializer('person', DS.JSONSerializer.extend({ customThingy: true })); personSerializer = lookupSerializer('person'); - assert.ok(personSerializer.get('customThingy'), 'uses the person serializer before any fallbacks if it is defined'); + assert.ok( + personSerializer.get('customThingy'), + 'uses the person serializer before any fallbacks if it is defined' + ); }); diff --git a/tests/unit/store/model-for-test.js b/tests/unit/store/model-for-test.js index 0c74eeaeb2c..dbcde0aa566 100644 --- a/tests/unit/store/model-for-test.js +++ b/tests/unit/store/model-for-test.js @@ -12,7 +12,7 @@ module('unit/store/model_for - DS.Store#modelFor', { beforeEach() { env = setupStore({ blogPost: DS.Model.extend(), - 'blog.post': DS.Model.extend() + 'blog.post': DS.Model.extend(), }); store = env.store; container = env.container; @@ -24,21 +24,29 @@ module('unit/store/model_for - DS.Store#modelFor', { container.destroy(); store.destroy(); }); - } + }, }); test('when fetching factory from string, sets a normalized key as modelName', function(assert) { env.replaceContainerNormalize(key => dasherize(camelize(key))); assert.equal(registry.normalize('some.post'), 'some-post', 'precond - container camelizes'); - assert.equal(store.modelFor('blog.post').modelName, 'blog.post', 'modelName is normalized to dasherized'); + assert.equal( + store.modelFor('blog.post').modelName, + 'blog.post', + 'modelName is normalized to dasherized' + ); }); test('when fetching factory from string and dashing normalizer, sets a normalized key as modelName', function(assert) { env.replaceContainerNormalize(key => dasherize(camelize(key))); assert.equal(registry.normalize('some.post'), 'some-post', 'precond - container dasherizes'); - assert.equal(store.modelFor("blog.post").modelName, "blog.post", "modelName is normalized to dasherized"); + assert.equal( + store.modelFor('blog.post').modelName, + 'blog.post', + 'modelName is normalized to dasherized' + ); }); test(`when fetching something that doesn't exist, throws error`, function(assert) { diff --git a/tests/unit/store/peek-record-test.js b/tests/unit/store/peek-record-test.js index 4e92782bdd6..4c8fb61bc03 100644 --- a/tests/unit/store/peek-record-test.js +++ b/tests/unit/store/peek-record-test.js @@ -14,7 +14,7 @@ module('unit/store/peekRecord - Store peekRecord', { Person = DS.Model.extend(); env = setupStore({ - person: Person + person: Person, }); store = env.store; @@ -22,7 +22,7 @@ module('unit/store/peekRecord - Store peekRecord', { afterEach() { run(store, 'destroy'); - } + }, }); test('peekRecord should return the record if it is in the store ', function(assert) { @@ -30,16 +30,24 @@ test('peekRecord should return the record if it is in the store ', function(asse let person = store.push({ data: { type: 'person', - id: '1' - } + id: '1', + }, }); - assert.equal(person, store.peekRecord('person', 1), 'peekRecord only return the corresponding record in the store'); + assert.equal( + person, + store.peekRecord('person', 1), + 'peekRecord only return the corresponding record in the store' + ); }); }); test('peekRecord should return null if the record is not in the store ', function(assert) { run(() => { - assert.equal(null, store.peekRecord('person', 1), 'peekRecord returns null if the corresponding record is not in the store'); + assert.equal( + null, + store.peekRecord('person', 1), + 'peekRecord returns null if the corresponding record is not in the store' + ); }); }); @@ -51,7 +59,9 @@ testInDebug('peekRecord should assert if not passed both model name and id', fun }); }); -testInDebug('peekRecord should assert if passed a model class instead of model name', function(assert) { +testInDebug('peekRecord should assert if passed a model class instead of model name', function( + assert +) { run(() => { assert.expectAssertion(() => { let modelClass = Ember.Object.extend(); diff --git a/tests/unit/store/push-test.js b/tests/unit/store/push-test.js index 22291b6e4d2..dfcd91a2340 100644 --- a/tests/unit/store/push-test.js +++ b/tests/unit/store/push-test.js @@ -17,22 +17,22 @@ module('unit/store/push - DS.Store#push', { Person = DS.Model.extend({ firstName: attr('string'), lastName: attr('string'), - phoneNumbers: hasMany('phone-number', { async: false }) + phoneNumbers: hasMany('phone-number', { async: false }), }); PhoneNumber = DS.Model.extend({ number: attr('string'), - person: belongsTo('person', { async: false }) + person: belongsTo('person', { async: false }), }); Post = DS.Model.extend({ - postTitle: attr('string') + postTitle: attr('string'), }); env = setupStore({ post: Post, person: Person, - "phone-number": PhoneNumber + 'phone-number': PhoneNumber, }); store = env.store; @@ -42,7 +42,7 @@ module('unit/store/push - DS.Store#push', { afterEach() { run(store, 'destroy'); - } + }, }); test('Changed attributes are reset when matching data is pushed', function(assert) { @@ -52,9 +52,9 @@ test('Changed attributes are reset when matching data is pushed', function(asser type: 'person', id: 1, attributes: { - firstName: 'original first name' - } - } + firstName: 'original first name', + }, + }, }); }); @@ -66,7 +66,10 @@ test('Changed attributes are reset when matching data is pushed', function(asser assert.equal(person.get('firstName'), 'updated first name'); assert.strictEqual(person.get('lastName'), undefined); assert.equal(person.get('currentState.stateName'), 'root.loaded.updated.uncommitted'); - assert.deepEqual(person.changedAttributes().firstName, ['original first name', 'updated first name']); + assert.deepEqual(person.changedAttributes().firstName, [ + 'original first name', + 'updated first name', + ]); run(() => { store.push({ @@ -74,9 +77,9 @@ test('Changed attributes are reset when matching data is pushed', function(asser type: 'person', id: 1, attributes: { - firstName: 'updated first name' - } - } + firstName: 'updated first name', + }, + }, }); }); @@ -96,17 +99,21 @@ test('Calling push with a normalized hash returns a record', function(assert) { id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' - } - } + lastName: 'Katz', + }, + }, }); return store.findRecord('person', 'wat').then(foundPerson => { - assert.equal(foundPerson, person, 'record returned via load() is the same as the record returned from findRecord()'); + assert.equal( + foundPerson, + person, + 'record returned via load() is the same as the record returned from findRecord()' + ); assert.deepEqual(foundPerson.getProperties('id', 'firstName', 'lastName'), { id: 'wat', firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }); }); }); @@ -126,16 +133,16 @@ test('Supplying a model class for `push` is the same as supplying a string', fun id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' - } - } + lastName: 'Katz', + }, + }, }); return store.findRecord('programmer', 'wat').then(foundProgrammer => { assert.deepEqual(foundProgrammer.getProperties('id', 'firstName', 'lastName'), { id: 'wat', firstName: 'Yehuda', - lastName: 'Katz' + lastName: 'Katz', }); }); }); @@ -153,7 +160,7 @@ test(`Calling push triggers 'didLoad' even if the record hasn't been requested f } catch (e) { reject(e); } - } + }, }); }); @@ -164,9 +171,9 @@ test(`Calling push triggers 'didLoad' even if the record hasn't been requested f id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' - } - } + lastName: 'Katz', + }, + }, }); }); @@ -184,9 +191,9 @@ test('Calling push with partial records updates just those attributes', function id: 'wat', attributes: { firstName: 'Yehuda', - lastName: 'Katz' - } - } + lastName: 'Katz', + }, + }, }); let person = store.peekRecord('person', 'wat'); @@ -196,17 +203,21 @@ test('Calling push with partial records updates just those attributes', function type: 'person', id: 'wat', attributes: { - lastName: "Katz!" - } - } + lastName: 'Katz!', + }, + }, }); return store.findRecord('person', 'wat').then(foundPerson => { - assert.equal(foundPerson, person, 'record returned via load() is the same as the record returned from findRecord()'); + assert.equal( + foundPerson, + person, + 'record returned via load() is the same as the record returned from findRecord()' + ); assert.deepEqual(foundPerson.getProperties('id', 'firstName', 'lastName'), { id: 'wat', firstName: 'Yehuda', - lastName: "Katz!" + lastName: 'Katz!', }); }); }); @@ -223,15 +234,17 @@ test('Calling push on normalize allows partial updates with raw JSON', function( id: '1', attributes: { firstName: 'Robert', - lastName: 'Jackson' - } - } + lastName: 'Jackson', + }, + }, }); - store.push(store.normalize('person', { - id: '1', - firstName: "Jacquie" - })); + store.push( + store.normalize('person', { + id: '1', + firstName: 'Jacquie', + }) + ); }); assert.equal(person.get('firstName'), 'Jacquie', 'you can push raw JSON into the store'); @@ -242,10 +255,9 @@ test('Calling push with a normalized hash containing IDs of related records retu assert.expect(1); Person.reopen({ - phoneNumbers: - hasMany('phone-number', { - async: true - }) + phoneNumbers: hasMany('phone-number', { + async: true, + }), }); env.adapter.findRecord = function(store, type, id) { @@ -257,14 +269,14 @@ test('Calling push with a normalized hash containing IDs of related records retu attributes: { number: '5551212' }, relationships: { person: { - data: { id: 'wat', type: 'person' } - } - } - } + data: { id: 'wat', type: 'person' }, + }, + }, + }, }); } - if (id === "2") { + if (id === '2') { return resolve({ data: { id: 2, @@ -272,44 +284,49 @@ test('Calling push with a normalized hash containing IDs of related records retu attributes: { number: '5552121' }, relationships: { person: { - data: { id: 'wat', type: 'person' } - } - } - } + data: { id: 'wat', type: 'person' }, + }, + }, + }, }); } }; return run(() => { - let person = store.push(store.normalize('person', { - id: 'wat', - type: 'person', - attributes: { - 'first-name': 'John', - 'last-name': 'Smith' - }, - relationships: { - 'phone-numbers': { - data: [{ id: 1, type: 'phone-number' }, { id: 2, type: 'phone-number' }] - } - } - })); + let person = store.push( + store.normalize('person', { + id: 'wat', + type: 'person', + attributes: { + 'first-name': 'John', + 'last-name': 'Smith', + }, + relationships: { + 'phone-numbers': { + data: [{ id: 1, type: 'phone-number' }, { id: 2, type: 'phone-number' }], + }, + }, + }) + ); return person.get('phoneNumbers').then(phoneNumbers => { - assert.deepEqual(phoneNumbers.map(item => { - return item.getProperties('id', 'number', 'person'); - }), [ - { - id: '1', - number: '5551212', - person: person - }, - { - id: '2', - number: '5552121', - person: person - } - ]); + assert.deepEqual( + phoneNumbers.map(item => { + return item.getProperties('id', 'number', 'person'); + }), + [ + { + id: '1', + number: '5551212', + person: person, + }, + { + id: '2', + number: '5552121', + person: person, + }, + ] + ); }); }); }); @@ -317,10 +334,12 @@ test('Calling push with a normalized hash containing IDs of related records retu test('Calling pushPayload allows pushing raw JSON', function(assert) { run(() => { store.pushPayload('post', { - posts: [{ - id: '1', - postTitle: "Ember rocks" - }] + posts: [ + { + id: '1', + postTitle: 'Ember rocks', + }, + ], }); }); @@ -330,10 +349,12 @@ test('Calling pushPayload allows pushing raw JSON', function(assert) { run(() => { store.pushPayload('post', { - posts: [{ - id: '1', - postTitle: 'Ember rocks (updated)' - }] + posts: [ + { + id: '1', + postTitle: 'Ember rocks (updated)', + }, + ], }); }); @@ -345,8 +366,8 @@ test('Calling pushPayload allows pushing singular payload properties', function( store.pushPayload('post', { post: { id: '1', - postTitle: 'Ember rocks' - } + postTitle: 'Ember rocks', + }, }); }); @@ -358,8 +379,8 @@ test('Calling pushPayload allows pushing singular payload properties', function( store.pushPayload('post', { post: { id: '1', - postTitle: 'Ember rocks (updated)' - } + postTitle: 'Ember rocks (updated)', + }, }); }); @@ -369,34 +390,40 @@ test('Calling pushPayload allows pushing singular payload properties', function( test(`Calling pushPayload should use the type's serializer for normalizing`, function(assert) { assert.expect(4); - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - normalize() { - assert.ok(true, 'normalized is called on Post serializer'); - return this._super(...arguments); - } - })); - - env.registry.register('serializer:person', DS.RESTSerializer.extend({ - normalize() { - assert.ok(true, 'normalized is called on Person serializer'); - return this._super(...arguments); - } - })); + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + normalize() { + assert.ok(true, 'normalized is called on Post serializer'); + return this._super(...arguments); + }, + }) + ); + + env.registry.register( + 'serializer:person', + DS.RESTSerializer.extend({ + normalize() { + assert.ok(true, 'normalized is called on Person serializer'); + return this._super(...arguments); + }, + }) + ); run(() => { store.pushPayload('post', { posts: [ { id: 1, - postTitle: 'Ember rocks' - } + postTitle: 'Ember rocks', + }, ], people: [ { id: 2, - firstName: 'Yehuda' - } - ] + firstName: 'Yehuda', + }, + ], }); }); @@ -412,16 +439,19 @@ test(`Calling pushPayload should use the type's serializer for normalizing`, fun test(`Calling pushPayload without a type uses application serializer's pushPayload method`, function(assert) { assert.expect(1); - env.registry.register('serializer:application', DS.RESTSerializer.extend({ - pushPayload() { - assert.ok(true, `pushPayload is called on Application serializer`); - return this._super(...arguments); - } - })); + env.registry.register( + 'serializer:application', + DS.RESTSerializer.extend({ + pushPayload() { + assert.ok(true, `pushPayload is called on Application serializer`); + return this._super(...arguments); + }, + }) + ); run(() => { store.pushPayload({ - posts: [{ id: '1', postTitle: 'Ember rocks' }] + posts: [{ id: '1', postTitle: 'Ember rocks' }], }); }); }); @@ -429,34 +459,40 @@ test(`Calling pushPayload without a type uses application serializer's pushPaylo test(`Calling pushPayload without a type should use a model's serializer when normalizing`, function(assert) { assert.expect(4); - env.registry.register('serializer:post', DS.RESTSerializer.extend({ - normalize() { - assert.ok(true, 'normalized is called on Post serializer'); - return this._super(...arguments); - } - })); - - env.registry.register('serializer:application', DS.RESTSerializer.extend({ - normalize() { - assert.ok(true, 'normalized is called on Application serializer'); - return this._super(...arguments); - } - })); + env.registry.register( + 'serializer:post', + DS.RESTSerializer.extend({ + normalize() { + assert.ok(true, 'normalized is called on Post serializer'); + return this._super(...arguments); + }, + }) + ); + + env.registry.register( + 'serializer:application', + DS.RESTSerializer.extend({ + normalize() { + assert.ok(true, 'normalized is called on Application serializer'); + return this._super(...arguments); + }, + }) + ); run(() => { store.pushPayload({ posts: [ { id: '1', - postTitle: 'Ember rocks' - } + postTitle: 'Ember rocks', + }, ], people: [ { id: '2', - firstName: 'Yehuda' - } - ] + firstName: 'Yehuda', + }, + ], }); }); @@ -474,11 +510,13 @@ test('Calling pushPayload allows partial updates with raw JSON', function(assert run(() => { store.pushPayload('person', { - people: [{ - id: '1', - firstName: 'Robert', - lastName: 'Jackson' - }] + people: [ + { + id: '1', + firstName: 'Robert', + lastName: 'Jackson', + }, + ], }); }); @@ -489,10 +527,12 @@ test('Calling pushPayload allows partial updates with raw JSON', function(assert run(() => { store.pushPayload('person', { - people: [{ - id: '1', - firstName: 'Jacquie' - }] + people: [ + { + id: '1', + firstName: 'Jacquie', + }, + ], }); }); @@ -501,18 +541,11 @@ test('Calling pushPayload allows partial updates with raw JSON', function(assert }); testInDebug('calling push without data argument as an object raises an error', function(assert) { - let invalidValues = [ - null, - 1, - 'string', - EmberObject.create(), - EmberObject.extend(), - true - ]; + let invalidValues = [null, 1, 'string', EmberObject.create(), EmberObject.extend(), true]; assert.expect(invalidValues.length); - invalidValues.forEach((invalidValue) => { + invalidValues.forEach(invalidValue => { assert.expectAssertion(() => { run(() => { store.push('person', invalidValue); @@ -521,57 +554,60 @@ testInDebug('calling push without data argument as an object raises an error', f }); }); -testInDebug('Calling push with a link for a non async relationship should warn if no data', function(assert) { - Person.reopen({ - phoneNumbers: hasMany('phone-number', { async: false }) - }); +testInDebug( + 'Calling push with a link for a non async relationship should warn if no data', + function(assert) { + Person.reopen({ + phoneNumbers: hasMany('phone-number', { async: false }), + }); - assert.expectWarning(() => { - run(() => { - store.push({ - data: { - type: 'person', - id: '1', - relationships: { - phoneNumbers: { - links: { - related: '/api/people/1/phone-numbers' - } - } - } - } + assert.expectWarning(() => { + run(() => { + store.push({ + data: { + type: 'person', + id: '1', + relationships: { + phoneNumbers: { + links: { + related: '/api/people/1/phone-numbers', + }, + }, + }, + }, + }); }); - }); - }, /You pushed a record of type 'person' with a relationship 'phoneNumbers' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload./); -}); + }, /You pushed a record of type 'person' with a relationship 'phoneNumbers' configured as 'async: false'. You've included a link but no primary data, this may be an error in your payload./); + } +); -testInDebug('Calling push with a link for a non async relationship should not warn when data is present', function(assert) { - Person.reopen({ - phoneNumbers: hasMany('phone-number', { async: false }) - }); +testInDebug( + 'Calling push with a link for a non async relationship should not warn when data is present', + function(assert) { + Person.reopen({ + phoneNumbers: hasMany('phone-number', { async: false }), + }); - assert.expectNoWarning(() => { - run(() => { - store.push({ - data: { - type: 'person', - id: '1', - relationships: { - phoneNumbers: { - data: [ - { type: 'phone-number', id: '2' }, - { type: 'phone-number', id: '3' } - ], - links: { - related: '/api/people/1/phone-numbers' - } - } - } - } + assert.expectNoWarning(() => { + run(() => { + store.push({ + data: { + type: 'person', + id: '1', + relationships: { + phoneNumbers: { + data: [{ type: 'phone-number', id: '2' }, { type: 'phone-number', id: '3' }], + links: { + related: '/api/people/1/phone-numbers', + }, + }, + }, + }, + }); }); }); - }); -}); + } +); testInDebug('Calling push with an unknown model name throws an assertion error', function(assert) { assert.expectAssertion(() => { @@ -579,8 +615,8 @@ testInDebug('Calling push with an unknown model name throws an assertion error', store.push({ data: { id: '1', - type: 'unknown' - } + type: 'unknown', + }, }); }); }, /You tried to push data with a type 'unknown' but no model could be found with that name/); @@ -588,22 +624,24 @@ testInDebug('Calling push with an unknown model name throws an assertion error', test('Calling push with a link containing an object', function(assert) { Person.reopen({ - phoneNumbers: hasMany('phone-number', { async: true }) + phoneNumbers: hasMany('phone-number', { async: true }), }); run(() => { - store.push(store.normalize('person', { - id: '1', - type: 'person', - attributes: { - 'first-name': 'Tan' - }, - relationships: { - 'phone-numbers': { - links: { related: '/api/people/1/phone-numbers' } - } - } - })); + store.push( + store.normalize('person', { + id: '1', + type: 'person', + attributes: { + 'first-name': 'Tan', + }, + relationships: { + 'phone-numbers': { + links: { related: '/api/people/1/phone-numbers' }, + }, + }, + }) + ); }); let person = store.peekRecord('person', 1); @@ -613,20 +651,22 @@ test('Calling push with a link containing an object', function(assert) { test('Calling push with a link containing the value null', function(assert) { run(() => { - store.push(store.normalize('person', { - id: '1', - type: 'person', - attributes: { - 'first-name': 'Tan' - }, - relationships: { - 'phone-numbers': { - links: { - related: null - } - } - } - })); + store.push( + store.normalize('person', { + id: '1', + type: 'person', + attributes: { + 'first-name': 'Tan', + }, + relationships: { + 'phone-numbers': { + links: { + related: null, + }, + }, + }, + }) + ); }); let person = store.peekRecord('person', 1); @@ -643,21 +683,17 @@ testInDebug('calling push with hasMany relationship the value must be an array', id: '1', relationships: { phoneNumbers: { - data: 1 - } - } - } + data: 1, + }, + }, + }, }); }); }); }); testInDebug('calling push with missing or invalid `id` throws assertion error', function(assert) { - let invalidValues = [ - {}, - { id: null }, - { id: '' } - ]; + let invalidValues = [{}, { id: null }, { id: '' }]; assert.expect(invalidValues.length); @@ -665,14 +701,16 @@ testInDebug('calling push with missing or invalid `id` throws assertion error', assert.expectAssertion(() => { run(() => { store.push({ - data: invalidValue + data: invalidValue, }); }); }, /You must include an 'id'/); }); }); -testInDebug('calling push with belongsTo relationship the value must not be an array', function(assert) { +testInDebug('calling push with belongsTo relationship the value must not be an array', function( + assert +) { assert.expectAssertion(() => { run(() => { store.push({ @@ -681,62 +719,68 @@ testInDebug('calling push with belongsTo relationship the value must not be an a id: '1', relationships: { person: { - data: [1] - } - } - } + data: [1], + }, + }, + }, }); }); }, /must not be an array/); }); -testInDebug('Enabling Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS should warn on unknown attributes', function(assert) { - run(() => { - let originalFlagValue = Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS; - try { - Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS = true; - assert.expectWarning(() => { - store.push({ - data: { - type: 'person', - id: '1', - attributes: { - firstName: 'Tomster', - emailAddress: 'tomster@emberjs.com', - isMascot: true - } - } - }); - }, `The payload for 'person' contains these unknown attributes: emailAddress,isMascot. Make sure they've been defined in your model.`); - } finally { - Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS = originalFlagValue; - } - }); -}); +testInDebug( + 'Enabling Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS should warn on unknown attributes', + function(assert) { + run(() => { + let originalFlagValue = Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS; + try { + Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS = true; + assert.expectWarning(() => { + store.push({ + data: { + type: 'person', + id: '1', + attributes: { + firstName: 'Tomster', + emailAddress: 'tomster@emberjs.com', + isMascot: true, + }, + }, + }); + }, `The payload for 'person' contains these unknown attributes: emailAddress,isMascot. Make sure they've been defined in your model.`); + } finally { + Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS = originalFlagValue; + } + }); + } +); -testInDebug('Enabling Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS should warn on unknown relationships', function(assert) { - run(() => { - var originalFlagValue = Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS; - try { - Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS = true; - assert.expectWarning(() => { - store.push({ - data: { - type: 'person', - id: '1', - relationships: { - phoneNumbers: {}, - emailAddresses: {}, - mascots: {} - } - } - }); - }, `The payload for 'person' contains these unknown relationships: emailAddresses,mascots. Make sure they've been defined in your model.`); - } finally { - Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS = originalFlagValue; - } - }); -}); +testInDebug( + 'Enabling Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS should warn on unknown relationships', + function(assert) { + run(() => { + var originalFlagValue = Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS; + try { + Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS = true; + assert.expectWarning(() => { + store.push({ + data: { + type: 'person', + id: '1', + relationships: { + phoneNumbers: {}, + emailAddresses: {}, + mascots: {}, + }, + }, + }); + }, `The payload for 'person' contains these unknown relationships: emailAddresses,mascots. Make sure they've been defined in your model.`); + } finally { + Ember.ENV.DS_WARN_ON_UNKNOWN_KEYS = originalFlagValue; + } + }); + } +); testInDebug('Calling push with unknown keys should not warn by default', function(assert) { assert.expectNoWarning(() => { @@ -748,9 +792,9 @@ testInDebug('Calling push with unknown keys should not warn by default', functio attributes: { firstName: 'Tomster', emailAddress: 'tomster@emberjs.com', - isMascot: true - } - } + isMascot: true, + }, + }, }); }); }, /The payload for 'person' contains these unknown .*: .* Make sure they've been defined in your model./); @@ -763,8 +807,8 @@ test('_push returns an instance of InternalModel if an object is pushed', functi pushResult = store._push({ data: { id: 1, - type: 'person' - } + type: 'person', + }, }); }); @@ -782,8 +826,8 @@ test('_push does not require a modelName to resolve to a modelClass', function(a store._push({ data: { id: 1, - type: 'person' - } + type: 'person', + }, }); }); @@ -796,10 +840,12 @@ test('_push returns an array of InternalModels if an array is pushed', function( run(() => { pushResult = store._push({ - data: [{ - id: 1, - type: 'person' - }] + data: [ + { + id: 1, + type: 'person', + }, + ], }); }); @@ -808,13 +854,12 @@ test('_push returns an array of InternalModels if an array is pushed', function( assert.notOk(pushResult[0].record, 'InternalModel is not materialized'); }); - test('_push returns null if no data is pushed', function(assert) { let pushResult; run(() => { pushResult = store._push({ - data: null + data: null, }); }); @@ -825,19 +870,19 @@ module('unit/store/push - DS.Store#push with JSON-API', { beforeEach() { const Person = DS.Model.extend({ name: DS.attr('string'), - cars: DS.hasMany('car', { async: false }) + cars: DS.hasMany('car', { async: false }), }); const Car = DS.Model.extend({ make: DS.attr('string'), model: DS.attr('string'), - person: DS.belongsTo('person', { async: false }) + person: DS.belongsTo('person', { async: false }), }); env = setupStore({ adapter: DS.Adapter, car: Car, - person: Person + person: Person, }); store = env.store; @@ -845,7 +890,7 @@ module('unit/store/push - DS.Store#push with JSON-API', { afterEach() { run(store, 'destroy'); - } + }, }); test('Should support pushing multiple models into the store', function(assert) { @@ -858,16 +903,17 @@ test('Should support pushing multiple models into the store', function(assert) { type: 'person', id: 1, attributes: { - name: 'Tom Dale' - } + name: 'Tom Dale', + }, }, { type: 'person', id: 2, attributes: { - name: "Tomster" - } - }] + name: 'Tomster', + }, + }, + ], }); }); @@ -878,7 +924,6 @@ test('Should support pushing multiple models into the store', function(assert) { assert.equal(tomster.get('name'), 'Tomster', 'Tomster should be in the store'); }); - test('Should support pushing included models into the store', function(assert) { assert.expect(2); @@ -889,18 +934,19 @@ test('Should support pushing included models into the store', function(assert) { type: 'person', id: 1, attributes: { - name: 'Tomster' + name: 'Tomster', }, relationships: { cars: [ { data: { - type: 'person', id: 1 - } - } - ] - } - } + type: 'person', + id: 1, + }, + }, + ], + }, + }, ], included: [ { @@ -908,17 +954,18 @@ test('Should support pushing included models into the store', function(assert) { id: 1, attributes: { make: 'Dodge', - model: 'Neon' + model: 'Neon', }, relationships: { person: { data: { - id: 1, type: 'person' - } - } - } - } - ] + id: 1, + type: 'person', + }, + }, + }, + }, + ], }); }); @@ -926,5 +973,5 @@ test('Should support pushing included models into the store', function(assert) { assert.equal(tomster.get('name'), 'Tomster', 'Tomster should be in the store'); let car = store.peekRecord('car', 1); - assert.equal(car.get('model'), 'Neon', 'Tomster\'s car should be in the store'); + assert.equal(car.get('model'), 'Neon', "Tomster's car should be in the store"); }); diff --git a/tests/unit/store/serializer-for-test.js b/tests/unit/store/serializer-for-test.js index 0bebe7a918a..10d1e368150 100644 --- a/tests/unit/store/serializer-for-test.js +++ b/tests/unit/store/serializer-for-test.js @@ -22,7 +22,7 @@ module('unit/store/serializer_for - DS.Store#serializerFor', { container.destroy(); store.destroy(); }); - } + }, }); test('Calling serializerFor looks up `serializer:` from the container', function(assert) { @@ -30,7 +30,10 @@ test('Calling serializerFor looks up `serializer:` from the container', fu registry.register('serializer:person', PersonSerializer); - assert.ok(store.serializerFor('person') instanceof PersonSerializer, 'serializer returned from serializerFor is an instance of the registered Serializer class'); + assert.ok( + store.serializerFor('person') instanceof PersonSerializer, + 'serializer returned from serializerFor is an instance of the registered Serializer class' + ); }); test('Calling serializerFor with a type that has not been registered looks up the default ApplicationSerializer', function(assert) { @@ -38,11 +41,17 @@ test('Calling serializerFor with a type that has not been registered looks up th registry.register('serializer:application', ApplicationSerializer); - assert.ok(store.serializerFor('person') instanceof ApplicationSerializer, 'serializer returned from serializerFor is an instance of ApplicationSerializer'); + assert.ok( + store.serializerFor('person') instanceof ApplicationSerializer, + 'serializer returned from serializerFor is an instance of ApplicationSerializer' + ); }); test('Calling serializerFor with a type that has not been registered and in an application that does not have an ApplicationSerializer looks up the default Ember Data serializer', function(assert) { - assert.ok(store.serializerFor('person') instanceof DS.JSONSerializer, 'serializer returned from serializerFor is an instance of DS.JSONSerializer'); + assert.ok( + store.serializerFor('person') instanceof DS.JSONSerializer, + 'serializer returned from serializerFor is an instance of DS.JSONSerializer' + ); }); testInDebug('Calling serializerFor with a model class should assert', function(assert) { diff --git a/tests/unit/store/unload-test.js b/tests/unit/store/unload-test.js index 772b5cd959e..2ba613a8ece 100644 --- a/tests/unit/store/unload-test.js +++ b/tests/unit/store/unload-test.js @@ -12,33 +12,34 @@ let store, tryToFind, Record; module('unit/store/unload - Store unloading records', { beforeEach() { - Record = DS.Model.extend({ title: DS.attr('string'), - wasFetched: DS.attr('boolean') + wasFetched: DS.attr('boolean'), }); Record.reopenClass({ toString() { return 'Record'; - } + }, }); store = createStore({ adapter: DS.Adapter.extend({ findRecord(store, type, id, snapshot) { tryToFind = true; - return resolve({ data: { id, type: snapshot.modelName, attributes: { 'was-fetched': true } } }); - } + return resolve({ + data: { id, type: snapshot.modelName, attributes: { 'was-fetched': true } }, + }); + }, }), - record: Record + record: Record, }); }, afterEach() { run(store, 'destroy'); - } + }, }); testInDebug('unload a dirty record asserts', function(assert) { @@ -50,9 +51,9 @@ testInDebug('unload a dirty record asserts', function(assert) { type: 'record', id: '1', attributes: { - title: 'toto' - } - } + title: 'toto', + }, + }, }); let record = store.peekRecord('record', 1); @@ -62,9 +63,15 @@ testInDebug('unload a dirty record asserts', function(assert) { assert.equal(get(record, 'hasDirtyAttributes'), true, 'record is dirty'); - assert.expectAssertion(function() { - record.unloadRecord(); - }, 'You can only unload a record which is not inFlight. `' + record._internalModel.toString() + '`', 'can not unload dirty record'); + assert.expectAssertion( + function() { + record.unloadRecord(); + }, + 'You can only unload a record which is not inFlight. `' + + record._internalModel.toString() + + '`', + 'can not unload dirty record' + ); // force back into safe to unload mode. run(() => { @@ -82,9 +89,9 @@ test('unload a record', function(assert) { type: 'record', id: '1', attributes: { - title: 'toto' - } - } + title: 'toto', + }, + }, }); return store.findRecord('record', 1).then(record => { @@ -119,38 +126,38 @@ test('can commit store after unload record with relationships', function(assert) assert.expect(1); const Brand = DS.Model.extend({ - name: DS.attr('string') + name: DS.attr('string'), }); Brand.reopenClass({ toString() { return 'Brand'; - } + }, }); const Product = DS.Model.extend({ description: DS.attr('string'), brand: DS.belongsTo('brand', { - async: false - }) + async: false, + }), }); Product.reopenClass({ toString() { return 'Product'; - } + }, }); const Like = DS.Model.extend({ product: DS.belongsTo('product', { - async: false - }) + async: false, + }), }); Like.reopenClass({ toString() { return 'Like'; - } + }, }); let store = createStore({ @@ -162,19 +169,19 @@ test('can commit store after unload record with relationships', function(assert) type: snapshot.modelName, attributes: { description: 'cuisinart', - brand: 1 - } - } + brand: 1, + }, + }, }); }, createRecord(store, type, snapshot) { return resolve(); - } + }, }), brand: Brand, product: Product, - like: Like + like: Like, }); return run(() => { @@ -184,33 +191,41 @@ test('can commit store after unload record with relationships', function(assert) type: 'brand', id: '1', attributes: { - name: 'EmberJS' - } + name: 'EmberJS', + }, }, { type: 'product', id: '1', attributes: { - description: 'toto' + description: 'toto', }, relationships: { brand: { - data: { type: 'brand', id: '1' } - } - } - }] + data: { type: 'brand', id: '1' }, + }, + }, + }, + ], }); let product = store.peekRecord('product', 1); let like = store.createRecord('like', { id: 1, product: product }); return like.save(); - }).then(() => { - // TODO: this is strange, future travelers please address - run(() => store.unloadRecord(store.peekRecord('product', 1))); - }).then(() => { - return store.findRecord('product', 1); - }).then(product => { - assert.equal(product.get('description'), 'cuisinart', "The record was unloaded and the adapter's `findRecord` was called"); - }); + }) + .then(() => { + // TODO: this is strange, future travelers please address + run(() => store.unloadRecord(store.peekRecord('product', 1))); + }) + .then(() => { + return store.findRecord('product', 1); + }) + .then(product => { + assert.equal( + product.get('description'), + 'cuisinart', + "The record was unloaded and the adapter's `findRecord` was called" + ); + }); }); diff --git a/tests/unit/system/relationships/polymorphic-relationship-payloads-test.js b/tests/unit/system/relationships/polymorphic-relationship-payloads-test.js index 5d73cce6798..43c2db2e5d4 100644 --- a/tests/unit/system/relationships/polymorphic-relationship-payloads-test.js +++ b/tests/unit/system/relationships/polymorphic-relationship-payloads-test.js @@ -11,7 +11,7 @@ module('unit/system/relationships/relationship-payloads-manager (polymorphic)', beforeEach() { const User = DS.Model.extend({ hats: hasMany('hat', { async: false, polymorphic: true, inverse: 'user' }), - sharedHats: hasMany('hat', { async: false, polymorphic: true, inverse: 'sharingUsers' }) + sharedHats: hasMany('hat', { async: false, polymorphic: true, inverse: 'sharingUsers' }), }); User.toString = () => 'User'; @@ -23,7 +23,7 @@ module('unit/system/relationships/relationship-payloads-manager (polymorphic)', user: belongsTo('user', { async: false, inverse: 'hats', polymorphic: true }), sharingUsers: belongsTo('users', { async: false, inverse: 'sharedHats', polymorphic: true }), hat: belongsTo('hat', { async: false, inverse: 'hats', polymorphic: true }), - hats: hasMany('hat', { async: false, inverse: 'hat', polymorphic: true }) + hats: hasMany('hat', { async: false, inverse: 'hat', polymorphic: true }), }); const BigHat = Hat.extend({}); const SmallHat = Hat.extend({}); @@ -33,9 +33,9 @@ module('unit/system/relationships/relationship-payloads-manager (polymorphic)', alien: Alien, hat: Hat, 'big-hat': BigHat, - 'small-hat': SmallHat + 'small-hat': SmallHat, }); - } + }, }); test('push one side is polymorphic, baseType then subTypes', function(assert) { @@ -53,9 +53,9 @@ test('push one side is polymorphic, baseType then subTypes', function(assert) { attributes: {}, relationships: { user: { - data: { id: '1' , type: 'user' } - } - } + data: { id: '1', type: 'user' }, + }, + }, }; const hatData1 = makeHat('hat', hatData), @@ -66,13 +66,9 @@ test('push one side is polymorphic, baseType then subTypes', function(assert) { data: { id: '1', type: 'user', - attributes: {} + attributes: {}, }, - included: [ - hatData1, - bigHatData1, - smallHatData1 - ] + included: [hatData1, bigHatData1, smallHatData1], }; const user = run(() => this.store.push(userData)); @@ -97,9 +93,9 @@ test('push one side is polymorphic, subType then baseType', function(assert) { attributes: {}, relationships: { user: { - data: { id: '1' , type: 'user' } - } - } + data: { id: '1', type: 'user' }, + }, + }, }; const bigHatData1 = makeHat('hat', hatData), @@ -111,14 +107,14 @@ test('push one side is polymorphic, subType then baseType', function(assert) { data: { id: '1', type: 'user', - attributes: {} + attributes: {}, }, - included + included, }; const user = run(() => this.store.push(userData)), finalResult = user.get('hats').mapBy('type'), - expectedResults = included.map(m=>m.type); + expectedResults = included.map(m => m.type); assert.deepEqual(finalResult, expectedResults, 'We got all our hats!'); }); @@ -135,32 +131,27 @@ test('push one side is polymorphic, different subtypes', function(assert) { } const hatData = { - attributes:{}, + attributes: {}, relationships: { user: { - data: { id: '1' , type: 'user' } - } - } + data: { id: '1', type: 'user' }, + }, + }, }; const bigHatData1 = makeHat('big-hat', hatData), smallHatData1 = makeHat('small-hat', hatData), bigHatData2 = makeHat('big-hat', hatData), smallHatData2 = makeHat('small-hat', hatData), - included = [ - bigHatData1, - smallHatData1, - bigHatData2, - smallHatData2 - ]; + included = [bigHatData1, smallHatData1, bigHatData2, smallHatData2]; const userData = { data: { id: '1', type: 'user', - attributes: {} + attributes: {}, }, - included + included, }; const user = run(() => this.store.push(userData)), @@ -185,9 +176,9 @@ test('push both sides are polymorphic', function(assert) { attributes: {}, relationships: { user: { - data: { id: '1' , type: 'alien' } - } - } + data: { id: '1', type: 'alien' }, + }, + }, }; const bigHatData1 = makeHat('hat', alienHatData), @@ -198,9 +189,9 @@ test('push both sides are polymorphic', function(assert) { data: { id: '1', type: 'alien', - attributes: {} + attributes: {}, }, - included: alienIncluded + included: alienIncluded, }; const expectedAlienResults = alienIncluded.map(m => m.type), @@ -220,10 +211,10 @@ test('handles relationships where both sides are polymorphic', function(assert) person: { data: { id: isForBigPerson ? '1' : '2', - type: isForBigPerson ? 'big-person' : 'small-person' - } - } - } + type: isForBigPerson ? 'big-person' : 'small-person', + }, + }, + }, }; } @@ -238,42 +229,34 @@ test('handles relationships where both sides are polymorphic', function(assert) data: { id: '1', type: 'big-person', - attributes: {} + attributes: {}, }, - included: [ - bigHatData1, - smallHatData1, - bigHatData2, - smallHatData2 - ] + included: [bigHatData1, smallHatData1, bigHatData2, smallHatData2], }; const smallPersonData = { data: { id: '2', type: 'small-person', - attributes: {} + attributes: {}, }, - included: [ - bigHatData3, - smallHatData3 - ] + included: [bigHatData3, smallHatData3], }; const PersonModel = Model.extend({ hats: hasMany('hat', { async: false, polymorphic: true, - inverse: 'person' - }) + inverse: 'person', + }), }); const HatModel = Model.extend({ type: attr('string'), person: belongsTo('person', { async: false, inverse: 'hats', - polymorphic: true - }) + polymorphic: true, + }), }); const BigHatModel = HatModel.extend({}); const SmallHatModel = HatModel.extend({}); @@ -281,14 +264,14 @@ test('handles relationships where both sides are polymorphic', function(assert) const BigPersonModel = PersonModel.extend({}); const SmallPersonModel = PersonModel.extend({}); - const store = this.store = createStore({ + const store = (this.store = createStore({ person: PersonModel, bigPerson: BigPersonModel, smallPerson: SmallPersonModel, hat: HatModel, bigHat: BigHatModel, - smallHat: SmallHatModel - }); + smallHat: SmallHatModel, + })); const bigPerson = run(() => { return store.push(bigPersonData); @@ -308,11 +291,11 @@ test('handles relationships where both sides are polymorphic', function(assert) test('handles relationships where both sides are polymorphic reflexive', function(assert) { function link(a, b, relationshipName, recurse = true) { a.relationships = a.relationships || {}; - const rel = a.relationships[relationshipName] = a.relationships[relationshipName] || {}; + const rel = (a.relationships[relationshipName] = a.relationships[relationshipName] || {}); if (Array.isArray(b)) { - rel.data = b.map((i) => { - let {type, id} = i; + rel.data = b.map(i => { + let { type, id } = i; if (recurse === true) { link(i, [a], relationshipName, false); @@ -323,7 +306,7 @@ test('handles relationships where both sides are polymorphic reflexive', functio } else { rel.data = { type: b.type, - id: b.id + id: b.id, }; if (recurse === true) { @@ -336,7 +319,7 @@ test('handles relationships where both sides are polymorphic reflexive', functio const Person = Model.extend({ name: attr(), family: hasMany('person', { async: false, polymorphic: true, inverse: 'family' }), - twin: belongsTo('person', { async: false, polymorphic: true, inverse: 'twin' }) + twin: belongsTo('person', { async: false, polymorphic: true, inverse: 'twin' }), }); const Girl = Person.extend({}); const Boy = Person.extend({}); @@ -346,29 +329,29 @@ test('handles relationships where both sides are polymorphic reflexive', functio type: 'boy', id: `${id++}`, attributes: { - name: 'Gavin' - } + name: 'Gavin', + }, }; const sisterPayload = { type: 'girl', id: `${id++}`, attributes: { - name: 'Rose' - } + name: 'Rose', + }, }; const fatherPayload = { type: 'grownup', id: `${id++}`, attributes: { - name: 'Garak' - } + name: 'Garak', + }, }; const motherPayload = { type: 'grownup', id: `${id++}`, attributes: { - name: 'Kira' - } + name: 'Kira', + }, }; link(brotherPayload, sisterPayload, 'twin'); @@ -376,32 +359,30 @@ test('handles relationships where both sides are polymorphic reflexive', functio const payload = { data: brotherPayload, - included: [ - sisterPayload, - fatherPayload, - motherPayload - ] + included: [sisterPayload, fatherPayload, motherPayload], }; const expectedFamilyReferences = [ { type: 'girl', id: sisterPayload.id }, { type: 'grownup', id: fatherPayload.id }, - { type: 'grownup', id: motherPayload.id } + { type: 'grownup', id: motherPayload.id }, ]; const expectedTwinReference = { type: 'girl', id: sisterPayload.id }; - const store = this.store = createStore({ + const store = (this.store = createStore({ person: Person, grownup: Grownup, boy: Boy, - girl: Girl - }); + girl: Girl, + })); const boyInstance = run(() => { return store.push(payload); }); - const familyResultReferences = boyInstance.get('family').toArray() - .map((i) => { + const familyResultReferences = boyInstance + .get('family') + .toArray() + .map(i => { return { type: i.constructor.modelName, id: i.id }; }); const twinResult = boyInstance.get('twin'); @@ -414,11 +395,11 @@ test('handles relationships where both sides are polymorphic reflexive', functio test('handles relationships where both sides are polymorphic reflexive but the primary payload does not include linkage', function(assert) { function link(a, b, relationshipName, recurse = true) { a.relationships = a.relationships || {}; - const rel = a.relationships[relationshipName] = a.relationships[relationshipName] || {}; + const rel = (a.relationships[relationshipName] = a.relationships[relationshipName] || {}); if (Array.isArray(b)) { - rel.data = b.map((i) => { - let {type, id} = i; + rel.data = b.map(i => { + let { type, id } = i; if (recurse === true) { link(i, [a], relationshipName, false); @@ -429,7 +410,7 @@ test('handles relationships where both sides are polymorphic reflexive but the p } else { rel.data = { type: b.type, - id: b.id + id: b.id, }; if (recurse === true) { @@ -442,7 +423,7 @@ test('handles relationships where both sides are polymorphic reflexive but the p const Person = Model.extend({ name: attr(), family: hasMany('person', { async: false, polymorphic: true, inverse: 'family' }), - twin: belongsTo('person', { async: false, polymorphic: true, inverse: 'twin' }) + twin: belongsTo('person', { async: false, polymorphic: true, inverse: 'twin' }), }); const Girl = Person.extend({}); const Boy = Person.extend({}); @@ -452,29 +433,29 @@ test('handles relationships where both sides are polymorphic reflexive but the p type: 'boy', id: `${id++}`, attributes: { - name: 'Gavin' - } + name: 'Gavin', + }, }; const sisterPayload = { type: 'girl', id: `${id++}`, attributes: { - name: 'Rose' - } + name: 'Rose', + }, }; const fatherPayload = { type: 'grownup', id: `${id++}`, attributes: { - name: 'Garak' - } + name: 'Garak', + }, }; const motherPayload = { type: 'grownup', id: `${id++}`, attributes: { - name: 'Kira' - } + name: 'Kira', + }, }; link(brotherPayload, sisterPayload, 'twin'); @@ -485,36 +466,37 @@ test('handles relationships where both sides are polymorphic reflexive but the p const payload = { data: brotherPayload, - included: [ - sisterPayload, - fatherPayload, - motherPayload - ] + included: [sisterPayload, fatherPayload, motherPayload], }; const expectedFamilyReferences = [ { type: 'girl', id: sisterPayload.id }, { type: 'grownup', id: fatherPayload.id }, - { type: 'grownup', id: motherPayload.id } + { type: 'grownup', id: motherPayload.id }, ]; const expectedTwinReference = { type: 'girl', id: sisterPayload.id }; - const store = this.store = createStore({ + const store = (this.store = createStore({ person: Person, grownup: Grownup, boy: Boy, - girl: Girl - }); + girl: Girl, + })); const boyInstance = run(() => { return store.push(payload); }); - const familyResultReferences = boyInstance.get('family').toArray() - .map((i) => { + const familyResultReferences = boyInstance + .get('family') + .toArray() + .map(i => { return { type: i.constructor.modelName, id: i.id }; }); const twinResult = boyInstance.get('twin'); - const twinResultReference = twinResult && { type: twinResult.constructor.modelName, id: twinResult.id }; + const twinResultReference = twinResult && { + type: twinResult.constructor.modelName, + id: twinResult.id, + }; assert.deepEqual(familyResultReferences, expectedFamilyReferences, 'We linked family correctly'); assert.deepEqual(twinResultReference, expectedTwinReference, 'We linked twin correctly'); @@ -526,8 +508,8 @@ test('push polymorphic self-referential non-reflexive relationship', function(as data: { id: '1', type: 'big-hat', - attributes: {} - } + attributes: {}, + }, }; const hat2Data = { data: { @@ -536,31 +518,34 @@ test('push polymorphic self-referential non-reflexive relationship', function(as attributes: {}, relationships: { hats: { - data: [{ id: '1', type: 'big-hat' }] - } - } - } + data: [{ id: '1', type: 'big-hat' }], + }, + }, + }, }; const hat1 = run(() => store.push(hat1Data)); const hat2 = run(() => store.push(hat2Data)); - const expectedHatReference = { id: '2', type: 'big-hat' }; + const expectedHatReference = { id: '2', type: 'big-hat' }; const expectedHatsReferences = [{ id: '1', type: 'big-hat' }]; - const finalHatsReferences = hat2.get('hats').toArray() - .map((i) => { + const finalHatsReferences = hat2 + .get('hats') + .toArray() + .map(i => { return { type: i.constructor.modelName, id: i.id }; }); const hatResult = hat1.get('hat'); - const finalHatReference = hatResult && { type: hatResult.constructor.modelName, id: hatResult.id }; - + const finalHatReference = hatResult && { + type: hatResult.constructor.modelName, + id: hatResult.id, + }; assert.deepEqual(finalHatReference, expectedHatReference, 'we set hat on hat:1'); assert.deepEqual(finalHatsReferences, expectedHatsReferences, 'We have hats on hat:2'); }); - test('push polymorphic self-referential circular non-reflexive relationship', function(assert) { const store = this.store; const hatData = { @@ -570,105 +555,104 @@ test('push polymorphic self-referential circular non-reflexive relationship', fu attributes: {}, relationships: { hat: { - data: { id: '1', type: 'big-hat' } + data: { id: '1', type: 'big-hat' }, }, hats: { - data: [{ id: '1', type: 'big-hat' }] - } - } - } + data: [{ id: '1', type: 'big-hat' }], + }, + }, + }, }; const hat = run(() => store.push(hatData)); - const expectedHatReference = { id: '1', type: 'big-hat' }; + const expectedHatReference = { id: '1', type: 'big-hat' }; const expectedHatsReferences = [{ id: '1', type: 'big-hat' }]; - const finalHatsReferences = hat.get('hats').toArray() - .map((i) => { + const finalHatsReferences = hat + .get('hats') + .toArray() + .map(i => { return { type: i.constructor.modelName, id: i.id }; }); const hatResult = hat.get('hat'); - const finalHatReference = hatResult && { type: hatResult.constructor.modelName, id: hatResult.id }; - + const finalHatReference = hatResult && { + type: hatResult.constructor.modelName, + id: hatResult.id, + }; assert.deepEqual(finalHatReference, expectedHatReference, 'we set hat on hat:1'); assert.deepEqual(finalHatsReferences, expectedHatsReferences, 'We have hats on hat:2'); }); test('polymorphic hasMany to types with separate id-spaces', function(assert) { - const user = run(() => this.store.push({ - data: { - id: '1', - type: 'user', - relationships: { - hats: { - data: [ - { id: '1', type: 'big-hat' }, - { id: '1', type: 'small-hat' } - ] - } - } - }, - included: [{ - id: '1', - type: 'big-hat' - }, { - id: '1', - type: 'small-hat' - }] - })); + const user = run(() => + this.store.push({ + data: { + id: '1', + type: 'user', + relationships: { + hats: { + data: [{ id: '1', type: 'big-hat' }, { id: '1', type: 'small-hat' }], + }, + }, + }, + included: [ + { + id: '1', + type: 'big-hat', + }, + { + id: '1', + type: 'small-hat', + }, + ], + }) + ); const hats = user.get('hats'); - assert.deepEqual( - hats.map(h => h.constructor.modelName), - ['big-hat', 'small-hat'] - ); - assert.deepEqual( - hats.map(h => h.id), - ['1', '1'] - ); + assert.deepEqual(hats.map(h => h.constructor.modelName), ['big-hat', 'small-hat']); + assert.deepEqual(hats.map(h => h.id), ['1', '1']); }); -test('polymorphic hasMany to types with separate id-spaces, from inverse payload', function (assert) { - const user = run(() => this.store.push({ - data: { - id: '1', - type: 'user' - }, - included: [{ - id: '1', - type: 'big-hat', - relationships: { - user: { - data: { id: '1', type: 'user' } - } - } - }, { - id: '1', - type: 'small-hat', - relationships: { - user: { - data: { id: '1', type: 'user' } - } - } - }] - })); +test('polymorphic hasMany to types with separate id-spaces, from inverse payload', function(assert) { + const user = run(() => + this.store.push({ + data: { + id: '1', + type: 'user', + }, + included: [ + { + id: '1', + type: 'big-hat', + relationships: { + user: { + data: { id: '1', type: 'user' }, + }, + }, + }, + { + id: '1', + type: 'small-hat', + relationships: { + user: { + data: { id: '1', type: 'user' }, + }, + }, + }, + ], + }) + ); const hats = user.get('hats'); - assert.deepEqual( - hats.map(h => h.constructor.modelName), - ['big-hat', 'small-hat'] - ); - assert.deepEqual( - hats.map(h => h.id), - ['1', '1'] - ); + assert.deepEqual(hats.map(h => h.constructor.modelName), ['big-hat', 'small-hat']); + assert.deepEqual(hats.map(h => h.id), ['1', '1']); }); -test('polymorphic hasMany to polymorphic hasMany types with separate id-spaces', function (assert) { +test('polymorphic hasMany to polymorphic hasMany types with separate id-spaces', function(assert) { let bigHatId = 1; let smallHatId = 1; function makePolymorphicHatForPolymorphicPerson(type, isForBigPerson = true) { @@ -680,10 +664,10 @@ test('polymorphic hasMany to polymorphic hasMany types with separate id-spaces', person: { data: { id: '1', - type: isForBigPerson ? 'big-person' : 'small-person' - } - } - } + type: isForBigPerson ? 'big-person' : 'small-person', + }, + }, + }, }; } @@ -698,42 +682,34 @@ test('polymorphic hasMany to polymorphic hasMany types with separate id-spaces', data: { id: '1', type: 'big-person', - attributes: {} + attributes: {}, }, - included: [ - bigHatData1, - smallHatData1, - bigHatData2, - smallHatData2 - ] + included: [bigHatData1, smallHatData1, bigHatData2, smallHatData2], }; const smallPersonData = { data: { id: '1', type: 'small-person', - attributes: {} + attributes: {}, }, - included: [ - bigHatData3, - smallHatData3 - ] + included: [bigHatData3, smallHatData3], }; const PersonModel = Model.extend({ hats: hasMany('hat', { async: false, polymorphic: true, - inverse: 'person' - }) + inverse: 'person', + }), }); const HatModel = Model.extend({ type: attr('string'), person: belongsTo('person', { async: false, inverse: 'hats', - polymorphic: true - }) + polymorphic: true, + }), }); const BigHatModel = HatModel.extend({}); const SmallHatModel = HatModel.extend({}); @@ -741,14 +717,14 @@ test('polymorphic hasMany to polymorphic hasMany types with separate id-spaces', const BigPersonModel = PersonModel.extend({}); const SmallPersonModel = PersonModel.extend({}); - const store = this.store = createStore({ + const store = (this.store = createStore({ person: PersonModel, bigPerson: BigPersonModel, smallPerson: SmallPersonModel, hat: HatModel, bigHat: BigHatModel, - smallHat: SmallHatModel - }); + smallHat: SmallHatModel, + })); const bigPerson = run(() => { return store.push(bigPersonData); @@ -763,27 +739,32 @@ test('polymorphic hasMany to polymorphic hasMany types with separate id-spaces', assert.deepEqual( finalBigResult.map(h => ({ type: h.constructor.modelName, id: h.get('id') })), - [{ type: 'big-hat', id: '1'}, { type: 'small-hat', id: '1'}, { type: 'big-hat', id: '2'}, { type: 'small-hat', id: '2'}], + [ + { type: 'big-hat', id: '1' }, + { type: 'small-hat', id: '1' }, + { type: 'big-hat', id: '2' }, + { type: 'small-hat', id: '2' }, + ], 'big-person hats is all good' ); assert.deepEqual( finalSmallResult.map(h => ({ type: h.constructor.modelName, id: h.get('id') })), - [{ type: 'big-hat', id: '3'}, { type: 'small-hat', id: '3'}], + [{ type: 'big-hat', id: '3' }, { type: 'small-hat', id: '3' }], 'small-person hats is all good' ); }); testInDebug('Invalid inverses throw errors', function(assert) { let PostModel = Model.extend({ - comments: hasMany('comment', { async: false, inverse: 'post' }) + comments: hasMany('comment', { async: false, inverse: 'post' }), }); let CommentModel = Model.extend({ - post: belongsTo('post', { async: false, inverse: null }) + post: belongsTo('post', { async: false, inverse: null }), }); let store = createStore({ post: PostModel, - comment: CommentModel + comment: CommentModel, }); function runInvalidPush() { @@ -794,11 +775,9 @@ testInDebug('Invalid inverses throw errors', function(assert) { id: '1', relationships: { comments: { - data: [ - { type: 'comment', id: '1' } - ] - } - } + data: [{ type: 'comment', id: '1' }], + }, + }, }, included: [ { @@ -808,15 +787,19 @@ testInDebug('Invalid inverses throw errors', function(assert) { post: { data: { type: 'post', - id: '1' - } - } - } - } - ] + id: '1', + }, + }, + }, + }, + ], }); }); } - assert.expectAssertion(runInvalidPush, /The comment:post relationship declares 'inverse: null', but it was resolved as the inverse for post:comments/, 'We detected the invalid inverse'); + assert.expectAssertion( + runInvalidPush, + /The comment:post relationship declares 'inverse: null', but it was resolved as the inverse for post:comments/, + 'We detected the invalid inverse' + ); }); diff --git a/tests/unit/system/snapshot-record-array-test.js b/tests/unit/system/snapshot-record-array-test.js index 7c8221a428c..38c25f8d73d 100644 --- a/tests/unit/system/snapshot-record-array-test.js +++ b/tests/unit/system/snapshot-record-array-test.js @@ -7,10 +7,10 @@ module('Unit - snapshot-record-array'); test('constructor', function(assert) { let array = A([1, 2]); array.type = 'some type'; - let meta = { }; + let meta = {}; let options = { adapterOptions: 'some options', - include: 'include me' + include: 'include me', }; let snapshot = new SnapshotRecordArray(array, meta, options); @@ -33,10 +33,10 @@ test('#snapshot', function(assert) { return snapshotTaken; }; - let meta = { }; + let meta = {}; let options = { adapterOptions: 'some options', - include: 'include me' + include: 'include me', }; let snapshot = new SnapshotRecordArray(array, meta, options); @@ -56,13 +56,13 @@ test('SnapshotRecordArray.type loads the class lazily', function(assert) { get() { typeLoaded = true; return 'some type'; - } + }, }); - let meta = { }; + let meta = {}; let options = { adapterOptions: 'some options', - include: 'include me' + include: 'include me', }; let snapshot = new SnapshotRecordArray(array, meta, options); diff --git a/tests/unit/transform/boolean-test.js b/tests/unit/transform/boolean-test.js index ddead45a024..6f9c206ccd2 100644 --- a/tests/unit/transform/boolean-test.js +++ b/tests/unit/transform/boolean-test.js @@ -4,7 +4,7 @@ import { module, test } from 'qunit'; module('unit/transform - DS.BooleanTransform'); -test("#serialize", function(assert) { +test('#serialize', function(assert) { let transform = new DS.BooleanTransform(); assert.strictEqual(transform.serialize(null, { allowNull: true }), null); diff --git a/tests/unit/transform/number-test.js b/tests/unit/transform/number-test.js index 10ed98761b2..d1f61ecb85c 100644 --- a/tests/unit/transform/number-test.js +++ b/tests/unit/transform/number-test.js @@ -9,7 +9,7 @@ test('#serialize', function(assert) { assert.strictEqual(transform.serialize(null), null); assert.strictEqual(transform.serialize(undefined), null); - assert.equal(transform.serialize("1.1"), 1.1); + assert.equal(transform.serialize('1.1'), 1.1); assert.equal(transform.serialize(1.1), 1.1); assert.equal(transform.serialize(new Number(1.1)), 1.1); assert.strictEqual(transform.serialize(NaN), null); diff --git a/tests/unit/utils-test.js b/tests/unit/utils-test.js index 6c97dbb7212..b1019afdd80 100644 --- a/tests/unit/utils-test.js +++ b/tests/unit/utils-test.js @@ -9,9 +9,7 @@ import DS from 'ember-data'; import Model from 'ember-data/model'; import { assertPolymorphicType } from 'ember-data/-debug'; -import { - modelHasAttributeOrRelationshipNamedType -} from 'ember-data/-private'; +import { modelHasAttributeOrRelationshipNamedType } from 'ember-data/-private'; let env, User, Message, Post, Person, Video, Medium; @@ -19,12 +17,12 @@ module('unit/utils', { beforeEach() { Person = Model.extend(); User = Model.extend({ - messages: DS.hasMany('message', { async: false }) + messages: DS.hasMany('message', { async: false }), }); Message = Model.extend(); Post = Message.extend({ - medias: DS.hasMany('medium', { async: false }) + medias: DS.hasMany('medium', { async: false }), }); Medium = Mixin.create(); @@ -35,7 +33,7 @@ module('unit/utils', { person: Person, message: Message, post: Post, - video: Video + video: Video, }); env.registry.register('mixin:medium', Medium); @@ -43,7 +41,7 @@ module('unit/utils', { afterEach() { run(env.container, 'destroy'); - } + }, }); testInDebug('assertPolymorphicType works for subclasses', function(assert) { @@ -51,21 +49,25 @@ testInDebug('assertPolymorphicType works for subclasses', function(assert) { run(() => { env.store.push({ - data: [{ - type: 'user', - id: '1', - relationships: { - messages: { - data: [] - } - } - }, { - type: 'post', - id: '1' - }, { - type: 'person', - id: '1' - }] + data: [ + { + type: 'user', + id: '1', + relationships: { + messages: { + data: [], + }, + }, + }, + { + type: 'post', + id: '1', + }, + { + type: 'person', + id: '1', + }, + ], }); user = env.store.peekRecord('user', 1); @@ -91,13 +93,13 @@ testInDebug('assertPolymorphicType works for subclasses', function(assert) { test('modelHasAttributeOrRelationshipNamedType', function(assert) { let ModelWithTypeAttribute = Model.extend({ - type: DS.attr() + type: DS.attr(), }); let ModelWithTypeBelongsTo = Model.extend({ - type: DS.belongsTo() + type: DS.belongsTo(), }); let ModelWithTypeHasMany = Model.extend({ - type: DS.hasMany() + type: DS.hasMany(), }); assert.equal(modelHasAttributeOrRelationshipNamedType(Model), false); @@ -112,16 +114,20 @@ testInDebug('assertPolymorphicType works for mixins', function(assert) { run(() => { env.store.push({ - data: [{ - type: 'post', - id: '1' - }, { - type: 'video', - id: '1' - }, { - type: 'person', - id: '1' - }] + 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); diff --git a/tests/unit/utils/parse-response-headers-test.js b/tests/unit/utils/parse-response-headers-test.js index d706a7b91d4..7ac9dde93dd 100644 --- a/tests/unit/utils/parse-response-headers-test.js +++ b/tests/unit/utils/parse-response-headers-test.js @@ -15,26 +15,38 @@ test('header parsing', function(assert) { let headersString = [ 'Content-Encoding: gzip', 'content-type: application/json; charset=utf-8', - 'date: Fri, 05 Feb 2016 21:47:56 GMT' + 'date: Fri, 05 Feb 2016 21:47:56 GMT', ].join(CRLF); let headers = parseResponseHeaders(headersString); assert.equal(headers['Content-Encoding'], 'gzip', 'parses basic header pair'); - assert.equal(headers['content-type'], 'application/json; charset=utf-8', 'parses header with complex value'); + assert.equal( + headers['content-type'], + 'application/json; charset=utf-8', + 'parses header with complex value' + ); assert.equal(headers['date'], 'Fri, 05 Feb 2016 21:47:56 GMT', 'parses header with date value'); }); test('field-name parsing', function(assert) { let headersString = [ ' name-with-leading-whitespace: some value', - 'name-with-whitespace-before-colon : another value' + 'name-with-whitespace-before-colon : another value', ].join(CRLF); let headers = parseResponseHeaders(headersString); - assert.equal(headers['name-with-leading-whitespace'], 'some value', 'strips leading whitespace from field-name'); - assert.equal(headers['name-with-whitespace-before-colon'], 'another value', 'strips whitespace before colon from field-name'); + assert.equal( + headers['name-with-leading-whitespace'], + 'some value', + 'strips leading whitespace from field-name' + ); + assert.equal( + headers['name-with-whitespace-before-colon'], + 'another value', + 'strips whitespace before colon from field-name' + ); }); test('field-value parsing', function(assert) { @@ -42,23 +54,39 @@ test('field-value parsing', function(assert) { 'value-with-leading-space: value with leading whitespace', 'value-without-leading-space:value without leading whitespace', 'value-with-colon: value with: a colon', - 'value-with-trailing-whitespace: banana ' + 'value-with-trailing-whitespace: banana ', ].join(CRLF); let headers = parseResponseHeaders(headersString); - assert.equal(headers['value-with-leading-space'], 'value with leading whitespace', 'strips leading whitespace in field-value'); - assert.equal(headers['value-without-leading-space'], 'value without leading whitespace', 'works without leaading whitespace in field-value'); - assert.equal(headers['value-with-colon'], 'value with: a colon', 'has correct value when value contains a colon'); - assert.equal(headers['value-with-trailing-whitespace'], 'banana', 'strips trailing whitespace from field-value'); + assert.equal( + headers['value-with-leading-space'], + 'value with leading whitespace', + 'strips leading whitespace in field-value' + ); + assert.equal( + headers['value-without-leading-space'], + 'value without leading whitespace', + 'works without leaading whitespace in field-value' + ); + assert.equal( + headers['value-with-colon'], + 'value with: a colon', + 'has correct value when value contains a colon' + ); + assert.equal( + headers['value-with-trailing-whitespace'], + 'banana', + 'strips trailing whitespace from field-value' + ); }); -"\r\nfoo: bar" +('\r\nfoo: bar'); test('ignores headers that do not contain a colon', function(assert) { let headersString = [ 'Content-Encoding: gzip', 'I am ignored because I do not contain a colon', - 'apple: pie' + 'apple: pie', ].join(CRLF); let headers = parseResponseHeaders(headersString); diff --git a/yarn.lock b/yarn.lock index 8953e5a9438..27aafafdff9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -102,17 +102,26 @@ agent-base@2: extend "~3.0.0" semver "~5.0.1" -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" -ajv@^4.7.0, ajv@^4.9.1: +ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.2.3, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -153,6 +162,10 @@ ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" +ansi-escapes@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" + ansi-regex@^0.2.0, ansi-regex@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" @@ -190,6 +203,12 @@ anymatch@^1.3.0: micromatch "^2.1.5" normalize-path "^2.0.0" +aot-test-generators@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/aot-test-generators/-/aot-test-generators-0.1.0.tgz#43f0f615f97cb298d7919c1b0b4e6b7310b03cd0" + dependencies: + jsesc "^2.5.0" + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -392,7 +411,7 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-code-frame@^6.26.0: +babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -609,7 +628,7 @@ babel-plugin-dead-code-elimination@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/babel-plugin-dead-code-elimination/-/babel-plugin-dead-code-elimination-1.0.2.tgz#5f7c451274dcd7cccdbfbb3e0b85dd28121f0f65" -babel-plugin-debug-macros@^0.1.10, babel-plugin-debug-macros@^0.1.11, babel-plugin-debug-macros@^0.1.7: +babel-plugin-debug-macros@^0.1.10, babel-plugin-debug-macros@^0.1.11: version "0.1.11" resolved "https://registry.yarnpkg.com/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.1.11.tgz#6c562bf561fccd406ce14ab04f42c218cf956605" dependencies: @@ -1416,16 +1435,17 @@ broccoli-kitchen-sink-helpers@^0.3.1: glob "^5.0.10" mkdirp "^0.5.1" -broccoli-lint-eslint@^2.0.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/broccoli-lint-eslint/-/broccoli-lint-eslint-2.7.0.tgz#a2d905d02b397a90ae82439f283c459ef819f140" +broccoli-lint-eslint@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/broccoli-lint-eslint/-/broccoli-lint-eslint-4.2.1.tgz#f780dc083a7357a9746a9cfa8f76feb092777477" dependencies: - broccoli-persistent-filter "^1.2.0" - escape-string-regexp "^1.0.5" - eslint "^2.13.0" - js-string-escape "^1.0.1" + aot-test-generators "^0.1.0" + broccoli-concat "^3.2.2" + broccoli-persistent-filter "^1.4.3" + eslint "^4.0.0" json-stable-stringify "^1.0.1" - md5-hex "^1.2.1" + lodash.defaultsdeep "^4.6.0" + md5-hex "^2.0.0" broccoli-merge-trees@^1.0.0, broccoli-merge-trees@^1.2.1: version "1.2.4" @@ -1458,7 +1478,7 @@ broccoli-node-info@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/broccoli-node-info/-/broccoli-node-info-1.1.0.tgz#3aa2e31e07e5bdb516dd25214f7c45ba1c459412" -broccoli-persistent-filter@^1.0.3, broccoli-persistent-filter@^1.1.5, broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.2.0, broccoli-persistent-filter@^1.4.0, broccoli-persistent-filter@^1.4.2: +broccoli-persistent-filter@^1.0.3, broccoli-persistent-filter@^1.1.5, broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.4.0, broccoli-persistent-filter@^1.4.2, broccoli-persistent-filter@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-1.4.3.tgz#3511bc52fc53740cda51621f58a28152d9911bc1" dependencies: @@ -1651,6 +1671,10 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" +buffer-from@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" + buffer@4.9.1: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" @@ -1835,6 +1859,10 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + charm@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/charm/-/charm-1.0.2.tgz#8add367153a6d9a581331052c4090991da995e35" @@ -2082,7 +2110,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.4.6, concat-stream@^1.4.7: +concat-stream@^1.4.7: version "1.6.1" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.1.tgz#261b8f518301f1d834e36342b9fea095d2620a26" dependencies: @@ -2090,6 +2118,15 @@ concat-stream@^1.4.6, concat-stream@^1.4.7: readable-stream "^2.2.2" typedarray "^0.0.6" +concat-stream@^1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + configstore@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/configstore/-/configstore-2.1.0.tgz#737a3a7036e9886102aa6099e47bb33ab1aba1a1" @@ -2436,12 +2473,11 @@ diff@^3.2.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" -doctrine@^1.2.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" dependencies: esutils "^2.0.2" - isarray "^1.0.0" dot-prop@^3.0.0: version "3.0.0" @@ -2502,7 +2538,7 @@ ember-cli-babel@6.12.0, ember-cli-babel@^6.0.0, ember-cli-babel@^6.10.0, ember-c ember-cli-version-checker "^2.1.0" semver "^5.4.1" -ember-cli-babel@^5.0.0, ember-cli-babel@^5.1.10, ember-cli-babel@^5.1.5, ember-cli-babel@^5.1.6, ember-cli-babel@^5.2.1: +ember-cli-babel@^5.0.0, ember-cli-babel@^5.1.10, ember-cli-babel@^5.1.6, ember-cli-babel@^5.2.1: version "5.2.4" resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-5.2.4.tgz#5ce4f46b08ed6f6d21e878619fb689719d6e8e13" dependencies: @@ -2544,13 +2580,14 @@ ember-cli-dependency-checker@^2.1.0: resolve "^1.5.0" semver "^5.3.0" -ember-cli-eslint@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ember-cli-eslint/-/ember-cli-eslint-1.3.0.tgz#8a7eda0d7e6a00c5a5a823f59664932d6429a8f1" +ember-cli-eslint@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/ember-cli-eslint/-/ember-cli-eslint-4.2.3.tgz#2844d3f5e8184f19b2d7132ba99eb0b370b55598" dependencies: - broccoli-lint-eslint "^2.0.0" - ember-cli-babel "^5.1.5" - js-string-escape "^1.0.0" + broccoli-lint-eslint "^4.2.1" + ember-cli-version-checker "^2.1.0" + rsvp "^4.6.1" + walk-sync "^0.3.0" ember-cli-get-component-path-option@^1.0.0: version "1.0.0" @@ -3086,14 +3123,14 @@ error@^7.0.0: string-template "~0.2.1" xtend "~4.0.0" -es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: +es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: version "0.10.39" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.39.tgz#fca21b67559277ca4ac1a1ed7048b107b6f76d87" dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" -es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: +es6-iterator@~2.0.1, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" dependencies: @@ -3101,7 +3138,7 @@ es6-iterator@^2.0.1, es6-iterator@~2.0.1, es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-map@^0.1.3, es6-map@^0.1.5: +es6-map@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" dependencies: @@ -3129,15 +3166,6 @@ es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: d "1" es5-ext "~0.10.14" -es6-weak-map@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -3150,54 +3178,83 @@ escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^ version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" +eslint-config-prettier@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" + dependencies: + get-stdin "^5.0.1" + +eslint-plugin-node@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz#bf19642298064379315d7a4b2a75937376fa05e4" + dependencies: + ignore "^3.3.6" + minimatch "^3.0.4" + resolve "^1.3.3" + semver "^5.4.1" + +eslint-plugin-prettier@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7" + dependencies: + fast-diff "^1.1.1" + jest-docblock "^21.0.0" + +eslint-scope@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" esrecurse "^4.1.0" estraverse "^4.1.1" -eslint@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.13.1.tgz#e4cc8fa0f009fb829aaae23855a29360be1f6c11" +eslint-visitor-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + +eslint@^4.0.0: + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" dependencies: - chalk "^1.1.3" - concat-stream "^1.4.6" - debug "^2.1.1" - doctrine "^1.2.2" - es6-map "^0.1.3" - escope "^3.6.0" - espree "^3.1.6" - estraverse "^4.2.0" + ajv "^5.3.0" + babel-code-frame "^6.22.0" + chalk "^2.1.0" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^3.1.0" + doctrine "^2.1.0" + eslint-scope "^3.7.1" + eslint-visitor-keys "^1.0.0" + espree "^3.5.4" + esquery "^1.0.0" esutils "^2.0.2" - file-entry-cache "^1.1.1" - glob "^7.0.3" - globals "^9.2.0" - ignore "^3.1.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.0.1" + ignore "^3.3.3" imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" + inquirer "^3.0.6" is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" + js-yaml "^3.9.1" + json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" - optionator "^0.8.1" - path-is-absolute "^1.0.0" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.6.0" - strip-json-comments "~1.0.1" - table "^3.7.8" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^7.0.0" + progress "^2.0.0" + regexpp "^1.0.1" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-ansi "^4.0.0" + strip-json-comments "~2.0.1" + table "4.0.2" text-table "~0.2.0" - user-home "^2.0.0" -espree@^3.1.6: +espree@^3.5.4: version "3.5.4" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" dependencies: @@ -3232,13 +3289,19 @@ esprimaq@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/esprimaq/-/esprimaq-0.0.1.tgz#3ea3a41f55ba0ab98fc3564c875818bd890aa2a3" +esquery@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + dependencies: + estraverse "^4.0.0" + esrecurse@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" dependencies: estraverse "^4.1.0" -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" @@ -3427,6 +3490,14 @@ external-editor@^1.1.0: spawn-sync "^1.0.15" tmp "^0.0.29" +external-editor@^2.0.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -3458,6 +3529,18 @@ fake-xml-http-request@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/fake-xml-http-request/-/fake-xml-http-request-1.6.0.tgz#bd0ac79ae3e2660098282048a12c730a6f64d550" +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-diff@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -3493,22 +3576,15 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" -figures@^1.3.5: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^1.1.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8" +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" dependencies: flat-cache "^1.2.1" object-assign "^4.0.1" @@ -3791,6 +3867,10 @@ fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: mkdirp ">=0.5 0" rimraf "2" +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -3804,16 +3884,6 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - get-caller-file@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" @@ -3826,6 +3896,10 @@ get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" +get-stdin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + get-stream@3.0.0, get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -3914,7 +3988,7 @@ glob@^5.0.10, glob@^5.0.13, glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.4, glob@^7.0.5, glob@^7.1.0: +glob@^7.0.0, glob@^7.0.3, glob@^7.0.4, glob@^7.0.5, glob@^7.1.0, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -3959,11 +4033,15 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" +globals@^11.0.1: + version "11.5.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.5.0.tgz#6bc840de6771173b191f13d3a9c94d441ee92642" + globals@^6.4.0: version "6.4.1" resolved "https://registry.yarnpkg.com/globals/-/globals-6.4.1.tgz#8498032b3b6d1cc81eebc5f79690d8fe29fabf4f" -globals@^9.18.0, globals@^9.2.0: +globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -4251,13 +4329,19 @@ iconv-lite@0.4.19, iconv-lite@^0.4.13, iconv-lite@^0.4.5, iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" +iconv-lite@^0.4.17: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" -ignore@^3.1.2: - version "3.3.7" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" +ignore@^3.3.3, ignore@^3.3.6: + version "3.3.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.8.tgz#3f8e9c35d38708a3a7e0e9abb6c73e7ee7707b2b" imurmurhash@^0.1.4: version "0.1.4" @@ -4306,24 +4390,6 @@ inline-source-map-comment@^1.0.5: sum-up "^1.0.1" xtend "^4.0.0" -inquirer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" - dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" - cli-width "^2.0.0" - figures "^1.3.5" - lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" - strip-ansi "^3.0.0" - through "^2.3.6" - inquirer@^2: version "2.0.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-2.0.0.tgz#e1351687b90d150ca403ceaa3cefb1e3065bef4b" @@ -4343,6 +4409,25 @@ inquirer@^2: strip-ansi "^3.0.0" through "^2.3.6" +inquirer@^3.0.6: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + into-stream@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" @@ -4494,20 +4579,6 @@ is-integer@^1.0.4: dependencies: is-finite "^1.0.0" -is-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - -is-my-json-valid@^2.10.0: - version "2.17.2" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -4576,10 +4647,6 @@ is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - is-reference@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.1.0.tgz#50e6ef3f64c361e2c53c0416cdc9420037f2685b" @@ -4676,6 +4743,10 @@ jade@0.26.3: commander "0.6.1" mkdirp "0.3.0" +jest-docblock@^21.0.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" + jmespath@0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" @@ -4688,10 +4759,6 @@ js-reporters@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/js-reporters/-/js-reporters-1.2.1.tgz#f88c608e324a3373a95bcc45ad305e5c979c459b" -js-string-escape@^1.0.0, js-string-escape@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - js-tokens@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-1.0.1.tgz#cc435a5c8b94ad15acb7983140fc80182c89aeae" @@ -4700,7 +4767,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.5.1, js-yaml@^3.6.1: +js-yaml@^3.2.5, js-yaml@^3.2.7, js-yaml@^3.6.1, js-yaml@^3.9.1: version "3.11.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" dependencies: @@ -4715,6 +4782,10 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsesc@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" + jsesc@~0.3.x: version "0.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.3.0.tgz#1bf5ee63b4539fe2e26d0c1e99c240b97a457972" @@ -4727,10 +4798,18 @@ json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" @@ -4769,10 +4848,6 @@ jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -5327,9 +5402,9 @@ matcher-collection@^1.0.0, matcher-collection@^1.0.4, matcher-collection@^1.0.5: dependencies: minimatch "^3.0.2" -md5-hex@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" +md5-hex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" dependencies: md5-o-matic "^0.1.1" @@ -5578,14 +5653,14 @@ mustache@^2.2.1: version "2.3.0" resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.0.tgz#4028f7778b17708a489930a6e52ac3bca0da41d0" -mute-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" - mute-stream@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.6.tgz#48962b19e169fd1dfc240b3f1e7317627bbc47db" +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + nan@^2.3.0: version "2.9.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.9.2.tgz#f564d75f5f8f36a6d9456cca7a6c4fe488ab7866" @@ -5607,6 +5682,10 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -5803,7 +5882,7 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -optionator@^0.8.1: +optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" dependencies: @@ -5843,7 +5922,7 @@ os-shim@^0.1.2: version "0.1.3" resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -5969,7 +6048,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@^1.0.1: +path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" @@ -6029,9 +6108,9 @@ plur@^2.1.2: dependencies: irregular-plurals "^1.0.0" -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" portfinder@^1.0.7: version "1.0.13" @@ -6064,6 +6143,10 @@ pretender@^1.4.2: fake-xml-http-request "^1.6.0" route-recognizer "^0.3.3" +prettier@^1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325" + pretty-ms@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/pretty-ms/-/pretty-ms-3.1.0.tgz#e9cac9c76bf6ee52fe942dd9c6c4213153b12881" @@ -6093,9 +6176,9 @@ process-relative-require@^1.0.0: dependencies: node-modules-path "^1.0.0" -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" promise-map-series@^0.2.1: version "0.2.3" @@ -6271,14 +6354,6 @@ readdirp@^2.0.0: readable-stream "^2.0.2" set-immediate-shim "^1.0.1" -readline2@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - mute-stream "0.0.5" - recast@0.10.33: version "0.10.33" resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.33.tgz#942808f7aa016f1fa7142c461d7e5704aaa8d697" @@ -6363,6 +6438,10 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexpp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -6465,7 +6544,7 @@ require-relative@^0.8.7: version "0.8.7" resolved "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" -require-uncached@^1.0.2: +require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" dependencies: @@ -6585,7 +6664,7 @@ rsvp@^3.0.14, rsvp@^3.0.16, rsvp@^3.0.17, rsvp@^3.0.18, rsvp@^3.0.21, rsvp@^3.0. version "3.6.2" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" -rsvp@^4.7.0: +rsvp@^4.6.1, rsvp@^4.7.0: version "4.8.2" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.2.tgz#9d5647108735784eb13418cdddb56f75b919d722" @@ -6597,21 +6676,21 @@ rsvp@~3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.2.1.tgz#07cb4a5df25add9e826ebc67dcc9fd89db27d84a" -run-async@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" - dependencies: - once "^1.3.0" - run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" dependencies: is-promise "^2.1.0" -rx-lite@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" rx@^4.1.0: version "4.1.0" @@ -6631,6 +6710,10 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + sane@^1.4.1: version "1.7.0" resolved "https://registry.yarnpkg.com/sane/-/sane-1.7.0.tgz#b3579bccb45c94cf20355cc81124990dfd346e30" @@ -6762,10 +6845,6 @@ shelljs@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.2.6.tgz#90492d72ffcc8159976baba62fb0f6884f0c3378" -shelljs@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" - shellwords@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" @@ -6796,9 +6875,11 @@ slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + dependencies: + is-fullwidth-code-point "^2.0.0" slide@^1.1.5: version "1.1.6" @@ -7080,7 +7161,7 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0: +string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: @@ -7154,10 +7235,6 @@ strip-indent@^1.0.1: dependencies: get-stdin "^4.0.1" -strip-json-comments@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" - strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -7194,16 +7271,16 @@ symlink-or-copy@^1.0.0, symlink-or-copy@^1.0.1, symlink-or-copy@^1.1.8: version "1.2.0" resolved "https://registry.yarnpkg.com/symlink-or-copy/-/symlink-or-copy-1.2.0.tgz#5d49108e2ab824a34069b68974486c290020b393" -table@^3.7.8: - version "3.8.3" - resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" +table@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" tap-parser@^5.1.0: version "5.4.0" @@ -7370,6 +7447,12 @@ tmp@^0.0.29: dependencies: os-tmpdir "~1.0.1" +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -7595,12 +7678,6 @@ user-home@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" -user-home@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" - dependencies: - os-homedir "^1.0.0" - user-info@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/user-info/-/user-info-1.0.0.tgz#81c82b7ed63e674c2475667653413b3c76fde239"