Fake timers with long delay fail
Prerequisites
- [X] I confirm my issue is not in the opened issues
- [X] I confirm the Frequently Asked Questions didn't contain the answer to my issue
Environment check
- [X] I'm using the latest
mswversion - [X] I'm using Node.js version 14 or higher
Node.js version
19.1.0
Reproduction repository
https://github.com/leepowelldev/msw-delay-bug
Reproduction steps
npm test
Current behavior
Currently, when using fake timers in jest, adding a long delay will result in the response not being resolved. Very short delays, seem to work, but I think this is more by luck.
The repo includes three tests, no delay, short delay and a long delay... the long delay fails. I believe this is down to this line https://github.com/mswjs/msw/blob/7380011de47460212065ca41be1b5a1c60ed1b98/src/node/SetupServerApi.ts#L91 using a real timer for the setTimeout. This causes jest's fake timers and the real timer to get out of sync.
Changing that line to use the faked global timeout (just for the delay!) allows us to advance any timers and have the promise resolve as expected.
if (response.delay) {
await new Promise((resolve) => {
globalThis.setTimeout(resolve, response.delay)
})
}
Obviously I don't have deep knoledge of this library (thats for BTW!) so am a bit uncertain of the concequenses of making this change. It may mean users of fake timers need to advance the timers when using a delay - but I would sort of expect this behaviour as it's consistent with other timers.
Happy to create a PR if needed.
Expected behavior
All tests to pass regardless of the delay duration.
Update - I did figure out a workaround is to use real timers to wait for the delay to complete... not ideal, but seems to work around the issue.
function wait(ms: number) {
return new Promise((resolve) => {
jest.requireActual('timers').setTimeout(resolve, ms);
});
}
Then in my test, wait for the delay duration to complete with real timers.
await act(() => wait(1000));