diff --git a/.vitepress/config.ts b/.vitepress/config.ts
index 3ef34e5c..aa7275f3 100644
--- a/.vitepress/config.ts
+++ b/.vitepress/config.ts
@@ -27,6 +27,7 @@ import { pwa } from './scripts/pwa'
import { transformHead } from './scripts/transformHead'
export default ({ mode }: { mode: string }) => {
+<<<<<<< HEAD
return withPwa(
defineConfig({
lang: 'en-US',
@@ -36,6 +37,138 @@ export default ({ mode }: { mode: string }) => {
root: {
label: '简体中文',
lang: 'zh',
+=======
+ return withPwa(defineConfig({
+ lang: 'en-US',
+ title: vitestName,
+ description: vitestDescription,
+ locales: {
+ root: {
+ label: 'English',
+ lang: 'en-US',
+ },
+ zh: {
+ label: '简体中文',
+ lang: 'zh',
+ link: 'https://cn.vitest.dev/',
+ },
+ },
+ head: [
+ ['meta', { name: 'theme-color', content: '#729b1a' }],
+ ['link', { rel: 'icon', href: '/favicon.ico', sizes: '48x48' }],
+ ['link', { rel: 'icon', href: '/logo.svg', sizes: 'any', 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, tinypool, tinyspy, node' }],
+ ['meta', { property: 'og:title', content: vitestName }],
+ ['meta', { property: 'og:description', content: vitestDescription }],
+ ['meta', { property: 'og:url', content: ogUrl }],
+ ['meta', { property: 'og:image', content: ogImage }],
+ ['meta', { name: 'twitter:title', content: vitestName }],
+ ['meta', { name: 'twitter:description', content: vitestDescription }],
+ ['meta', { name: 'twitter:image', content: ogImage }],
+ ['meta', { name: 'twitter:card', content: 'summary_large_image' }],
+ ['link', { rel: 'preload', as: 'style', onload: 'this.onload=null;this.rel=\'stylesheet\'', href: font }],
+ ['noscript', {}, ``],
+ ['link', { rel: 'mask-icon', href: '/logo.svg', color: '#ffffff' }],
+ ['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }],
+ ],
+ lastUpdated: true,
+ vite: {
+ plugins: [
+ groupIconVitePlugin({
+ customIcon: {
+ 'CLI': 'vscode-icons:file-type-shell',
+ 'vitest.shims': 'vscode-icons:file-type-vitest',
+ 'vitest.workspace': 'vscode-icons:file-type-vitest',
+ 'vitest.config': 'vscode-icons:file-type-vitest',
+ '.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',
+ },
+ }),
+ ],
+ },
+ markdown: {
+ config(md) {
+ md.use(tabsMarkdownPlugin)
+ md.use(groupIconMdPlugin)
+ },
+ theme: {
+ light: 'github-light',
+ dark: 'github-dark',
+ },
+ codeTransformers: mode === 'development'
+ ? [transformerNotationWordHighlight()]
+ : [
+ transformerNotationWordHighlight(),
+ transformerTwoslash({
+ processHoverInfo: (info) => {
+ if (info.includes(process.cwd())) {
+ return info.replace(new RegExp(process.cwd(), 'g'), '')
+ }
+ return info
+ },
+ }),
+ ],
+ },
+ themeConfig: {
+ logo: '/logo.svg',
+
+ editLink: {
+ pattern: 'https://github.com/vitest-dev/vitest/edit/main/docs/:path',
+ text: 'Suggest changes to this page',
+ },
+
+ search: {
+ provider: 'local',
+ /* provider: 'algolia',
+ options: {
+ appId: 'ZTF29HGJ69',
+ apiKey: '9c3ced6fed60d2670bb36ab7e8bed8bc',
+ indexName: 'vitest',
+ // searchParameters: {
+ // facetFilters: ['tags:en'],
+ // },
+ }, */
+ },
+
+ carbonAds: {
+ code: 'CW7DVKJE',
+ placement: 'vitestdev',
+ },
+
+ socialLinks: [
+ { icon: 'bluesky', link: bluesky },
+ { icon: 'mastodon', link: mastodon },
+ { icon: 'discord', link: discord },
+ { icon: 'github', link: github },
+ ],
+
+ footer: {
+ message: 'Released under the MIT License.',
+ copyright: 'Copyright © 2021-PRESENT Anthony Fu, Matías Capeletto and Vitest contributors',
+ },
+
+ nav: [
+ { text: 'Guide & API', link: '/guide/', activeMatch: '^/(guide|api)/(?!browser)' },
+ { text: 'Config', link: '/config/', activeMatch: '^/config/' },
+ { text: 'Browser Mode', link: '/guide/browser', activeMatch: '^/guide/browser/' },
+ {
+ text: 'Resources',
+ items: [
+ {
+ text: 'Advanced API',
+ link: '/advanced/api/',
+ activeMatch: '^/advanced/',
+ },
+ {
+ text: 'Team',
+ link: '/team',
+ },
+ ],
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
},
en: {
label: 'English',
@@ -202,10 +335,80 @@ export default ({ mode }: { mode: string }) => {
activeMatch: '^/guide/browser/',
},
{
+<<<<<<< HEAD
text: '相关连接',
items: [
{
text: '高级 API',
+=======
+ text: 'Configuration',
+ collapsed: false,
+ items: [
+ {
+ text: 'Browser Config Reference',
+ link: '/guide/browser/config',
+ docFooterText: 'Browser Config Reference | Browser Mode',
+ },
+ {
+ text: 'Configuring Playwright',
+ link: '/guide/browser/playwright',
+ docFooterText: 'Configuring Playwright | Browser Mode',
+ },
+ {
+ text: 'Configuring WebdriverIO',
+ link: '/guide/browser/webdriverio',
+ docFooterText: 'Configuring WebdriverIO | Browser Mode',
+ },
+ ],
+ },
+ {
+ text: 'API',
+ collapsed: false,
+ items: [
+ {
+ text: 'Context API',
+ link: '/guide/browser/context',
+ docFooterText: 'Context API | Browser Mode',
+ },
+ {
+ text: 'Interactivity API',
+ link: '/guide/browser/interactivity-api',
+ docFooterText: 'Interactivity API | Browser Mode',
+ },
+ {
+ text: 'Locators',
+ link: '/guide/browser/locators',
+ docFooterText: 'Locators | Browser Mode',
+ },
+ {
+ text: 'Assertion API',
+ link: '/guide/browser/assertion-api',
+ docFooterText: 'Assertion API | Browser Mode',
+ },
+ {
+ text: 'Commands API',
+ link: '/guide/browser/commands',
+ docFooterText: 'Commands | Browser Mode',
+ },
+ ],
+ },
+ {
+ text: 'Guides',
+ collapsed: false,
+ items: [
+ {
+ text: 'Multiple Setups',
+ link: '/guide/browser/multiple-setups',
+ docFooterText: 'Multiple Setups | Browser Mode',
+ },
+ ],
+ },
+ {
+ items: [
+ ...footer(),
+ {
+ text: 'Node API Reference',
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
link: '/advanced/api/',
activeMatch: '^/advanced/',
},
diff --git a/.vitepress/scripts/cli-generator.ts b/.vitepress/scripts/cli-generator.ts
index b71dfa5c..4f3ba4fe 100644
--- a/.vitepress/scripts/cli-generator.ts
+++ b/.vitepress/scripts/cli-generator.ts
@@ -75,7 +75,7 @@ const options = resolveOptions(cliOptionsConfig)
const template = options.map((option) => {
const title = option.title
const cli = option.cli
- const config = skipConfig.has(title) ? '' : `[${title}](/config/#${title.toLowerCase().replace(/\./g, '-')})`
+ const config = skipConfig.has(title) ? '' : `[${title}](${title.includes('browser.') ? '/guide/browser/config' : '/config/'}#${title.toLowerCase().replace(/\./g, '-')})`
return `### ${title}\n\n- **CLI:** ${cli}\n${config ? `- **Config:** ${config}\n` : ''}\n${option.description}\n`
}).join('\n')
diff --git a/advanced/api/vitest.md b/advanced/api/vitest.md
index cb8582ba..ad6861e9 100644
--- a/advanced/api/vitest.md
+++ b/advanced/api/vitest.md
@@ -34,7 +34,6 @@ Vitest 3 is one step closer to stabilising the public API. To achieve that, we d
- `changeNamePattern`
- `changeFilenamePattern`
- `rerunFailed`
-- `updateSnapshot`
- `_createRootProject` (renamed to `_ensureRootProject`, but still private)
- `filterTestsBySource` (this was moved to the new internal `vitest.specifications` instance)
- `runFiles` (use [`runTestSpecifications`](#runtestspecifications) instead)
@@ -326,6 +325,14 @@ function runTestSpecifications(
This method emits `reporter.onWatcherRerun` and `onTestsRerun` events, then it runs tests with [`runTestSpecifications`](#runtestspecifications). If there were no errors in the main process, it will emit `reporter.onWatcherStart` event.
+## updateSnapshot
+
+```ts
+function updateSnapshot(files?: string[]): Promise
+```
+
+Update snapshots in specified files. If no files are provided, it will update files with failed tests and obsolete snapshots.
+
## collectTests
```ts
diff --git a/api/expect.md b/api/expect.md
index 65ba06a7..91048933 100644
--- a/api/expect.md
+++ b/api/expect.md
@@ -310,6 +310,42 @@ test('getApplesCount has some unusual side effects...', () => {
})
```
+## toBeOneOf
+
+- **Type:** `(sample: Array) => any`
+
+`toBeOneOf` asserts if a value matches any of the values in the provided array.
+
+```ts
+import { expect, test } from 'vitest'
+
+test('fruit is one of the allowed values', () => {
+ expect(fruit).toBeOneOf(['apple', 'banana', 'orange'])
+})
+```
+
+The asymmetric matcher is particularly useful when testing optional properties that could be either `null` or `undefined`:
+
+```ts
+test('optional properties can be null or undefined', () => {
+ const user = {
+ firstName: 'John',
+ middleName: undefined,
+ lastName: 'Doe'
+ }
+
+ expect(user).toEqual({
+ firstName: expect.any(String),
+ middleName: expect.toBeOneOf([expect.any(String), undefined]),
+ lastName: expect.any(String),
+ })
+})
+```
+
+:::tip
+You can use `expect.not` with this matcher to ensure a value does NOT match any of the provided options.
+:::
+
## toBeTypeOf
- **类型:** `(c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable`
diff --git a/config/index.md b/config/index.md
index f5c973c0..691cc5ad 100644
--- a/config/index.md
+++ b/config/index.md
@@ -1763,8 +1763,9 @@ test('doNotRun', () => {
提供 API 服务的端口。当设置为 true 时,默认端口为 51204
-### browser {#browser}
+### browser experimental {#browser}
+<<<<<<< HEAD
- **类型:** `{ enabled?, name?, provider?, headless?, api? }`
- **默认值:** `{ enabled: false, headless: process.env.CI, api: 63315 }`
- **命令行终端:** `--browser`, `--browser=`, `--browser.name=chrome --browser.headless`
@@ -1774,11 +1775,18 @@ test('doNotRun', () => {
::: tip NOTE
在 [指南页面](/guide/browser/) 中阅读有关在真实浏览器中进行测试的更多信息。
:::
+=======
+- **Default:** `{ enabled: false }`
+- **CLI:** `--browser=`, `--browser.name=chrome --browser.headless`
+
+Configuration for running browser tests. Please, refer to the ["Browser Config Reference"](/guide/browser/config) article.
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
::: warning
这是一项实验性功能。重大更改可能不会遵循 semver,请在使用时锁定 Vitest 的版本。
:::
+<<<<<<< HEAD
#### browser.enabled
- **类型:** `boolean`
@@ -1982,6 +1990,8 @@ export interface BrowserScript {
自定义[命令](/guide/browser/commands),可在浏览器测试期间从 `@vitest/browser/commands` 导入。
+=======
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
### clearMocks
- **类型:** `boolean`
diff --git a/guide/browser/commands.md b/guide/browser/commands.md
index 9ba1e798..0da1e1b4 100644
--- a/guide/browser/commands.md
+++ b/guide/browser/commands.md
@@ -61,7 +61,11 @@ CDP session仅适用于 `playwright` provider,并且仅在使用 `chromium`
## Custom Commands
+<<<<<<< HEAD
你也可以通过 [`browser.commands`](/config/#browser-commands) 配置选项添加自己的命令。如果你开发了一个库,你可以通过插件内的 `config` 钩子来提供它们:
+=======
+You can also add your own commands via [`browser.commands`](/guide/browser/config#browser-commands) config option. If you develop a library, you can provide them via a `config` hook inside a plugin:
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
```ts
import type { Plugin } from 'vitest/config'
diff --git a/guide/browser/config.md b/guide/browser/config.md
new file mode 100644
index 00000000..e71099de
--- /dev/null
+++ b/guide/browser/config.md
@@ -0,0 +1,327 @@
+# Browser Config Reference
+
+You can change the browser configuration by updating the `test.browser` field in your [config file](/config/). An example of a simple config file:
+
+```ts [vitest.config.ts]
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ browser: {
+ enabled: true,
+ provider: 'playwright',
+ instances: [
+ {
+ browser: 'chromium',
+ setupFile: './chromium-setup.js',
+ },
+ ],
+ },
+ },
+})
+```
+
+Please, refer to the ["Config Reference"](/config/) article for different config examples.
+
+::: warning
+_All listed options_ on this page are located within a `test` property inside the configuration:
+
+```ts [vitest.config.js]
+export default defineConfig({
+ test: {
+ browser: {},
+ },
+})
+```
+:::
+
+## browser.enabled
+
+- **Type:** `boolean`
+- **Default:** `false`
+- **CLI:** `--browser`, `--browser.enabled=false`
+
+Run all tests inside a browser by default. Note that `--browser` only works if you have at least one [`browser.instances`](#browser-instances) item.
+
+## browser.instances
+
+- **Type:** `BrowserConfig`
+- **Default:** `[{ browser: name }]`
+
+Defines multiple browser setups. Every config has to have at least a `browser` field. The config supports your providers configurations:
+
+- [Configuring Playwright](/guide/browser/playwright)
+- [Configuring WebdriverIO](/guide/browser/webdriverio)
+
+::: tip
+To have a better type safety when using built-in providers, you should reference one of these types (for provider that you are using) in your [config file](/config/):
+
+```ts
+///
+///
+```
+:::
+
+In addition to that, you can also specify most of the [project options](/config/) (not marked with a icon) and some of the `browser` options like `browser.testerHtmlPath`.
+
+::: warning
+Every browser config inherits options from the root config:
+
+```ts{3,9} [vitest.config.ts]
+export default defineConfig({
+ test: {
+ setupFile: ['./root-setup-file.js'],
+ browser: {
+ enabled: true,
+ testerHtmlPath: './custom-path.html',
+ instances: [
+ {
+ // will have both setup files: "root" and "browser"
+ setupFile: ['./browser-setup-file.js'],
+ // implicitly has "testerHtmlPath" from the root config // [!code warning]
+ // testerHtmlPath: './custom-path.html', // [!code warning]
+ },
+ ],
+ },
+ },
+})
+```
+
+During development, Vitest supports only one [non-headless](#browser-headless) configuration. You can limit the headed project yourself by specifying `headless: false` in the config, or by providing the `--browser.headless=false` flag, or by filtering projects with `--project=chromium` flag.
+
+For more examples, refer to the ["Multiple Setups" guide](/guide/browser/multiple-setups).
+:::
+
+List of available `browser` options:
+
+- [`browser.headless`](#browser-headless)
+- [`browser.locators`](#browser-locators)
+- [`browser.viewport`](#browser-viewport)
+- [`browser.testerHtmlPath`](#browser-testerhtmlpath)
+- [`browser.screenshotDirectory`](#browser-screenshotdirectory)
+- [`browser.screenshotFailures`](#browser-screenshotfailures)
+
+By default, Vitest creates an array with a single element which uses the [`browser.name`](#browser-name) field as a `browser`. Note that this behaviour will be removed with Vitets 4.
+
+Under the hood, Vitest transforms these instances into separate [test projects](/advanced/api/test-project) sharing a single Vite server for better caching performance.
+
+## browser.name deprecated {#browser-name}
+
+- **Type:** `string`
+- **CLI:** `--browser=safari`
+
+::: danger
+This API is deprecated an will be removed in Vitest 4. Please, use [`browser.instances`](#browser-instances) option instead.
+:::
+
+Run all tests in a specific browser. Possible options in different providers:
+
+- `webdriverio`: `firefox`, `chrome`, `edge`, `safari`
+- `playwright`: `firefox`, `webkit`, `chromium`
+- custom: any string that will be passed to the provider
+
+## browser.headless
+
+- **Type:** `boolean`
+- **Default:** `process.env.CI`
+- **CLI:** `--browser.headless`, `--browser.headless=false`
+
+Run the browser in a `headless` mode. If you are running Vitest in CI, it will be enabled by default.
+
+## browser.isolate
+
+- **Type:** `boolean`
+- **Default:** `true`
+- **CLI:** `--browser.isolate`, `--browser.isolate=false`
+
+Run every test in a separate iframe.
+
+## browser.testerHtmlPath
+
+- **Type:** `string`
+
+A path to the HTML entry point. Can be relative to the root of the project. This file will be processed with [`transformIndexHtml`](https://vite.dev/guide/api-plugin#transformindexhtml) hook.
+
+## browser.api
+
+- **Type:** `number | { port?, strictPort?, host? }`
+- **Default:** `63315`
+- **CLI:** `--browser.api=63315`, `--browser.api.port=1234, --browser.api.host=example.com`
+
+Configure options for Vite server that serves code in the browser. Does not affect [`test.api`](#api) option. By default, Vitest assigns port `63315` to avoid conflicts with the development server, allowing you to run both in parallel.
+
+## browser.provider experimental {#browser-provider}
+
+- **Type:** `'webdriverio' | 'playwright' | 'preview' | string`
+- **Default:** `'preview'`
+- **CLI:** `--browser.provider=playwright`
+
+::: danger ADVANCED API
+The provider API is highly experimental and can change between patches. If you just need to run tests in a browser, use the [`browser.instances`](#browser-instances) option instead.
+:::
+
+Path to a provider that will be used when running browser tests. Vitest provides three providers which are `preview` (default), `webdriverio` and `playwright`. Custom providers should be exported using `default` export and have this shape:
+
+```ts
+export interface BrowserProvider {
+ name: string
+ supportsParallelism: boolean
+ getSupportedBrowsers: () => readonly string[]
+ beforeCommand?: (command: string, args: unknown[]) => Awaitable
+ afterCommand?: (command: string, args: unknown[]) => Awaitable
+ getCommandsContext: (sessionId: string) => Record
+ openPage: (sessionId: string, url: string, beforeNavigate?: () => Promise) => Promise
+ getCDPSession?: (sessionId: string) => Promise
+ close: () => Awaitable
+ initialize(
+ ctx: TestProject,
+ options: BrowserProviderInitializationOptions
+ ): Awaitable
+}
+```
+
+## browser.providerOptions deprecated {#browser-provideroptions}
+
+- **Type:** `BrowserProviderOptions`
+
+::: danger
+This API is deprecated an will be removed in Vitest 4. Please, use [`browser.instances`](#browser-instances) option instead.
+:::
+
+Options that will be passed down to provider when calling `provider.initialize`.
+
+```ts
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ browser: {
+ providerOptions: {
+ launch: {
+ devtools: true,
+ },
+ },
+ },
+ },
+})
+```
+
+::: tip
+To have a better type safety when using built-in providers, you should reference one of these types (for provider that you are using) in your [config file](/config/):
+
+```ts
+///
+///
+```
+:::
+
+## browser.ui
+
+- **Type:** `boolean`
+- **Default:** `!isCI`
+- **CLI:** `--browser.ui=false`
+
+Should Vitest UI be injected into the page. By default, injects UI iframe during development.
+
+## browser.viewport
+
+- **Type:** `{ width, height }`
+- **Default:** `414x896`
+
+Default iframe's viewport.
+
+## browser.locators
+
+Options for built-in [browser locators](/guide/browser/locators).
+
+### browser.locators.testIdAttribute
+
+- **Type:** `string`
+- **Default:** `data-testid`
+
+Attribute used to find elements with `getByTestId` locator.
+
+## browser.screenshotDirectory
+
+- **Type:** `string`
+- **Default:** `__snapshots__` in the test file directory
+
+Path to the screenshots directory relative to the `root`.
+
+## browser.screenshotFailures
+
+- **Type:** `boolean`
+- **Default:** `!browser.ui`
+
+Should Vitest take screenshots if the test fails.
+
+## browser.orchestratorScripts
+
+- **Type:** `BrowserScript[]`
+- **Default:** `[]`
+
+Custom scripts that should be injected into the orchestrator HTML before test iframes are initiated. This HTML document only sets up iframes and doesn't actually import your code.
+
+The script `src` and `content` will be processed by Vite plugins. Script should be provided in the following shape:
+
+```ts
+export interface BrowserScript {
+ /**
+ * If "content" is provided and type is "module", this will be its identifier.
+ *
+ * If you are using TypeScript, you can add `.ts` extension here for example.
+ * @default `injected-${index}.js`
+ */
+ id?: string
+ /**
+ * JavaScript content to be injected. This string is processed by Vite plugins if type is "module".
+ *
+ * You can use `id` to give Vite a hint about the file extension.
+ */
+ content?: string
+ /**
+ * Path to the script. This value is resolved by Vite so it can be a node module or a file path.
+ */
+ src?: string
+ /**
+ * If the script should be loaded asynchronously.
+ */
+ async?: boolean
+ /**
+ * Script type.
+ * @default 'module'
+ */
+ type?: string
+}
+```
+
+## browser.testerScripts
+
+- **Type:** `BrowserScript[]`
+- **Default:** `[]`
+
+::: danger
+This API is deprecated an will be removed in Vitest 4. Please, use [`browser.testerHtmlPath`](#browser-testerHtmlPath) field instead.
+:::
+
+Custom scripts that should be injected into the tester HTML before the tests environment is initiated. This is useful to inject polyfills required for Vitest browser implementation. It is recommended to use [`setupFiles`](#setupfiles) in almost all cases instead of this.
+
+The script `src` and `content` will be processed by Vite plugins.
+
+## browser.commands
+
+- **Type:** `Record`
+- **Default:** `{ readFile, writeFile, ... }`
+
+Custom [commands](/guide/browser/commands) that can be imported during browser tests from `@vitest/browser/commands`.
+
+## browser.connectTimeout
+
+- **Type:** `number`
+- **Default:** `60_000`
+
+The timeout in milliseconds. If connection to the browser takes longer, the test suite will fail.
+
+::: info
+This is the time it should take for the browser to establish the WebSocket connection with the Vitest server. In normal circumstances, this timeout should never be reached.
+:::
diff --git a/guide/browser/index.md b/guide/browser/index.md
index 062d7b75..c1267e05 100644
--- a/guide/browser/index.md
+++ b/guide/browser/index.md
@@ -95,7 +95,11 @@ bun add -D vitest @vitest/browser webdriverio
## 配置
+<<<<<<< HEAD
要在 Vitest 配置中激活浏览器模式,可以使用 `--browser` 标志,或在 Vitest 配置文件中将 `browser.enabled` 字段设为 `true`。下面是一个使用浏览器字段的配置示例:
+=======
+To activate browser mode in your Vitest configuration, you can use the `--browser=name` flag or set the `browser.enabled` field to `true` in your Vitest configuration file. Here is an example configuration using the browser field:
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
```ts [vitest.config.ts]
import { defineConfig } from 'vitest/config'
@@ -104,7 +108,10 @@ export default defineConfig({
browser: {
provider: 'playwright', // or 'webdriverio'
enabled: true,
- name: 'chromium', // browser name is required
+ // at least one instance is required
+ instances: [
+ { browser: 'chromium' },
+ ],
},
}
})
@@ -129,7 +136,9 @@ export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
- name: 'chromium',
+ instances: [
+ { browser: 'chromium' },
+ ],
}
}
})
@@ -144,7 +153,9 @@ export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
- name: 'chromium',
+ instances: [
+ { browser: 'chromium' },
+ ],
}
}
})
@@ -159,7 +170,9 @@ export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
- name: 'chromium',
+ instances: [
+ { browser: 'chromium' },
+ ],
}
}
})
@@ -174,7 +187,9 @@ export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
- name: 'chromium',
+ instances: [
+ { browser: 'chromium' },
+ ],
}
}
})
@@ -189,7 +204,9 @@ export default defineConfig({
browser: {
enabled: true,
provider: 'playwright',
- name: 'chromium',
+ instances: [
+ { browser: 'chromium' },
+ ],
}
}
})
@@ -227,13 +244,16 @@ export default defineWorkspace([
name: 'browser',
browser: {
enabled: true,
- name: 'chrome',
+ instances: [
+ { browser: 'chromium' },
+ ],
},
},
},
])
```
+<<<<<<< HEAD
### Provider 配置
:::tabs key:provider
@@ -283,6 +303,9 @@ export default defineConfig({
:::
## 浏览器选项类型
+=======
+## Browser Option Types
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
Vitest 中的浏览器选项取决于provider。如果在配置文件中传递 `--browser` 且未指定其名称,则 Vitest 将失败。可用选项:
- `webdriverio` 支持这些浏览器:
@@ -359,7 +382,7 @@ npx vitest --browser=chrome
或者你可以使用点符号向 CLI 提供浏览器选项:
```sh
-npx vitest --browser.name=chrome --browser.headless
+npx vitest --browser.headless
```
默认情况下,Vitest 会自动打开浏览器用户界面进行开发。您的测试将在中间的 iframe 中运行。您可以通过选择首选尺寸、在测试中调用 `page.viewport` 或在 [the config](/config/#browser-viewport) 中设置默认值来配置视口。
@@ -388,7 +411,7 @@ export default defineConfig({
你还可以在 CLI 中使用 `--browser.headless` 标志设置 headless 模式,如下所示:
```sh
-npx vitest --browser.name=chrome --browser.headless
+npx vitest --browser.headless
```
在这种情况下,Vitest 将使用 Chrome 浏览器以 headless 模式运行。
diff --git a/guide/browser/locators.md b/guide/browser/locators.md
index be8ed5e5..f30b05cc 100644
--- a/guide/browser/locators.md
+++ b/guide/browser/locators.md
@@ -364,7 +364,7 @@ page.getByTitle('Create') // ❌
function getByTestId(text: string | RegExp): Locator
```
-Creates a locator capable of finding an element that matches the specified test id attribute. You can configure the attribute name with [`browser.locators.testIdAttribute`](/config/#browser-locators-testidattribute).
+Creates a locator capable of finding an element that matches the specified test id attribute. You can configure the attribute name with [`browser.locators.testIdAttribute`](/guide/browser/config#browser-locators-testidattribute).
```tsx
@@ -569,7 +569,7 @@ function screenshot(options?: LocatorScreenshotOptions & { base64?: false }): Pr
Creates a screenshot of the element matching the locator's selector.
-You can specify the save location for the screenshot using the `path` option, which is relative to the current test file. If the `path` option is not set, Vitest will default to using [`browser.screenshotDirectory`](/config/#browser-screenshotdirectory) (`__screenshot__` by default), along with the names of the file and the test to determine the screenshot's filepath.
+You can specify the save location for the screenshot using the `path` option, which is relative to the current test file. If the `path` option is not set, Vitest will default to using [`browser.screenshotDirectory`](/guide/browser/config#browser-screenshotdirectory) (`__screenshot__` by default), along with the names of the file and the test to determine the screenshot's filepath.
If you also need the content of the screenshot, you can specify `base64: true` to return it alongside the filepath where the screenshot is saved.
diff --git a/guide/browser/multiple-setups.md b/guide/browser/multiple-setups.md
new file mode 100644
index 00000000..78bb6259
--- /dev/null
+++ b/guide/browser/multiple-setups.md
@@ -0,0 +1,134 @@
+# Multiple Setups
+
+Since Vitest 3, you can specify several different browser setups using the new [`browser.instances`](/guide/browser/config#browser-instances) option.
+
+The main advatage of using the `browser.instances` over the [workspace](/guide/workspace) is improved caching. Every project will use the same Vite server meaning the file transform and [dependency pre-bundling](https://vite.dev/guide/dep-pre-bundling.html) has to happen only once.
+
+## Several Browsers
+
+You can use the `browser.instances` field to specify options for different browsers. For example, if you want to run the same tests in different browsers, the minimal configuration will look like this:
+
+```ts [vitest.config.ts]
+import { defineConfig } from 'vitest/config'
+export default defineConfig({
+ test: {
+ browser: {
+ enabled: true,
+ provider: 'playwright',
+ headless: true,
+ instances: [
+ { browser: 'chromium' },
+ { browser: 'firefox' },
+ { browser: 'webkit' },
+ ],
+ },
+ },
+})
+```
+
+## Different Setups
+
+You can also specify different config options independently from the browser (although, the instances _can_ also have `browser` fields):
+
+::: code-group
+```ts [vitest.config.ts]
+import { defineConfig } from 'vitest/config'
+export default defineConfig({
+ test: {
+ browser: {
+ enabled: true,
+ provider: 'playwright',
+ headless: true,
+ instances: [
+ {
+ browser: 'chromium',
+ name: 'chromium-1',
+ setupFiles: ['./ratio-setup.ts'],
+ provide: {
+ ratio: 1,
+ }
+ },
+ {
+ browser: 'chromium',
+ name: 'chromium-2',
+ provide: {
+ ratio: 2,
+ }
+ },
+ ],
+ },
+ },
+})
+```
+```ts [example.test.ts]
+import { expect, inject, test } from 'vitest'
+import { globalSetupModifier } from './example.js'
+
+test('ratio works', () => {
+ expect(inject('ratio') * globalSetupModifier).toBe(14)
+})
+```
+:::
+
+In this example Vitest will run all tests in `chromium` browser, but execute a `'./ratio-setup.ts'` file only in the first configuration and inject a different `ratio` value depending on the [`provide` field](/config/#provide).
+
+::: warning
+Note that you need to define the custom `name` value if you are using the same browser name because Vitest will assign the `browser` as the project name otherwise.
+:::
+
+## Filtering
+
+You can filter what projects to run with the [`--project` flag](/guide/cli#project). Vitest will automatically assign the browser name as a project name if it is not assigned manually. If the root config already has a name, Vitest will merge them: `custom` -> `custom (browser)`.
+
+```shell
+$ vitest --project=chromium
+```
+
+::: code-group
+```ts{6,8} [default]
+export default defineConfig({
+ test: {
+ browser: {
+ instances: [
+ // name: chromium
+ { browser: 'chromium' },
+ // name: custom
+ { browser: 'firefox', name: 'custom' },
+ ]
+ }
+ }
+})
+```
+```ts{3,7,9} [custom]
+export default defineConfig({
+ test: {
+ name: 'custom',
+ browser: {
+ instances: [
+ // name: custom (chromium)
+ { browser: 'chromium' },
+ // name: manual
+ { browser: 'firefox', name: 'manual' },
+ ]
+ }
+ }
+})
+```
+:::
+
+::: warning
+Vitest cannot run multiple instances that have `headless` mode set to `false` (the default behaviour). During development, you can select what project to run in your terminal:
+
+```shell
+? Found multiple projects that run browser tests in headed mode: "chromium", "firefox".
+Vitest cannot run multiple headed browsers at the same time. Select a single project
+to run or cancel and run tests with "headless: true" option. Note that you can also
+start tests with --browser=name or --project=name flag. › - Use arrow-keys. Return to submit.
+❯ chromium
+ firefox
+```
+
+If you have several non-headless projects in CI (i.e. the `headless: false` is set manually in the config and not overriden in CI env), Vitest will fail the run and won't start any tests.
+
+The ability to run tests in headless mode is not affected by this. You can still run all instances in parallel as long as they don't have `headless: false`.
+:::
diff --git a/guide/browser/playwright.md b/guide/browser/playwright.md
new file mode 100644
index 00000000..d143a2b4
--- /dev/null
+++ b/guide/browser/playwright.md
@@ -0,0 +1,96 @@
+# Configuring Playwright
+
+By default, TypeScript doesn't recognize providers options and extra `expect` properties. Make sure to reference `@vitest/browser/providers/playwright` so TypeScript can pick up definitions for custom options:
+
+```ts [vitest.shims.d.ts]
+///
+```
+
+Alternatively, you can also add it to `compilerOptions.types` field in your `tsconfig.json` file. Note that specifying anything in this field will disable [auto loading](https://www.typescriptlang.org/tsconfig/#types) of `@types/*` packages.
+
+```json [tsconfig.json]
+{
+ "compilerOptions": {
+ "types": ["@vitest/browser/providers/playwright"]
+ }
+}
+```
+
+Vitest opens a single page to run all tests in the same file. You can configure the `launch` and `context` properties in `instances`:
+
+```ts{9-10} [vitest.config.ts]
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ browser: {
+ instances: [
+ {
+ browser: 'firefox',
+ launch: {},
+ context: {},
+ },
+ ],
+ },
+ },
+})
+```
+
+::: warning
+Before Vitest 3, these options were located on `test.browser.providerOptions` property:
+
+```ts [vitest.config.ts]
+export default defineConfig({
+ test: {
+ browser: {
+ providerOptions: {
+ launch: {},
+ context: {},
+ },
+ },
+ },
+})
+```
+
+`providerOptions` is deprecated in favour of `instances`.
+:::
+
+## launch
+
+These options are directly passed down to `playwright[browser].launch` command. You can read more about the command and available arguments in the [Playwright documentation](https://playwright.dev/docs/api/class-browsertype#browser-type-launch).
+
+::: warning
+Vitest will ignore `launch.headless` option. Instead, use [`test.browser.headless`](/guide/browser/config#browser-headless).
+
+Note that Vitest will push debugging flags to `launch.args` if [`--inspect`](/guide/cli#inspect) is enabled.
+:::
+
+## context
+
+Vitest creates a new context for every test file by calling [`browser.newContext()`](https://playwright.dev/docs/api/class-browsercontext). You can configure this behaviour by specifying [custom arguments](https://playwright.dev/docs/api/class-apirequest#api-request-new-context).
+
+::: tip
+Note that the context is created for every _test file_, not every _test_ like in playwright test runner.
+:::
+
+::: warning
+Vitest awlays sets `ignoreHTTPSErrors` to `true` in case your server is served via HTTPS and `serviceWorkers` to `'allow'` to support module mocking via [MSW](https://mswjs.io).
+
+It is also recommended to use [`test.browser.viewport`](/guide/browser/config#browser-headless) instead of specifying it here as it will be lost when tests are running in headless mode.
+:::
+
+## `actionTimeout` 3.0.0
+
+- **Default:** no timeout, 1 second before 3.0.0
+
+This value configures the default timeout it takes for Playwright to wait until all accessibility checks pass and [the action](/guide/browser/interactivity-api) is actually done.
+
+You can also configure the action timeout per-action:
+
+```ts
+import { page, userEvent } from '@vitest/browser/context'
+
+await userEvent.click(page.getByRole('button'), {
+ timeout: 1_000,
+})
+```
diff --git a/guide/browser/webdriverio.md b/guide/browser/webdriverio.md
new file mode 100644
index 00000000..b0afdf78
--- /dev/null
+++ b/guide/browser/webdriverio.md
@@ -0,0 +1,69 @@
+# Configuring WebdriverIO
+
+::: info Playwright vs WebdriverIO
+If you do not already use WebdriverIO in your project, we recommend starting with [Playwright](/guide/browser/playwright) as it is easier to configure and has more flexible API.
+:::
+
+By default, TypeScript doesn't recognize providers options and extra `expect` properties. Make sure to reference `@vitest/browser/providers/webdriverio` so TypeScript can pick up definitions for custom options:
+
+```ts [vitest.shims.d.ts]
+///
+```
+
+Alternatively, you can also add it to `compilerOptions.types` field in your `tsconfig.json` file. Note that specifying anything in this field will disable [auto loading](https://www.typescriptlang.org/tsconfig/#types) of `@types/*` packages.
+
+```json [tsconfig.json]
+{
+ "compilerOptions": {
+ "types": ["@vitest/browser/providers/webdriverio"]
+ }
+}
+```
+
+Vitest opens a single page to run all tests in the same file. You can configure any property specified in `RemoteOptions` in `instances`:
+
+```ts{9-12} [vitest.config.ts]
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ browser: {
+ instances: [
+ {
+ browser: 'chrome',
+ capabilities: {
+ browserVersion: 86,
+ platformName: 'Windows 10',
+ },
+ },
+ ],
+ },
+ },
+})
+```
+
+::: warning
+Before Vitest 3, these options were located on `test.browser.providerOptions` property:
+
+```ts [vitest.config.ts]
+export default defineConfig({
+ test: {
+ browser: {
+ providerOptions: {
+ capabilities: {},
+ },
+ },
+ },
+})
+```
+
+`providerOptions` is deprecated in favour of `instances`.
+:::
+
+You can find most available options in the [WebdriverIO documentation](https://webdriver.io/docs/configuration/). Note that Vitest will ignore all test runner options because we only use `webdriverio`'s browser capabilities.
+
+::: tip
+Most useful options are located on `capabilities` object. WebdriverIO allows nested capabilities, but Vitest will ignore those options because we rely on a different mechanism to spawn several browsers.
+
+Note that Vitest will ignore `capabilities.browserName`. Use [`test.browser.instances.name`](/guide/browser/config#browser-capabilities-name) instead.
+:::
diff --git a/guide/cli-generated.md b/guide/cli-generated.md
index 28ead1c3..fe9bea30 100644
--- a/guide/cli-generated.md
+++ b/guide/cli-generated.md
@@ -316,77 +316,81 @@ High and low watermarks for functions in the format of `,`
### browser.enabled
- **CLI:** `--browser.enabled`
-- **Config:** [browser.enabled](/config/#browser-enabled)
+- **Config:** [browser.enabled](/guide/browser/config#browser-enabled)
在浏览器中运行测试。 相当于 `--browser.enabled` (默认值: `false`)
### browser.name
- **CLI:** `--browser.name `
-- **Config:** [browser.name](/config/#browser-name)
+- **Config:** [browser.name](/guide/browser/config#browser-name)
+<<<<<<< HEAD
在特定浏览器中运行所有测试。某些浏览器只适用于特定的 providers (比如 `--browser.provider`). 通过 [`browser.name`](https://vitest.dev/config/#browser-name) 查看更多信息
+=======
+Run all tests in a specific browser. Some browsers are only available for specific providers (see `--browser.provider`). Visit [`browser.name`](https://vitest.dev/guide/browser/config/#browser-name) for more information
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
### browser.headless
- **CLI:** `--browser.headless`
-- **Config:** [browser.headless](/config/#browser-headless)
+- **Config:** [browser.headless](/guide/browser/config#browser-headless)
在无头模式下运行浏览器(即不打开图形用户界面)。如果在 CI 中运行 Vitest,默认情况下将启用无头模式 (默认值: `process.env.CI`)
### browser.api.port
- **CLI:** `--browser.api.port [port]`
-- **Config:** [browser.api.port](/config/#browser-api-port)
+- **Config:** [browser.api.port](/guide/browser/config#browser-api-port)
指定服务器端口。注意,如果端口已被使用,Vite 会自动尝试下一个可用端口,因此这可能不是服务器最终监听的实际端口。如果为 `true`,将设置为 `63315`
### browser.api.host
- **CLI:** `--browser.api.host [host]`
-- **Config:** [browser.api.host](/config/#browser-api-host)
+- **Config:** [browser.api.host](/guide/browser/config#browser-api-host)
指定服务器应该监听哪些 IP 地址。设为 `0.0.0.0` 或 `true` 则监听所有地址,包括局域网地址和公共地址
### browser.api.strictPort
- **CLI:** `--browser.api.strictPort`
-- **Config:** [browser.api.strictPort](/config/#browser-api-strictport)
+- **Config:** [browser.api.strictPort](/guide/browser/config#browser-api-strictport)
设置为 true 时,如果端口已被使用,则退出,而不是自动尝试下一个可用端口
### browser.provider
- **CLI:** `--browser.provider `
-- **Config:** [browser.provider](/config/#browser-provider)
+- **Config:** [browser.provider](/guide/browser/config#browser-provider)
用于运行浏览器测试的 Provider。某些浏览器只适用于特定的提供 Provider,可以是"webdriverio", "playwright", "preview",或自定义 provider. 通过 [`browser.provider`](https://vitest.dev/config/#browser-provider) 查看更多信息 (默认值: `"preview"`)
### browser.providerOptions
- **CLI:** `--browser.providerOptions `
-- **Config:** [browser.providerOptions](/config/#browser-provideroptions)
+- **Config:** [browser.providerOptions](/guide/browser/config#browser-provideroptions)
传递给浏览器提供程序的选项。更多信息请访问 [`browser.providerOptions`](https://vitest.dev/config/#browser-provideroptions)。
### browser.isolate
- **CLI:** `--browser.isolate`
-- **Config:** [browser.isolate](/config/#browser-isolate)
+- **Config:** [browser.isolate](/guide/browser/config#browser-isolate)
隔离运行每个浏览器测试文件。要禁用隔离请使用 `--browser.isolate=false` (默认值: `true`)
### browser.ui
- **CLI:** `--browser.ui`
-- **Config:** [browser.ui](/config/#browser-ui)
+- **Config:** [browser.ui](/guide/browser/config#browser-ui)
运行测试时显示 Vitest UI(默认值: `!process.env.CI`)
### browser.fileParallelism
- **CLI:** `--browser.fileParallelism`
-- **Config:** [browser.fileParallelism](/config/#browser-fileparallelism)
+- **Config:** [browser.fileParallelism](/guide/browser/config#browser-fileparallelism)
浏览器测试文件是否应并行运行。使用 `--browser.fileParallelism=false` 可禁用 (默认值: `true`)
diff --git a/guide/migration.md b/guide/migration.md
index 32a3d8f0..15387ccd 100644
--- a/guide/migration.md
+++ b/guide/migration.md
@@ -29,6 +29,31 @@ test('validation works', () => {
}, 1000) // Ok ✅
```
+### `browser.name` and `browser.providerOptions` are Deprecated
+
+Both [`browser.name`](/guide/browser/config#browser-name) and [`browser.providerOptions`](/guide/browser/config#browser-provideroptions) will be removed in Vitest 4. Instead of them, use the new [`browser.instances`](/guide/browser/config#browser-instances) option:
+
+```ts
+export default defineConfig({
+ test: {
+ browser: {
+ name: 'chromium', // [!code --]
+ providerOptions: { // [!code --]
+ launch: { devtools: true }, // [!code --]
+ }, // [!code --]
+ instances: [ // [!code ++]
+ { // [!code ++]
+ browser: 'chromium', // [!code ++]
+ launch: { devtools: true }, // [!code ++]
+ }, // [!code ++]
+ ], // [!code ++]
+ },
+ },
+})
+```
+
+With the new `browser.instances` field you can also specify multiple browser configurations.
+
### `Custom` Type is Deprecated API {#custom-type-is-deprecated}
`Custom` 类型现在等同于 `Test` 类型。需要注意一下,Vitest 在 2.1 版本中更新了公共类型,并将导出的名称更改为 `RunnerCustomCase` 和 `RunnerTestCase`。
diff --git a/package.json b/package.json
index 83fc11f7..d0c7a03d 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"vue": "^3.5.12"
},
"devDependencies": {
+<<<<<<< HEAD
"@antfu/eslint-config": "^2.26.0",
"@antfu/ni": "^0.22.4",
"@iconify-json/carbon": "^1.2.4",
@@ -30,6 +31,13 @@
"@types/fs-extra": "^11.0.4",
"@types/node": "^22.10.2",
"@unocss/reset": "^0.65.1",
+=======
+ "@iconify-json/carbon": "^1.2.5",
+ "@iconify-json/logos": "^1.2.4",
+ "@shikijs/transformers": "^1.24.3",
+ "@shikijs/vitepress-twoslash": "^1.24.3",
+ "@unocss/reset": "^0.65.2",
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
"@vite-pwa/assets-generator": "^0.2.6",
"@vite-pwa/vitepress": "^0.5.3",
"@vitejs/plugin-vue": "^5.2.1",
@@ -44,10 +52,15 @@
"ofetch": "^1.4.1",
"pathe": "^1.1.2",
"tinyglobby": "^0.2.10",
+<<<<<<< HEAD
"tsx": "^4.19.2",
"typescript": "^5.7.2",
"unocss": "^0.65.1",
"unplugin-vue-components": "^0.27.5",
+=======
+ "unocss": "^0.65.2",
+ "unplugin-vue-components": "^0.28.0",
+>>>>>>> ad8972b35b240f2baee9909f2fec09db81c2ee8b
"vite": "^5.2.8",
"vite-plugin-pwa": "^0.21.1",
"vitepress": "^1.5.0",