I am trying to test a bit of nodejs code that does the following (Connector
is an eventEmitter
) using jest
async () => {
let initialisationComplete = false;
while (!initialisationComplete) {
await new Promise (accept => {
const initialConnection = new Connector();
initialConnection.once('connect',err => {
if(err) {
accept();
} else {
initialisationComplete = true;
.... //go on to do some other async stuff before calling accept()
}
});
initialConnection.connect();
});
if (!initialisationComplete) {
await new Promise(accept => setTimeout(accept, 10000));
}
}
}
I have mocked the complete module to contains the connector and can essentially get an event emitted to me when a Connector.connect() is called, which enables me to then emit the "connect" event back.
I have told jest
to use fakeTimers, and I want to test the error condition to show that in an error scenario, we get a ten second delay and then a retry
My test code is essentially this:-
err = {
toString: () => 'testing'
}
connection.emit('connect', err);
console.log('before promise resolve')
Promise.resolve().then(() => {
jest.runAllTimers();
}); //we have to allow for the promise to resolve before we can run the timers forward
The problem I have is that I am calling jest.runAllTimers before the test code has a chance to setup the 10 second timeout, so my test fails because the timeout never happens and the test itself times out.
My argument is that in the synchronous code that gets executed as a result of connection.emit('connect',err)
causes the code under test to resolve the promise in the loop. I then call Promise.resolve().then(...
I would have thought that the "accepted" Promise should already be on the promise processing queue when I call Promise.resolve()
in the test, so its resolution should follow.
However lots of console.logs
show the accept()
gets called first, then Promise.resolve()
in the test gets called, BUT, the then(() => jest.runAllTimers())
gets called next AND then the code after Promise
in the while
loop gets called (which then calls the setTimeout
Firstly I don't now why its like that rather than the Promise.resolve().then
. Is it perhaps because the promise gets resolved and then the await
has to be rescheduled?
Secondly - is there a way I can somehow delay (bearing in mind I cannot use timers)?