http-mock naming conventions - ember.js

I've setup a http-mock route using Ember CLI with the following command:
ember g http-mock exercise-templates
Which then sets up the file exercise-templates.js which is defined as:
module.exports = function(app) {
var express = require('express');
var exerciseTemplatesRouter = express.Router();
exerciseTemplatesRouter.get('/', function(req, res) {
res.send({
"exercise-templates":[
{id: 1, name: 'Military Press', type: 'strength', muscles: [] },
{id: 2, name: 'Situps', type: 'strength', muscles: [] },
{id: 3, name: 'Yoga', type: 'class', muscles: [] },
{id: 4, name: 'Pilattes', type: 'class', muscles: [] }
]
});
});
app.use('/api/exercise-templates', exerciseTemplatesRouter);
};
So, when I then point the browser to http://localhost:4200/api/exercise-templates I was expecting to get my static JSON response defined above. Instead I get a 404. Then to my surprise I typed in http://localhost:4200/api/exercise-template (aka, without the 's') and it worked. Huh? Makes me wonder what is going on ... I mean I'm no Express guru but doesn't:
app.use('/api/exercise-templates', exerciseTemplatesRouter);
imply that the plural naming convention will be used?

Ok well the answer turns out to be ... turn off "ember serve" and restart. Not sure why it wasn't refreshing but apparently the mocking does not always (ever?) gracefully refresh when updated. In any event, my expectation about "naming convention" appears to be the naming convention so I can happily report that all is right in the world again.

Related

EmberJS Mirage 404 error on get /rentals

