diff --git a/.vitepress/config.ts b/.vitepress/config.ts
index 5507bc49..a580ea7e 100644
--- a/.vitepress/config.ts
+++ b/.vitepress/config.ts
@@ -6,7 +6,6 @@ import { defineConfig } from 'vitepress'
import {
groupIconMdPlugin,
groupIconVitePlugin,
- localIconLoader,
} from 'vitepress-plugin-group-icons'
import llmstxt from 'vitepress-plugin-llms'
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
@@ -72,17 +71,11 @@ export default ({ mode }: { mode: string }) => {
groupIconVitePlugin({
customIcon: {
'CLI': 'vscode-icons:file-type-shell',
- 'vitest.shims': localIconLoader(import.meta.url, '../public/logo-without-border.svg'),
- 'vitest.config': localIconLoader(import.meta.url, '../public/logo-without-border.svg'),
- 'vitest.workspace': localIconLoader(import.meta.url, '../public/logo-without-border.svg'),
'.spec.ts': 'vscode-icons:file-type-testts',
'.test.ts': 'vscode-icons:file-type-testts',
'.spec.js': 'vscode-icons:file-type-testjs',
'.test.js': 'vscode-icons:file-type-testjs',
- 'marko': 'vscode-icons:file-type-marko',
- 'qwik': 'logos:qwik-icon',
'next': '',
- 'vite.config': localIconLoader(import.meta.url, '../public/logo-without-border-vite.svg'),
},
}) as any,
llmstxt(),
diff --git a/api/browser/context.md b/api/browser/context.md
index 917cceba..2daa222d 100644
--- a/api/browser/context.md
+++ b/api/browser/context.md
@@ -186,6 +186,8 @@ export const server: {
}
```
+
+
## `utils`
Utility functions useful for custom render libraries.
@@ -225,3 +227,71 @@ export const utils: {
getElementError(selector: string, container?: Element): Error
}
```
+
+### configurePrettyDOM 4.0.0 {#configureprettydom}
+
+The `configurePrettyDOM` function allows you to configure default options for the `prettyDOM` and `debug` functions. This is useful for customizing how HTML is formatted in test failure messages.
+
+```ts
+import { utils } from 'vitest/browser'
+
+utils.configurePrettyDOM({
+ maxDepth: 3,
+ filterNode: 'script, style, [data-test-hide]'
+})
+```
+
+#### Options
+
+- **`maxDepth`** - Maximum depth to print nested elements (default: `Infinity`)
+- **`maxLength`** - Maximum length of the output string (default: `7000`)
+- **`filterNode`** - A CSS selector string or function to filter out nodes from the output. When a string is provided, elements matching the selector will be excluded. When a function is provided, it should return `false` to exclude a node.
+- **`highlight`** - Enable syntax highlighting (default: `true`)
+- And other options from [`pretty-format`](https://www.npmjs.com/package/@vitest/pretty-format)
+
+#### Filtering with CSS Selectors 4.1.0 {#filtering-with-css-selectors}
+
+The `filterNode` option allows you to hide irrelevant markup (like scripts, styles, or hidden elements) from test failure messages, making it easier to identify the actual cause of failures.
+
+```ts
+import { utils } from 'vitest/browser'
+
+// Filter out common noise elements
+utils.configurePrettyDOM({
+ filterNode: 'script, style, [data-test-hide]'
+})
+
+// Or use directly with prettyDOM
+const html = utils.prettyDOM(element, undefined, {
+ filterNode: 'script, style'
+})
+```
+
+**Common Patterns:**
+
+Filter out scripts and styles:
+```ts
+utils.configurePrettyDOM({ filterNode: 'script, style' })
+```
+
+Hide specific elements with data attributes:
+```ts
+utils.configurePrettyDOM({ filterNode: '[data-test-hide]' })
+```
+
+Hide nested content within an element:
+```ts
+// Hides all children of elements with data-test-hide-content
+utils.configurePrettyDOM({ filterNode: '[data-test-hide-content] *' })
+```
+
+Combine multiple selectors:
+```ts
+utils.configurePrettyDOM({
+ filterNode: 'script, style, [data-test-hide], svg'
+})
+```
+
+::: tip
+This feature is inspired by Testing Library's [`defaultIgnore`](https://testing-library.com/docs/dom-testing-library/api-configuration/#defaultignore) configuration.
+:::
diff --git a/config/browser/playwright.md b/config/browser/playwright.md
index 8a166e2e..cdbceeca 100644
--- a/config/browser/playwright.md
+++ b/config/browser/playwright.md
@@ -104,3 +104,37 @@ await userEvent.click(page.getByRole('button'), {
timeout: 1_000,
})
```
+
+
+
+## `persistentContext` 4.1.0 {#persistentcontext}
+
+- **Type:** `boolean | string`
+- **Default:** `false`
+
+When enabled, Vitest uses Playwright's [persistent context](https://playwright.dev/docs/api/class-browsertype#browser-type-launch-persistent-context) instead of a regular browser context. This allows browser state (cookies, localStorage, DevTools settings, etc.) to persist between test runs.
+
+::: warning
+This option is ignored when running tests in parallel (e.g. when headless with [`fileParallelism`](/config/fileparallelism) enalbed) since persistent context cannot be shared across parallel sessions.
+:::
+
+- When set to `true`, the user data is stored in `./node_modules/.cache/vitest-playwright-user-data`
+- When set to a string, the value is used as the path to the user data directory
+
+```ts [vitest.config.js]
+import { playwright } from '@vitest/browser-playwright'
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ browser: {
+ provider: playwright({
+ persistentContext: true,
+ // or specify a custom directory:
+ // persistentContext: './my-browser-data',
+ }),
+ instances: [{ browser: 'chromium' }],
+ },
+ },
+})
+```
diff --git a/config/server.md b/config/server.md
index a999b7cf..94a986a2 100644
--- a/config/server.md
+++ b/config/server.md
@@ -68,6 +68,6 @@ If a `RegExp` is provided, it is matched against the full file path.
- **Type:** `boolean`
- **Default:** `false`
-When a dependency is a valid ESM package, try to guess the cjs version based on the path. This might be helpful, if a dependency has the wrong ESM file.
+When enabled, Vitest will try to guess a CommonJS build for an ESM entry by checking a few common CJS/UMD file name and folder patterns (like `.mjs`, `.umd.js`, `.cjs.js`, `umd/`, `cjs/`, `lib/`).
-This might potentially cause some misalignment if a package has different logic in ESM and CJS mode.
+This is a best-effort heuristic to work around confusing or incorrect ESM/CJS packaging and may not work for all dependencies.
diff --git a/guide/cli.md b/guide/cli.md
index ea493a1a..52acef2a 100644
--- a/guide/cli.md
+++ b/guide/cli.md
@@ -123,6 +123,51 @@ tests/test1.test.ts
tests/test2.test.ts
```
+
+
+## Shell Autocompletions
+
+Vitest provides shell autocompletions for commands, options, and option values powered by [`@bomb.sh/tab`](https://github.com/bombshell-dev/tab).
+
+### Setup
+
+For permanent setup in zsh, add this to your `~/.zshrc`:
+
+```bash
+# Add to ~/.zshrc for permanent autocompletions (same can be done for other shells)
+source <(vitest complete zsh)
+```
+
+### Package Manager Integration
+
+`@bomb.sh/tab` integrates with [package managers](https://github.com/bombshell-dev/tab?tab=readme-ov-file#package-manager-completions). Autocompletions work when running vitest directly:
+
+::: code-group
+
+```bash [npm]
+npm vitest
+```
+
+```bash [npm]
+npm exec vitest
+```
+
+```bash [pnpm]
+pnpm vitest
+```
+
+```bash [yarn]
+yarn vitest
+```
+
+```bash [bun]
+bun vitest
+```
+
+:::
+
+For package manager autocompletions, you should install [tab's package manager completions](https://github.com/bombshell-dev/tab?tab=readme-ov-file#package-manager-completions) separately.
+
## 选项 {#options}
::: tip
diff --git a/package.json b/package.json
index 247659b3..e7f81892 100644
--- a/package.json
+++ b/package.json
@@ -46,7 +46,7 @@
"vite": "^7.3.1",
"vite-plugin-pwa": "^1.2.0",
"vitepress": "2.0.0-alpha.15",
- "vitepress-plugin-group-icons": "^1.6.5",
+ "vitepress-plugin-group-icons": "^1.7.1",
"vitepress-plugin-llms": "^1.10.0",
"vitepress-plugin-tabs": "^0.7.3",
"vitest": "^4.0.17",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 80a9a517..8f410a81 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -88,8 +88,8 @@ importers:
specifier: 2.0.0-alpha.15
version: 2.0.0-alpha.15(@algolia/client-search@5.46.2)(@types/node@25.0.3)(change-case@5.4.4)(jiti@2.6.1)(lightningcss@1.30.2)(postcss@8.5.6)(react@19.2.3)(search-insights@2.17.3)(terser@5.44.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2)
vitepress-plugin-group-icons:
- specifier: ^1.6.5
- version: 1.6.5(vite@7.3.1(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
+ specifier: ^1.7.1
+ version: 1.7.1(vite@7.3.1(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))
vitepress-plugin-llms:
specifier: ^1.10.0
version: 1.10.0
@@ -1084,8 +1084,8 @@ packages:
'@iconify-json/simple-icons@1.2.65':
resolution: {integrity: sha512-v/O0UeqrDz6ASuRVE5g2Puo5aWyej4M/CxX6WYDBARgswwxK0mp3VQbGgPFEAAUU9QN02IjTgjMuO021gpWf2w==}
- '@iconify-json/vscode-icons@1.2.37':
- resolution: {integrity: sha512-HLRdU6nZks4N8x3JYz6j+b3+hcUCvYvlTLwGzM3xyXfTJyDSA2cAdWcEXfoA4hQMJGA+zCDSPAWFelFptH5Kbw==}
+ '@iconify-json/vscode-icons@1.2.40':
+ resolution: {integrity: sha512-Q7JIWAxENwmcRg4EGRY+u16gBwrAj6mWeuSmuyuPvNvoTJHh8Ss8qoeDhrFYNgtWqNkzH5hSf4b2T9XLK5MsrA==}
'@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
@@ -4629,8 +4629,8 @@ packages:
yaml:
optional: true
- vitepress-plugin-group-icons@1.6.5:
- resolution: {integrity: sha512-+pg4+GKDq2fLqKb1Sat5p1p4SuIZ5tEPxu8HjpwoeecZ/VaXKy6Bdf0wyjedjaTAyZQzXbvyavJegqAcQ+B0VA==}
+ vitepress-plugin-group-icons@1.7.1:
+ resolution: {integrity: sha512-3ZPcIqwHNBg1btrOOSecOqv8yJxHdu3W2ugxE5LusclDF005LAm60URMEmBQrkgl4JvM32AqJirqghK6lGIk8g==}
peerDependencies:
vite: '>=3'
peerDependenciesMeta:
@@ -5996,7 +5996,7 @@ snapshots:
dependencies:
'@iconify/types': 2.0.0
- '@iconify-json/vscode-icons@1.2.37':
+ '@iconify-json/vscode-icons@1.2.40':
dependencies:
'@iconify/types': 2.0.0
@@ -10060,10 +10060,10 @@ snapshots:
tsx: 4.21.0
yaml: 2.8.2
- vitepress-plugin-group-icons@1.6.5(vite@7.3.1(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)):
+ vitepress-plugin-group-icons@1.7.1(vite@7.3.1(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)):
dependencies:
'@iconify-json/logos': 1.2.10
- '@iconify-json/vscode-icons': 1.2.37
+ '@iconify-json/vscode-icons': 1.2.40
'@iconify/utils': 3.1.0
optionalDependencies:
vite: 7.3.1(@types/node@25.0.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)
diff --git a/todo.md b/todo.md
deleted file mode 100644
index fbaf505c..00000000
--- a/todo.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# Remove UnoCSS - Migration Complete
-
-UnoCSS was causing OOM in CI. Removed entirely and replaced with `@iconify/vue` + plain CSS.
-
-## Summary
-
-- Removed UnoCSS plugin from `vite.config.ts`
-- Removed `uno.css` import from `theme/index.ts`
-- Added `@iconify/vue` for icons
-- Converted all UnoCSS utilities to scoped CSS
-
-## Completed
-
-- [x] `vite.config.ts` - removed UnoCSS plugin
-- [x] `theme/index.ts` - removed `import 'uno.css'`
-- [x] `CRoot.vue` - @iconify/vue + CSS
-- [x] `ListItem.vue` - @iconify/vue + CSS (spinner, checkmark, close icons)
-- [x] `CourseLink.vue` - @iconify/vue + CSS
-- [x] `FeaturesList.vue` - plain CSS
-- [x] `Advanced.vue` - plain CSS
-- [x] `Experimental.vue` - plain CSS
-
-## Test pages
-
-- `/guide/features` - FeaturesList, ListItem, CourseLink
-- `/config/projects` - CRoot
-- `/api/advanced/vitest` - Experimental
-
-## Not used (skipped)
-
-- `HomePage.vue` - not used in new theme