Skip to content

Commit f957246

Browse files
author
pierrezimmermann
committed
fix: do not use a real timeout in waitfor when using fake timers
1 parent 932c547 commit f957246

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

src/__tests__/waitFor.test.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,37 @@ test.each([false, true])(
204204
}
205205
);
206206

207+
const fibonaci = (n: number): number => {
208+
if (n === 0 || n === 1) {
209+
return 1;
210+
}
211+
212+
return fibonaci(n - 1) + fibonaci(n - 2);
213+
};
214+
215+
test.each([false, true])(
216+
'it should not depend on real time when using fake timers (legacyFakeTimers = %s)',
217+
async () => {
218+
jest.useFakeTimers({ legacyFakeTimers: false });
219+
220+
const mockErrorFn = jest.fn(() => {
221+
fibonaci(30);
222+
throw new Error('test');
223+
});
224+
225+
try {
226+
await waitFor(() => mockErrorFn(), {
227+
timeout: 200,
228+
interval: 5,
229+
});
230+
} catch (error) {
231+
// suppress
232+
}
233+
234+
expect(mockErrorFn).toHaveBeenCalledTimes(41);
235+
}
236+
);
237+
207238
test.each([false, true])(
208239
'awaiting something that succeeds before timeout works with fake timers (legacyFakeTimers = %s)',
209240
async (legacyFakeTimers) => {

src/waitFor.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function waitForInternal<T>(
3838
let finished = false;
3939
let promiseStatus = 'idle';
4040

41-
const overallTimeoutTimer = setTimeout(handleTimeout, timeout);
41+
let overallTimeoutTimer: NodeJS.Timeout | null = null;
4242

4343
const usingFakeTimers = jestFakeTimersAreEnabled();
4444

@@ -64,6 +64,7 @@ function waitForInternal<T>(
6464

6565
// when fake timers are used we want to simulate the interval time passing
6666
if (fakeTimeRemaining <= 0) {
67+
handleTimeout();
6768
return;
6869
} else {
6970
fakeTimeRemaining -= interval;
@@ -90,6 +91,7 @@ function waitForInternal<T>(
9091
await new Promise((resolve) => setImmediate(resolve));
9192
}
9293
} else {
94+
overallTimeoutTimer = setTimeout(handleTimeout, timeout);
9395
intervalId = setInterval(checkRealTimersCallback, interval);
9496
checkExpectation();
9597
}
@@ -98,7 +100,9 @@ function waitForInternal<T>(
98100
done: { type: 'result'; result: T } | { type: 'error'; error: unknown }
99101
) {
100102
finished = true;
101-
clearTimeout(overallTimeoutTimer);
103+
if (overallTimeoutTimer) {
104+
clearTimeout(overallTimeoutTimer);
105+
}
102106

103107
if (!usingFakeTimers) {
104108
clearInterval(intervalId);

0 commit comments

Comments
 (0)