Skip to content

Commit

Permalink
[BUGFIX] ensure MandatorySetter does not trigger for modelName
Browse files Browse the repository at this point in the history
  • Loading branch information
runspired authored and igorT committed Nov 15, 2019
1 parent 282320a commit 4baa29f
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 1 deletion.
83 changes: 83 additions & 0 deletions packages/-ember-data/tests/integration/store/model-name-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import Model, { attr } from '@ember-data/model';
import { computed } from '@ember/object';
import Service, { inject } from '@ember/service';
import Store from '@ember-data/store';
import { P } from 'Object/_api';

module('@ember-data/model klass.modelName', function(hooks) {
setupTest(hooks);

test('Extending a model properly sets the modelName', function(assert) {
const { owner } = this;
class Animal extends Model {
@attr() species;
}
class Pet extends Animal {
@attr() name;
}
class AnimalHelper extends Service {
@inject store;

@computed('animal.constructor.modelName')
get animalModelName() {
return this.animal.constructor.modelName;
}
}
owner.register('model:animal', Animal);
owner.register('model:pet', Pet);
owner.register('service:animal-helper', AnimalHelper);
owner.register('sercice:store', Store);
const store = owner.lookup('service:store');
const animalHelper = owner.lookup('service:animal-helper');

// first we push the base class
const snake = store.push({
data: {
type: 'animal',
id: '1',
attributes: { species: 'snake' },
},
});

// then we do a thing that could install a MandatorySetter
// on the modelName property on the `Animal` class.
animalHelper.set('animal', snake);
assert.strictEqual(snake.constructor.modelName, 'animal', 'Snake has the right modelName');
assert.strictEqual(animalHelper.animalModelName, 'animal', 'We got the modelName');

// ensure modelName is immutable
try {
snake.constructor.modelName = 'bear';
assert.ok(false, 'expected modelName to be immutable');
} catch (e) {
assert.strictEqual(
e.message.startsWith(`Cannot assign to read only property 'modelName' of `),
true,
'modelName is immutable'
);
}

// this will error if we installed a MandatorySetter
// when we try to set the modelName property on the `Pet` class.
try {
const fido = store.push({
data: {
type: 'pet',
id: '1',
attribute: { species: 'dog', name: 'fido' },
},
});

assert.strictEqual(fido.constructor.modelName, 'pet', 'Fido has the right modelName');
assert.strictEqual(snake.constructor.modelName, 'animal', 'Snake has the right modelName');
assert.strictEqual(animalHelper.animalModelName, 'animal', 'AnimalHelper has the right modelName');
} catch (e) {
assert.ok(
false,
`Failed to add fido to the store, likely encountered an unexpected MandatorySetter. Full error below:\n\n${e.message}`
);
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { RelationshipsSchema, AttributesSchema } from '../ts-interfaces/record-d
import require from 'require';
import CoreStore from './core-store';
import { HAS_MODEL_PACKAGE } from '@ember-data/private-build-infra';
import { assert } from '@ember/debug';
type Model = import('@ember-data/model').default;

let _Model;
Expand Down Expand Up @@ -103,7 +104,7 @@ export function getModelFactory(store: CoreStore, cache, normalizedModelName: st
if (klass.isModel) {
let hasOwnModelNameSet = klass.modelName && Object.prototype.hasOwnProperty.call(klass, 'modelName');
if (!hasOwnModelNameSet) {
klass.modelName = normalizedModelName;
Object.defineProperty(klass, 'modelName', { value: normalizedModelName });
}
}

Expand Down

0 comments on commit 4baa29f

Please sign in to comment.