How to make serializer get called - ember-cli

I'm using ember cli
ember 1.12.0
ember data 1.0.0-beta.18
router.js:
import Ember from 'ember';
import config from './config/environment';
var Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
this.route('datasource');
});
//export default Router;
export default Router;
routes/datasource.js:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
// the model is an Array of all of the posts
// fetched from this url
return Ember.$.ajax('/datasource/');
//return [{'datasource': '1'}, {'datasource': '2'}];
}
});
adapters/application.js:
import DS from 'ember-data';
export default DS.Adapter.extend({
// ...your code here
});
models/datasource.js:
import DS from 'ember-data';
export default DS.Model.extend({
dsn: DS.attr()
});
serializers/datasource.js:
import DS from 'ember-data';
export default DS.RESTSerializer.extend({
extractArray: function(store, type, payload) {
var datasources = payload._items;
payload = {datasources: datasources};
return this._super(store, type, payload);
}
});
Ie my api returns the list of items inside the key _items.
But it looks like the serializer is never executed,
What should I do to make the serializer take effect?
This is the error -
Uncaught Error: Assertion Failed: The value that #each loops over must be an Array. You passed '{_items: [object Object],[object Object], _links: [object Object], _meta: [object Object]}' (wrapped in (generated datasource controller))Ember.default.assert # ember.debug.js:4854exports.default.CollectionView.default.extend._assertArrayLike # ember.debug.js:38837(anonymous function) # ember.debug.js:37836ContainerView.default.extend.init # ember.debug.js:37804superWrapper # ember.debug.js:17426superFunction # ember.debug.js:13805mixin.Mixin.create.init # ember.debug.js:38898superWrapper # ember.debug.js:17426superFunction # ember.debug.js:13805exports.default.CollectionView.default.extend.init # ember.debug.js:38832superWrapper # ember.debug.js:17426Class # ember.debug.js:30649ClassMixinProps.create # ember.debug.js:31071mixin.Mixin.create.createChildView # ember.debug.js:35755merge.default.appendChild # ember.debug.js:39847mixin.Mixin.create.appendChild # ember.debug.js:35697appendTemplatedView # ember.debug.js:8051viewHelper # ember.debug.js:7559collectionHelper # ember.debug.js:6410eachHelper # ember.debug.js:6598block # ember.debug.js:7807render # datasource.js:89renderHTMLBarsTemplate # ember.debug.js:8491renderView # ember.debug.js:8463renderView # ember.debug.js:35400mixin.Mixin.create.render # ember.debug.js:35423EmberRenderer_createElement # ember.debug.js:37468Renderer_renderTree # ember.debug.js:9140scheduledRenderTree # ember.debug.js:9216Queue.invoke # ember.debug.js:878Queue.flush # ember.debug.js:943DeferredActionQueues.flush # ember.debug.js:748Backburner.end # ember.debug.js:173(anonymous function) # ember.debug.js:576

In the model hook of your route you are doing a ajax call instead of calling the store to find records. With the ajax call you are bypassing your store and so the serializer will never be called to serialize the payload returned from your server.
In order to pass the payload to the store you can do:
// route
model: function() {
var store = this.store;
return Ember.$.ajax('/datasource/').then(function(payload) {
store.pushPayload('datasource', payload);
});
}
Alternatively you can call the store to do the call to your back-end so you don't have to do a ajax call yourself (not sure if it was your intention to do a custom call for some reason):
// route
model: function() {
return this.store.find('datasource');
}

Related

Write test axios-mock-adapter with axios.create()

I want to test my http service but get error.
So, my test file
api.js
import axios from 'axios';
export const api = axios.create();
fetchUsers.js
import api from './api';
export const fetchUsers = (params) api.get('/api/users', { params })
.then(({data}) => data)
fetchUsers.spec.js
import MockAdapter from 'axios-mock-adapter'
import api from './api';
const mock = new MockAdapter(api);
describe('fetchUsers', () => {
it('should send request', (done) => {
const data = { data: ['user'] };
mock.onGet('/api/users').reply(200, data);
fetchUsers().then((response) => {
expect(response).toEqual(data.data);
done();
});
});
});
But I get error here
Error: connect ECONNREFUSED 127.0.0.1:80
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1158:14)
If I replace in api.js axios.create() with axios its' working. But how to test with created axios instance? I'll need to ass there parameters when create it.
Anyone can help with that?
Hi I had the same issue and had to answer myself here https://stackoverflow.com/a/51414152/73323
Here is the gist:
First off, you don't need the axios-mock-adapter library.
Create a mock for axios in src/__mocks__:
// src/__mocks__/axios.ts
const mockAxios = jest.genMockFromModule('axios')
// this is the key to fix the axios.create() undefined error!
mockAxios.create = jest.fn(() => mockAxios)
export default mockAxios
Then in your test file, the gist would look like:
import mockAxios from 'axios'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
// for some reason i need this to fix reducer keys undefined errors..
jest.mock('../../store/rootStore.ts')
// you need the 'async'!
test('Retrieve transaction data based on a date range', async () => {
const middlewares = [thunk]
const mockStore = configureMockStore(middlewares)
const store = mockStore()
const mockData = {
'data': 123
}
/**
* SETUP
* This is where you override the 'post' method of your mocked axios and return
* mocked data in an appropriate data structure-- {data: YOUR_DATA} -- which
* mirrors the actual API call, in this case, the 'reportGet'
*/
mockAxios.post.mockImplementationOnce(() =>
Promise.resolve({ data: mockData }),
)
const expectedActions = [
{ type: REQUEST_TRANSACTION_DATA },
{ type: RECEIVE_TRANSACTION_DATA, data: mockData },
]
// work
await store.dispatch(reportGet())
// assertions / expects
expect(store.getActions()).toEqual(expectedActions)
expect(mockAxios.post).toHaveBeenCalledTimes(1)
})

