Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test express route with passport authenticate

How can one unit test an express router that is dependent on passport authentication to call the helper methods?

I'm new to express unit testing and I've seen a lot of code that actually hits the server to call the method. But would that not make it an integration test? This ultimately comes down to my lack of understanding on the best practices on express unit testing.

I've tried to just mock out the passport but that didn't work because I need to get to the callbacks. I've also tried using rewire and just try to test the helper methods and that didn't seem to work either, I think, because file is wrapped in module.export.

Any help here would be much appreciated.

File I'm trying to unit test:

module.exports = function (inject) {
var router = require('express').Router();
var app = inject.app;

return router.get('/', app.passport.authenticate('bearer', { session: false }), [editContentCheck, getUser]);

function editContentCheck(req,res,next) {
    if(req.authInfo.scope.indexOf('readOwnUser') == -1) {
        res.statusCode = 403;
        return res.end('Forbidden');
    }
    return next();
}

function getUser(req, res) {

    var authHeader = req.headers.authorization.split(' ');
    var token = authHeader[1];
    var models = require('../models');

    models.AccessToken.getAccessToken(token,function(err,tokenObj) {
        models.User.getUser(tokenObj.userId, function(err, user) {
            if (err) { return done(err); }
            if (!user) { return done(null, false); }
            res.send(JSON.stringify(user));
        });
    });

 }
};
like image 345
FruitPunchSamurai Avatar asked Oct 04 '16 21:10

FruitPunchSamurai


People also ask

What does passport authenticate () do?

In this route, passport. authenticate() is middleware which will authenticate the request. By default, when authentication succeeds, the req. user property is set to the authenticated user, a login session is established, and the next function in the stack is called.

Does passport use Express session?

Now, one thing to note here is that Passport works on top of the express session. So you have to use the express session middleware before using Passport middleware. Once you've set up the middleware, your passport strategy will come into the picture, which will be looking like this.

Is passport good for authentication?

Passport is a popular, modular authentication middleware for Node. js applications. With it, authentication can be easily integrated into any Node- and Express-based app. The Passport library provides more than 500 authentication mechanisms, including OAuth, JWT, and simple username and password based authentication.


1 Answers

Check this repository, it has all You want: https://github.com/num8er/alttab-nodejs-challenge

Also a look at example and implement it as You wish:

1)server.js :

var 
  http = require('http'),
  app = require('./app'); // app.js file

http.createServer(app).listen(8080);

2)app.js :

var
  express = require('express'),
  app = express();

app.use(require('./routes')); // routes.js file

module.exports = app;

3)routes.js :

var router = require('express').Router();

function editContentCheck(req,res,next) {}
function getUser(req, res) {}

router.get('/posts', app.passport.authenticate('bearer', { session: false }), [editContentCheck, getUser]);

module.exports = router;

4)spec/AppSpec.js :

var 
  request = require('supertest-as-promised'), // npm i --save-dev supertest-as-promised
  app = require('./../app');

var token = "some token here";

describe('App', function() {

  describe("Posts", function() {

    it('should pass auth check and get posts', function() {
      return request(app)
               .get('/posts')
               .set('Authorization', 'Bearer ' + token)
               .expect(200);
    });

  });
});

p.s. I'm using jasmine as testing framework, but even with mocha it's same style. Because of it's using supertest-as-promised that gets app module and calls the route without creating http object.

p.s.2. it's not unit testing, You're testing the feature, so it's more an integration test to check if all chains of code is properly integrated.

like image 69
num8er Avatar answered Oct 04 '22 15:10

num8er