Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

supertest agent doesn't seem to persist sessions in node.js express.js app

From all the documents and examples I've read, it should be possible to persist a session in supertest using an agent:

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

var user = {
    name: 'Sterling Archer',
    email: '[email protected]',
    password: 'guest'
};

describe('user.me', function() {

    var url = '/user';
    var agent = request.agent(app);
    var new_user = new User(user);
    new_user.save();

    it('should return a user object', function(done) {

        agent
            .post('/signin')
            .send(_.omit(user, 'name'))
            .expect(200).end(function(err, res) {
                console.log(res.headers['set-cookie']);
            });

        agent
            .get(url)
            .expect(200)
            .end(function(err, res) {
                should.not.exist(err);
                console.log(res.headers['set-cookie']);
                res.body.should.have.property('user');
                res.body.user.should.have.properties('name', 'email');
                done();
            });

    });
});

The session should persist since each request above is using the same agent. However that doesn't seem to be the case - the output from the set-cookie logs follows:

[ 'connect.sid=s%3AsFl1DQ4oOxC8MNAm79mnnr9q.gMkp8iEWtG8XlZZ2rkmheBwxKAyLyhixqDUOkYftwzA; Path=/; HttpOnly' ]
[ 'connect.sid=s%3AEzfbPyRGMff7yBXc9OAX3vGT.Ze2YoxZzuB6F6OwOk7mvrk96yPP2G4MGV%2Bt1rVjTyS8; Path=/; HttpOnly' ]

passport.js is being used for authentication and sessions. I would expect connect.sid above to be constant for both requests, but it looks like a new session is being created on each call so the agent isn't logged in on the second call and no user object is returned.

When I test my app manually in a browser connect.sid remains constant after login and the functionality I'm testing does work.

I must be doing something wrong with agent, and I'm hoping someone can spot it. Otherwise, suggestions on how I could debug the issue would be much appreciated.

like image 282
Matt Avatar asked Aug 31 '25 20:08

Matt


1 Answers

You're sending the second request without waiting for the first one to be responded; if you don't give the agent time to receive the Set-Cookie header in the response and use its value as a the Cookie header in the same request, a new session will be created. Try it this way:

it('should return a user object', function(done) {

    agent
        .post('/signin')
        .send(_.omit(user, 'name'))
        .expect(200).end(function(err, res) {
            console.log(res.headers['set-cookie']);
            agent
                .get(url)
                .expect(200)
                .end(function(err, res) {
                    should.not.exist(err);
                    console.log(res.headers['set-cookie']); // Should print nothing.
                    res.body.should.have.property('user');
                    res.body.user.should.have.properties('name', 'email');
                    done();
                });
        });
});
like image 70
Esteban Avatar answered Sep 04 '25 22:09

Esteban