aws-amplify integration with Nativescript (angular)

I am trying to integrate ams-amplify with NativeScript but I am not able to get it to work successfully.
import { Component, OnInit } from "#angular/core";
require("nativescript-nodeify");
var Amplify = require("aws-amplify");
#Component({
selector: "Home",
moduleId: module.id,
templateUrl: "./home.component.html"
})
export class HomeComponent implements OnInit {
constructor() {
// Use the component constructor to inject providers.
Amplify.configure({
Auth: {
// REQUIRED - Amazon Cognito Identity Pool ID
identityPoolId: 'xxxxx',
// REQUIRED - Amazon Cognito Region
region: 'xxxx',
// OPTIONAL - Amazon Cognito User Pool ID
userPoolId: 'xxxx',
// OPTIONAL - Amazon Cognito Web Client ID
userPoolWebClientId: 'xxxxx',
}
});
}
ngOnInit(): void {
}
}
But I am getting some "navigator is not defined" error.
JS: ERROR Error: Uncaught (in promise): ReferenceError: navigator is
not defined JS: ReferenceError: navigator is not defined JS: at
standardBrowserEnv
(file:///data/data/org.nativescript.awsamplify/files/app/tns_modules/axios/lib/helpers/isURLSameOrigin.js:11:39)
JS: at Object.
(file:///data/data/org.nativescript.awsamplify/files/app/tns_modules/axios/lib/helpers/isURLSameOrigin.js:60:5)
JS: at require (:1:266) JS: at Object.
(file:///data/data/org.nativescript.awsamplify/files/app/tns_modules/axios/lib/adapters/xhr.js:7:23)
JS: at require (:1:266) JS: at getDefaultAdapter
(file:///data/data/org.nativescript.awsamplify/files/app/tns_modules/axios/lib/defaults.js:20:15)
JS: at Object.
(file:///data/data/org.nativescript.awsamplify/files/app/tns_modules/axios/lib/defaults.js:29:12)
JS: at require (:1:266) JS: at Object.
(file:///data/data/org.nativescript.awsamplify/files/app/tns_modules/axios/lib/core/Axios.js:3:16)
JS: at require (:1:266) JS: at Object.
(file:///data/data/org.nativescript.awsamplify/files/app/tns_modules/axios/lib/axios.js:5:13)
JS: at require (:1:266) JS: at Object.
(file:///data/data/org.nativescript.awsamplify/files/app/tns_modules/axios/index.js:1:78)
JS: at require (:1:266) JS: at Object.
(file:///data/data/org.nativescript.awsamplify/files/app/tns_modules/aws-amplify/lib/API/RestClient.js:70:15)
If anyone has working code, please share.
The problem is with latest version of aws-amplify.
Changed it to "aws-amplify": "^0.2.9" version and everything working fine now :)
Edit: Working Solution with latest Amplify version
import * as storage from "nativescript-localstorage";
import { Buffer } from "buffer";
import "nativescript-nodeify";
global["window"] = {};
global["window"]["localStorage"] = storage;
global["window"]["addEventListener"] = args => {
return args;
};
global["window"]["navigator"] = {};
global["window"]["Buffer"] = Buffer;
global["window"]["setTimeout"] = setTimeout;
global["window"]["clearTimeout"] = clearTimeout;
global["navigator"] = {};
global["navigator"]["product"] = "ReactNative";
import Amplify, { Auth, Storage } from "aws-amplify";
import aws_config from "~/aws-exports";
Amplify.configure(aws_config);

import * doesn't load the object in es6

i18n directory with index.js and the localization files: es.js, it.js and en.js.
index.js content:
export { default as es } from './es'
export { default as it } from './it'
export { default as en } from './en'
en.js content file (similar to es.js and it.js):
/*eslint-disable max-len,quotes*/
export default {
"about.h1": "This is the title from the about page",
...
}
I try to load localization messages:
import * as i18n from 'i18n'
...
const intlData = {
locale: 'en',
messages: i18n['en']
}
However messages variable is undefined.
When I checked the console log with:
window.console.log(i18n)
I get undefined:
Object {__esMOdule: true}
es:undefined
get es: function get()
it: undefined
get it: function get()
en: undefined
get en: function get()
__proto__: Object
Where I should get something like:
Object {__esMOdule: true}
es: Object
it: Object
en: Object
__proto__: Object

Custom authorizer not called

I'm trying to implement a custom authorizer (using ember-cli and ember-cli-simple-auth) but the authorize method is not being called on any requests. The init function is being called and the message that appears in the console when there is no authorizer registered is no longer showing up. Here is the initializer code:
import Ember from 'ember';
import Base from 'simple-auth/authorizers/base';
import ENV from '../config/environment';
ENV['simple-auth'] = ENV['simple-auth'] || {};
ENV['simple-auth'].authorizer = 'authorizer:custom';
ENV['simple-auth'].crossOriginWhiteList = [ENV.NET.API_ENDPOINT];
var CustomAuthorizer = Base.extend({
init: function () {
console.log('Intialize authorizer');
},
authorize: function(jqXHR, requestOptions) {
console.log('Authorize');
var token = this.get('session.token');
if(this.get('session.isAuthenticated') && !Ember.isEmpty(token)) {
authValue = "Token " + token;
jqXHR.setRequestHeader('Authorization', authValue);
}
}
});
export default {
name: 'authorization',
before: 'simple-auth',
initialize: function(container, application) {
console.log('Registered');
container.register('authorizer:custom', CustomAuthorizer);
}
};
Any help would be appreciated.
Problem here was something quite dumb: my casing of crossOriginWhitelist was incorrect.

Custom authenticator with Ember simple auth + Ember CLI

I'm trying to write a custom authenticator, similar to the one from this example in the docs. The goal is to be able to retrieve the currently logged in user via session.user.
I'm using Ember CLI, so in initializers/authentication.js I have
import Ember from 'ember';
var customAuthenticator = Ember.SimpleAuth.Authenticators.Devise.extend({
authenticate: function(credentials) {
debugger;
}
});
export default {
name: 'authentication',
initialize: function(container, application) {
Ember.SimpleAuth.Session.reopen({
user: function() {
var userId = this.get('user_id');
if (!Ember.isEmpty(userId)) {
return container.lookup('store:main').find('user', userId);
}
}.property('userId')
});
// register the custom authenticator so the session can find it
container.register('authenticator:custom', customAuthenticator);
Ember.SimpleAuth.setup(container, application, {
routeAfterAuthentication: 'landing-pages',
authorizerFactory: 'ember-simple-auth-authorizer:devise'
});
}
};
When I try to authenticate, I get the following error:
TypeError: Cannot read property 'authenticate' of undefined
at __exports__.default.Ember.ObjectProxy.extend.authenticate
Any idea why?
As of Simple Auth 0.6.4, you can now do something like:
index.html:
window.ENV['simple-auth'] = {
authorizer: 'simple-auth-authorizer:devise',
session: 'session:withCurrentUser'
};
initializers/customize-session.js:
import Ember from 'ember';
import Session from 'simple-auth/session';
var SessionWithCurrentUser = Session.extend({
currentUser: function() {
var userId = this.get('user_id');
if (!Ember.isEmpty(userId)) {
return this.container.lookup('store:main').find('user', userId);
}
}.property('user_id')
});
export default {
name: 'customize-session',
initialize: function(container) {
container.register('session:withCurrentUser', SessionWithCurrentUser);
}
};
You would need to do something like this:
Em.SimpleAuth.Authenticators.OAuth2.reopen
serverTokenEndpoint: "http://myapp.com/token"
authenticate: (credentials) ->
new Em.RSVP.Promise (resolve, reject) =>
data =
grant_type: "password"
username: credentials.identification
password: credentials.password
#makeRequest(data).then (response) =>
# success call
, (xhr, status, error) ->
# fail call
What I think might be happening is that you are registering the authenticator with the application and not the authenticator itself?
The problem is that the AMD build does not currently automatically register the extension libraries' components (see https://github.com/simplabs/ember-simple-auth/issues/198). I'll change that in the next release and will probably also adopt the documentation to be more focussed on the AMD build instead of the browserified version. For the moment you'd have to run this in your initializer
container.register(
'ember-simple-auth-authorizer:devise',
Ember.SimpleAuth.Authorizers.Devise
);
container.register(
'ember-simple-auth-authenticator:devise',
Ember.SimpleAuth.Authenticators.Devise
);