Skip to content

Commit 40187bd

Browse files
feat: add runAllTimersAsync from sinonjs (#2209)
close #1804
1 parent 6145d7b commit 40187bd

File tree

4 files changed

+501
-0
lines changed

4 files changed

+501
-0
lines changed

docs/api/index.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2553,6 +2553,19 @@ Vitest provides utility functions to help you out through it's **vi** helper. Yo
25532553
vi.advanceTimersByTime(150)
25542554
```
25552555
2556+
### vi.advanceTimersByTimeAsync
2557+
2558+
- **Type:** `(ms: number) => Promise<Vitest>`
2559+
2560+
Works just like `runAllTimersAsync`, but will end after passed milliseconds. This will include asynchronously set timers. For example this will log `1, 2, 3` and will not throw:
2561+
2562+
```ts
2563+
let i = 0
2564+
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50)
2565+
2566+
await vi.advanceTimersByTimeAsync(150)
2567+
```
2568+
25562569
### vi.advanceTimersToNextTimer
25572570
25582571
- **Type:** `() => Vitest`
@@ -2568,6 +2581,21 @@ Vitest provides utility functions to help you out through it's **vi** helper. Yo
25682581
.advanceTimersToNextTimer() // log 3
25692582
```
25702583
2584+
### vi.advanceTimersToNextTimerAsync
2585+
2586+
- **Type:** `() => Promise<Vitest>`
2587+
2588+
Will call next available timer even if it was set asynchronously. Useful to make assertions between each timer call. You can chain call it to manage timers by yourself.
2589+
2590+
```ts
2591+
let i = 0
2592+
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50)
2593+
2594+
vi.advanceTimersToNextTimerAsync() // log 1
2595+
.advanceTimersToNextTimerAsync() // log 2
2596+
.advanceTimersToNextTimerAsync() // log 3
2597+
```
2598+
25712599
### vi.getTimerCount
25722600
25732601
- **Type:** `() => number`
@@ -2984,6 +3012,21 @@ IntersectionObserver === undefined
29843012
vi.runAllTimers()
29853013
```
29863014
3015+
### vi.runAllTimersAsync
3016+
3017+
- **Type:** `() => Promise<Vitest>`
3018+
3019+
This method will asynchronously invoke every initiated timer until the timers queue is empty. It means that every timer called during `runAllTimersAsync` will be fired even asynchronous timers. If you have an infinite interval,
3020+
it will throw after 10 000 tries. For example this will log `result`:
3021+
3022+
```ts
3023+
setTimeout(async () => {
3024+
console.log(await Promise.resolve('result'))
3025+
}, 100)
3026+
3027+
await vi.runAllTimersAsync()
3028+
```
3029+
29873030
### vi.runOnlyPendingTimers
29883031
29893032
- **Type:** `() => Vitest`
@@ -2997,6 +3040,28 @@ IntersectionObserver === undefined
29973040
vi.runOnlyPendingTimers()
29983041
```
29993042
3043+
### vi.runOnlyPendingTimersAsync
3044+
3045+
- **Type:** `() => Promise<Vitest>`
3046+
3047+
This method will asynchronously call every timer that was initiated after `vi.useFakeTimers()` call, even asynchronous ones. It will not fire any timer that was initiated during its call. For example this will log `2, 3, 3, 1`:
3048+
3049+
```ts
3050+
setTimeout(() => {
3051+
console.log(1)
3052+
}, 100)
3053+
setTimeout(() => {
3054+
Promise.resolve().then(() => {
3055+
console.log(2)
3056+
setInterval(() => {
3057+
console.log(3)
3058+
}, 40)
3059+
})
3060+
}, 10)
3061+
3062+
await vi.runOnlyPendingTimersAsync()
3063+
```
3064+
30003065
### vi.setSystemTime
30013066
30023067
- **Type**: `(date: string | number | Date) => void`

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,21 @@ export class FakeTimers {
5252
this._clock.runAll()
5353
}
5454

55+
async runAllTimersAsync(): Promise<void> {
56+
if (this._checkFakeTimers())
57+
await this._clock.runAllAsync()
58+
}
59+
5560
runOnlyPendingTimers(): void {
5661
if (this._checkFakeTimers())
5762
this._clock.runToLast()
5863
}
5964

65+
async runOnlyPendingTimersAsync(): Promise<void> {
66+
if (this._checkFakeTimers())
67+
await this._clock.runToLastAsync()
68+
}
69+
6070
advanceTimersToNextTimer(steps = 1): void {
6171
if (this._checkFakeTimers()) {
6272
for (let i = steps; i > 0; i--) {
@@ -70,11 +80,29 @@ export class FakeTimers {
7080
}
7181
}
7282

83+
async advanceTimersToNextTimerAsync(steps = 1): Promise<void> {
84+
if (this._checkFakeTimers()) {
85+
for (let i = steps; i > 0; i--) {
86+
await this._clock.nextAsync()
87+
// Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250
88+
this._clock.tick(0)
89+
90+
if (this._clock.countTimers() === 0)
91+
break
92+
}
93+
}
94+
}
95+
7396
advanceTimersByTime(msToRun: number): void {
7497
if (this._checkFakeTimers())
7598
this._clock.tick(msToRun)
7699
}
77100

101+
async advanceTimersByTimeAsync(msToRun: number): Promise<void> {
102+
if (this._checkFakeTimers())
103+
await this._clock.tickAsync(msToRun)
104+
}
105+
78106
runAllTicks(): void {
79107
if (this._checkFakeTimers()) {
80108
// @ts-expect-error method not exposed

packages/vitest/src/integrations/vi.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,21 @@ class VitestUtils {
6161
return this
6262
}
6363

64+
public async runOnlyPendingTimersAsync() {
65+
await this._timers.runOnlyPendingTimersAsync()
66+
return this
67+
}
68+
6469
public runAllTimers() {
6570
this._timers.runAllTimers()
6671
return this
6772
}
6873

74+
public async runAllTimersAsync() {
75+
await this._timers.runAllTimersAsync()
76+
return this
77+
}
78+
6979
public runAllTicks() {
7080
this._timers.runAllTicks()
7181
return this
@@ -76,11 +86,21 @@ class VitestUtils {
7686
return this
7787
}
7888

89+
public async advanceTimersByTimeAsync(ms: number) {
90+
await this._timers.advanceTimersByTimeAsync(ms)
91+
return this
92+
}
93+
7994
public advanceTimersToNextTimer() {
8095
this._timers.advanceTimersToNextTimer()
8196
return this
8297
}
8398

99+
public async advanceTimersToNextTimerAsync() {
100+
await this._timers.advanceTimersToNextTimerAsync()
101+
return this
102+
}
103+
84104
public getTimerCount() {
85105
return this._timers.getTimerCount()
86106
}

0 commit comments

Comments
 (0)