Skip to content
Merged
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: 1 addition & 3 deletions docs/config/faketimers.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ Mocking `nextTick` is not supported when running Vitest inside `node:child_proce
- **Type:** `('setTimeout' | 'clearTimeout' | 'setImmediate' | 'clearImmediate' | 'setInterval' | 'clearInterval' | 'Date' | 'nextTick' | 'hrtime' | 'requestAnimationFrame' | 'cancelAnimationFrame' | 'requestIdleCallback' | 'cancelIdleCallback' | 'performance' | 'queueMicrotask' | 'Intl' | 'Temporal')[]`
- **Default:** `[]`

An array with names of global methods and APIs to keep native. All other available timers will be mocked. For example, to keep `setInterval()` native and mock all other timers, specify this property as `['setInterval']`.

Mocking `nextTick` is not supported when running Vitest inside `node:child_process` by using `--pool=forks`. When running with `--pool=forks`, Vitest automatically adds `nextTick` to the `toNotFake` array.
An array of global methods and APIs to exclude from fake timers. Vitest always excludes `nextTick` and `queueMicrotask` when this option is used. To fake either API, use `toFake` instead.

::: warning
Using both `toFake` and `toNotFake` together is not supported.
Expand Down
8 changes: 8 additions & 0 deletions packages/vitest/src/integrations/mock/timers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ export class FakeTimers {
toFake = (Object.keys(this._fakeTimers.timers) as FakeMethod[])
.filter(timer => timer !== 'nextTick' && timer !== 'queueMicrotask')
}
else if (toFake === undefined && toNotFake !== undefined) {
// Do not mock timers internally used by node via `toNotFake`
for (const timer of ['nextTick', 'queueMicrotask'] as const) {
if (!toNotFake.includes(timer)) {
toNotFake = [...toNotFake, timer]
}
}
}
if (isChildProcess() && toNotFake && !toNotFake.includes('nextTick')) {
toNotFake = [...toNotFake, 'nextTick']
}
Expand Down
18 changes: 16 additions & 2 deletions test/unit/test/fixtures/timers.suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ describe('FakeTimers', () => {
expect(global.clearImmediate).toBe(origClearImmediate)
})

it.skipIf(isChildProcess)('mocks process.nextTick when toNotFake does not include nextTick', () => {
it.skipIf(isChildProcess)('does not mock process.nextTick when toNotFake is used without nextTick', () => {
const origNextTick = () => {}
const global = {
Date: FakeDate,
Expand All @@ -166,7 +166,21 @@ describe('FakeTimers', () => {
}
const timers = new FakeTimers({ global, config: { toNotFake: [] } })
timers.useFakeTimers()
expect(global.process.nextTick).not.toBe(origNextTick)
expect(global.process.nextTick).toBe(origNextTick)
})

it('does not mock queueMicrotask when toNotFake is used', () => {
const origQueueMicrotask = () => {}
const global = {
Date: FakeDate,
clearTimeout,
queueMicrotask: origQueueMicrotask,
setTimeout,
}
const timers = new FakeTimers({ global, config: { toNotFake: ['Temporal'] } })
timers.useFakeTimers()
expect(global.queueMicrotask).toBe(origQueueMicrotask)
expect(global.setTimeout).not.toBe(setTimeout)
})

it.runIf(isChildProcess)('does not mock process.nextTick when toNotFake does not include nextTick and is child_process', () => {
Expand Down
Loading