Skip to content

Commit

Permalink
fix fakeTimer problem
Browse files Browse the repository at this point in the history
add new fakeTimer test and revise the function

add advanceTime

revise the advanceTime

use  jest.advanceTimersByTime

change timeout type

fix converage and revise type
  • Loading branch information
Lei Chen authored and Lei Chen committed Sep 9, 2021
1 parent 4a03704 commit ac1b559
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 6 deletions.
35 changes: 35 additions & 0 deletions src/__tests__/asyncHook.fakeTimers.test.ts
Expand Up @@ -51,6 +51,41 @@ describe('async hook (fake timers) tests', () => {

expect(complete).toBe(true)
})

test('should waitFor arbitrary expectation to pass when fake timers are not advanced explicitly', async () => {
const fn = jest.fn().mockReturnValueOnce(false).mockReturnValueOnce(true)

const { waitFor } = renderHook(() => null)

await waitFor(() => {
expect(fn()).toBe(true)
})
})

test('should reject if timeout is passed close to when promise resolves', async () => {
const { waitFor } = renderHook(() => null)

let actual = 0
const expected = 1

setTimeout(() => {
actual = expected
}, 101)

let complete = false

await expect(
waitFor(
() => {
expect(actual).toBe(expected)
complete = true
},
{ timeout: 100, interval: 50 }
)
).rejects.toThrow(Error('Timed out in waitFor after 100ms.'))

expect(complete).toBe(false)
})
})
})

Expand Down
6 changes: 3 additions & 3 deletions src/core/asyncUtils.ts
Expand Up @@ -10,8 +10,8 @@ import {
import { createTimeoutController } from '../helpers/createTimeoutController'
import { TimeoutError } from '../helpers/error'

const DEFAULT_INTERVAL = 50
const DEFAULT_TIMEOUT = 1000
const DEFAULT_INTERVAL = 50

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

const timeoutSignal = createTimeoutController(timeout)
const timeoutSignal = createTimeoutController(timeout as number | boolean, false)

const waitForResult = async () => {
while (true) {
const intervalSignal = createTimeoutController(interval)
const intervalSignal = createTimeoutController(interval as number | boolean, true)
timeoutSignal.onTimeout(() => intervalSignal.cancel())

await intervalSignal.wrap(new Promise<void>(addResolver))
Expand Down
10 changes: 7 additions & 3 deletions src/helpers/createTimeoutController.ts
@@ -1,6 +1,6 @@
import { WaitOptions } from '../types'
import { jestFakeTimersAreEnabled } from './jestFakeTimersAreEnabled'

function createTimeoutController(timeout: WaitOptions['timeout']) {
function createTimeoutController(timeout: number | boolean, allowFakeTimers: boolean) {
let timeoutId: NodeJS.Timeout
const timeoutCallbacks: Array<() => void> = []

Expand All @@ -18,7 +18,11 @@ function createTimeoutController(timeout: WaitOptions['timeout']) {
timeoutController.timedOut = true
timeoutCallbacks.forEach((callback) => callback())
resolve()
}, timeout)
}, timeout as number)

if (jestFakeTimersAreEnabled() && allowFakeTimers) {
jest.advanceTimersByTime(timeout as number)
}
}

promise
Expand Down
13 changes: 13 additions & 0 deletions src/helpers/jestFakeTimersAreEnabled.ts
@@ -0,0 +1,13 @@
export const jestFakeTimersAreEnabled = () => {
/* istanbul ignore else */
if (typeof jest !== 'undefined' && jest !== null) {
return (
// legacy timers
jest.isMockFunction(setTimeout) ||
// modern timers
Object.prototype.hasOwnProperty.call(setTimeout, 'clock')
)
}
// istanbul ignore next
return false
}

0 comments on commit ac1b559

Please sign in to comment.