request.cookies не определен при использовании Supertest

Я передаю свой токен аутентификации через файл cookie только для HTTP в моем NestJS API.

Таким образом, при написании некоторых тестов E2E для моих конечных точек Auth у меня возникает проблема с файлами cookie, которые находятся не там, где я их ожидал.

Вот мой упрощенный тестовый код:

describe('auth/logout', () => {
  it('should log out a user', async (done) => {
    // ... code to create user account

    const loginResponse: Response = await request(app.getHttpServer())
                                              .post('/auth/login')
                                              .send({ username: newUser.email, password });

    // get cookie manually from response.headers['set-cookie']
    const cookie = getCookieFromHeaders(loginResponse);

    // Log out the new user
    const logoutResponse: Response = await request(app.getHttpServer())
                                            .get('/auth/logout')
                                            .set('Cookie', [cookie]);

  });
});

В своей стратегии JWT я использую собственный синтаксический анализатор файлов cookie. У меня проблема в том, что request.cookies всегда undefined, когда доходит до парсера. Однако файл cookie будет присутствовать в request.headers.

Я следую примеру файла cookie вручную из этой статьи на Medium: https://medium.com/@juha.a.hytonen/testing-authenticated-requests-with-supertest-325ccf47c2bb, и, похоже, нет никаких других методов, доступных для объекта запроса для установить куки.

Если я протестирую ту же функциональность в Postman, все работает, как ожидалось. Что я делаю неправильно?


person Brandon    schedule 01.02.2020    source источник
comment
Вы используете Fastify? В таком случае вам необходимо зарегистрировать FastifyCookies еще при создании тестового приложения.   -  person Andre C    schedule 01.06.2020
comment
Нет, я не подаю в суд на Fastify   -  person Brandon    schedule 01.06.2020


Ответы (2)


Я знаю, что это старая ветка, но ...

Еще у меня req.cookies undefined, но по другой причине.

Я тестирую свой роутер самостоятельно, а не приложение верхнего уровня. Поэтому я загружаю приложение в beforeEach и добавляю маршрут для тестирования.

Я получал req.cookies undefined, потому что экспресс 4 требует наличия промежуточного программного обеспечения cookieParser для анализа файлов cookie из заголовков.

E.g.


const express           = require('express');
const bodyParser        = require('body-parser');
const cookieParser      = require('cookie-parser');
const request           = require('supertest');

const {router}  = require('./index');

describe('router', () => {
    let app;    
    
    beforeAll(() => {        
        app  = express();
        app.use(bodyParser.json());
        app.use(bodyParser.urlencoded({ extended: true }));
        app.use(cookieParser());
        app.use('/', router);
    });

    beforeEach(() => jest.clearAllMocks());

    it('GET to /', async () => {
        const jwt = 'qwerty-1234567890';
        
        const resp = await request(app)
            .get('/')
            .set('Cookie', `jwt=${jwt};`)
            .set('Content-Type', 'application/json')
            .send({});        
    });
    
});

Такое тестирование позволяет мне проводить модульное тестирование маршрутизатора изолированно от приложения. Req.cookies появляются, как и ожидалось.

person GetafixIT    schedule 08.07.2020
comment
Извините за медленный ответ, я уже некоторое время болею. Большое спасибо за пост, я должен попробовать. - person Brandon; 15.07.2020

Согласно статье, которую вы читаете, код на https://medium.com/@juha.a.hytonen/testing-authenticated-requests-with-supertest-325ccf47c2bb:
1) имеет значение cookie в .set('cookie', cookie) в нижнем регистре и в вашем кодируйте его в регистре Pascal ==> Вы пробовали использовать строчные буквы в своем коде вместо этого?
2) значение cookie, присвоенное заголовку cookie, не является array, тогда как в вашем коде вы назначаете массив ==> Пробовали ли вы использовать значение, отличное от массива?

Итак, чтобы продолжить, можете ли вы попробовать следующий код:

describe('auth/logout', () => {
  it('should log out a user', async (done) => {
    // ... code to create user account

    const loginResponse: Response = await request(app.getHttpServer())
                                              .post('/auth/login')
                                              .send({ username: newUser.email, password });

    // get cookie manually from response.headers['set-cookie']
    const cookie = getCookieFromHeaders(loginResponse);

    // Log out the new user
    const logoutResponse: Response = await request(app.getHttpServer())
                                            .get('/auth/logout')
                                            .set('cookie', cookie) // <== here goes the diff
                                            .expect(200, done);

  });
});

Сообщите нам, если это поможет :)

person A. Maitre    schedule 03.02.2020
comment
Привет. Приношу свои извинения за очень поздний ответ. Да, я ранее пытался уменьшить значение в нижнем регистре и использовать значение, не являющееся массивом, но файл cookie все равно оказался заголовком, а не в коллекции request.cookies. Чтобы обойти это, я добавил экстрактор для извлечения токена из заголовка в качестве запасного варианта в моей стратегии Passport. - person Brandon; 07.02.2020