From 24ea0ce6062b4a8a0db404f23eef6d7625cbdc36 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 2 Apr 2026 08:51:45 +0900 Subject: [PATCH 1/3] fix: fix suite hook throwing errors for unused auto test-scoped fixture (#10035) Co-authored-by: Claude Sonnet 4.6 --- guide/test-context.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/test-context.md b/guide/test-context.md index 826a7b85..f1d775ee 100644 --- a/guide/test-context.md +++ b/guide/test-context.md @@ -891,7 +891,7 @@ This applies to all suite-level hooks: `beforeAll`, `afterAll`, and `aroundAll`. ::: ::: tip -Suite-level hooks can only access [**file-scoped** and **worker-scoped** fixtures](#fixture-scopes). Test-scoped fixtures are not available in these hooks because they run outside the context of individual tests. If you try to access a test-scoped fixture in a suite-level hook, Vitest will throw an error. +Suite-level hooks can only access [**file-scoped** and **worker-scoped** fixtures](#fixture-scopes), including `auto` fixtures. Test-scoped fixtures are not available in these hooks because they run outside the context of individual tests. If you try to access a test-scoped fixture in a suite-level hook, Vitest will throw an error. ```ts const test = baseTest From 7bcfba99069917ceca25fdcb80d58c38fdcd7233 Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Thu, 2 Apr 2026 09:08:22 +0900 Subject: [PATCH 2/3] feat(experimental/snapshot): support custom snapshot matcher (#9973) Co-authored-by: Claude Opus 4.6 (1M context) Co-authored-by: Codex --- guide/extending-matchers.md | 4 +++ guide/migration.md | 30 ++++++++++++++++ guide/snapshot.md | 70 +++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/guide/extending-matchers.md b/guide/extending-matchers.md index 27653c83..2d634c22 100644 --- a/guide/extending-matchers.md +++ b/guide/extending-matchers.md @@ -107,6 +107,10 @@ function customMatcher(this: MatcherState, received: unknown, arg1: unknown, arg expect.extend({ customMatcher }) ``` +::: tip +To build custom **snapshot matchers** (wrappers around `toMatchSnapshot` / `toMatchInlineSnapshot` / `toMatchFileSnapshot`), use the composable functions from `vitest/runtime`. See [Custom Snapshot Matchers](/guide/snapshot#custom-snapshot-matchers). +::: + Matcher function has access to `this` context with the following properties: ## `isNot` diff --git a/guide/migration.md b/guide/migration.md index e5742cc8..952da819 100644 --- a/guide/migration.md +++ b/guide/migration.md @@ -650,6 +650,36 @@ export default defineConfig({ Otherwise your snapshots will have a lot of escaped `"` characters. +### Custom Snapshot Matchers experimental 4.1.3 + +Jest imports snapshot composables from `jest-snapshot`. In Vitest, import from `vitest/runtime` instead: + +```ts +const { toMatchSnapshot } = require('jest-snapshot') // [!code --] +import { toMatchSnapshot } from 'vitest/runtime' // [!code ++] + +expect.extend({ + toMatchTrimmedSnapshot(received: string, length: number) { + return toMatchSnapshot.call(this, received.slice(0, length)) + }, +}) +``` + +For inline snapshots, the same applies: + +```ts +const { toMatchInlineSnapshot } = require('jest-snapshot') // [!code --] +import { toMatchInlineSnapshot } from 'vitest/runtime' // [!code ++] + +expect.extend({ + toMatchTrimmedInlineSnapshot(received: string, inlineSnapshot?: string) { + return toMatchInlineSnapshot.call(this, received.slice(0, 10), inlineSnapshot) + }, +}) +``` + +See [Custom Snapshot Matchers](/guide/snapshot#custom-snapshot-matchers) for the full guide. + ## Migrating from Mocha + Chai + Sinon {#mocha-chai-sinon} Vitest provides excellent support for migrating from Mocha+Chai+Sinon test suites. While Vitest uses a Jest-compatible API by default, it also provides Chai-style assertions for spy/mock testing, making migration easier. diff --git a/guide/snapshot.md b/guide/snapshot.md index 18b0b58a..2ca266c4 100644 --- a/guide/snapshot.md +++ b/guide/snapshot.md @@ -200,6 +200,76 @@ Pretty foo: Object { We are using Jest's `pretty-format` for serializing snapshots. You can read more about it here: [pretty-format](https://github.com/facebook/jest/blob/main/packages/pretty-format/README.md#serialize). +## Custom Snapshot Matchers experimental 4.1.3 {#custom-snapshot-matchers} + +You can build custom snapshot matchers using the composable functions exported from `vitest/runtime`. These let you transform values before snapshotting while preserving full snapshot lifecycle support (creation, update, inline rewriting). + +```ts +import { expect, test } from 'vitest' +import { toMatchFileSnapshot, toMatchInlineSnapshot, toMatchSnapshot } from 'vitest/runtime' + +expect.extend({ + toMatchTrimmedSnapshot(received: string, length: number) { + return toMatchSnapshot.call(this, received.slice(0, length)) + }, + toMatchTrimmedInlineSnapshot(received: string, inlineSnapshot?: string) { + return toMatchInlineSnapshot.call(this, received.slice(0, 10), inlineSnapshot) + }, + async toMatchTrimmedFileSnapshot(received: string, file: string) { + return toMatchFileSnapshot.call(this, received.slice(0, 10), file) + }, +}) + +test('file snapshot', () => { + expect('extra long string oh my gerd').toMatchTrimmedSnapshot(10) +}) + +test('inline snapshot', () => { + expect('extra long string oh my gerd').toMatchTrimmedInlineSnapshot() +}) + +test('raw file snapshot', async () => { + await expect('extra long string oh my gerd').toMatchTrimmedFileSnapshot('./raw-file.txt') +}) +``` + +The composables return `{ pass, message }` so you can further customize the error: + +```ts +expect.extend({ + toMatchTrimmedSnapshot(received: string, length: number) { + const result = toMatchSnapshot.call(this, received.slice(0, length)) + return { ...result, message: () => `Trimmed snapshot failed: ${result.message()}` } + }, +}) +``` + +::: warning +For inline snapshot matchers, the snapshot argument must be the last parameter (or second-to-last when using property matchers). Vitest rewrites the last string argument in the source code, so custom arguments before the snapshot work, but custom arguments after it are not supported. +::: + +::: tip +File snapshot matchers must be `async` — `toMatchFileSnapshot` returns a `Promise`. Remember to `await` the result in the matcher and in your test. +::: + +For TypeScript, extend the `Assertion` interface: + +```ts +import 'vitest' + +declare module 'vitest' { + interface Assertion { + toMatchTrimmedSnapshot: (length: number) => T + toMatchTrimmedInlineSnapshot: (inlineSnapshot?: string) => T + toMatchTrimmedFileSnapshot: (file: string) => Promise + } +} +``` + +::: tip +See [Extending Matchers](/guide/extending-matchers) for more on `expect.extend` and custom matcher conventions. +::: + ## Difference from Jest Vitest provides an almost compatible Snapshot feature with [Jest's](https://jestjs.io/docs/snapshot-testing) with a few exceptions: From 70440c79331d9c222326b11fb82a40527f7d1166 Mon Sep 17 00:00:00 2001 From: noise Date: Sat, 4 Apr 2026 20:54:06 +0800 Subject: [PATCH 3/3] docs(cn): dissolve the conflict --- guide/extending-matchers.md | 8 ++------ guide/migration.md | 8 ++------ guide/snapshot.md | 8 ++------ 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/guide/extending-matchers.md b/guide/extending-matchers.md index 19bbaac2..f262d369 100644 --- a/guide/extending-matchers.md +++ b/guide/extending-matchers.md @@ -107,16 +107,12 @@ function customMatcher(this: MatcherState, received: unknown, arg1: unknown, arg expect.extend({ customMatcher }) ``` - -<<<<<<< HEAD -断言方法可以访问上下文 `this` 对象中的这些属性: -======= + ::: tip To build custom **snapshot matchers** (wrappers around `toMatchSnapshot` / `toMatchInlineSnapshot` / `toMatchFileSnapshot`), use the composable functions from `vitest/runtime`. See [Custom Snapshot Matchers](/guide/snapshot#custom-snapshot-matchers). ::: -Matcher function has access to `this` context with the following properties: ->>>>>>> 7bcfba99069917ceca25fdcb80d58c38fdcd7233 +断言方法可以访问上下文 `this` 对象中的这些属性: ## `isNot` diff --git a/guide/migration.md b/guide/migration.md index 33c3d165..189f6577 100644 --- a/guide/migration.md +++ b/guide/migration.md @@ -640,10 +640,7 @@ export default defineConfig({ ``` 否则快照中会出现大量转义的 `"` 字符。 - -<<<<<<< HEAD -## 从 Mocha + Chai + Sinon 迁移 {#mocha-chai-sinon} -======= + ### Custom Snapshot Matchers experimental 4.1.3 Jest imports snapshot composables from `jest-snapshot`. In Vitest, import from `vitest/runtime` instead: @@ -674,8 +671,7 @@ expect.extend({ See [Custom Snapshot Matchers](/guide/snapshot#custom-snapshot-matchers) for the full guide. -## Migrating from Mocha + Chai + Sinon {#mocha-chai-sinon} ->>>>>>> 7bcfba99069917ceca25fdcb80d58c38fdcd7233 +## 从 Mocha + Chai + Sinon 迁移 {#mocha-chai-sinon} Vitest 对从 Mocha+Chai+Sinon 测试套件迁移提供了完善支持。虽然 Vitest 默认使用与 Jest 兼容的 API,但它同时也提供 Chai 风格的断言用于 spy/mock 测试,从而降低迁移成本。 diff --git a/guide/snapshot.md b/guide/snapshot.md index 64815654..49233055 100644 --- a/guide/snapshot.md +++ b/guide/snapshot.md @@ -192,10 +192,7 @@ Pretty foo: Object { ``` 我们使用的是 Jest 的 `pretty-format` 来序列化快照。你可以在这里阅读更多相关内容:[pretty-format](https://github.com/facebook/jest/blob/main/packages/pretty-format/README.md#serialize). - -<<<<<<< HEAD -## 与 Jest 的区别 {#difference-from-jest} -======= + ## Custom Snapshot Matchers experimental 4.1.3 {#custom-snapshot-matchers} You can build custom snapshot matchers using the composable functions exported from `vitest/runtime`. These let you transform values before snapshotting while preserving full snapshot lifecycle support (creation, update, inline rewriting). @@ -266,8 +263,7 @@ declare module 'vitest' { See [Extending Matchers](/guide/extending-matchers) for more on `expect.extend` and custom matcher conventions. ::: -## Difference from Jest ->>>>>>> 7bcfba99069917ceca25fdcb80d58c38fdcd7233 +## 与 Jest 的区别 {#difference-from-jest} Vitest 提供了与 [Jest](https://jestjs.io/docs/snapshot-testing) 几乎兼容的快照功能,除少数例外: