request params when using Mocha and Chai to test file node.js - node.js

In the code below, I use req.body to get param from request.
Now, I want get param by using req.user (or req.someName, ...) but I don't know how to do this.
it.only('updateEmail',function(done){
chai.request(server)
.post('updateEmail')
.send({
new_email: faker.internet.email()
})
.end(function(err, res){
if (err){
console.log('err: ', err)
done()
}
else {
console.log('res: ', res.body)
done()
}
});
});

Related

Chai not reaching .end()

I am using Mocha and Chai to test my Node/Express API, and I can't figure out why the test is not reaching the .end()
Here is the test:
it('should authenticate successfully with user credentials', function (done) {
agent
.post('/login')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send({ 'username': 'username', 'password': 'password'})
.end(function (err, res) {
console.log(res);
console.log('***************************Authenticated*********************************************');
expect(res).to.have.status(200);
});
done();
});
And here is the route I am hitting:
app.post('/login', passport.authenticate('ldapauth', { successRedirect: '/' }));
I figure my problem may be with the fact that there is no formal response, but rather a redirect, but I am not sure how to handle it.
The solution ended up being to move the done() callback into my .end() method. Thanks #robertklep
If you are testing async methods int mocha, you should call call method in callback function as below.
it('should authenticate successfully with user credentials', function (done) {
agent
.post('/login')
.set('Content-Type', 'application/x-www-form-urlencoded')
.send({ 'username': 'username', 'password': 'password'})
.end(function (err, res) {
console.log(res);
console.log('***************************Authenticated*********************************************');
expect(res).to.have.status(200);
done();
});
});
I have the same problem with chai request. I want to wait for .end callback before going to another function. but I can't use mocha because I'm using cucumber. how can I wait for chai .end callback?
in fact, I want to log (1) first but it does not work properly
When('I submit with method {string}:', function (string, docString) {
chai.request(app)
.post(endpoint)
.send(docString)
.end(function (err, res) {
console.log(1)
response = res
})
});
Then('I recieved ok', function () {
console.log(2)
// expect(response.status).to.deep.equal(200)
});

Why am I getting a 401 response in my tests?

