Jest.js Cookie在超级测试/超级代理测试中持续存在,但用户不保持登录状态

qgelzfjb  于 2023-04-10  发布在  Jest
关注(0)|答案(2)|浏览(153)

我的目标

我尝试在jest beforeEach()中使用supertest的agent函数在每次测试之前登录用户,因为我希望每个测试都在假设用户已登录的情况下运行。

这是我尝试的(为了简洁起见,部分内容被删除):

测试文件:

import { agent, SuperAgentTest } from 'supertest';
import app from '../../src/app';

// create a `testRequest` variable to use in the tests
// that will be refreshed in between
let testRequest: SuperAgentTest;

const fakeUser = { email: 'john@john', username: 'john', password: 'john' };

beforeEach(async () => {
  // create new agent
  testRequest = agent(app);

  // register and login
  await testRequest.post('/register').send(fakeUser).expect(302);

  // other irrelevant stuff...
});

// protected route
describe('POST /campgrounds/new', () => {
  it('returns 200 OK', () => {
    return testRequest.get('/campgrounds/new');
  })
});

/register路由:

router.post('/register', async (req, res) => {
  const { password, ...details } = req.body;
  try {
    // I am using passport-local-mongoose for this function-
    // it just registers the user
    const user = await User.register(new User(details), password);
    req.login(user, (err) => {
      // error handling and redirect
    });
  } catch (e) {
    // error handling
  }
})

这是我的成果

我得到的不是200状态,而是302状态,这意味着我被重定向到登录页面。为了调试这个,我创建了一个名为/current的测试路由,它将记录当前用户和会话ID cookie。然后我分别在itbeforeEach函数中向这个路由发送GET请求。
有趣的是,它们都记录了相同的会话ID,但只有beforeEach中的请求具有附加到请求的用户对象。

j9per5c4

j9per5c41#

#1确保body解析器顺序正确

确保你在任何路由或与auth-related的东西之前有这个。

app.use(express.json())

#2检查Passport中间件连线

确保在任何app.use('/', aRouter)router.getrouter.post等之前调用app.use(passport.initialize())app.use(passport.session())

// Set up session w/ specific config
app.use(session({
  secret: 'bquyqueajhbd',
  resave: true,
  saveUninitialized: true,
  store: new FileStore({path: '/tmp/session'})
}));
// Wire up the 
app.use(passport.initialize())
app.use(passport.session())

编辑:req.user的注意事项

Passport设计用于在会话中存储用户ID。
每个对服务器的请求都必须从数据库中重新加载用户,这是中间件passport.initialize()passport.session()的工作。
这里的逻辑将调用passport.deserializeUser来按ID查找用户,该ID与passport.serializeUser登录会话时保存的ID相同。

passport.serializeUser(function(user, done) {
  done(null, user.id); // <-- Here's where the ID is saved to session.
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user); // <-- Here is where the `req.user` get's it's value from.
  });
});

为了调试这个问题,我将重点放在passport.deserializeUser回调上,在DB查询前后添加日志。
(Note:我已经有几年没有教过这个了。如果我没有使用精确的术语,请道歉,等等。)

djmepvbi

djmepvbi2#

首先,要理解supertest包不附带会话管理,这是你面临的挑战。另外,还有一个supertest-session可以用来管理会话。

// dependencies
const request = require('supertest')
const session = require('supertest-session)
const app = require('../app')
const { describe, expect, test, beforeAll, afterAll } = 
require('@jest/globals)

describe('UserController', () => {
let server;
let testSession;

beforeAll(() => {
    server = app.listen(3000);
    testSession = session(app);
})

afterAll((done) => {
    testSession.destroy();
    server.close();
})

describe('POST /user', () => {
    test('respons with 200 and success object with user data', async () => {
        const res = await request(app).post('/api/v1/login').send({ username: 'bruce', password: 'helloworld' })
        /**
        * now once your session is set well using express-session,
        * you can get the set-cokie hey on the response header sent
        */
        // get the session id from the cookies
        testSession = res.headers['set-cookie']

        // now you have session availble in testSession and can be userd like this
        const res1 = await request(app).post('api/v1/update-profile').set('Cookie', `sessionId=${testSession.sessionId}`)

        expect(res1.statusCode).toBe(200)

    })
})

})

相关问题