Skip to content

Commit 167a98d

Browse files
authoredFeb 18, 2025··
fix: exclude queueMicrotask from default fake timers to not break node fetch (#7505)
1 parent 6cc408d commit 167a98d

File tree

4 files changed

+32
-5
lines changed

4 files changed

+32
-5
lines changed
 

‎docs/api/vi.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -818,8 +818,8 @@ Mocking `nextTick` is not supported when running Vitest inside `node:child_proce
818818
The implementation is based internally on [`@sinonjs/fake-timers`](https://github.com/sinonjs/fake-timers).
819819

820820
::: tip
821-
`vi.useFakeTimers()` does not automatically mock `process.nextTick`.
822-
But you can enable it by specifying the option in `toFake` argument: `vi.useFakeTimers({ toFake: ['nextTick'] })`.
821+
`vi.useFakeTimers()` does not automatically mock `process.nextTick` and `queueMicrotask`.
822+
But you can enable it by specifying the option in `toFake` argument: `vi.useFakeTimers({ toFake: ['nextTick', 'queueMicrotask'] })`.
823823
:::
824824

825825
### vi.isFakeTimers {#vi-isfaketimers}

‎docs/config/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2345,7 +2345,7 @@ Installs fake timers with the specified Unix epoch.
23452345
#### fakeTimers.toFake
23462346

23472347
- **Type:** `('setTimeout' | 'clearTimeout' | 'setImmediate' | 'clearImmediate' | 'setInterval' | 'clearInterval' | 'Date' | 'nextTick' | 'hrtime' | 'requestAnimationFrame' | 'cancelAnimationFrame' | 'requestIdleCallback' | 'cancelIdleCallback' | 'performance' | 'queueMicrotask')[]`
2348-
- **Default:** everything available globally except `nextTick`
2348+
- **Default:** everything available globally except `nextTick` and `queueMicrotask`
23492349

23502350
An array with names of global methods and APIs to fake.
23512351

‎packages/vitest/src/integrations/mock/timers.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ export class FakeTimers {
153153

154154
if (!this._fakingTime) {
155155
const toFake = Object.keys(this._fakeTimers.timers)
156-
// Do not mock nextTick by default. It can still be mocked through userConfig.
156+
// Do not mock timers internally used by node by default. It can still be mocked through userConfig.
157157
.filter(
158-
timer => timer !== 'nextTick',
158+
timer => timer !== 'nextTick' && timer !== 'queueMicrotask',
159159
) as (keyof FakeTimerWithContext['timers'])[]
160160

161161
if (this._userConfig?.toFake?.includes('nextTick') && isChildProcess()) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { expect, onTestFinished, test, vi } from 'vitest'
2+
3+
test(`node fetch works without fake timers`, async () => {
4+
expect(await Response.json('ok').json()).toBe('ok')
5+
})
6+
7+
test(`node fetch works with fake timers`, async () => {
8+
vi.useFakeTimers()
9+
onTestFinished(() => {
10+
vi.useRealTimers()
11+
})
12+
expect(await Response.json('ok').json()).toBe('ok')
13+
})
14+
15+
// skipped since this might cause a weird OOM on CI
16+
test.skip(`node fetch timeouts with fake queueMicrotask`, async () => {
17+
vi.useFakeTimers({ toFake: ['queueMicrotask'] })
18+
onTestFinished(() => {
19+
vi.useRealTimers()
20+
})
21+
expect(
22+
await Promise.race([
23+
new Promise(r => setTimeout(() => r('timeout'), 200)),
24+
Response.json('ok').json(),
25+
]),
26+
).toBe('timeout')
27+
})

0 commit comments

Comments
 (0)
Please sign in to comment.