I am trying to test a route with authentication in my Node / Express / Mongoose back-end.
Here's the test file
var should = require('should');
var _ = require('lodash');
var async = require('async');
var app = require('../../../../app');
var request = require('supertest');
var mongoose = require('mongoose');
var User = mongoose.model('User');
var Firm = mongoose.model('Firm');
var firm, user, userPassword, createdFirm, loggedInUser;
describe('GET /api/firms', function(){
beforeEach(function (done) {
firm = new Firm({
company: 'My test company',
corporateMail: 'test.com'
});
userPassword = 'password';
user = new User({
fistname: 'Fake User',
lastname: 'Fake User',
email: 'test#test.com',
job: 'Partner',
firmName:firm.company,
password:userPassword,
isActivated:true,
_firmId:firm._id
});
function createFirm(cb){
request(app)
.post('/api/firms')
.send(firm)
.expect(201)
.end(function(err, res){
if ( err ) throw err;
createdFirm = res.body;
cb();
});
}
function createUser(cb){
request(app)
.post('/api/common/users')
.send(user)
.expect(200)
.end(function(err, res){
createdUser = res.body;
if ( err ) throw err;
cb();
});
};
async.series([function(cb){
createFirm(cb);
}, function(cb){
createUser(cb);
}], done);
});
afterEach(function (done) {
firm.remove();
user.remove();
done();
});
it('should respond with 401 error', function(done) {
request(app)
.get('/api/firms')
.expect(401)
.end(function(err, res) {
if (err) return done(err);
done();
});
});
it('should login', function(done) {
request(app)
.post('/auth/local')
.send({email:user.email, password:user.password})
.expect(200)
.end(function(err, res) {
if (err) return done(err);
done();
});
});
it('should respond with 200 after login', function(done) {
request(app)
.get('/api/firms')
.expect(200)
.end(function(err, res) {
if (err) return done(err);
done();
});
});
});
In the workflow the firm object is created first and then returns its Id so I can create the user with the firmId as a reference.
I would like to test the /api/firms route after the user is authenticated but in spite of my various attempts (using superagent, logging in the before section) I always get a 401 response in the last should section instead of an expected 200.
Actually the important thing to keep in mind is, as KJ3 said, how the authentication is set up. In my case I forgot to mention that I was using jwt. The way it works is the following, you supply a username and a password and the server returns a token created with jwt.
So it makes sense to send the token back for each request in the tests.
The way to achieve this is first by storing the token after authentication in the before section
function createUser(cb){
request(app)
.post('/api/users')
.send(user)
.expect(200)
.end(function(err, res){
if ( err ) throw err;
authToken = res.body.token;
cb();
});
};
Then by adding .set in the request with the token in the correct format ('Bearer ' + token , which is defined in the authentication service):
it('should respond with 200', function(done) {
var authToken = 'Bearer ' + createdUser.token;
request(app)
.get('/api/firms')
.set('Authorization', authToken)
.expect(200)
.end(function(err, res) {
if (err) return done(err);
done();
});
});
In the case the test sends a 200 back, which is expected and sends a 401 if the .set(...) is commented out.
Good news is that this is achieved with supertest, so no need to add anything, less good news is that you need to add the .set(...) to each test request.
If you were to go through the last 2 tests in a browser, depending on how you have it setup, yes it would work thanks to cookies and sessions, but here the /api/firms test is independent of the auth/local test. So a 401 is the correct response.
It really depends on how your auth is setup, but you need to authenticate on the /api/firms test too. Either by sending the credentials again (every single one of my mocha tests authenticates each time) or implement sessions into the tests, see this SO post for some direction.

Sails.js and Mocha, res.view testing

I write test for my sails application, but have some problem in controller. When user signup I check for duplication, if yes - render form with error, if no - render form with success message. So can anyone know how to test it right? Or maybe you can suggest better code structure, thanks a lot.
Controller :
User.findOne({ email: req.body.email }, function(err, user) {
if(err) return res.json(err)
if(!user) {
User.create({email:req.body.email, password:req.body.password}).exec(function createCB(err, user){
if(err) return res.json(err);
res.view('signup', { message: 'Done, user created'})
})
} else
res.view('signup', { message: 'User already exist'})
})
Test :
it('should show error if duplicated user - TODO', function (done) {
request(sails.hooks.http.app)
.post('/signup')
.send({ email: 'test#test.te', password: 'test' })
.expect(200)
.end(done)
})
So question is, how can I test res.view?
I usually use simple request at my test if I want to test my view. Like this:
it('able to test view', function(done) {
require('request-promise')('http://localhost:1337/')
.then(function(res) {
res.should.contains('Done, user created');
done();
})
.catch(done);
});
It will check the whole body, is there any match string that we provide. Remember to do npm install request-promise --save-dev first (or any relevant library that can make request).
Or you can use supertest library as mentioned by #Yann like this
it('should be able to test view', function(done) {
require('supertest')
.agent(sails.hooks.http.app)
.post('/signup')
.send({ email: 'test#test.te', password: 'test' })
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.should.contains('Done, user created');
return done();
});
});
You can use a library like supertest to do an HTTP request:
it('should be able to test view', function(done) {
require('supertest')
.agent(sails.hooks.http.app)
.post('/signup')
.send({ email: 'test#test.te', password: 'test' })
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.should.contains('Done, user created');
return done();
});
});

How to write a post request test in mocha with data to test if response matches?

