Skip to content

Commit

Permalink
feat: add runAllTimersAsync from sinonjs (#2209)
Browse files Browse the repository at this point in the history
close #1804
  • Loading branch information
guillaumeduboc committed Jan 16, 2023
1 parent 6145d7b commit 40187bd
Show file tree
Hide file tree
Showing 4 changed files with 501 additions and 0 deletions.
65 changes: 65 additions & 0 deletions docs/api/index.md
Expand Up @@ -2553,6 +2553,19 @@ Vitest provides utility functions to help you out through it's **vi** helper. Yo
vi.advanceTimersByTime(150)
```

### vi.advanceTimersByTimeAsync

- **Type:** `(ms: number) => Promise<Vitest>`

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:

```ts
let i = 0
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50)

await vi.advanceTimersByTimeAsync(150)
```

### vi.advanceTimersToNextTimer

- **Type:** `() => Vitest`
Expand All @@ -2568,6 +2581,21 @@ Vitest provides utility functions to help you out through it's **vi** helper. Yo
.advanceTimersToNextTimer() // log 3
```

### vi.advanceTimersToNextTimerAsync

- **Type:** `() => Promise<Vitest>`

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.

```ts
let i = 0
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50)

vi.advanceTimersToNextTimerAsync() // log 1
.advanceTimersToNextTimerAsync() // log 2
.advanceTimersToNextTimerAsync() // log 3
```

### vi.getTimerCount

- **Type:** `() => number`
Expand Down Expand Up @@ -2984,6 +3012,21 @@ IntersectionObserver === undefined
vi.runAllTimers()
```

### vi.runAllTimersAsync

- **Type:** `() => Promise<Vitest>`

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,
it will throw after 10 000 tries. For example this will log `result`:

```ts
setTimeout(async () => {
console.log(await Promise.resolve('result'))
}, 100)

await vi.runAllTimersAsync()
```

### vi.runOnlyPendingTimers

- **Type:** `() => Vitest`
Expand All @@ -2997,6 +3040,28 @@ IntersectionObserver === undefined
vi.runOnlyPendingTimers()
```

### vi.runOnlyPendingTimersAsync

- **Type:** `() => Promise<Vitest>`

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`:

```ts
setTimeout(() => {
console.log(1)
}, 100)
setTimeout(() => {
Promise.resolve().then(() => {
console.log(2)
setInterval(() => {
console.log(3)
}, 40)
})
}, 10)

await vi.runOnlyPendingTimersAsync()
```

### vi.setSystemTime

- **Type**: `(date: string | number | Date) => void`
Expand Down
28 changes: 28 additions & 0 deletions packages/vitest/src/integrations/mock/timers.ts
Expand Up @@ -52,11 +52,21 @@ export class FakeTimers {
this._clock.runAll()
}

async runAllTimersAsync(): Promise<void> {
if (this._checkFakeTimers())
await this._clock.runAllAsync()
}

runOnlyPendingTimers(): void {
if (this._checkFakeTimers())
this._clock.runToLast()
}

async runOnlyPendingTimersAsync(): Promise<void> {
if (this._checkFakeTimers())
await this._clock.runToLastAsync()
}

advanceTimersToNextTimer(steps = 1): void {
if (this._checkFakeTimers()) {
for (let i = steps; i > 0; i--) {
Expand All @@ -70,11 +80,29 @@ export class FakeTimers {
}
}

async advanceTimersToNextTimerAsync(steps = 1): Promise<void> {
if (this._checkFakeTimers()) {
for (let i = steps; i > 0; i--) {
await this._clock.nextAsync()
// Fire all timers at this point: https://github.com/sinonjs/fake-timers/issues/250
this._clock.tick(0)

if (this._clock.countTimers() === 0)
break
}
}
}

advanceTimersByTime(msToRun: number): void {
if (this._checkFakeTimers())
this._clock.tick(msToRun)
}

async advanceTimersByTimeAsync(msToRun: number): Promise<void> {
if (this._checkFakeTimers())
await this._clock.tickAsync(msToRun)
}

runAllTicks(): void {
if (this._checkFakeTimers()) {
// @ts-expect-error method not exposed
Expand Down
20 changes: 20 additions & 0 deletions packages/vitest/src/integrations/vi.ts
Expand Up @@ -61,11 +61,21 @@ class VitestUtils {
return this
}

public async runOnlyPendingTimersAsync() {
await this._timers.runOnlyPendingTimersAsync()
return this
}

public runAllTimers() {
this._timers.runAllTimers()
return this
}

public async runAllTimersAsync() {
await this._timers.runAllTimersAsync()
return this
}

public runAllTicks() {
this._timers.runAllTicks()
return this
Expand All @@ -76,11 +86,21 @@ class VitestUtils {
return this
}

public async advanceTimersByTimeAsync(ms: number) {
await this._timers.advanceTimersByTimeAsync(ms)
return this
}

public advanceTimersToNextTimer() {
this._timers.advanceTimersToNextTimer()
return this
}

public async advanceTimersToNextTimerAsync() {
await this._timers.advanceTimersToNextTimerAsync()
return this
}

public getTimerCount() {
return this._timers.getTimerCount()
}
Expand Down

0 comments on commit 40187bd

Please sign in to comment.