Skip to content

Commit 4452982

Browse files
Lei ChenLei Chen
Lei Chen
authored and
Lei Chen
committed
fix fakeTimer problem
add new fakeTimer test and revise the function add advanceTime revise the advanceTime
1 parent 4a03704 commit 4452982

File tree

4 files changed

+69
-7
lines changed

4 files changed

+69
-7
lines changed

src/__tests__/asyncHook.fakeTimers.test.ts

+35
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,41 @@ describe('async hook (fake timers) tests', () => {
5151

5252
expect(complete).toBe(true)
5353
})
54+
55+
test('should waitFor arbitrary expectation to pass when fake timers are not advanced explicitly', async () => {
56+
const fn = jest.fn().mockReturnValueOnce(false).mockReturnValueOnce(true)
57+
58+
const { waitFor } = renderHook(() => null)
59+
60+
await waitFor(() => {
61+
expect(fn()).toBe(true)
62+
})
63+
})
64+
65+
test('should reject if timeout is passed close to when promise resolves', async () => {
66+
const { waitFor } = renderHook(() => null)
67+
68+
let actual = 0
69+
const expected = 1
70+
71+
setTimeout(() => {
72+
actual = expected
73+
}, 101)
74+
75+
let complete = false
76+
77+
await expect(
78+
waitFor(
79+
() => {
80+
expect(actual).toBe(expected)
81+
complete = true
82+
},
83+
{ timeout: 100, interval: 50 }
84+
)
85+
).rejects.toThrow(Error('Timed out in waitFor after 100ms.'))
86+
87+
expect(complete).toBe(false)
88+
})
5489
})
5590
})
5691

src/core/asyncUtils.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ import {
77
AsyncUtils
88
} from '../types'
99

10-
import { createTimeoutController } from '../helpers/createTimeoutController'
10+
import { createTimeoutController, DEFAULT_TIMEOUT } from '../helpers/createTimeoutController'
1111
import { TimeoutError } from '../helpers/error'
1212

1313
const DEFAULT_INTERVAL = 50
14-
const DEFAULT_TIMEOUT = 1000
1514

1615
function asyncUtils(act: Act, addResolver: (callback: () => void) => void): AsyncUtils {
1716
const wait = async (callback: () => boolean | void, { interval, timeout }: WaitOptions) => {
@@ -20,11 +19,11 @@ function asyncUtils(act: Act, addResolver: (callback: () => void) => void): Asyn
2019
return callbackResult ?? callbackResult === undefined
2120
}
2221

23-
const timeoutSignal = createTimeoutController(timeout)
22+
const timeoutSignal = createTimeoutController(timeout, false)
2423

2524
const waitForResult = async () => {
2625
while (true) {
27-
const intervalSignal = createTimeoutController(interval)
26+
const intervalSignal = createTimeoutController(interval, true)
2827
timeoutSignal.onTimeout(() => intervalSignal.cancel())
2928

3029
await intervalSignal.wrap(new Promise<void>(addResolver))

src/helpers/createTimeoutController.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
import { WaitOptions } from '../types'
2+
import { jestFakeTimersAreEnabled } from './jestFakeTimersAreEnabled'
3+
const DEFAULT_TIMEOUT = 1000
24

3-
function createTimeoutController(timeout: WaitOptions['timeout']) {
5+
function createTimeoutController(
6+
timeout: WaitOptions['timeout'] = DEFAULT_TIMEOUT,
7+
allowFakeTimers: boolean
8+
) {
49
let timeoutId: NodeJS.Timeout
510
const timeoutCallbacks: Array<() => void> = []
611

12+
const advanceTime = async () => {
13+
jest.advanceTimersByTime(timeout as number)
14+
await Promise.resolve()
15+
}
716
const timeoutController = {
817
onTimeout(callback: () => void) {
918
timeoutCallbacks.push(callback)
@@ -19,12 +28,18 @@ function createTimeoutController(timeout: WaitOptions['timeout']) {
1928
timeoutCallbacks.forEach((callback) => callback())
2029
resolve()
2130
}, timeout)
31+
32+
if (jestFakeTimersAreEnabled() && allowFakeTimers) {
33+
advanceTime()
34+
}
2235
}
2336

2437
promise
2538
.then(resolve)
2639
.catch(reject)
27-
.finally(() => timeoutController.cancel())
40+
.finally(() => {
41+
timeoutController.cancel()
42+
})
2843
})
2944
},
3045
cancel() {
@@ -36,4 +51,4 @@ function createTimeoutController(timeout: WaitOptions['timeout']) {
3651
return timeoutController
3752
}
3853

39-
export { createTimeoutController }
54+
export { createTimeoutController, DEFAULT_TIMEOUT }
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const jestFakeTimersAreEnabled = () => {
2+
/* istanbul ignore else */
3+
if (typeof jest !== 'undefined' && jest !== null) {
4+
return (
5+
// legacy timers
6+
jest.isMockFunction(setTimeout) ||
7+
// modern timers
8+
Object.prototype.hasOwnProperty.call(setTimeout, 'clock')
9+
)
10+
}
11+
// istanbul ignore next
12+
return false
13+
}

0 commit comments

Comments
 (0)