Reputation: 1059
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.
Upvotes: 4
Views: 7227
Reputation: 1059
Esteban's suggestion pointed out that I was overlooking the asynchronous nature of the code. Going back to this example I realized I missed the significance of logging in in a separate test; doing so solved my problem.
Though I'm now creating dependent tests, which I'm not crazy about.
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'
};
var agent = request.agent(app);
describe('User Controller', function() {
before(function(done) {
var new_user = new User(user);
new_user.save();
done();
});
describe('user.signin', function() {
var url = '/signin';
it('should signin and return a user object', function(done) {
agent
.post(url)
.send(_.omit(user, 'name'))
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.have.property('user');
res.body.user.should.have.properties('name', 'email');
done();
});
});
});
describe('user.me', function() {
var url = '/user';
it('should return a user object', function(done) {
agent
.get(url)
.expect(200)
.end(function(err, res) {
should.not.exist(err);
res.body.should.have.property('user');
res.body.user.should.have.properties('name', 'email');
done();
});
});
});
after(function(done) {
User.remove().exec();
done();
});
});
Upvotes: 2
Reputation: 2579
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();
});
});
});
Upvotes: 4