Can't call success function - node.js

I'm developing a Backbone Node.js with Express.js app. I'm trying to trigger a function after receiving a response from my server like the code bellow:
mainView.js
...
user: null,
initialize: function () {
_.bindAll(this, 'registerSuccess', 'loginSuccess');
this.user = new userModel();
}
registerSuccess: function () {
this.user.auth({
success: this.loginSuccess
});
});
loginSuccess: function () {
console.log('loginSuccess');
}
userModel.js
...
, auth: function (options) {
$.ajax({
url: 'users/auth'
, type: 'post'
}, options);
})
app.js
var api = require('./routes/apiController');
app.post('/users/auth', api.userAuth);
apiController.js
exports.userAuth = function (req, res) {
return res.send( {
status: 200
});
}
I´m getting the response:
But it doesn't print the console.log('loginSuccess') sentence from this function.

There are two ways to call $.ajax:
jQuery.ajax(url, settings)
jQuery.ajax(settings)
In the first case, url must be a string and settings is an optional object; in the second case, settings is again an optional object. You're calling $.ajax with two objects:
auth: function (options) {
$.ajax({
url: 'users/auth'
, type: 'post'
}, options);
}
Since the first argument is not a string, $.ajax will use the second calling form and ignore options completely. You probably want to use _.extend to merge the arguments:
$.ajax(_({
url: 'users/auth'
, type: 'post'
}).extend(options));
Or _.defaults if you want to avoid accidentally overwriting url and type:
$.ajax(_({
url: 'users/auth'
, type: 'post'
}).defaults(options));
Or, since you only have two things, just stuff them in manually:
options = _(options).clone(); // Avoid accidentally messing with the argument.
options.url = 'users/auth';
options.type = 'post';
$.ajax(options);

Related

customize CRUD operation in loopback js

i am new to loopback js trying to create remote method Create,Read,update and delete operation.
i have created a model name class and now i want to write the crud operation in my project file
models/class.js file.
'use strict';
module.exports = function(Class) {
};
I have no idea how to do it , read docs but does not clearify things if anyone can give example to write CRUD operation would be better understanding. (Using loopback 3 for practice.)
To create a custom method for a model, you need to do two things:
1/ Create the method within your model like this:
module.exports = function (Mymodel) {
Mymodel.myCustomMethod = function (req, res, cb) {
// method body
}
}
2/ To declare the remote to your model, so it can be exposed
module.exports = function (Mymodel) {
/* custom methods, hooks, ... */
Mymodel.remoteMethod(
'myCustomMethod', {
http: {
path: '/myCustomMethod',
verb: 'post' // it could also be 'post', 'put', 'delete'
},
accepts: {
arg: 'data',
type: 'object', // accepting an object in the body
'http': {
source: 'body' // Reading the body of the request. It could also be 'req' to read the req url for parameters.
}
},
returns: {
type: 'object', // Returns an object to the front
root: true
}
}
)
}
This is an example for a 'post' remote method. A 'put' remote method will look exactly the same, except for the keyword 'put' instead of 'post'.
For a 'get' or 'delete' requests, only the request url will be read, so the remote method should contain:
http: { path: '/myCustomMethod/:projectId', verb: 'get' },
accepts: { arg: 'projectId', type: 'number' },
With projectId the name of a property given in the URL, and number being the type of projectId.

Set params on request when testing hapi routes

