supertest агентът изглежда не продължава сесиите в приложението node.js express.js

От всички документи и примери, които прочетох, трябва да е възможно да се поддържа сесия в супертест с помощта на агент:

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();
            });

    });
});

Сесията трябва да продължи, тъй като всяка заявка по-горе използва един и същ агент. Това обаче изглежда не е така - изходът от регистрационните файлове на set-cookie следва:

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

passport.js се използва за удостоверяване и сесии. Бих очаквал connect.sid по-горе да бъде постоянен и за двете заявки, но изглежда, че се създава нова сесия при всяко повикване, така че агентът не е влязъл при второто повикване и не се връща потребителски обект.

Когато тествам приложението си ръчно в браузър, connect.sid остава постоянен след влизане и функционалността, която тествам, работи.

Сигурно правя нещо нередно с агента и се надявам някой да го забележи. В противен случай предложения за това как мога да отстраня проблема ще бъдат много оценени.


person Matt    schedule 03.04.2014    source източник
comment
.set('Cookie',<sid>) метод при второ повикване на агент, работи ли?   -  person Gntem    schedule 04.04.2014
comment
Бях се опитал да настроя бисквитката, защото бях виждал този подход в някои други примери. Въпреки това не би трябвало да е необходимо и така или иначе не работи; set() ще бъде извикан на втория агент преди първото извикване да завърши (така че стойността на бисквитката все още няма да е налична.)   -  person Matt    schedule 07.04.2014


Отговори (2)


Изпращате втората заявка, без да чакате отговор на първата; ако не дадете време на агента да получи заглавката Set-Cookie в отговора и да използва неговата стойност като заглавка Cookie в същата заявка, ще бъде създадена нова сесия. Опитайте по този начин:

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();
                });
        });
});
person Esteban    schedule 04.04.2014
comment
Вашето предложение не проработи, но посочихте, че съм пренебрегнал асинхронния характер на кода. Бях опитвал това веднъж преди; въпреки че сега разбирам по-добре какво се случва, не разбирам защо и това не работи! Отново се регистрират различни бисквитки (дори когато сте коментирали, че не трябва да отпечатва нищо.) Въпреки това намерих решение, вижте по-долу. - person Matt; 04.04.2014

Предложението на Естебан посочи, че пренебрегвам асинхронния характер на кода. Връщайки се към този пример разбрах, че съм пропуснал значението на влизането в отделен тест; това реши проблема ми.

Въпреки че сега създавам зависими тестове, по които не съм луд.

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();
});
});
person Matt    schedule 04.04.2014
comment
Страхотно е, че това работи! Мисля, че знам защо това проработи, но нямам време да го тествам точно сега, за съжаление (подсказка: когато end извиква вашето обратно извикване, агентът не е приключил с управлението на set-cookie заглавката). Бих подобрил вашето решение, като хвърлям данните за влизане във функция before вместо различен тест (въпреки че тестването на влизане все още е добра идея). - person Esteban; 08.04.2014
comment
Току-що открих, че сте жертва на тази грешка. За щастие е издадена заявка за изтегляне, за да се поправи. - person Esteban; 10.04.2014