Testing an ember-data model - can't find relationship - ember.js

I am trying to test a model relationship in an ember-cli application but it keeps telling me: No model was found for 'rateType'. It appears that it can't find my models.
Files
~app/models/account.js
~app/models/rate-type.js
Account Model
export default DS.Model.extend({
...
rateType: DS.belongsTo('rateType'),
});
Test
import Ember from 'ember';
import { test, moduleForModel } from 'ember-qunit';
import Account from 'app/models/account';
import RateType from 'app/models/rate-type';
moduleForModel('account', 'Account Model', {
// Specify the other units that are required for this test.
needs: ['model:rate-type']
});
test('rateType relationship', function() {
expect(0);
this.subject(); //error here
// var relationships = Ember.get(Account, 'relationships');
// deepEqual(relationships.get('rate-type'), [
// { name: 'rateType', kind: 'belongsTo' }
// ]);
});
I have tried camel casing the needs attribute butit does not like that at all.
needs: ['model:rateType', 'model:fuelGroup']

I think what you need is the needs keyword:
moduleForModel('post', 'Unit | Model | post', {
needs: ['model:comment', 'model:user']
});
I found it in the docs here: http://guides.emberjs.com/v1.10.0/testing/testing-models/

Your issue is with the model. Try dasherizing 'rate-type' in the belongsTo relationship.
export default DS.Model.extend({
...
rateType: DS.belongsTo('rate-type')
});

Related

Can't get relationships with Ember Mirage

I'm currently writing tests for my App written with EmberJS. I'm using Mirage.
I have the two following models:
mirage/models/paperwork.js
export default Model.extend({
customer: belongsTo('customer'),
paperwork_products: hasMany('paperwork-product', { inverse: 'paperwork' }),
mirage/models/paperwork-product.js
export default Model.extend({
paperwork: belongsTo('paperwork', { inverse: 'paperwork_products' }),
});
In my scenario, I'm creating my datas like this:
const paperwork = server.create('paperwork');
const paperworkProduct = server.create('paperwork-product', { paperwork });
paperwork.paperwork_products.add(paperworkProduct);
My route:
export default ApplicationRoute.extend({
model(params) {
return this.store.findRecord('paperwork', params.paperwork_id, { include: 'paperwork_products' }),
},
});
The problem is that I can't access paperwork.paperwork_products in my template. It's undefined (other paperwork attributes are here, but not relationship). I already even tried to put a debugger in my mirage/config.js when routes are declared. My paperwork exists, and his "paperwork_products" too. But I can't get paperwork_products data in my template.
What am I doing wrong ? I think I must change something in my :
this.get('v1/paperworks/:id');
But I don't know what ...
Thanks in advance !
Edit: Here are my real Ember models:
models/paperwork.js
export default DS.Model.extend({
customer: DS.belongsTo('customer'),
paperwork_products: DS.hasMany('paperwork-product', { async: true }),
});
models/paperwork-product.js
export default DS.Model.extend({
paperwork: DS.belongsTo('paperwork'),
});
Yesterday I tried to compare the real JsonApi response from my back, and Mirage response, and I saw that in the relationships hash, my relationship "paperwork_products" was changed to paperwork-products (with Mirage). So there is a problem with relationships with an underscore or models with dash ...
In config.js, I tried to mock JSONAPI Backend, and it works wells. Just replaced "paperwork-products" by "paperwork_products"
Mirage response :
"relationships":{
"customer":{
"data":{
"type":"customers",
"id":"1"
}
},
"paperwork-products":{
"data":[
{
"type":"paperwork-products",
"id":"1"
}
]
}
}
Should be :
"relationships":{
"customer":{
"data":{
"type":"customers",
"id":"1"
}
},
"paperwork_products":{
"data":[
{
"type":"paperwork_products",
"id":"1"
}
]
}
}
My other models with hasMany relationships do not have any problems.
To confirm, do you have Ember Data models setup with the same relationships? Without those, things may. It work very well ...
If you do, could you post those models as well?
Also, as an FYI, Mirage 0.3.0 comes with an auto-sync setup that will read your Ember Data models and create corresponding Mirage models without any work. It's been lovely ...
Edit:
I would suggest you rework your Ember Data model to use camel cased relationships. If you do the following:
models/paperwork.js
export default DS.Model.extend({
customer: DS.belongsTo('customer'),
paperworkProducts: DS.hasMany('paperwork-product', { async: true }),
});
I would expect it to work without issue, as Ember Data automatically translates camelCased relationships to the appropriate JSON-API key
Does that work for you?

Add column to existing ember model

Wow this is hard to find.
I have an existing model in ember and I would like to add a new column. I have't been able to see how to generate this from the CLI, so have manually added it to my component.js and models/post.js. I've added the field to my form and the handlebar to my view. Checking Firebase I can confirm I'm not updating the field.
In Rails I would simply run rails generate migration add_snippet_to_posts snippet:string but doing this in Ember just creates a new model.
model/post.js
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr('string'),
author: DS.attr('string'),
createdDate: DS.attr('date'),
text: DS.attr('string'),
snippet: DS.attr('string') #<=manually added this.
});
component.js
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
createPost: function (model) {
this.sendAction('createPost', model);
// Clear each input field
this.set('newPost.title', null);
this.set('newPost.author', null);
this.set('newPost.text', null);
this.set('newPost.snippet', null); #<= manually added this
}
}
});
How do I do this?
Solved
Needed to update routes/index.js too:
import Ember from 'ember';
export default Ember.Route.extend({
model: function () {
return this.store.findAll('post');
},
actions: {
createPost: function (model) {
let post = this.store.createRecord('post', {
title: model.title,
text: model.text,
author: model.author,
snippet: model.snippet, # <= add this too
createdDate: new Date()
});
post.save();
}
}
});
The official answer would be that you cannot just add an attribute with ember-CLI to a model that has already been created - and at the same time, update everything it may effect throughout your app. You have to manually write the attributes and how they are used in routes/components/templates etc.
That sounds awesome that Rails can just know all that stuff. : )