Question:
How do would I write a post request test in mocha that tests if the response matches?
The response will just be a url string as it is a redirect for a 3rd party service.
Working Example Payload:
curl -H "Content-Type: application/json" -X POST -d '{"participant":{"nuid":"98ASDF988SDF89SDF89989SDF9898"}}' http://localhost:9000/api/members
member.controller.js // post method
// Creates a new member in the DB.
exports.create = function(req, res) {
Member.findByIdAndUpdate(req.body.participant.nuid,
{ "$setOnInsert": { "_id": req.body.participant.nuid } },
{ "upsert": true },
function(err,doc) {
if (err) throw err;
res.send({
'redirectUrl': req.protocol + '://' + req.get('host') + '/registration/' + req.body.participant.nuid
})
}
);
};
Expected res.send
{"redirectUrl":"http://localhost:9000/registration/98ASDF988SDF89SDF89989SDF9898"}
Working Example GET request Test
var should = require('should');
var app = require('../../app');
var request = require('supertest');
describe('GET /api/members', function() {
it('should respond with JSON array', function(done) {
request(app)
.get('/api/members')
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) return done(err);
res.body.should.be.instanceof(Array);
done();
});
});
it('should respond with redirect on post', function(done) {
// need help here
});
});
Try with this:
it('should respond with redirect on post', function(done) {
request(app)
.post('/api/members')
.send({"participant":{"nuid":"98ASDF988SDF89SDF89989SDF9898"}})
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) done(err);
res.body.should.have.property('participant');
res.body.participant.should.have.property('nuid', '98ASDF988SDF89SDF89989SDF9898');
});
done();
});
You can also set the type to "form" and content type to json as I show below:
it("returns a token when user and password are valid", (done) => {
Users.createUserNotAdmin().then((user: any) => {
supertestAPI
.post("/login")
.set("Connection", "keep alive")
.set("Content-Type", "application/json")
.type("form")
.send({"email": user.email, password: "123456"})
.end((error: any, resp: any) => {
chai.expect(JSON.parse(resp.text)["token"].length).above(400, "The token length should be bigger than 400 characters.");
done();
})
});
});
You also have to set the body-parser when you create the server as I show below:
server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());

'Body Parse' error for 404 test in Mocha + Supertest

I am trying to write tests to ensure that my Express API is correctly returning the right HTTP status codes for various scenarios. I am using Mocha, and Supertest for requests to the API in the tests. Right now I'm getting very unexpected results, which are detailed below.
Using: Express, body-parser, Sequelize, Mocha, Supertest
GET /users/:id
models.User.find(req.params.id).complete(function(err, foundUser) {
if (err) {
logger.error(err, 'Error');
return err;
}
console.log('user: ' + foundUser);
if (foundUser != null) {
res.json({ user: foundUser.getJsonRepresentation() });
}
else {
res.status(404);
res.json({ error: 'Not found' });
}
});
Tests for this method
it('responds with the right user', function(done){
request(app)
.get(apiPath + '/users/' + createdUser.id)
.set('Accept', 'application/json')
.expect(function(res) {
res.body.user.id.should.equal(createdUser.id);
})
.expect(200, done);
});
it('responds with the right error code for non-existent resource', function(done) {
request(app)
.get(apiPath + '/users/1000')
.expect(404, function(err, res) {
console.log(err);
console.log('Response: ' + res);
done();
});
});
For the 404 test, I get this error: { [Error: Parse Error] bytesParsed: 12, code: 'HPE_INVALID_STATUS' } in the callback. The res is undefined.
I have tried several different syntax forms for this expect call: .expect(404, function(err, res) { and none of them have worked. I've also tried all the different syntax forms for this as well:
res.status(404);
res.json({ error: 'Not found' });
Can anyone offer some insight into what is going on here?
Maybe the issue is in the following code snippet:
if (err) {
logger.error(err, 'Error');
return err;
}
It seems to be triggering the error but not actually returning it to the supertest client.
You can try to return the error to the client instead of only logging it, like this:
if (err) {
logger.error(err, 'Error');
res
.status(500);
.json({ error: error.message });
return err;
}

Resources