diff --git a/.vitepress/config.ts b/.vitepress/config.ts index d2228f9d..6959c157 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -246,6 +246,11 @@ export default ({ mode }: { mode: string }) => { link: '/guide/browser/webdriverio', docFooterText: 'Configuring WebdriverIO | Browser Mode', }, + { + text: 'Configuring Preview', + link: '/guide/browser/preview', + docFooterText: 'Configuring Preview | Browser Mode', + }, ], }, { diff --git a/guide/browser/assertion-api.md b/guide/browser/assertion-api.md index 9220073d..aad91ac4 100644 --- a/guide/browser/assertion-api.md +++ b/guide/browser/assertion-api.md @@ -7,18 +7,27 @@ title: Assertion API | Browser Mode Vitest 默认提供了一组丰富的 DOM 断言,这些断言源自 [`@testing-library/jest-dom`](https://github.com/testing-library/jest-dom) 库,并增加了对定位器的支持以及内置的重试能力。 ::: tip TypeScript Support +<<<<<<< HEAD 如果您使用 [TypeScript](/guide/browser/#typescript) 或希望在 `expect` 中获得正确的类型提示,请确保在某个地方引用了 `@vitest/browser/context`。如果您从未从该模块导入过,可以在 `tsconfig.json` 覆盖范围内的任何文件中添加一个 `reference` 注释: +======= +If you are using [TypeScript](/guide/browser/#typescript) or want to have correct type hints in `expect`, make sure you have `vitest/browser` referenced somewhere. If you never imported from there, you can add a `reference` comment in any file that's covered by your `tsconfig.json`: +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ```ts -/// +/// ``` ::: 浏览器中的测试由于其异步特性,可能会不一致地失败。因此,即使条件延迟(如超时、网络请求或动画),也必须有办法保证断言成功。为此,Vitest 通过 [`expect.poll`](/api/expect#poll)和 `expect.element` API 提供了可重试的断言: ```ts +<<<<<<< HEAD import { page } from '@vitest/browser/context' import { expect, test } from 'vitest' +======= +import { expect, test } from 'vitest' +import { page } from 'vitest/browser' +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a test('error banner is rendered', async () => { triggerError() diff --git a/guide/browser/commands.md b/guide/browser/commands.md index 0766cad9..7c8c0059 100644 --- a/guide/browser/commands.md +++ b/guide/browser/commands.md @@ -20,7 +20,7 @@ outline: deep ::: ```ts -import { server } from '@vitest/browser/context' +import { server } from 'vitest/browser' const { readFile, writeFile, removeFile } = server.commands @@ -38,10 +38,14 @@ it('handles files', async () => { ## CDP Session +<<<<<<< HEAD Vitest 通过 `@vitest/browser/context` 中导出的 `cdp` 方法访问原始 Chrome Devtools 协议。它主要用于库作者在其基础上构建工具。 +======= +Vitest exposes access to raw Chrome Devtools Protocol via the `cdp` method exported from `vitest/browser`. It is mostly useful to library authors to build tools on top of it. +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ```ts -import { cdp } from '@vitest/browser/context' +import { cdp } from 'vitest/browser' const input = document.createElement('input') document.body.appendChild(input) @@ -97,10 +101,14 @@ export default function BrowserCommands(): Plugin { } ``` +<<<<<<< HEAD 然后,你可以通过从 `@vitest/brower/context` 导入它,在测试中调用它: +======= +Then you can call it inside your test by importing it from `vitest/browser`: +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ```ts -import { commands } from '@vitest/browser/context' +import { commands } from 'vitest/browser' import { expect, test } from 'vitest' test('custom command works correctly', async () => { @@ -108,8 +116,13 @@ test('custom command works correctly', async () => { expect(result).toEqual({ someValue: true }) }) +<<<<<<< HEAD // 如果你使用 TypeScript,你可以扩展模块。 declare module '@vitest/browser/context' { +======= +// if you are using TypeScript, you can augment the module +declare module 'vitest/browser' { +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a interface BrowserCommands { myCustomCommand: (arg1: string, arg2: string) => Promise<{ someValue: true diff --git a/guide/browser/component-testing.md b/guide/browser/component-testing.md index 8ea0d022..6af86876 100644 --- a/guide/browser/component-testing.md +++ b/guide/browser/component-testing.md @@ -138,7 +138,7 @@ test('ProductList filters and displays products correctly', async () => { ```jsx // For Solid.js components import { render } from '@testing-library/solid' -import { page } from '@vitest/browser/context' +import { page } from 'vitest/browser' test('Solid component handles user interaction', async () => { // Use Testing Library to render the component @@ -563,9 +563,15 @@ import { render } from 'vitest-browser-react' // [!code ++] ### 主要差异 +<<<<<<< HEAD - 使用 `await expect.element()` 而不是 `expect()` 进行 DOM 断言 - 使用 `@vitest/browser/context` 进行用户交互而不是 `@testing-library/user-event` - 浏览器模式提供真实的浏览器环境以进行准确的测试 +======= +- Use `await expect.element()` instead of `expect()` for DOM assertions +- Use `vitest/browser` for user interactions instead of `@testing-library/user-event` +- Browser Mode provides real browser environment for accurate testing +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ## 了解更多 diff --git a/guide/browser/config.md b/guide/browser/config.md index 5ff9c9a4..910b9bc5 100644 --- a/guide/browser/config.md +++ b/guide/browser/config.md @@ -4,7 +4,7 @@ ```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { @@ -46,6 +46,7 @@ export default defineConfig({ ## browser.instances +<<<<<<< HEAD - **类型:** `BrowserConfig` - **默认值:** `[{ browser: name }]` @@ -55,6 +56,14 @@ export default defineConfig({ - [配置 WebdriverIO](/guide/browser/webdriverio) 除此之外,你还可以指定大多数[项目选项](/config/)(未标记为图标的选项)和一些 `browser` 选项,例如`browser.testerHtmlPath`。 +======= +- **Type:** `BrowserConfig` +- **Default:** `[]` + +Defines multiple browser setups. Every config has to have at least a `browser` field. + +You can specify most of the [project options](/config/) (not marked with a icon) and some of the `browser` options like `browser.testerHtmlPath`. +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ::: warning 每个浏览器配置都从根配置继承选项: @@ -79,9 +88,13 @@ export default defineConfig({ }) ``` +<<<<<<< HEAD 在开发过程中,Vitest 仅支持一个 [非无头](#browser-headless) 配置。我们可以通过在配置中指定 `headless: false`,或提供 `--browser.headless=false` 标志,或使用 `--project=chromium` 标志过滤项目来限制有头项目。 有关更多示例,请参阅 ["多设置" 指南](/guide/browser/multiple-setups)。 +======= +For more examples, refer to the ["Multiple Setups" guide](/guide/browser/multiple-setups). +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ::: 可用的 `browser` 选项列表: @@ -94,9 +107,13 @@ export default defineConfig({ - [`browser.screenshotFailures`](#browser-screenshotfailures) - [`browser.provider`](#browser-provider) +<<<<<<< HEAD 默认情况下,Vitest 创建一个包含单个元素的数组,该元素使用 [`browser.name`](#browser-name) 字段作为 `browser`。请注意,此行为将在 Vitest 4 中移除。 在底层,Vitest 将这些实例转换为共享单个 Vite 服务器的单独 [测试项目](/advanced/api/test-project),以获得更好的缓存性能。 +======= +Under the hood, Vitest transforms these instances into separate [test projects](/advanced/api/test-project) sharing a single Vite server for better caching performance. +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ## browser.headless @@ -134,12 +151,16 @@ HTML 入口点的路径。可以是相对于项目根目录的路径。此文件 - **默认值:** `'preview'` - **CLI:** `--browser.provider=playwright` +<<<<<<< HEAD 提供者工厂的返回值。你可以从 `@vitest/browser/providers/` 导入工厂函数,或者创建自己的提供者: +======= +The return value of the provider factory. You can import the factory from `@vitest/browser-` or make your own provider: +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ```ts{8-10} -import { playwright } from '@vitest/browser/providers/playwright' -import { webdriverio } from '@vitest/browser/providers/webdriverio' -import { preview } from '@vitest/browser/providers/preview' +import { playwright } from '@vitest/browser-playwright' +import { webdriverio } from '@vitest/browser-webdriverio' +import { preview } from '@vitest/browser-preview' export default defineConfig({ test: { @@ -155,7 +176,7 @@ export default defineConfig({ 要配置提供者如何初始化浏览器,你可以将选项传递给工厂函数: ```ts{7-13,20-26} -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { @@ -294,7 +315,11 @@ export interface BrowserScript { - **类型:** `Record` - **默认值:** `{ readFile, writeFile, ... }` +<<<<<<< HEAD 可以从 `@vitest/browser/commands` 导入的自定义 [命令](/guide/browser/commands)。 +======= +Custom [commands](/guide/browser/commands) that can be imported during browser tests from `vitest/browser`. +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ## browser.connectTimeout diff --git a/guide/browser/context.md b/guide/browser/context.md index ad803637..ecc2d017 100644 --- a/guide/browser/context.md +++ b/guide/browser/context.md @@ -4,7 +4,11 @@ title: Context API | Browser Mode # 上下文 +<<<<<<< HEAD Vitest 通过 `@vitest/browser/context` 入口点公开上下文模块。从 2.0 开始,它公开了一小部分实用程序,这些实用程序可能在测试中对你有用。 +======= +Vitest exposes a context module via `vitest/browser` entry point. As of 2.0, it exposes a small set of utilities that might be useful to you in tests. +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ## `userEvent` diff --git a/guide/browser/index.md b/guide/browser/index.md index 0a424c63..e6220c4d 100644 --- a/guide/browser/index.md +++ b/guide/browser/index.md @@ -99,7 +99,7 @@ bun add -D vitest @vitest/browser webdriverio ```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { @@ -126,7 +126,7 @@ Vitest 默认分配端口号 `63315` 以避免与开发服务器冲突,允许 ::: code-group ```ts [react] import react from '@vitejs/plugin-react' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ plugins: [react()], @@ -143,7 +143,7 @@ export default defineConfig({ ``` ```ts [vue] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' import vue from '@vitejs/plugin-vue' import { defineConfig } from 'vitest/config' @@ -162,7 +162,7 @@ export default defineConfig({ ``` ```ts [svelte] import { svelte } from '@sveltejs/vite-plugin-svelte' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ plugins: [svelte()], @@ -179,7 +179,7 @@ export default defineConfig({ ``` ```ts [solid] import solidPlugin from 'vite-plugin-solid' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ plugins: [solidPlugin()], @@ -196,7 +196,7 @@ export default defineConfig({ ``` ```ts [marko] import marko from '@marko/vite' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ plugins: [marko()], @@ -213,7 +213,7 @@ export default defineConfig({ ``` ```ts [qwik] import { qwikVite } from '@builder.io/qwik/optimizer' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' // optional, run the tests in SSR mode import { testSSR } from 'vitest-browser-qwik/ssr-plugin' @@ -239,7 +239,7 @@ export default defineConfig({ ```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { @@ -333,7 +333,7 @@ headless 模式是浏览器模式下可用的另一个选项。在 headless 模 ```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { @@ -363,8 +363,13 @@ npx vitest --browser.headless 一般情况下,我们不需要任何依赖来使用浏览器模式: ```js [example.test.js] +<<<<<<< HEAD import { page } from '@vitest/browser/context' import { expect, test } from 'vitest' +======= +import { expect, test } from 'vitest' +import { page } from 'vitest/browser' +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a import { render } from './my-render-function.js' test('properly handles form inputs', async () => { @@ -401,15 +406,25 @@ test('properly handles form inputs', async () => { 除了渲染组件和定位元素外,你还需要进行断言。Vitest 基于 [`@testing-library/jest-dom`](https://github.com/testing-library/jest-dom) 库提供了一整套开箱即用的 DOM 断言。更多信息请参阅 [Assertions API](/guide/browser/assertion-api)。 ```ts +<<<<<<< HEAD import { page } from '@vitest/browser/context' import { expect } from 'vitest' // element is rendered correctly await expect.element(page.getByText('Hello World')).toBeInTheDocument() ``` Vitest 公开了一个[Context API](/guide/browser/context),其中包含一小套在测试中可能有用的实用程序。例如,如果我们需要进行交互,如点击元素或在输入框中输入文本,我们可以使用 `@vitest/browser/context` 中的 `userEvent`。更多信息请参阅 [Interactivity API](/guide/browser/interactivity-api)。 +======= +import { expect } from 'vitest' +import { page } from 'vitest/browser' +// element is rendered correctly +await expect.element(page.getByText('Hello World')).toBeInTheDocument() +``` + +Vitest exposes a [Context API](/guide/browser/context) with a small set of utilities that might be useful to you in tests. For example, if you need to make an interaction, like clicking an element or typing text into an input, you can use `userEvent` from `vitest/browser`. Read more at the [Interactivity API](/guide/browser/interactivity-api). +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ```ts -import { page, userEvent } from '@vitest/browser/context' +import { page, userEvent } from 'vitest/browser' await userEvent.fill(page.getByLabelText(/username/i), 'Alice') // or just locator.fill await page.getByLabelText(/username/i).fill('Alice') @@ -526,7 +541,11 @@ Vitest 并不支持所有开箱即用的框架,但我们可以使用外部工 我们还可以在 [`browser-examples`](https://github.com/vitest-tests/browser-examples) 中查看更多的案例。 ::: warning +<<<<<<< HEAD `testing-library` 提供了一个软件包 `@testing-library/user-event`。我们不建议直接使用它,因为它会模拟事件而非实际触发事件--相反,请使用从 `@vitest/browser/context`导入的 [`userEvent`](/guide/browser/interactivity-api),它在引擎盖下使用 Chrome DevTools 协议或 Webdriver(取决于provider)。 +======= +`testing-library` provides a package `@testing-library/user-event`. We do not recommend using it directly because it simulates events instead of actually triggering them - instead, use [`userEvent`](/guide/browser/interactivity-api) imported from `vitest/browser` that uses Chrome DevTools Protocol or Webdriver (depending on the provider) under the hood. +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ::: ::: code-group diff --git a/guide/browser/interactivity-api.md b/guide/browser/interactivity-api.md index 3b2cacfb..928524aa 100644 --- a/guide/browser/interactivity-api.md +++ b/guide/browser/interactivity-api.md @@ -7,7 +7,7 @@ title: Interactivity API | Browser Mode Vitest 使用 [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) 或 [webdriver](https://www.w3.org/TR/webdriver/) 实现了 [`@testing-library/user-event`](https://testing-library.com/docs/user-event/intro) 库的子集 API,而不是伪造事件,这使得浏览器行为更加可靠和一致,符合用户与页面交互的方式。 ```ts -import { userEvent } from '@vitest/browser/context' +import { userEvent } from 'vitest/browser' await userEvent.click(document.querySelector('.button')) ``` @@ -23,9 +23,16 @@ function setup(): UserEvent 创建一个新的用户事件实例。如果需要保持键盘状态,以便正确按下和释放按钮,这将非常有用。 ::: warning +<<<<<<< HEAD 与 `@testing-library/user-event` 不同,来自 `@vitest/browser/context` 的默认 `userEvent` 实例只创建一次,而不是每次调用其方法时都创建一次!您可以从本代码段中看到其工作方式的不同之处: ```ts +======= +Unlike `@testing-library/user-event`, the default `userEvent` instance from `vitest/browser` is created once, not every time its methods are called! You can see the difference in how it works in this snippet: + +```ts +import { userEvent as vitestUserEvent } from 'vitest/browser' +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a import { userEvent as originalUserEvent } from '@testing-library/user-event' import { userEvent as vitestUserEvent } from '@vitest/browser/context' @@ -51,7 +58,7 @@ function click( 点击元素。继承 provider 的选项。有关此方法如何工作的详细说明,请参阅 provider 的文档。 ```ts -import { page, userEvent } from '@vitest/browser/context' +import { page, userEvent } from 'vitest/browser' test('clicks on an element', async () => { const logo = page.getByRole('img', { name: /logo/ }) @@ -82,7 +89,7 @@ function dblClick( 请参阅你的 provider 的文档以获取有关此方法如何工作的详细说明。 ```ts -import { page, userEvent } from '@vitest/browser/context' +import { page, userEvent } from 'vitest/browser' test('triggers a double click on an element', async () => { const logo = page.getByRole('img', { name: /logo/ }) @@ -113,7 +120,7 @@ function tripleClick( 请参阅你的提供商文档以获取有关此方法工作原理的详细说明。 ```ts -import { page, userEvent } from '@vitest/browser/context' +import { page, userEvent } from 'vitest/browser' test('triggers a triple click on an element', async () => { const logo = page.getByRole('img', { name: /logo/ }) @@ -150,7 +157,7 @@ function fill( 为 `input` `、textarea` 或 `contenteditable` 元素设置新的内容,并且在赋值前会先清空其中已有的文本。 ```ts -import { page, userEvent } from '@vitest/browser/context' +import { page, userEvent } from 'vitest/browser' test('update input', async () => { const input = page.getByRole('input') @@ -189,7 +196,7 @@ function keyboard(text: string): Promise 此 API 支持 [user-event `keyboard` 语法](https://testing-library.com/docs/user-event/keyboard)。 ```ts -import { userEvent } from '@vitest/browser/context' +import { userEvent } from 'vitest/browser' test('trigger keystrokes', async () => { await userEvent.keyboard('foo') // translates to: f, o, o @@ -215,7 +222,7 @@ function tab(options?: UserEventTabOptions): Promise 发送一个 `Tab` 键事件。这是`userEvent.keyboard('{tab}')`的简写。 ```ts -import { page, userEvent } from '@vitest/browser/context' +import { page, userEvent } from 'vitest/browser' test('tab works', async () => { const [input1, input2] = page.getByRole('input').elements() @@ -259,7 +266,7 @@ function type( 如果只需按下字符而无需输入,请使用 [`userEvent.keyboard`](#userevent-keyboard) API。 ```ts -import { page, userEvent } from '@vitest/browser/context' +import { page, userEvent } from 'vitest/browser' test('update input', async () => { const input = page.getByRole('input') @@ -289,7 +296,7 @@ function clear(element: Element | Locator, options?: UserEventClearOptions): Pro 此方法会清除输入元素的内容。 ```ts -import { page, userEvent } from '@vitest/browser/context' +import { page, userEvent } from 'vitest/browser' test('clears input', async () => { const input = page.getByRole('input') @@ -336,7 +343,7 @@ The `userEvent.selectOptions` allows selecting a value in a `` 元素中选择一个或多个值。 ```ts -import { page } from '@vitest/browser/context' +import { page } from 'vitest/browser' const languages = page.getByRole('select', { name: 'Languages' }) @@ -784,7 +784,7 @@ function screenshot(options?: LocatorScreenshotOptions & { base64?: false }): Pr 如果你还需要屏幕截图的内容,可以指定 `base64: true` 以返回屏幕截图的 base64 编码内容以及保存路径。 ```ts -import { page } from '@vitest/browser/context' +import { page } from 'vitest/browser' const button = page.getByRole('button', { name: 'Click Me!' }) @@ -945,8 +945,13 @@ const test: BrowserCommand = function test(context, selector) { ``` ```ts [example.test.ts] +<<<<<<< HEAD import { commands, page } from '@vitest/browser/context' import { test } from 'vitest' +======= +import { test } from 'vitest' +import { commands, page } from 'vitest/browser' +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a test('works correctly', async () => { await commands.test(page.getByText('Hello').selector) // ✅ @@ -988,7 +993,7 @@ The selector syntax is identical to Playwright locators. Please, read [their gui ::: ```ts -import { locators } from '@vitest/browser/context' +import { locators } from 'vitest/browser' locators.extend({ getByArticleTitle(title) { @@ -1010,7 +1015,7 @@ locators.extend({ // if you are using typescript, you can extend LocatorSelectors interface // to have the autocompletion in locators.extend, page.* and locator.* methods -declare module '@vitest/browser/context' { +declare module 'vitest/browser' { interface LocatorSelectors { // if the custom method returns a string, it will be converted into a locator // if it returns anything else, then it will be returned as usual diff --git a/guide/browser/multiple-setups.md b/guide/browser/multiple-setups.md index 392a27be..13cf3506 100644 --- a/guide/browser/multiple-setups.md +++ b/guide/browser/multiple-setups.md @@ -1,6 +1,10 @@ # 多种设置 +<<<<<<< HEAD 自 Vitest 3 起,你可以使用新的 [`browser.instances`](/guide/browser/config#browser-instances) 选项来指定多个不同的浏览器设置。 +======= +You can specify several different browser setups using the [`browser.instances`](/guide/browser/config#browser-instances) option. +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a 与 [测试项目](/guide/projects) 相比,使用 `browser.instances` 的最大好处在于缓存效率更高。所有项目会共享同一个 Vite 服务器,因此文件转换和 [依赖的预打包](https://vite.dev/guide/dep-pre-bundling.html) 只需进行一次即可。 @@ -10,7 +14,7 @@ ```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { @@ -35,7 +39,7 @@ export default defineConfig({ ::: code-group ```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { @@ -50,14 +54,14 @@ export default defineConfig({ setupFiles: ['./ratio-setup.ts'], provide: { ratio: 1, - } + }, }, { browser: 'chromium', name: 'chromium-2', provide: { ratio: 2, - } + }, }, ], }, @@ -119,6 +123,7 @@ export default defineConfig({ }) ``` ::: +<<<<<<< HEAD ::: warning Vitest 无法运行多个将 `headless` 模式设置为 `false`(默认行为)的实例。在开发过程中,你可以在终端中选择要运行的项目: @@ -136,3 +141,5 @@ start tests with --browser=name or --project=name flag. › - Use arrow-keys. Re 这一限制不影响在无头模式下运行测试的能力。只要实例没有设置 `headless: false`,你仍然可以并行运行所有实例。 ::: +======= +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a diff --git a/guide/browser/playwright.md b/guide/browser/playwright.md index 2e539fba..54653709 100644 --- a/guide/browser/playwright.md +++ b/guide/browser/playwright.md @@ -1,9 +1,13 @@ # 配置 Playwright +<<<<<<< HEAD 要使用 playwright 运行测试,你需要在配置中的 `test.browser.provider` 属性中指定它: +======= +To run tests using playwright, you need to install the [`@vitest/browser-playwright`](https://www.npmjs.com/package/@vitest/browser-playwright) npm package and specify its `playwright` export in the `test.browser.provider` property of your config: +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ```ts [vitest.config.js] -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -16,10 +20,14 @@ export default defineConfig({ }) ``` +<<<<<<< HEAD Vitest 在单个页面中运行同一文件中的所有测试。你可以在顶层或实例内部调用 `playwright` 时配置 `launch`、`connect` 和 `context`: +======= +You can configure the [`launchOptions`](https://playwright.dev/docs/api/class-browsertype#browser-type-launch), [`connectOptions`](https://playwright.dev/docs/api/class-browsertype#browser-type-connect) and [`contextOptions`](https://playwright.dev/docs/api/class-browser#browser-new-context) when calling `playwright` at the top level or inside instances: +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ```ts{7-14,21-26} [vitest.config.js] -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -53,6 +61,10 @@ export default defineConfig({ }) ``` +::: warning +Unlike Playwright test runner, Vitest opens a _single_ page to run all tests that are defined in the same file. This means that isolation is restricted to a single test file, not to every individual test. +::: + ## launchOptions 这些选项直接传递给 `playwright[browser].launch` 命令。我们可以在 [Playwright 文档](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) 中阅读有关该命令和可用参数的更多信息。 @@ -94,7 +106,7 @@ Vitest 通过调用 [`browser.newContext()`](https://playwright.dev/docs/api/cla 我们还可以为每个操作配置操作超时: ```ts -import { page, userEvent } from '@vitest/browser/context' +import { page, userEvent } from 'vitest/browser' await userEvent.click(page.getByRole('button'), { timeout: 1_000, diff --git a/guide/browser/preview.md b/guide/browser/preview.md new file mode 100644 index 00000000..8b8bb3d4 --- /dev/null +++ b/guide/browser/preview.md @@ -0,0 +1,32 @@ +# Configuring Preview + +::: warning +The `preview` provider's main functionality is to show tests in a real browser environment. However, it does not support advanced browser automation features like multiple browser instances or headless mode. For more complex scenarios, consider using [Playwright](/guide/browser/playwright) or [WebdriverIO](/guide/browser/webdriverio). +::: + +To see your tests running in a real browser, you need to install the [`@vitest/browser-preview`](https://www.npmjs.com/package/@vitest/browser-preview) npm package and specify its `preview` export in the `test.browser.provider` property of your config: + +```ts [vitest.config.js] +import { preview } from '@vitest/browser-preview' +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + browser: { + provider: preview(), + instances: [{ browser: 'chromium' }] + }, + }, +}) +``` + +This will open a new browser window using your default browser to run the tests. You can configure which browser to use by setting the `browser` property in the `instances` array. Vitest will try to open that browser automatically, but it might not work in some environments. In that case, you can manually open the provided URL in your desired browser. + +## Differences with Other Providers + +The preview provider has some limitations compared to other providers like [Playwright](/guide/browser/playwright) or [WebdriverIO](/guide/browser/webdriverio): + +- It does not support headless mode; the browser window will always be visible. +- It does not support multiple instances of the same browser; each instance must use a different browser. +- It does not support advanced browser capabilities or options; you can only specify the browser name. +- It does not support CDP (Chrome DevTools Protocol) commands or other low-level browser interactions. Unlike Playwright or WebdriverIO, the [`userEvent`](/guide/browser/interactivity-api) API is just re-exported from [`@testing-library/user-event`](https://www.npmjs.com/package/@testing-library/user-event) and does not have any special integration with the browser. diff --git a/guide/browser/trace-viewer.md b/guide/browser/trace-viewer.md index 2e8984dd..2d17ef52 100644 --- a/guide/browser/trace-viewer.md +++ b/guide/browser/trace-viewer.md @@ -9,7 +9,7 @@ Generating trace files is only available when using the [Playwright provider](/g ::: code-group ```ts [vitest.config.js] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { @@ -39,7 +39,7 @@ To change the output directory, you can set the `tracesDir` option in the `test. ```ts [vitest.config.js] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { diff --git a/guide/browser/visual-regression-testing.md b/guide/browser/visual-regression-testing.md index 5d8ac7bf..7a1b6310 100644 --- a/guide/browser/visual-regression-testing.md +++ b/guide/browser/visual-regression-testing.md @@ -39,8 +39,13 @@ Vitest 原生支持可视化回归测试。它会自动截取 UI 组件或页面 在 Vitest 中,可通过 [`toMatchScreenshot` assertion](/guide/browser/assertion-api.html#tomatchscreenshot) 断言运行可视化回归测试: ```ts +<<<<<<< HEAD import { page } from '@vitest/browser/context' import { expect, test } from 'vitest' +======= +import { expect, test } from 'vitest' +import { page } from 'vitest/browser' +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a test('hero section looks correct', async () => { // ...the rest of the test @@ -213,7 +218,7 @@ await page.viewport(1280, 720) ``` ```ts [vitest.config.ts] -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -560,7 +565,7 @@ jobs: ```ts [vitest.config.ts] import { env } from 'node:process' import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ // ...global Vite config diff --git a/guide/browser/webdriverio.md b/guide/browser/webdriverio.md index 702188ec..f63ecc04 100644 --- a/guide/browser/webdriverio.md +++ b/guide/browser/webdriverio.md @@ -4,10 +4,14 @@ 如果我们的项目尚未使用 WebdriverIO,我们建议从 [Playwright](/guide/browser/playwright) 开始,因为它更易于配置且 API 更灵活。 ::: +<<<<<<< HEAD 要使用 WebdriverIO 运行测试,你需要在配置中的 `test.browser.provider` 属性中指定它: +======= +To run tests using WebdriverIO, you need to install the [`@vitest/browser-webdriverio`](https://www.npmjs.com/package/@vitest/browser-webdriverio) npm package and specify its `webdriverio` export in the `test.browser.provider` property of your config: +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ```ts [vitest.config.js] -import { webdriverio } from '@vitest/browser/providers/webdriverio' +import { webdriverio } from '@vitest/browser-webdriverio' import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -20,10 +24,14 @@ export default defineConfig({ }) ``` +<<<<<<< HEAD Vitest 打开一个页面以在同一文件中运行所有测试。你可以配置 [`remote`](https://webdriver.io/docs/api/modules/#remoteoptions-modifier) 函数接受的所有参数: +======= +You can configure all the parameters that [`remote`](https://webdriver.io/docs/api/modules/#remoteoptions-modifier) function accepts: +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a -```ts{8-12,19-23} [vitest.config.js] -import { webdriverio } from '@vitest/browser/providers/webdriverio' +```ts{8-12,19-25} [vitest.config.js] +import { webdriverio } from '@vitest/browser-webdriverio' import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -42,11 +50,13 @@ export default defineConfig({ // overriding options only for a single instance // this will NOT merge options with the parent one provider: webdriverio({ - 'moz:firefoxOptions': { - args: ['--disable-gpu'], + capabilities: { + 'moz:firefoxOptions': { + args: ['--disable-gpu'], + }, }, }) - } + }, ], }, }, @@ -58,5 +68,9 @@ export default defineConfig({ ::: tip 最有用的选项位于 `capabilities` 对象上。WebdriverIO 允许嵌套功能,但 Vitest 将忽略这些选项,因为我们依赖于不同的机制来生成多个浏览器。 +<<<<<<< HEAD 请注意,Vitest 将忽略 `capabilities.browserName`。请改用 [`test.browser.instances.browser`](/guide/browser/config#browser-capabilities-name)。 +======= +Note that Vitest will ignore `capabilities.browserName` — use [`test.browser.instances.browser`](/guide/browser/config#browser-capabilities-name) instead. +>>>>>>> 19c97cda6761cd60ffae67ea0d917be9f960dd1a ::: diff --git a/guide/debugging.md b/guide/debugging.md index b065608e..cf114c24 100644 --- a/guide/debugging.md +++ b/guide/debugging.md @@ -66,7 +66,7 @@ vitest --inspect-brk --browser --no-file-parallelism ``` ```ts [vitest.config.js] import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser/providers/playwright' +import { playwright } from '@vitest/browser-playwright' export default defineConfig({ test: { diff --git a/guide/migration.md b/guide/migration.md index d058551a..133cd79f 100644 --- a/guide/migration.md +++ b/guide/migration.md @@ -209,12 +209,12 @@ export default defineWorkspace([ // [!code --] ``` ::: -### Browser Provider Accepts an Object +### Browser Provider Rework -In Vitest 4.0, the browser provider now accepts an object instead of a string (`'playwright'`, `'webdriverio'`). This makes it simpler to work with custom options and doesn't require adding `/// { + await page.getByRole('button').click() +}) +``` + +The modules are identical, so doing a simple "Find and Replace" should be sufficient. + +If you were using the `@vitest/browser/utils` module, you can now import those utilities from `vitest/browser` as well: + +```ts +import { getElementError } from '@vitest/browser/utils' // [!code --] +import { utils } from 'vitest/browser' // [!code ++] +const { getElementError } = utils // [!code ++] +``` + +::: warning +Both `@vitest/browser/context` and `@vitest/browser/utils` work at runtime during the transition period, but they will be removed in a future release. +::: + ### Reporter Updates Reporter APIs `onCollected`, `onSpecsCollected`, `onPathsCollected`, `onTaskUpdate` and `onFinished` were removed. See [`Reporters API`](/advanced/api/reporters) for new alternatives. The new APIs were introduced in Vitest `v3.0.0`. @@ -271,7 +296,7 @@ export default defineConfig({ In Vitest 4.0 snapshots that include custom elements will print the shadow root contents. To restore the previous behavior, set the [`printShadowRoot` option](/config/#snapshotformat) to `false`. -```js +```js{15-22} // before Vite 4.0 exports[`custom element with shadow root 1`] = ` "