Hmmm just double checking if I'm making some silly error, however doesn't seem like it. I just want this test to pass but it keeps giving me a timeout error. This module should work, it is sending mail correctly, but mocha keeps giving a timeout.
// describe('POST /api/mail', function() {
// it('should successfully send mail', function(done) {
// request(app)
// .post('/api/mail')
// .send(form)
// .expect(200)
// .end(function(err, res) {
// if (err) return done(err);
// done();
// });
// });
// });
This is the actual function being tested
'use strict';
var transporter = require('./transporter.js').transporter;
exports.sendMail = function(req, res){
// setup e-mail data with unicode symbols
var mailOptions = {
from: req.body.name + ' <'+req.body.email+'>',
to: 'test#gmail.com',
subject: req.body.subject,
text: req.body.message
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function(err, info){
if(err){
res.status(400); //error
}else{
res.status(200); //success
}
});
};
I think Mocha is waiting for sendMail result via callback. I have a similar sendMail, using nodemailer.js, in an application:
function send(fr, to, sj, msg, callback){
//...
var transport = nodemailer.createTransport();
console.log("Message content: "+msg);
transport.sendMail({from:fr, to:to, subject: sj, text: "\r\n\r\n" + msg},
function(err,response){
if(err){
callback(err);
}else{
callback(response);
}
});
};
In my test:
describe('when this example is tested',function(done){
it('should be sending an email', function(done){
mailSender.sendMail('test#test.es', 'Test', 'Test text', function(sent){
sent.should.be.ok;
done();
});
});
You get the sent in your callback and then Mocha can reach the done() method to indicate the test has finished.
Also, you can use Supertest to test your endpoint. It should be something like this:
it('should return 200 on /api/mail', function(done) {
supertest('http://localhost:3000').post('/api/mail').expect(200)
.end(
function(err, res) {
if (err) {
return done(err);
}
done();
});
});
Related
When i try to use JWT with socket.io it wont respsonse when i get connection. I dont get any errors, but i dont get any respsonse when doing things on localhost. The localstorage is empty also. Please help, i've tried everything:)
client.js
var socket = io('http://localhost:4000', {query: 'auth_token=THE_JWT_TOKEN'});
socket.on('error', function(err) {
console.log("test")
throw new Error(err);
});
// Connection succeeded
socket.on('success', function(data) {
console.log(data.message);
console.log('user info: ' + data.user);
console.log('logged in: ' + data.user.logged_in)
})
server.js
var io = require("socket.io")(server);
var socketioJwt = require("socketio-jwt");
// set authorization for socket.io
var io = require('socket.io')();
var jwtAuth = require('socketio-jwt-auth');
var jwt = require('jsonwebtoken')
// using middleware
io.use(jwtAuth.authenticate({
secret: 'Your Secret', // required, used to verify the token's signature
algorithm: 'HS256' // optional, default to be HS256
}, function(payload, done) {
// done is a callback, you can use it as follows
User.findOne({id: payload.sub}, function(err, user) {
if (err) {
// return error
return done(err);
}
if (!user) {
// return fail with an error message
return done(null, false, 'user does not exist');
}
// return success with a user info
return done(null, user);
});
}));
io.on('connection', function(socket) {
console.log('Authentication passed!');
// now you can access user info through socket.request.user
// socket.request.user.logged_in will be set to true if the user was authenticated
socket.emit('success', {
message: 'success logged in!',
user: socket.request.user
});
I am writing a MEAN API at the minute and I have a route called /authenticate where users can log in. Below I have shown the route it's self.
// User Login Route - http://localhost:8080/api/authenticate
router.post('/authenticate', function(req, res) {
User.findOne({ username: req.body.username }).select('email username password').exec(function(err, user) {
if (err) throw err;
if (!user) {
res.json({ success: false, message: 'Could not authenticate user.'});
} else if (user) {
//Using comparePassword Method
if (req.body.password) {
var validatePassword = user.comparePassword(req.body.password);
if (!validatePassword) {
res.json({success : false, message : 'Could not authenticate password!'});
}
else{
res.status(200).json({success : true, message : 'User authenticated!'});
}
}
else{
res.json({success : false, message : 'Not password provided!'});
}
}
});
});
I am now trying to test the route using the mocha and chai libraries. Below I have shown the describe block that I am using to test this function.
describe('POST /authenticate', function() {
it('should return an error', function (done) {
var newUser = {
"username" : "testetet",
"password" : "hgfhghg"
};
chai.request(server)
.post('/api/authenticate')
.send(newUser)
.end(function (err, res) {
expect(res).to.have.status(201);
expect(res.body).to.have.property('message').equal('User Created.');
});
done();
});
});
As you can see from the test above the test should fail because none of the response criteria in the test matches the response that should be coming back from the API, but it still continues to pass every time I run it.
Does anyone have any ideas why this would be happening?
Thanks for any help in advance.
Hi guys found the problem the done() in the test code was in the wrong place. It should look like the code below.
it('should return a user authenticated message', function (done) {
var user = {
"username": "testuser1",
"password": "testPassword1"
};
chai.request(server)
.post('/api/authenticate')
.send(user)
.end(function (err, res) {
expect(res).to.have.status(200);
expect(res.body).to.have.property('message').equal('User Authenticated!');
done();
});
});
i am new to developing apis in node js. recently i started working on a node js application there i use jwt tokens to authentication purposes.
my jwt validation function is as bellow
var jwt = require('jsonwebtoken');
var config = require('../config.js')
var JwtValidations = {
//will validate the JTW token
JwtValidation: function(req, res, next, callback) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secret, callback);
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
}
}
module.exports = JwtValidations;
to this function i am passing a call back function so that if the jtw token validation passed i can serve to the request. bellow is one example of adding a user to the system
// addmin a user to the database
router.post('/add', function(req, res, next) {
JwtValidations.JwtValidation(req, res, next, function(err, decoded) {
if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
} else {
retrunval = User.addUser(req.body);
if (retrunval === true) {
res.json({ message: "_successful", body: true });
} else {
res.json({ message: "_successful", body: false });
}
}
})
});
// addmin a user to the database
router.put('/edit', function(req, res, next) {
JwtValidations.JwtValidation(req, res, next, function(err, decoded) {
if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
} else {
User.UpdateUser(req.body, function(err, rows) {
if (err) {
res.json({ message: "_err", body: err });
} else {
res.json({ message: "_successful", body: rows });
}
});
}
})
});
as you can see in both of these function i am repeating same code segment
return res.json({ success: false, message: 'Failed to authenticate token.' });
how do i avoid that and call the callback function if and only if JwtValidations.JwtValidation does not consists any error
how do i avoid that and call the callback function if and only if JwtValidations.JwtValidation does not consists any error
Just handle it at a level above the callback, either in JwtValidations.JwtValidation itself or a wrapper you put around the callback.
If you were doing it in JwtValidations.JwtValidation itself, you'd do this where you call the callback:
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secret, function(err, decoded) {
if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
}
callback(decoded);
});
} else /* ... */
Now when you use it, you know either you'll get the callback with a successfully-decoded token, or you won't get a callback at all but an error response will have been sent for you:
router.put('/edit', function(req, res, next) {
JwtValidations.JwtValidation(req, res, next, function(decoded) {
User.UpdateUser(req.body, function(err, rows) {
if (err) {
res.json({ message: "_err", body: err });
} else {
res.json({ message: "_successful", body: rows });
}
});
})
});
The code above is using a lot of (old-style) NodeJS callbacks. That's absolutely fine, but you may find it's simpler to compose bits of code if you use promises instead. One of the useful things do is split the return path in two, one for normal resolution, one for errors (rejection).
Use the jwt authentication function as a middleware function and not as a route, plenty of examples on the express documentation.
http://expressjs.com/en/guide/using-middleware.html
I'm testing the controller logic behind API endpoints in my node server with jasmine-node. Here is what this controller logic typically looks like:
var getSummary = function(req, res) {
var playerId = req.params.playerId;
db.players.getAccountSummary(playerId, function(err, summary) {
if (err) {
logger.warn('Error while retrieving summary for player %d.', playerId, err);
return res.status(500).json({
message: err.message || 'Error while retrieving summary.',
success: false
});
} else {
res.json({success: true, summary: summary});
}
});
};
Below is how I successfully test the else block:
describe('GET /api/players/:playerId/summary', function() {
it('should return an object summarizing the player account', function(done) {
request
.get('/api/players/' + playerId + '/summary')
.set('Content-Type', 'application/json')
.set('cookie', cookie)
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
expect(err).toBeNull(err ? err.message : null);
expect(res.body.success).toBe(true);
expect(res.body.summary).toBeDefined();
done();
});
});
});
This works nicely, but leaves me with poor branch coverage as the if block is never tested. My question is, how do I force the error block to run in a test? Can I mock a response which is set to return an error so that I can test the correct warning is logged and correct data is passed back?
It depends on your tests. If you only want to unit test, spies are the way to go.
You can just stub your db response. Be aware that in this case the database is not called though. It's just simulated.
const db = require('./yourDbModel');
spyOn(db.players, 'getAccountSummary').and.callFake(function(id, cb) {
cb(new Error('database error');
});
request
.get('/api/players/' + playerId + '/summary')
.set('Content-Type', 'application/json')
.set('cookie', cookie)
.expect(500)
// ...
If you want functional/integration tests, you need to call your request simply with wrong data, for example a players id that doesn't exist in your database.
request
.get('/api/players/i_am_no_player/summary')
.set('Content-Type', 'application/json')
.set('cookie', cookie)
.expect(500)
// ...
I have built a login process with a basic MEAN stack and using passport for the authentication process.
I am trying to set up a test to make sure the login process is working. To do the login part here is the code I used:
it ('login', function(done) {
agent.post(config.web.vhost + '/login')
.send({ email: 'bruce#wayne.inc', password: 'batman' })
.end(function(err, res) {
if (err) console.log('error' + err.message);
res.should.have.status(200);
done();
});
});
I get the following error:
no error
email: bruce#wayne.inc
․no error
errorsocket hang up
․double callback!
1 passing (2s)
1 failing
1) User login:
Uncaught TypeError: Cannot read property 'should' of undefined
I know my routes and credentials are good but I cant figure out whats not working here. This is my first steps with user testing so I am probably not getting something right.
Here is the rest of my test:
var should = require("should");
var mongoose = require('mongoose');
var request = require('superagent');
var agent = request.agent();
var config = require("../settings/conf");
var dbUrl = require("../config/database.js");
var User = require('../server/models/user');
var db;
describe('User', function() {
before(function(done) {
db = mongoose.connect(dbUrl.url);
done();
});
after(function(done) {
mongoose.connection.close()
done();
});
beforeEach(function(done) {
var user = new User({
email: 'bruce#wayne.inc',
password: 'batman',
firstName: 'Bruce',
lastName: 'Wayne'
});
user.save(function(err, user) {
if (err) console.log('error' + err.message);
else console.log('no error');
done();
});
});
it('find a user by username', function(done) {
User.findOne({ email: 'bruce#wayne.inc' }, function(err, user) {
user.email.should.eql('bruce#wayne.inc');
console.log(" email: ", user.email)
done();
});
});
it ('login', function(done) {
agent.post(config.web.vhost + '/login')
.send({ email: 'bruce#wayne.inc', password: 'batman' })
.end(function(err, res) {
if (err) console.log('error' + err.message);
res.should.have.status(200);
done();
});
});
afterEach(function(done) {
User.remove({ email: 'bruce#wayne.inc' }, function() {
done();
});
});
});
I notice that the failure you're seeing is connect ECONNREFUSED -- so it's not anything about passport, it's just that you're not connecting successfully to your server in your agent.post.
I would guess either your config.web.vhost value isn't set correctly or isn't in the right form for what superagent is looking for (for instance, superagent may require a full absolute url with the 'http://' on the front, and your vhost value may only be the hostname).