Skip to content

Commit

Permalink
[BUGFIX] ensure MandatorySetter does not trigger for modelName (#6749)
Browse files Browse the repository at this point in the history
  • Loading branch information
igorT committed Nov 16, 2019
1 parent 1685ffa commit b101be1
Show file tree
Hide file tree
Showing 2 changed files with 84 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}`
);
}
});
});
2 changes: 1 addition & 1 deletion packages/store/addon/-private/system/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3096,7 +3096,7 @@ function getModelFactory(store, cache, normalizedModelName) {
// TODO: deprecate this
let hasOwnModelNameSet = klass.modelName && klass.hasOwnProperty('modelName');
if (!hasOwnModelNameSet) {
klass.modelName = normalizedModelName;
Object.defineProperty(klass, 'modelName', { value: normalizedModelName });
}

cache[normalizedModelName] = factory;
Expand Down

0 comments on commit b101be1

Please sign in to comment.