Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make authenticated requests in mocha test using supertest and agent?

I'm having trouble getting my authenticated tests to run (server returns 401 Unauthenticated) after logging in.

var should = require('should'),
    _ = require('lodash'),
    app = require('../../../server'),
    mongoose = require('mongoose'),
    User = mongoose.model('User'),
    request = require('supertest');

var user
    , user1;

describe('GET /api/jobs', function () {
    before(function (done) {
        user = new User({
            provider: 'local',
            name: 'Fake User',
            email: '[email protected]',
            password: 'password'
        });

        // Clear users before testing
        User.remove().exec();

        request(app)
            .post('/api/users')
            .send(user)
            // end handles the response
            .end(function(err, res) {
                if (err) {
                    throw err;
                }

                res.should.have.status(200);
                res.body._id.should.exist;

                user1 = request.agent(app); //user1 will be used in all subsequent tests since he's supposed to be authenticated
                user1
                    .post('/api/session')
                    .send({ email: user.email, password: user.password })
                    .end(function(err, res) {
                        if ( err ) throw err;
                        // user1 will manage its own cookies
                        // res.redirects contains an Array of redirects
                        res.should.have.status(200);

                        done();
                    });
            });
    });

    afterEach(function (done) {
        User.remove().exec();
        done();
    });

    it('should create a job by user1', function (done) {
        var job = {
            //jobs stuff
        };

        user1
            .post('/api/jobs')
            .send(job)
            .expect(200) //It fails here, getting 401 Unauthenticated. Session is using passport local strategy
            .expect('Content-Type', /json/)
            .end(function (err, res) {
                if (err) return done(err);
                res.body.should.be.instanceof(Object);

                done();
            });
    });
});

The sesssion is setting a cookie like this:

    if (req.user) {
        res.cookie('user', JSON.stringify(req.user.userInfo));
    }
like image 953
chovy Avatar asked Jul 17 '14 07:07

chovy


People also ask

What library does SuperTest make use of to perform requests?

SuperTest is a Node. js library that helps developers test APIs. It extends another library called superagent, a JavaScript HTTP client for Node.

What is difference between Jest and SuperTest?

Jest is a javascript test runner for running automated tests, and supertest provides a high-level abstraction for testing HTTP. The app that we will be testing will will contain a single endpoint to POST a new user given a username and password.

What is the use of SuperTest?

Supertest can be used as a standalone library or with testing frameworks like Mocha and Jest. It provides a high-level abstraction to test HTTP requests. That is, if the developer's Node. js application is running an HTTP server, they don't need a running server.


1 Answers

Made a stupid mistake. I was using before() instead of beforeEach() to create and login the user.

beforeEach(function (done) {
// do stuff before each test
});

The afterEach() was deleting Users in the db.

Here's the full solution if anyone is interested:

beforeEach(function (done) {
    // Clear data before testing
    user1 = {
        name: 'Fake User',
        username: 'test',
        email: '[email protected]',
        password: 'password'
    };

    user2 = {
        name: 'Fake User2',
        username: 'test2',
        email: '[email protected]',
        password: 'password2'
    };

    job = {
        email: '[email protected]'
        , title: 'Title'
        , description: 'Job description that is at least 60 characters with much detail'
        , apply: 'Application instructions'
        , company: 'Company'
        , location: 'Location'
    };

    function createUser1(cb){
        agent1
            .post('/api/users')
            .send(user1)
            .expect(200)
            .end(function(err, res){
                if ( err ) throw err;

                loginUser1.call(null, cb);
            });
    }

    function loginUser1(cb){
        agent1
            .post('/api/session')
            .send({
                email: user1.email
                , password: user1.password
            })
            .expect(200)
            .end(function(err, res){
                if ( err ) throw err;

                loggedInUser1 = res.body;

                cb();
            });
    }

    function createUser2(cb){
        agent2
            .post('/api/users')
            .expect(200)
            .send(user2)
            .end(function(err, res){
                if (err) throw err;

                loginUser2.call(null, cb);
            });
    }

    function loginUser2(cb){
        agent2
            .post('/api/session')
            .send({
                email: user2.email
                , password: user2.password
            })
            .end(function(err, res){
                if ( err ) throw err;

                loggedInUser2 = res.body;

                cb();
            });
    }

    async.series([function(cb){
        createUser1(cb);
    }, function(cb){
        createUser2(cb);
    }], done);

    //working, but looks like shiet with callbacks
    //      agent1
    //          .post('/api/users')
    //          .send(user1)
    //          .expect(200)
    //          // end handles the response
    //          .end(function(err, res) {
    //              if (err) throw err;
    //
    //              agent1
    //                  .post('/api/session')
    //                  .send({
    //                      email: user1.email
    //                      , password: user1.password
    //                  })
    //                  .expect(200)
    //                  .end(function(err, res) {
    //                      if ( err ) throw err;
    //
    //                      loggedInUser1 = res.body;
    //
    //                      //login the 2nd user
    //                      agent2
    //                          .post('/api/users')
    //                          .expect(200)
    //                          .send(user2)
    //                          // end handles the response
    //                          .end(function(err, res) {
    //                              if (err) throw err;
    //
    //                              agent2
    //                                  .post('/api/session')
    //                                  .send({
    //                                      email: user2.email
    //                                      , password: user2.password
    //                                  })
    //                                  .end(function(err, res) {
    //                                      if ( err ) throw err;
    //
    //                                      loggedInUser2 = res.body;
    //
    //                                      done();
    //                                  });
    //                          });
    //                  });
    //          });
});

afterEach(function (done) {
    User.remove()
        .execQ()
        .then(function(){
            return Job.remove().execQ()
        })
        .done(function(){
            done();
        });
});

agent1 is the request as promised object.

var requestp = require("supertest-as-promised");
var agent1 = requestp.agent(app)
like image 52
chovy Avatar answered Sep 29 '22 14:09

chovy