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 .vitepress/components/FeaturesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ import ListItem from './ListItem.vue'
<a target="_blank" href="https://jestjs.io/zh-Hans/docs/expect" rel="noopener noreferrer">Jest expect</a> API
</ListItem>
<ListItem>
内置
<a target="_blank" href="https://github.com/Aslemammad/tinyspy" rel="noopener noreferrer">Tinyspy</a> 用于对象
Mock
兼容 Jest 对象模拟
</ListItem>
<ListItem>
使用
Expand Down
2 changes: 1 addition & 1 deletion .vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default ({ mode }: { mode: string }) => {
['link', { rel: 'icon', href: '/favicon.ico', sizes: '48x48' }],
['link', { rel: 'icon', href: '/logo-without-border.svg', type: 'image/svg+xml' }],
['meta', { name: 'author', content: `${teamMembers.map(c => c.name).join(', ')} and ${vitestName} contributors` }],
['meta', { name: 'keywords', content: 'vitest, vite, test, coverage, snapshot, react, vue, preact, svelte, solid, lit, marko, ruby, cypress, puppeteer, jsdom, happy-dom, test-runner, jest, typescript, esm, tinyspy, node' }],
['meta', { name: 'keywords', content: 'vitest, vite, test, coverage, snapshot, react, vue, preact, svelte, solid, lit, marko, ruby, cypress, puppeteer, jsdom, happy-dom, test-runner, jest, typescript, esm, node' }],
['meta', { property: 'og:title', content: vitestName }],
['meta', { property: 'og:description', content: vitestDescription }],
['meta', { property: 'og:url', content: ogUrl }],
Expand Down
46 changes: 46 additions & 0 deletions api/expect.md
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,52 @@ test('throws non-Error values', () => {
})
```
:::
<!-- TODO: translation -->
:::warning Unhandled Rejections with Fake Timers
When using fake timers, an async function that rejects _during_ a `vi.advanceTimersByTimeAsync` call will trigger an [unhandled rejection](https://nodejs.org/api/process.html#event-unhandledrejection) — even if you later assert it with `.rejects.toThrow()`. This happens because the error is thrown before the `expect` chain has a chance to catch it.

```ts
async function foo() {
await new Promise(resolve => setTimeout(resolve, 100))
throw new Error('boom')
}

test('rejects', async () => {
const result = foo()

await vi.advanceTimersByTimeAsync(100)

// The assertion passes, but the error was already "unhandled" during advanceTimersByTimeAsync
await expect(result).rejects.toThrow()
})
```

To avoid this, prefer [`vi.setTimerTickMode('nextTimerAsync')`](/api/vi#vi-settimertickmode) so that timers tick automatically as promises settle, without needing a manual advance:

```ts
beforeEach(() => {
vi.useFakeTimers()
vi.setTimerTickMode('nextTimerAsync')
})

test('rejects', async () => {
// No advanceTimersByTimeAsync needed — the error is caught by rejects.toThrow()
await expect(foo()).rejects.toThrow('boom')
})
```

Alternatively, set up the `.rejects.toThrow()` assertion _before_ advancing timers so the rejection is handled immediately:

```ts
test('rejects', async () => {
const result = foo()
const assertion = expect(result).rejects.toThrow('boom')

await vi.advanceTimersByTimeAsync(100)
await assertion
})
```
:::

## toMatchSnapshot

Expand Down
2 changes: 1 addition & 1 deletion guide/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ it('renders correctly', () => {

## 对象模拟 (Mocking) {#mocking}

内置 [Tinyspy](https://github.com/tinylibs/tinyspy) 用于在 `vi` 对象上使用 `jest` 兼容的 API 进行对象模拟
Vitest 在 `vi` 对象上提供了与 `Jest` 兼容的 API 接口

```ts
import { expect, vi } from 'vitest'
Expand Down
Loading