Skip to content

feat: add advanceTimers option #1402

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/__tests__/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ describe('configuration API', () => {

describe('RTL options', () => {
test('configure can set by a plain JS object', () => {
configure({reactStrictMode: true})
const advanceTimers = jest.fn()
configure({reactStrictMode: true, advanceTimers})

expect(getConfig().reactStrictMode).toBe(true)
expect(getConfig().advanceTimers).toBe(advanceTimers)
})

test('configure can set by a function', () => {
Expand Down
24 changes: 23 additions & 1 deletion src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,29 @@ import {
configure as configureDTL,
} from '@testing-library/dom'

function jestFakeTimersAreEnabled() {
/* istanbul ignore else */
if (typeof jest !== 'undefined' && jest !== null) {
return (
// legacy timers
setTimeout._isMockFunction === true || // modern timers
// eslint-disable-next-line prefer-object-has-own -- No Object.hasOwn in all target environments we support.
Object.prototype.hasOwnProperty.call(setTimeout, 'clock')
)
} // istanbul ignore next

return false
}

function maybeAdvanceJestTimers(delay) {
if (jestFakeTimersAreEnabled()) {
jest.advanceTimersByTime(delay)
}
}

let configForRTL = {
reactStrictMode: false,
advanceTimers: maybeAdvanceJestTimers,
}

function getConfig() {
Expand All @@ -21,13 +42,14 @@ function configure(newConfig) {
newConfig = newConfig(getConfig())
}

const {reactStrictMode, ...configForDTL} = newConfig
const {reactStrictMode, advanceTimers, ...configForDTL} = newConfig

configureDTL(configForDTL)

configForRTL = {
...configForRTL,
reactStrictMode,
advanceTimers,
}
}

Expand Down
20 changes: 2 additions & 18 deletions src/pure.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,6 @@ import act, {
import {fireEvent} from './fire-event'
import {getConfig, configure} from './config'

function jestFakeTimersAreEnabled() {
/* istanbul ignore else */
if (typeof jest !== 'undefined' && jest !== null) {
return (
// legacy timers
setTimeout._isMockFunction === true || // modern timers
// eslint-disable-next-line prefer-object-has-own -- No Object.hasOwn in all target environments we support.
Object.prototype.hasOwnProperty.call(setTimeout, 'clock')
)
} // istanbul ignore next

return false
}

configureDTL({
unstable_advanceTimersWrapper: cb => {
return act(cb)
Expand All @@ -42,14 +28,12 @@ configureDTL({
// Drain microtask queue.
// Otherwise we'll restore the previous act() environment, before we resolve the `waitFor` call.
// The caller would have no chance to wrap the in-flight Promises in `act()`
await new Promise(resolve => {
await new Promise(async resolve => {
setTimeout(() => {
resolve()
}, 0)

if (jestFakeTimersAreEnabled()) {
jest.advanceTimersByTime(0)
}
await getConfig().advanceTimers(0)
})

return result
Expand Down
6 changes: 6 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export * from '@testing-library/dom'

export interface Config extends ConfigDTL {
reactStrictMode: boolean
/**
* A function to be called internally to advance your fake timers (if applicable)
*
* @example jest.advanceTimersByTime
*/
advanceTimers?: ((delay: number) => Promise<void>) | ((delay: number) => void)
}

export interface ConfigFn {
Expand Down
Loading