I'm following tutorial on this page (https://guides.emberjs.com/v2.7.0/tutorial/installing-addons/) until the next tutorial page. (Actually I follow until finished the tutorial.)
Everything seems to working fine. ✔
Ember server is serving and display in the browser correctly. ✔
Ember development build also display correctly. ✔
But Ember production build give me /rentals 404 error. ✖
How to fix this 404 error on production build?
Here is my mirage/config.js
export default function() {
// These comments are here to help you get started. Feel free to delete them.
/*
Config (with defaults).
Note: these only affect routes defined *after* them!
*/
// this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server
// this.namespace = ''; // make this `api`, for example, if your API is namespaced
// this.timing = 400; // delay for each request, automatically set to 0 during testing
/*
Shorthand cheatsheet:
this.get('/posts');
this.post('/posts');
this.get('/posts/:id');
this.put('/posts/:id'); // or this.patch
this.del('/posts/:id');
http://www.ember-cli-mirage.com/docs/v0.2.x/shorthands/
*/
this.get('/rentals', function(db, request) {
let rentals = [{
type: 'rentals',
id: 1,
attributes: {
title: 'Grand Old Mansion',
owner: 'Veruca Salt',
city: 'San Francisco',
type: 'Estate',
bedrooms: 15,
image: 'https://upload.wikimedia.org/wikipedia/commons/c/cb/Crane_estate_(5).jpg'
}
}, {
type: 'rentals',
id: 2,
attributes: {
title: 'Urban Living',
owner: 'Mike Teavee',
city: 'Seattle',
type: 'Condo',
bedrooms: 1,
image: 'https://upload.wikimedia.org/wikipedia/commons/0/0e/Alfonso_13_Highrise_Tegucigalpa.jpg'
}
}, {
type: 'rentals',
id: 3,
attributes: {
title: 'Downtown Charm',
owner: 'Violet Beauregarde',
city: 'Portland',
type: 'Apartment',
bedrooms: 3,
image: 'https://upload.wikimedia.org/wikipedia/commons/f/f7/Wheeldon_Apartment_Building_-_Portland_Oregon.jpg'
}
}];
if(request.queryParams.city !== undefined) {
let filteredRentals = rentals.filter(function(i) {
return i.attributes.city.toLowerCase().indexOf(request.queryParams.city.toLowerCase()) !== -1;
});
return { data: filteredRentals };
} else {
return { data: rentals };
}
});
}
The url prefix and namespace don't change anything, still /rentals 404 error.
GET http://localhost/rentals 404 Not Found
"NetworkError: 404 Not Found - http://localhost/rentals"
Error while processing route: index Ember Data Request GET /rentals returned a 404
ember-cli-mirage is disabled in production build, you should explicitly enable it in config:
if (environment === 'production') {
ENV['ember-cli-mirage'] = {
enabled: true
};
}
Mirage Documentation
The docs have been updated to include a fix for this issue.
Now if you go to the section in the docs called Setting up Application Tests to use Mirage you will see it says to open /tests/acceptance/list-rentals-test.js and insert in this import statements at the top:
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
Then in tests/acceptance/list-rentals-test.js and add a setupMirage(hooks); right after setupApplicationTest(hooks)
module('Acceptance | list rentals', function(hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
...
}
Then the data and the tests will pass.

Error returning promise from Ember Data

I am working on my first Ember app and got it to display the way I wanted with the route returning a static JSON object from model():
element: {
name: "First Element",
divisions: [{
name: "First Division",
sets: [{name: "Set 1"},{name: "Set 2"},{name: "Set 3"}]
}, {
name: "Second Division",
sets: [{name: "Set 1"},{name: "Set 2"},{name: "Set 3"}]
}]
}
Now I am trying to refactor to use Ember Data + Mirage and having an awful time.
Here’s my index.js route
export default Ember.Route.extend({
model() {
return this.store.find('element', 1);
},
If I set up my Mirage config.js like this:
this.get('/elements', function() {
return {
elements: [
{
id: 1,
name: 'First Element',
divisions: [1, 2]
}
]
}
});
then I get this error:
Your Ember app tried to GET '/elements/1', but there was no route defined to handle this request.
If I set up my Mirage config.js like this:
this.get('/elements/1', function() {
return {
id: 1,
name: 'First Element',
divisions: [1, 2]
}
});
then I get this error:
22:46:40.883 "Error while processing route: index" "Assertion Failed: normalizeResponse must return a valid JSON API document:
* One or more of the following keys must be present: "data", "errors", "meta"." "EmberError#http://localhost:4200/assets/vendor.js:25582:15
EDIT:
So this isn't a solution to the problem as stated but it got me past this. I gave up on Pretender and started again creating an actual Rails server according to this excellent tutorial: http://emberigniter.com/modern-bridge-ember-and-rails-5-with-json-api/
I was able to do everything I wanted this way and if I ever want to make this a production app, I'm a lot closer.
So the issue is that you aren't actually adhering to the JSON API specification. You can solve this by reading Mirage's page on how to conform.
Essentially you need to either be returning an object at the top level of your JSON response in the case of a GET /foo/1 call. You'll also need to change your "elements" attribute to "data" for GET /foo and that should do the trick. Right now there isn't a simple, re-usable way to do this Mirage out of the box. The best bet right now for both issues is to use the solution presented in this issue.
ember error normalizeResponse must return a valid JSON API document
can be fixed in three ways
return a valid JSONAPI response
see your error message:
normalizeResponse must return a valid JSON API document:
* One or more of the following keys must be present: "data", "errors", "meta".
this.get('/elements/1', function() {
return {
data: {
id: 1,
name: 'First Element',
divisions: [1, 2]
}
}
});
see also https://jsonapi.org/examples/
normalize all responses
// app/serializers/application.js
import EmberData from "ember-data";
export default EmberData.JSONAPISerializer.extend({
normalizeResponse() {
return {
data: this._super(...arguments),
};
},
//normalize(){},
//serialize(){},
// ...
});
problem: error handling
by wrapping all responses in { data: ... }, they never return errors
on errors, the response should be
this.get('/elements/1', function() {
return {
errors: [
{
id: 12345,
title: 'title for error #12345'
}
]
}
});
see also https://jsonapi.org/format/#error-objects
replace JSONAPI with REST
sed -i 's/JSONAPISerializer/RESTSerializer/g' app/serializers/*.js
sed -i 's/JSONAPIAdapter/RESTAdapter/g' app/adapters/*.js
ember docs: adapters and serializers
duplicate: How can ember application be integrated to use with json-server?

How do I properly setup app-test.js when unit testing ExtJS using Jasmine?

I am fairly new to both Jasmine(2.2) as well as ExtJS(4.2.1). I am following the Unit Testing instructions in the Sencha docs to test the feed-viewer example ExtJS application. I cannot seem to get the app-test file quite right to load the application.
Here is my app-test.js
Ext.Loader.setConfig({ enabled : true });
var Application = null;
Ext.onReady( function() {
Application = Ext.create('app', {
name: 'FV',
controllers: [
'Articles'
],
launch: function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
jasmineEnv.execute();
}
});
});
Here is the app.js
Ext.application({
name: 'FV',
paths: {
'Ext.ux': '../../../examples/ux/'
},
controllers: [
'Articles',
'Feeds'
],
autocreateViewport: true
});
And, in case this may be a part of the issue, my folders are structured as such:
FV/
- app/
- app-test/
- resources/
- specs/
- app.js
- app-test.js
- run-test.html
My test to see that the application has been properly loaded is failing. Chrome's dev tools show me two errors. The first is an XMLHttpRequest cannot load, and the second is an Uncaught TypeError: Object is not a function being thrown at the third line of app-test.js
I feel like there's something remarkably simple I may have missed.
Any help would be immensely appreciated!
I finally got it working. Here is my revised app-test.js
Ext.Loader.setConfig({ enabled : true });
Ext.ns('FV');
Ext.application({
name: 'FV',
appFolder: 'app',
controllers: ['Articles'],
autoCreateViewport: false,
launch: function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
jasmineEnv.execute();
}
});
Considering how different this is from the tutorial in the Sencha docs, and how much Jasmine has changed since 1.1.0 (which is the version their tutorial uses), it's definitely time for them to do an update.

Uncaught #<error> on loading fixtures

I'm doing something wrong with fixtures.
I have to models where a Contract has many Contractitems and try to load fixtures for them
App.Contract = DS.Model.extend({
contractItems: DS.hasMany('contractItem'),
//
});
App.ContractItem = DS.Model.extend({
contract: DS.belongsTo('contract'),
//
});
App.Contract.FIXTURES = [{
id: 1,
runtime: 12,
//
contractItems: [1, 2]
},{
id: 2,
//
}];
App.ContractItem.FIXTURES = [{
id: 1,
//
},{
id: 2,
//
}];
I commented out some dull attrubutes, but the full file is up here.
When I load the page, i get an Error
Uncaught #<error> VM1615:956
ProfileManager.ended VM1615:956
Ember.subscribe.after VM1615:2007
finalizer ember-1.5.1.js:1802
Ember.tryCatchFinally ember-1.5.1.js:1554
Ember.Instrumentation.instrument ember-1.5.1.js:1810
Ember.CoreView.Ember.Object.extend.renderToBuffer ember-1.5.1.js:22472
Ember.View.Ember.CoreView.extend.createElement ember-1.5.1.js:23993
Ember.merge.insertElement ember-1.5.1.js:24944
Ember.View.Ember.CoreView.extend._insertElement ember-1.5.1.js:23921
DeferredActionQueues.flush ember-1.5.1.js:6125
Backburner.end ember-1.5.1.js:6215
Backburner.run ember-1.5.1.js:6254
executeTimers ember-1.5.1.js:6552
(anonymous function)
Removing the line contractItems: [1, 2] resolves this, but obviously the related objects are not loaded then.
I thought, I did something wrong with camelcasing and tried different versions, but no success.
Ember is used in version 1.5.1, Ember-Data in version 1.0.0-beta9.
Any hints are welcome...
You're relationships will need to be defined as async since they aren't loaded in the same payload as the record you are loading.
App.Contract = DS.Model.extend({
contractItems: DS.hasMany('contractItem', {async:true}),
//
});
App.ContractItem = DS.Model.extend({
contract: DS.belongsTo('contract', {async:true}),
//
});
Remember when accessing async properties to use then
contract.get('contractItems').then(function(items){
console.log(items.get('length'));
});

Traversing a complex RESTful output (version 12)

I'm getting following (simplified) output from a RESTful API:
{products: [{
product: {
id: 1, name: "T-Shirt red"
},
images: [{
id: 1, size: 'm', url: 'http://db.co/t-shirt-red_m.jpg'
}, {
id: 2, size: 'xl', url: 'http://db.co/t-shirt-red_xl.jpg'
}]
}, {
product: {
id: 2, name: "T-Shirt blue"
},
images: [{
id: 3, size: 'm', url: 'http://db.co/t-shirt-blue_m.jpg'
}, {
id: 4, size: 'xl', url: 'http://db.co/t-shirt-blue_xl.jpg'
}]
}]}
Using Ember version 12, how should the declaration of the Product model looks like and how can I traverse the results? Haven't been able to find any example in that direction.
Following to access the data doesn't work (I just can't find the right syntax):
var products = App.Product.find(); // seems to work
var prodNames = products.getEach('product.name'); // doesn't work
var secondProd = products.getObject(1).get('name'); // doesn't work
Thanks a lot in advance!
claudio.
DS.hasMany and some options for the REST adapter may help you.
I've used a similar setup with MongoDB embedded models. I've attached some examples below.
I didn't want to try to save to the embedded array, so I've used embedded:load, but you can use embedded: 'always' to persist the total object back to the server (although it didn't work quite as I expected) with 'always' if you save the parent object.
DS.RESTAdapter.map 'App.Check',
line_items: { embedded: 'load' }
parties: { embedded: 'load' }
App.Check = DS.Model.extend
description: DS.attr("string")
modified_date: DS.attr("date")
parties: DS.hasMany('App.Party')
App.Party = DS.Model.extend
name: DS.attr("string")
check: DS.belongsTo('App.Party')
You can then reference the item. In a view, I've accessed it as below from a ArrayController where the content is set to an instance of DS.Check.
{{#each party in content.parties }}