You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have a test suite that uses Jest. When I use the default memory session storage, all my tests work fine. When I upgraded to this package for session storage, a bunch of the tests broke. However, with manual testing everything is still working as designed.
I inserted a bunch of console.log calls everywhere and I've narrowed the problem down to when I call the req.login function in my route (simplified example code):
The test looks something like this:
constrequest=require('supertest')beforeAll(async()=>{// Make the connection using my database handlerdb.connect()})test('Sets a cookie and redirects to / after logging in.',async()=>{// This is a synchronous function that just returns an object with keys `id` and `password`constnewCredentials=newValidUserCredentials()// An asynchronous function that creates this user in the database for testingawaitprocessNewUserRegistrationData(newCredentials)constagent=request.agent(app)awaitagent.post('/login').send(newCredentials).expect(302).expect('set-cookie',/sessionID=/).expect('Location','/').then(async(resp)=>{// Shows the 'set-cookie' field when using MemoryStore, but when using MySQLStore it never even console.logsconsole.log(resp.header)// It is important to access the cookie here so I can call `agent` again in tests that require authentication})})afterAll(async()=>{// Close the connection using my database handlerdb.close()})
The route is setup something like this:
loginRouter.post('/',someMiddleware(req,res,next),asyncfunctionauthenticateMiddleware(req,res,next){awaitpassport.authenticate('local',async(err,user,errorMessage)=>{if(errorMessage){// Do some error event logging stuff// ...returnres.render('pages/login',{failureMessage:
'Unable to authenticate with that email and password combination'})}console.log('SUCCESSFULLY AUTHENTICATED:',user)// There is an existing user, and this user has successfully authenticated. Log them in.console.log('LOGGING IN USER')req.login(user,(error)=>{console.log('OPERATING INSIDE THE LOGIN CALLBACK FUNCTION NOW...')// Do some event logging stuff// ...returnnext()})})(req,res,next)},moreMiddleware(req,res,next),(req,res)=>{console.log('FINAL REQUEST COOKIE IN HEADER:',req.headers.cookie)res.redirect('/')})
The app.js has a session store configuration like this.
// ...app.use(session({store: newMySQLStore({host: config.EXPRESS_HOST,port: config.DATABASE_PORT,user: config.DATABASE_USER,password: config.DATABASE_PASSWORD,database: config.DATABASE_NAME,createDatabaseTable: false,clearExpired: true,checkExpirationInterval: 900*1000,schema: {tableName: 'SESSIONS',columnNames: {session_id: 'SESSION_ID',expires: 'EXPIRES',data: 'DATA'}}}),name: 'sessionID',secret: config.EXPRESS_SESSION_SECRET,resave: false,saveUninitialized: false,rolling: true,cookie: {secure: false,// Dev environments on 'localhost' run on http so secure won't work. Set to true on the production serverhttpOnly: true,domain: config.EXPRESS_HOST,maxAge: config.EXPRESS_SESSION_LIMIT_DAYS*24*60*60*1000}})// ...// ...
Commenting out the store key reverts Express to using the MemoryStore method and the test works again with all console.log statements outputting as expected.
When the MySQLStore store is used during the test, it console logs all the way up to LOGGING IN USER, then nothing. The test then fails with the error
thrown: "Exceeded timeout of 5000 ms for a test.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."
as well as telling me
A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --detectOpenHandles to find leaks. Active timers can also cause this, ensure that .unref() was called on them.
Expected Behavior
The test should successfully complete just like the MemoryStore test does. If this is not possible, there should be documentation to show how to test the functionality works as desired.
I am not familiar with supertest, but it looks like your beforeAll and afterAll hooks aren't waiting for db.connect to finish. The database connection is synchronous when using the memory store, but asynchronous when using MySQL store.
Current Behavior
I have a test suite that uses Jest. When I use the default memory session storage, all my tests work fine. When I upgraded to this package for session storage, a bunch of the tests broke. However, with manual testing everything is still working as designed.
I inserted a bunch of
console.log
calls everywhere and I've narrowed the problem down to when I call thereq.login
function in my route (simplified example code):The test looks something like this:
The route is setup something like this:
The
app.js
has a session store configuration like this.Commenting out the
store
key reverts Express to using the MemoryStore method and the test works again with allconsole.log
statements outputting as expected.When the
MySQLStore
store is used during the test, it console logs all the way up toLOGGING IN USER
, then nothing. The test then fails with the erroras well as telling me
Expected Behavior
The test should successfully complete just like the MemoryStore test does. If this is not possible, there should be documentation to show how to test the functionality works as desired.
Cross reference to Stack Overflow post: Express App Test Suite with Supertest Breaks when switching from MemoryStore to express-mysql-session
The text was updated successfully, but these errors were encountered: