Skip to content

Commit 233b57f

Browse files
committed
Use same interval handler in all supported clocks
1 parent ff84a50 commit 233b57f

File tree

2 files changed

+32
-27
lines changed

2 files changed

+32
-27
lines changed

src/__tests__/wait-for.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ test('if you switch from fake timers to real timers during the wait period you g
207207
const error = await waitForError
208208

209209
expect(error.message).toMatchInlineSnapshot(
210-
`Changed from using fake timers to real timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to real timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830`,
210+
`Changed from using fake timers to real timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing what timers your test is using. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830`,
211211
)
212212
// stack trace has this file in it
213213
expect(error.stack).toMatch(__dirname)
@@ -223,7 +223,7 @@ test('if you switch from real timers to fake timers during the wait period you g
223223
const error = await waitForError
224224

225225
expect(error.message).toMatchInlineSnapshot(
226-
`Changed from using real timers to fake timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to fake timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830`,
226+
`Changed from using real timers to fake timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing what timers your test is using. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830`,
227227
)
228228
// stack trace has this file in it
229229
expect(error.stack).toMatch(__dirname)

src/wait-for.js

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,26 @@ function waitFor(
4343
}
4444

4545
return new Promise(async (resolve, reject) => {
46-
let lastError, intervalId, observer
46+
let lastError, observer
4747
let finished = false
4848
let promiseStatus = 'idle'
4949

50-
const overallTimeoutTimer = setTimeout(handleTimeout, timeout)
50+
const overallTimeout = setTimeout(handleTimeout, timeout)
51+
const intervalId = setInterval(handleInterval, interval)
5152

52-
const usingJestFakeTimers = jestFakeTimersAreEnabled()
53-
if (usingJestFakeTimers) {
53+
const wasUsingJestFakeTimers = jestFakeTimersAreEnabled()
54+
if (wasUsingJestFakeTimers) {
5455
checkCallback()
5556
// this is a dangerous rule to disable because it could lead to an
5657
// infinite loop. However, eslint isn't smart enough to know that we're
5758
// setting finished inside `onDone` which will be called when we're done
5859
// waiting or when we've timed out.
5960
// eslint-disable-next-line no-unmodified-loop-condition
6061
while (!finished) {
61-
if (!jestFakeTimersAreEnabled()) {
62-
const error = new Error(
63-
`Changed from using fake timers to real timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to real timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830`,
64-
)
65-
if (!showOriginalStackTrace) copyStackTrace(error, stackTraceError)
62+
try {
63+
// jest.advanceTimersByTime will not throw if
64+
ensureInvariantTimers()
65+
} catch (error) {
6666
reject(error)
6767
return
6868
}
@@ -73,12 +73,6 @@ function waitFor(
7373
// by an interval instead. (We have a test for this case).
7474
jest.advanceTimersByTime(interval)
7575

76-
// It's really important that checkCallback is run *before* we flush
77-
// in-flight promises. To be honest, I'm not sure why, and I can't quite
78-
// think of a way to reproduce the problem in a test, but I spent
79-
// an entire day banging my head against a wall on this.
80-
checkCallback()
81-
8276
// In this rare case, we *need* to wait for in-flight promises
8377
// to resolve before continuing. We don't need to take advantage
8478
// of parallelization so we're fine.
@@ -96,19 +90,18 @@ function waitFor(
9690
reject(e)
9791
return
9892
}
99-
intervalId = setInterval(checkRealTimersCallback, interval)
10093
const {MutationObserver} = getWindowFromNode(container)
101-
observer = new MutationObserver(checkRealTimersCallback)
94+
observer = new MutationObserver(handleInterval)
10295
observer.observe(container, mutationObserverOptions)
10396
checkCallback()
10497
}
10598

10699
function onDone(error, result) {
107100
finished = true
108-
clearTimeout(overallTimeoutTimer)
101+
clearTimeout(overallTimeout)
102+
clearInterval(intervalId)
109103

110-
if (!usingJestFakeTimers) {
111-
clearInterval(intervalId)
104+
if (observer !== undefined) {
112105
observer.disconnect()
113106
}
114107

@@ -119,15 +112,27 @@ function waitFor(
119112
}
120113
}
121114

122-
function checkRealTimersCallback() {
123-
if (jestFakeTimersAreEnabled()) {
115+
function ensureInvariantTimers() {
116+
const isUsingJestFakeTimers = jestFakeTimersAreEnabled()
117+
if (wasUsingJestFakeTimers !== isUsingJestFakeTimers) {
124118
const error = new Error(
125-
`Changed from using real timers to fake timers while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing to fake timers. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830`,
119+
`Changed from using ${
120+
wasUsingJestFakeTimers ? 'fake timers' : 'real timers'
121+
} to ${
122+
isUsingJestFakeTimers ? 'fake timers' : 'real timers'
123+
} while using waitFor. This is not allowed and will result in very strange behavior. Please ensure you're awaiting all async things your test is doing before changing what timers your test is using. For more info, please go to https://github.com/testing-library/dom-testing-library/issues/830`,
126124
)
127125
if (!showOriginalStackTrace) copyStackTrace(error, stackTraceError)
128-
return reject(error)
129-
} else {
126+
throw error
127+
}
128+
}
129+
130+
function handleInterval() {
131+
try {
132+
ensureInvariantTimers()
130133
return checkCallback()
134+
} catch (error) {
135+
return reject(error)
131136
}
132137
}
133138

0 commit comments

Comments
 (0)