Could not find the "presence" validator with Ember Validations addon

I'm trying to use the Ember Validations addon and I can't get it working. In the Chrome console, I see: WARNING: Could not find the "presence" validator.
Here is my model:
import Ember from 'ember';
import DS from 'ember-data';
import EmberValidations from 'ember-validations';
export default DS.Model.extend(EmberValidations.Mixin, {
name: DS.attr('string'),
validations: {
name: {
presence: true
}
}
});
And here is the my test:
import Ember from 'ember';
import EmberValidations from 'ember-validations';
import { moduleForModel, test } from 'ember-qunit';
moduleForModel('person', 'Unit | Model | person', {
// Specify the other units that are required for this test.
needs: ['ember-validations#validator:local/presence'],
afterEach: function() {
window.sessionStorage.clear();
}
});
test('isValid should be false if name is not set', function(assert) {
stop();
var model = this.subject();
console.log(model);
Ember.run(function() {
sinon.spy(model, 'save');
model.validate().then(function() {
start();
assert.equal(model.get('isValid'), false);
});
});
});
The result of this test is:
Died on test #1 at Object.test (http://localhost:4200/assets/test-support.js:1644:11)
at http://localhost:4200/assets/myproj.js:14450:15
at mod.state (http://localhost:4200/assets/vendor.js:150:29)
at tryFinally (http://localhost:4200/assets/vendor.js:30:14)
at requireModule (http://localhost:4200/assets/vendor.js:148:5)
at Object.TestLoader.require (http://localhost:4200/assets/test-loader.js:29:9)
at Object.TestLoader.loadModules (http://localhost:4200/assets/test-loader.js:21:18): <(unknown mixin):ember848>
You need to add dependencies to test suite as defined in ember-validations docs in testing part. However, take notice that these docs are a little bit outdated. The proper needs should include only the validators you use (presence) and look like this:
needs: ['ember-validations#validator:local/presence']
Do not indclude service:validations.
I posted an issue quite a while ago but it's not discussed yet.

"Attempting to register an unknown factory" in model test

I have these models in an ember-cli app:
var PuzzleRound = DS.Model.extend({
year: DS.attr('number')
});
var Puzzle = DS.Model.extend({
puzzleRounds: DS.hasMany('puzzleRound', {async: true})
});
And here's my test from tests/unit/models/puzzle-test.js:
import {
moduleForModel,
test
} from 'ember-qunit';
import PuzzleRound from 'weather-roulette/models/puzzle-round';
moduleForModel('puzzle', 'Puzzle', {
// Specify the other units that are required for this test.
needs: ['model:puzzleRound']
});
test('it exists', function() {
var model = this.subject();
// var store = this.store();
ok(!!model);
});
I get this error when running ember test:
Attempting to register an unknown factory: `model:puzzleRound`
I'm using ember-cli 0.1.1, Ember.js 1.7.0, Ember Data 1.0.0-beta.11. Does anyone have anything I can try to fix this?
I just tried out this code with ember-cli 0.0.44 and I got the same error that you did.
I renamed both references to the puzzleRound model path to puzzle-round and then your test passed for me. So:
DS.Model.extend({
puzzleRounds: DS.hasMany('puzzle-round', {async: true})
});
and
moduleForModel('puzzle', 'Puzzle', {
needs: ['model:puzzle-round']
});
I knew that the hyphenated style was preferred over the camelCase style, but I'm not sure when this became mandatory. This requirement may be specific to ember-cli or ember-qunit.
I was looking for a solution similar to this one for awhile, and did not see any mention of my solution so I thought I would post here anyways. It's quite simple really: make sure that the controller you're referencing is actually there.
// my-ember-application/tests/unit/controllers/index/bar-test.js
moduleFor('controller:index/bar', 'My Bar Test', {
beforeEach() { .. }
});
test('it exists', function (assert) {
assert.ok(true);
});
This code would reference a controller at this location:
my-ember-application/app/controllers/index/bar.js

Ember-cli : relationship unit test for model failing

I am using Ember-cli and qunit for testing.
Item Model
import DS from 'ember-data';
var attr = DS.attr,
belongsTo = DS.belongsTo;
export default DS.Model.extend({
offer: belongsTo('offer'),
});
Here am adding test for relation between item and Offer model.
Item Tests
import Ember from "ember";
import DS from "ember-data";
import { test, moduleForModel } from 'ember-qunit';
moduleForModel('item', 'Item Model', {
needs: ['model:item']
});
test('offer relationship', function() {
var relationships = Ember.get(App.Item, 'relationships');
deepEqual(relationships.get(App.Offer), [
{ name: 'offer', kind: 'belongsTo' }
]);
});
Error Trace:
Died on test #1 at test (http://localhost:4200/assets/vendor.js:73836:13)
at eval (goodcity/tests/unit/item-test.js:44:5)
at requireModule (http://localhost:4200/assets/vendor.js:54:29)
at http://localhost:4200/assets/test-loader.js:14:29: App is not defined
Source:
ReferenceError: App is not defined
at Object.eval (goodcity/tests/unit/item-test.js:45:37)
at Object.wrapper (http://localhost:4200/assets/vendor.js:73824:31)
at Object.Test.run (http://localhost:4200/assets/qunit.js:203:18)
at http://localhost:4200/assets/qunit.js:361:10
at process (http://localhost:4200/assets/qunit.js:1453:24)
at http://localhost:4200/assets/qunit.js:479:5
Am i missing something?
I'm just now in the process of converting over an older Ember App to the new ember-cli and ran into a similar situation. Since Ember CLI uses ES6 module syntax you can't access anything directly on the App object.
You will need to import your objects from their respective model files.
import Item from "<modulePrefix>/models/item";
import Offer from "<modulePrefix>/models/offer";
Second, your moduleForModel('item') should have needs: ['model:offer'].
Here's a passing a test using the provided files. (I used: ember new stackoverflow)
import Ember from "ember";
import { test, moduleForModel } from 'ember-qunit';
/* Import Models */
import Item from "stackoverflow/models/item";
import Offer from "stackoverflow/models/offer";
moduleForModel('item', 'Item', {
// Item needs the offer model.
needs: ['model:offer']
});
test('offer relationship', function() {
/* For some reason this was necessary to prime the store. */
/* Without this line I get the error:
'undefined' is not an object (evaluating 'store.modelFor') */
var model = this.subject();
/* App.Item -> Item, App.Offer -> Offer */
var relationships = Ember.get(Item, 'relationships');
deepEqual(relationships.get(Offer), [
{ name: 'offer', kind: 'belongsTo' }
]);
});