To start, my stack :
- MongoDB Native
- NodeJS
- Express
- Mocha/Chai/Supertest
- Passport for auth
My error :
I have "Error: Timeout of 100000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.".
This error appears only on the signin.test.ts file, and only on the first test of my file.
Example :
if my first test is signin user :
and if my first test is an other test (for example, test "user does not exist") :
log test if other first test error
This error also appears only when my test db is remote (mongodb atlas url for the connection). If my db is local, I have no error.
My code :
db.ts
import { MongoClient, Db } from 'mongodb'
let defaultDbname = 'DBProd'
const options = {}
let url: any = process.env.MONGODB_URI
if (process.env.NODE_ENV === 'dev') {
url = process.env.MONGODB_URI
defaultDbname = 'DBDev'
}
if (process.env.NODE_ENV === 'test') {
url = process.env.MONGODB_URI_TEST
defaultDbname = 'DBTest'
}
const client = new MongoClient(url, options)
export let db: Db
export const connect = async (dbName: string = defaultDbname) => {
const conn = await client.connect()
db = conn.db(dbName)
console.log('Database connected')
return client
}
In app.ts, call connect()
import { connect } from './database/db'
connect()
....
Part of my tests in signin.test.ts :
describe('POST /api/authentication/signin', function () {
it('respond with 200, signin user', async function () {
const res = await request(app)
.post('/api/authentication/signin')
.send({
email: 'client@test.fr',
password: 'Password123456789*'
})
.set('Accept', 'application/json')
expect(res.statusCode).to.equal(200)
expect(res.body.isAuthenticated).to.equal(true)
expect(res.body.user.email).to.equal('client@test.fr')
expect(res.body).to.have.property('token').to.be.an('string')
})
it('respond with 400, user does not exist', async function () {
const res = await request(app)
.post('/api/authentication/signin')
.send({
email: 'email@ttee.fr',
password: 'Password123456789*'
})
.set('Accept', 'application/json')
expect(res.statusCode).to.equal(400)
expect(res.body.message).to.equal("L'utilisateur n'existe pas.")
})
......
Passport local strategy in passport.config.ts
passport.use('local', new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
}, (username, password, done) => {
if (!Validator.isValidEmail(username)) {
return done(null, false, { message: 'Le format de l\'email est incorrect.' })
}
if (!Validator.isValidPassword(password)) {
return done(null, false, { message: 'Votre mot de passe doit contenir au moins 8 caractères, une minuscule, une majuscule, un chiffre et un symbole spécial.' })
}
const getUser = async () => {
try {
const user = await db.collection('user').findOne({ email: username })
if (!user) {
return done(null, false, { message: 'L\'utilisateur n\'existe pas.' })
}
const userPassword = _.get(user, 'password')
const match = await comparePassword(password, userPassword)
if (match) {
done(null, user)
} else {
done(null, false, { message: 'Le mot de passe ne correspond pas.' })
}
} catch(err) {
throw err
}
}
getUser()
}))
signin.controller.ts
export const userSignIn = (req: Request, res: Response, next: NextFunction) => {
passport.authenticate('local', { session: false }, async (err, user, info) => {
if (err) {
next(err)
}
if (!user) {
return res.status(400).json({ message: info.message })
}
if (user) {
const { _id, email, role } = user
const token = signToken(_id)
res.status(200).json({
message: 'Authentification réussie.',
isAuthenticated: true,
user: {
email: email,
role: role
},
token
})
console.info('User signed in', user)
}
}
)(req, res)
}
PS: I have "--timeout 10000" in cmd line.