I am currently writing some tests for our hapi routes. The route I want to test looks like that:
server.route(
{
method: 'POST',
path: '/',
options: {
tags: ['api'],
cors: true,
handler: async (req: Hapi.Request | any, h: Hapi.ResponseObject) => {
if (!req.params.userId) {
throw Boom.badRequest();
}
return 200;
}
}});
So my test looks like this:
it('should return 200', async () => {
const request : ServerInjectOptions = {
url: '/user',
method: 'POST',
payload: {
email: 'e#email.de',
password: 'secred',
firstname: 'John',
lastname: 'Doe'
},
app: {}
};
const response = await server.inject(request);
expect(response.statusCode).toEqual(200);
});
As you can see the route expects a param in the params array with the name userId but i am not able to set the parameter on the ServerInjectOptions object. The error I get is that the property does not exist on the ServerInjectOptions type.
Is there any other way i can set the params array? I didn`t find something in the docs maybe i missed it and someone can tell me where to find it.
Thanks in advance
For the route I believe you add the name of the parameter to the path like so:
server.route(
{
method: 'POST',
path: '/:userId',
//
}});
And for the test you should be able to add your parameter to the url option:
const request : ServerInjectOptions = {
url: '/user/parameterYouNeedToAdd',
//
};
Or if the parameter is a variable:
const request : ServerInjectOptions = {
url: '/user/' + parameterYouNeedToAdd,
//
};

Using serverless-mocha-plugin to test dynamic endpoint

I am creating an API application in NodeJS using the Serverless framework. I have installed the serverless-mocha-plugin and am trying to create some unit tests for my functions.
In my serverless.yml file, I have the following endpoints:
...
equipmentGetAll:
handler: ./api/equipment/equipment.getAll
events:
- http:
path: equipment
method: get
cors: true
equipmentGetOne:
handler: ./api/equipment/equipment.getOne
events:
- http:
path: equipment/{po_number}
method: get
cors: true
...
When testing the getAll endpoint, I use the following test which passes successfully. I have verified it works by logging the response to the console.
'use strict';
// tests for equipmentGetAll
// Generated by serverless-mocha-plugin
const mochaPlugin = require('serverless-mocha-plugin');
const expect = mochaPlugin.chai.expect;
let wrapped = mochaPlugin.getWrapper('equipmentGetAll', '/api/equipment/equipment.js', 'getAll');
describe('equipmentGetAll', () => {
before((done) => {
done();
});
it('should get all Equipment', () => {
return wrapped.run({po_number:117}).then((response) => {
expect(response.statusCode).to.be.equal(200);
expect(response.body.length).to.be.greaterThan(0);
});
});
});
Similarly, for the getOneendpoint, I am (for now) doing a very similar test:
'use strict';
// tests for equipmentGetOne
// Generated by serverless-mocha-plugin
const mochaPlugin = require('serverless-mocha-plugin');
const expect = mochaPlugin.chai.expect;
let wrapped = mochaPlugin.getWrapper('equipmentGetOne', '/api/equipment/equipment.js', 'getOne');
describe('equipmentGetOne', () => {
before((done) => {
done();
});
it('should get one single Equipment', () => {
return wrapped.run({}).then((response) => {
expect(response.statusCode).to.be.equal(200);
expect(response.body.length).to.be.equal(1);
});
});
});
The Problem
The current response I'm receiving for getOne is:
{
statusCode: 500,
headers: { 'Content-Type': 'text/plain' },
body: 'Cannot read property \'po_number\' of undefined'
}
Due to the fact that the path for getOne from serverless.yml is equipment/{po_number} rather than just equipment/.
What is the proper way to pass the path value for the test?
A sample call would hit endpoint my-api-endpoint.com/equipment/117 and return the Equipment with po_number 117. This works properly when testing with POSTMan, but how can I make it work with mocha-serverless-plugin?
To pass data to lambda you should use
wrappedLambda.run({body: "String, not Object"})
To pass queryStringParametr to lambda you should use wrappedLambda.run({queryStringParameters: {a: "first",b:"second"}})
To pass pathParameters to lambda you should use
wrappedLambda.run({pathParameters: {a: "first", b:"second"})
Simple example for testing post method
context('save flashcard', () => {
before((done) => {
done();
});
it('save flashcard successfully', () => {
return saveFlashcard.run({body: correctInput})
.then((response) => {
const body = JSON.parse(response.body);
expect(body).to.have.property('_id')
})
});
});
this body will be located inside event object.
To pass body you need to do something like this
{
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
releaseDate: 2231213213,
title: 'sfsdf',
authorName: 'L'
})
}

Request parameters while consuming a REST API in node.js

I would like to consume a REST service in Node.js using request.js, as follows:
var request = require('request');
request.get({
url: 'https://www.googleapis.com/storage/v1/b',
auth: {
'bearer': 'oauth2_token'
}
}, function(err, res) {
console.log(res.body);
});
However, I would like to specify also a set of request parameters, such as project, prefix, etc. (as specified at https://cloud.google.com/storage/docs/json_api/v1/buckets/list).
How can I pass these parameters in the request for consuming the API service?
You can pass in qs as the additional queries. See example below:
const queryObject = { project: 'project', prefix: 'prefix' };
request.get({
url: 'https://www.googleapis.com/storage/v1/b',
qs: queryObject,
auth: {
'bearer': "oauth2_token"
}
}, function(err, res) {
console.log(res.body);
});
See here for github issue.

Why is my cookie not available in my handler function when testing?

I am using Hapi and this is my handler function:
function propertyDetailsValidateHandler(request, reply, source, error) {
console.log(request.state)
var data = joiValidationHelper.checkForErrors(request, error);
if (typeof data !== "undefined"){
return reply.view('property-details', data).code(400);
} else {
var details = request.state.details;
details.propertyType = request.payload.propertyType;
details.newBuild = request.payload.newBuild;
return reply.redirect('/property-details/postcode').state('details', details, {path: '/'});
}
}
And this is my test written using Jasmine:
describe('tell us about the property youre buying flow', function(){
it('test /property-details, status code and location', function(done){
var options = {
method: 'POST',
url: '/property-details',
headers: {
cookie: {details: { test: "test"}}
},
payload: {
propertyType: "freehold",
newBuild: true
}
};
server.inject(options, function(response){
detailsTestCookie = response.headers['set-cookie'][0].split(';')[0];
expect(response.statusCode).toBe(302);
expect(response.headers.location).toMatch("/property-details/postcode");
done();
});
});
})
The handler function runs correctly when I run my server and use the browser but when I run the test request.state is an empty object when I was expecting it to be the cookie I provided in the test hence my test fails as request.state.details is undefined. Is this the correct way to provide the headers with a cookie in my test?
This works in our project, using tape and Hapi.
var cookie = the_cookie_you_want_to_send;
Then in your test payload:
headers: { cookie: `details=${cookie}`}
The cookie needed to be encoded as that is how the cookie was registered in our server file:
server.state('details', {
ttl: null,
isSecure: false,
isHttpOnly: false,
encoding: 'base64json', //this is not encrypted just encoded
clearInvalid: false, // remove invalid cookies
strictHeader: false // don't allow violations of RFC 6265
});

Resources