could not find module 'ember-resources' - ember.js

am trying to build an web app with ember and in the process of making a request to server and receiving a response and for that i used resources from ember-resource
yet it always popping the error module not found ember-resources
the js code
import { use, resource } from 'ember-resources';
import { tracked } from '#glimmer/tracking';
class RequestState {
#tracked value;
#tracked error;
get isPending() {
return !this.error && !this.value;
}
}
export default class RoomselectController extends Controller {
#service router;
#use request = resource(({ on }) => {
const mobile = '123123123';
const state = new RequestState();
$.ajax({
url: 'My',
method: 'GET',
dataType: 'json',
data: { mobile },
success: (response) => state.value = response;,
error: (xhr, status, error) => state.error = `${status}: ${xhr.statusText}`,
});
return state;
});
get result() {
return this.request.value || [];
}
}
i installed ember-resource using
ember install ember-resources
also done npm install ember-resources
still showing the same module not found errro what to do?

Related

Vue Jest - Create Mock Api server

I want to create a Mock API Server for my Jest tests so that I can define all my backend endpoints and create responses and authentication checks.
I have managed to set up the server and routes by following some of the source code from Chris Fritz "Vue-Enterprice-boilerplate":
https://github.com/chrisvfritz/vue-enterprise-boilerplate/tree/master/tests/unit
// jest.config.js
const _ = require("lodash");
process.env.MOCK_API_PORT = process.env.MOCK_API_PORT || _.random(9000, 9999);
module.exports = {
preset: "#vue/cli-plugin-unit-jest",
setupFiles: ["./tests/unit/setup"],
globalSetup: "<rootDir>/tests/unit/global-setup",
globalTeardown: "<rootDir>/tests/unit/global-teardown",
testMatch: ["**/(*.)spec.js"],
moduleFileExtensions: ["js", "jsx", "json", "vue"],
transform: {
"^.+\\.vue$": "vue-jest",
"^.+\\.js$": "babel-jest",
".+\\.(css|scss|jpe?g|png|gif|webp|svg|mp4|webm|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf)$":
"jest-transform-stub"
},
transformIgnorePatterns: ["/node_modules/(?!vue-spinner)"],
testURL: process.env.API_BASE_URL || `http://localhost:${process.env.MOCK_API_PORT}`
};
The server runs when the tests starts and I can console log the route files.
I just don't know how the axios call from my Vuex would go with the mock API instead of the real one.
Might need to import axios somewhere in the test to prevent the development URL to be used?
/tests/mock-api/routes/auth.js
const Users = require("../resources/users");
module.exports = app => {
console.log('I can see this during tests!');
app.post("/api/v1/login", async (req, res) => {
console.log("I don't see this..");
await Users.authenticate(req.body)
.then(user => {
res.json(user);
})
.catch(error => {
res.status(401).json({ message: error.message });
});
});
});
// /views/Login.spec.js
import Vue from "vue";
import Vuelidate from "vuelidate";
import Login from "#/views/Login";
import BaseButton from "#/components/Globals/_base-button.vue";
import BaseInput from "#/components/Globals/_base-input.vue";
import BaseLabel from "#/components/Globals/_base-label.vue";
import flushPromises from "flush-promises";
import store from "#/store";
import { shallowMount } from "#vue/test-utils";
Vue.use(Vuelidate);
describe("#/views/Login", () => {
// other tests..
it("redirects to posts on successful login", async () => {
const wrapper = shallowMount(Login, { store, stubs: { BaseInput, BaseButton, BaseLabel } });
wrapper.vm.$v.$touch();
const spyDispatch = jest.spyOn(wrapper.vm.$store, "dispatch");
const username = wrapper.find("#username");
const password = wrapper.find("#password");
username.element.value = "johndoe#email.com";
password.element.value = "passwordz";
username.trigger("input");
password.trigger("input");
await wrapper.find("#submitBtn").trigger("click.prevent");
await wrapper.vm.$nextTick();
await flushPromises();
await expect(spyDispatch).toHaveBeenCalledWith("auth/login", {
username: username.element.value,
password: password.element.value
});
// #TODO add expect for redirect as well
});
// /store/auth.js (vuex)
export const actions = {
async login({ commit }, { username, password }) {
console.log("I see this");
const response = await axios.post("/login",
{ username, password }, { withCredentials: true });
console.log("I don't see this");
// #TODO error handling
if (!response) return;
commit("setUser", { ...response.data.user });
router.push({ name: "Posts" });
},
The login action gets called but I don't get passed the axios.post.
Do I need to import axios somewhere to make sure I get a fresh instance? (Vuex uses one I set the baseURL and headers)
All the other tests and logic works except this.

How to get a file from the backend withou getting it JSON-parsed

I’m able to get an xlsx file from my rails backend with a GET-Request to “/companies/export_xslx”, now I’m facing the problem of getting the file passed the JSON parser. For every request the console shows “JSON.parse: unexpected character at line 1 column 1 of the JSON data”.
This is my setup:
//company model ...
exportXlsx: function() {
const adapter = this.store.adapterFor('company');
return adapter.exportXlsx();
}
//adapters/company.js
import DS from 'ember-data';
import TokenAuthorizerMixin from 'ember-simple-auth-token/mixins/token-authorizer';
export default DS.JSONAPIAdapter.extend(TokenAuthorizerMixin, {
exportXlsx() {
const url = 'companies/export_xlsx';
return this.ajax(url, 'GET',
{ dataType: 'text',
accepts: { xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
} });
}
});
I’ll try to alter the default accept header but the requests gets sent with “Accept: application/vnd.api+json”.
I already tried different approaches with “ember-custom-actions” or “ember-cli-file-saver”, they all failed with the JSON.parse… response.
I've found a solution. I tackle the problem in the component with a download service:
// components/companies-download.js
import Component from '#ember/component';
import { computed } from '#ember/object';
import { inject as service } from '#ember/service';
export default Component.extend({
download: service(),
actions: {
downloadXlsx() {
let url = `/companies/export_xlsx`;
this.get('download').file(url);
}
}
});
// services/download.js
import Service from "#ember/service";
import { inject as service } from '#ember/service';
export default Service.extend({
session: service(),
file(url) {
let xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = () => {
let [, fileName] = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(
xhr.getResponseHeader("Content-Disposition")
);
let file = new File([xhr.response], decodeURIComponent(fileName));
let link = document.createElement('a');
link.style.display = 'none';
link.href = URL.createObjectURL(file);
link.download = file.name;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
xhr.open('GET', url);
xhr.setRequestHeader(
'Authorization',
'Bearer ' + this.get('session.data.authenticated.token')
);
xhr.send();
}
});

How to resolve Don't use Ember's function prototype extensions

I received an error of Don't use Ember's function prototype extensions ember/no-function-prototype-extensions
and my line of code is this
import JSONAPIAdapter from 'ember-data/adapters/json-api';
import $ from 'jquery';
import config from 'appName/config/environment';
export default JSONAPIAdapter.extend({
shouldReloadAll: function() {
return false;
},
shouldBackgroundReloadRecord: function() {
return true;
},
namespace: 'api/v1',
host: window.location.origin,
coalesceFindRequests: true,
headers: function() {
// Reference https://github.com/DavyJonesLocker/ember-appkit-rails/issues/220
// Only set the X-CSRF-TOKEN in staging or production, since API will only look for a CSRF token on those environments
let csrfToken;
if (config.environment === 'staging' || config.environment === 'production') {
csrfToken = $('meta[name="csrf-token"]').attr('content');
}
let authorizationToken = 'Token ' + this.currentSession.get('token');
return {
'X-CSRF-TOKEN': csrfToken,
'Authorization': authorizationToken
};
}.property().volatile(),
handleResponse(status, headers, payload, requestData) {
if (this.isInvalid(status, headers, payload)) {
if (payload && typeof payload === 'object' && payload.errors &&
typeof payload.errors === 'object') {
return payload.errors = [payload.errors];
}
}
return this._super(status, headers, payload, requestData);
}
});
this was the line of code that my terminal is referring to .property().volatile(), I have looked on the google but I couldn’t find a similar examples to my work. Btw, I have updated my ember version from 1.13.13 to 3.1.0 and that is the reason why I received the error.
Please help me
Ember's .property() is deprecated.
Instead of:
headers: function() {
// ...
}.property().volatile(),
...do:
headers: computed(function () {
// ...
}).volatile(),
Also add the computed import at the top:
import { computed } from '#ember/object';
When you see these eslint errors, do a google search for the name of the rule, in this case ember/no-function-prototype-extensions. You'll find the description of the error and how to fix:
https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/no-function-prototype-extensions.md

Unit testing Sails/Waterline models with mocha/supertest: toJSON() issue

I'm setting up unit tests on my Sails application's models, controllers and services.
I stumbled upon a confusing issue, while testing my User model. Excerpt of User.js:
module.exports = {
attributes: {
username: {
type: 'string',
required: true
},
[... other attributes...] ,
isAdmin: {
type: 'boolean',
defaultsTo: false
},
toJSON: function() {
var obj = this.toObject();
// Don't send back the isAdmin attribute
delete obj.isAdmin;
delete obj.updatedAt;
return obj;
}
}
}
Following is my test.js, meant to be run with mocha. Note that I turned on the pluralize flag in blueprints config. Also, I use sails-ember-blueprints, in order to have Ember Data-compliant blueprints. So my request has to look like {user: {...}}.
// Require app factory
var Sails = require('sails/lib/app');
var assert = require('assert');
var request = require('supertest');
// Instantiate the Sails app instance we'll be using
var app = Sails();
var User;
before(function(done) {
// Lift Sails and store the app reference
app.lift({
globals: true,
// load almost everything but policies
loadHooks: ['moduleloader', 'userconfig', 'orm', 'http', 'controllers', 'services', 'request', 'responses', 'blueprints'],
}, function() {
User = app.models.user;
console.log('Sails lifted!');
done();
});
});
// After Function
after(function(done) {
app.lower(done);
});
describe.only('User', function() {
describe('.update()', function() {
it('should modify isAdmin attribute', function (done) {
User.findOneByUsername('skippy').exec(function(err, user) {
if(err) throw new Error('User not found');
user.isAdmin = false;
request(app.hooks.http.app)
.put('/users/' + user.id)
.send({user:user})
.expect(200)
.expect('Content-Type', /json/)
.end(function() {
User.findOneByUsername('skippy').exec(function(err, user) {
assert.equal(user.isAdmin, false);
done();
});
});
});
});
});
});
Before I set up a policy that will prevent write access on User.isAdmin, I expect my user.isAdmin attribute to be updated by this request.
Before running the test, my user's isAdmin flag is set to true. Running the test shows the flag isn't updated:
1) User .update() should modify isAdmin attribute:
Uncaught AssertionError: true == false
This is even more puzzling since the following QUnit test, run on client side, does update the isAdmin attribute, though it cannot tell if it was updated, since I remove isAdmin from the payload in User.toJSON().
var user;
module( "user", {
setup: function( assert ) {
stop(2000);
// Authenticate with user skippy
$.post('/auth/local', {identifier: 'skippy', password: 'Guru-Meditation!!'}, function (data) {
user = data.user;
}).always(QUnit.start);
}
, teardown: function( assert ) {
$.get('/logout', function(data) {
});
}
});
asyncTest("PUT /users with isAdmin attribute should modify it in the db and return the user", function () {
stop(1000);
user.isAdmin = true;
$.ajax({
url: '/users/' + user.id,
type: 'put',
data: {user: user},
success: function (data) {
console.log(data);
// I can not test isAdmin value here
equal(data.user.firstName, user.firstName, "first name should not be modified");
start();
},
error: function (reason) {
equal(typeof reason, 'object', 'reason for failure should be an object');
start();
}
});
});
In the mongoDB console:
> db.user.find({username: 'skippy'});
{ "_id" : ObjectId("541d9b451043c7f1d1fd565a"), "isAdmin" : false, ..., "username" : "skippy" }
Yet even more puzzling, is that commenting out delete obj.isAdmin in User.toJSON() makes the mocha test pass!
So, I wonder:
Is the toJSON() method on Waterline models only used for output filtering? Or does it have an effect on write operations such as update().
Might this issue be related to supertest? Since the jQuery.ajax() in my QUnit test does modify the isAdmin flag, it is quite strange that the supertest request does not.
Any suggestion really appreciated.

Trying to mock $http in Angular

I am trying to create some basic test coverage of a service that I have created. Here is my service:
App.factory('encounterService', function ($resource, $rootScope) {
return {
encounters: [],
encountersTotalCount: 0,
encountersIndex: 0,
resource: $resource('/encounters/:encounterId', {encounterId:'#encounterId'}, {
search: {
method: 'GET',
headers: {
'RemoteUser': 'jjjyyy',
'Content-Type': 'application/json'
}
}
}),
getMoreEncounters: function() {
var that = this;
that.resource.search({}, function(data) {
that.encountersTotalCount = data.metadata.totalCount;
_.each(data.encounters, function(encounter) {
that.encounters.push(encounter);
});
that.busy = false;
that.offset += 10;
$rootScope.$broadcast('encountersFetched');
});
}
};
});
Here is my test that I cannot get to work:
describe('encounterService', function() {
var _encounterService, httpBackend;
beforeEach(inject(function(encounterService, $httpBackend) {
_encounterService = encounterService;
httpBackend = $httpBackend;
var url = '/encounters/';
httpBackend.when('GET', url).respond([{}, {}, {}]);
}));
afterEach(function() {
httpBackend.verifyNoOutstandingExpectation();
httpBackend.verifyNoOutstandingRequest();
});
it('should return a list of encounters', function() {
_encounterService.getMoreEncounters();
httpBackend.flush();
expect(_encounterService.encounters.size).toBe(3);
});
});
The error I get is
Chrome 31.0.1650 (Mac OS X 10.8.5) Clinical App services encounterService should return a list of encounters FAILED
Error: Unexpected request: GET encounters
No more request expected
at $httpBackend (/Users/mhamm/Developer/clinical/app/bower_components/angular-mocks/angular-mocks.js:1179:9)
at sendReq (/Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:7611:9)
at $http.serverRequest (/Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:7345:16)
at wrappedCallback (/Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:10549:81)
at wrappedCallback (/Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:10549:81)
at /Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:10635:26
at Scope.$eval (/Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:11528:28)
at Scope.$digest (/Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:11373:31)
at Function.$httpBackend.flush (/Users/mhamm/Developer/clinical/app/bower_components/angular-mocks/angular-mocks.js:1453:16)
at null.<anonymous> (/Users/mhamm/Developer/clinical/test/spec/clinical.spec.js:78:21)
Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.2.0/$rootScope/inprog?p0=%24digest
at /Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:78:12
at beginPhase (/Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:11830:15)
at Scope.$digest (/Users/mhamm/Developer/clinical/app/bower_components/angular/angular.js:11364:9)
at Function.$httpBackend.verifyNoOutstandingExpectation (/Users/mhamm/Developer/clinical/app/bower_components/angular-mocks/angular-mocks.js:1486:16)
at null.<anonymous> (/Users/mhamm/Developer/clinical/test/spec/clinical.spec.js:68:21)
I do not fully understand mocking, so I am sure I am doing something basic incorrectly. Please show me what I am doing wrong.
$resource automatically removes the trailing slashes from the url.
From version 1.3.0 there is a fourth argument that allows you to set stripTrailingSlashes: false to keep those.