Description
Relevant code or config:
const {waitFor} = require('@testing-library/dom')
beforeEach(() => jest.useFakeTimers())
afterEach(() => jest.useRealTimers())
test('example', async () => {
const doAsyncThing = () =>
new Promise((r) => setTimeout(() => r('data'), 300))
let result
doAsyncThing().then((r) => (result = r))
await waitFor(() => expect(result).toBe('data'))
})
What you did:
I expected waitFor
to work even with jest fake timers enabled
What happened:
It times out because there's nothing telling jest to advance timers
Reproduction:
https://github.com/kentcdodds/testing-library-fake-timers
Problem description:
When enabling fake timers with DOM Testing Library, the waitFor
utility doesn't work (so none of the other async utils will either). The reason for this is there's nothing telling the clock to advance the timers.
Suggested solution:
I'm pretty sure we actually do want the async utils to work seamlessly when fake timers are enabled.
Here's a waitFor
function that will work only if fake timers are enabled. Maybe we can detect fake timers (we already have a function for this) and if they're enabled, then we could do this instead?
async function waitForWithFakeTimers(cb) {
let waiting = true
while (waiting) {
await act(() =>
Promise.resolve()
.then(() => jest.runAllTimers())
.then(() => new Promise(resolve => setImmediate(resolve))),
)
try {
cb()
waiting = false
} catch {}
}
}
It's pretty basic, it doesn't support timeout etc. But it's a good start.
Mostly, I'm looking for feedback. Should we do something like this if fake timers are enabled? Or is there another approach we can take?