Skip to content
Vitest 2
Main Navigation 指南API配置浏览器模式高级
3.2.0
2.1.9
1.6.1
0.34.6

简体中文

English
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

简体中文

English
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

主题

Sidebar Navigation

Why Browser Mode?

Getting Started

Context API

Interactivity API

Locators

Assertion API

Commands API

页面导航

浏览器模式 实验性 ​

本页介绍 Vitest API 中实验性的浏览器模式功能。此功能允许您在浏览器中原生运行测试,并提供访问 window 和 document 等浏览器全局对象。此功能目前处于开发阶段,未来 API 可能会有所变化。

Vitest UIVitest UI

安装 ​

为了简化设置,您可以使用 vitest init browser 命令来安装所需的依赖项并创建浏览器配置。

bash
npx vitest init browser
bash
yarn exec vitest init browser
bash
pnpx vitest init browser
bash
bunx vitest init browser

手动安装 ​

您也可以手动安装软件包。默认情况下,浏览器模式在本地运行测试时不需要任何额外的 E2E 提供程序,因为它会复用您现有的浏览器。

bash
npm install -D vitest @vitest/browser
bash
yarn add -D vitest @vitest/browser
bash
pnpm add -D vitest @vitest/browser
bash
bun add -D vitest @vitest/browser

WARNING

不过,要在 CI 中运行测试,您需要安装 playwright 或 webdriverio。我们还建议在本地测试时切换到其中任一个,而不是使用默认的 preview 提供程序,因为它依赖于模拟事件而不是使用 Chrome DevTools Protocol。

如果您还未使用这些工具中的任何一个,我们建议您从 Playwright 开始,因为它支持并行执行,可以加快测试运行速度。此外,Playwright 使用的 Chrome DevTools 协议通常比 WebDriver 更快。

::: tabs key:provider == Playwright Playwright 是一个用于 Web 测试和自动化的框架。

bash
npm install -D vitest @vitest/browser playwright
bash
yarn add -D vitest @vitest/browser playwright
bash
pnpm add -D vitest @vitest/browser playwright
bash
bun add -D vitest @vitest/browser playwright

== WebdriverIO

WebdriverIO 允许您使用 WebDriver 协议在本地运行测试。

bash
npm install -D vitest @vitest/browser webdriverio
bash
yarn add -D vitest @vitest/browser webdriverio
bash
pnpm add -D vitest @vitest/browser webdriverio
bash
bun add -D vitest @vitest/browser webdriverio

配置 ​

要在 Vitest 配置中激活浏览器模式,您可以使用 --browser 标志或在 Vitest 配置文件中将 browser.enabled 字段设置为 true。以下是使用 browser 字段的配置示例:

ts
export default defineConfig({
  test: {
    browser: {
      provider: 'playwright', // 或 'webdriverio'
      enabled: true,
      name: 'chromium', // 必须指定浏览器名称
    },
  },
});

INFO

Vitest 分配端口 63315 以避免与开发服务器冲突,从而允许您并行运行两者。您可以使用 browser.api 选项更改此设置。

自 Vitest 2.1.5 起,CLI 不再自动打印 Vite URL。在监听模式下运行时,您可以按“b”打印 URL。

如果您之前没有使用过 Vite,请确保您已安装框架的插件并在配置中指定。某些框架可能需要额外配置才能正常运行 - 请查看其 Vite 相关文档以确保。

ts
import { defineConfig } from 'vitest/config';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  test: {
    browser: {
      enabled: true,
      provider: 'playwright',
      name: 'chromium',
    },
  },
});
ts
import { defineConfig } from 'vitest/config';
import { svelte } from '@sveltejs/vite-plugin-svelte';

export default defineConfig({
  plugins: [svelte()],
  test: {
    browser: {
      enabled: true,
      provider: 'playwright',
      name: 'chromium',
    },
  },
});
ts
import { defineConfig } from 'vitest/config';
import solidPlugin from 'vite-plugin-solid';

export default defineConfig({
  plugins: [solidPlugin()],
  test: {
    browser: {
      enabled: true,
      provider: 'playwright',
      name: 'chromium',
    },
  },
});
ts
import { defineConfig } from 'vitest/config';
import marko from '@marko/vite';

export default defineConfig({
  plugins: [marko()],
  test: {
    browser: {
      enabled: true,
      provider: 'playwright',
      name: 'chromium',
    },
  },
});

TIP

react 不需要插件即可工作,但 preact 需要额外配置才能使别名工作。

如果您需要使用基于 Node 的运行器运行某些测试,您可以定义一个工作区文件,其中包含针对不同测试策略的单独配置:

ts
// vitest.workspace.ts
import { defineWorkspace } from 'vitest/config';

export default defineWorkspace([
  {
    test: {
      // 基于文件命名的示例,
      // 您无需严格遵循
      include: [
        'tests/unit/**/*.{test,spec}.ts',
        'tests/**/*.unit.{test,spec}.ts',
      ],
      name: 'unit',
      environment: 'node',
    },
  },
  {
    test: {
      // 基于文件命名的示例,
      // 您无需严格遵循
      include: [
        'tests/browser/**/*.{test,spec}.ts',
        'tests/**/*.browser.{test,spec}.ts',
      ],
      name: 'browser',
      browser: {
        enabled: true,
        name: 'chrome',
      },
    },
  },
]);

提供程序配置 ​

:::tabs key:provider == Playwright 您可以通过 providerOptions 字段配置 Vitest 如何启动浏览器和创建页面上下文:

ts
export default defineConfig({
  test: {
    browser: {
      providerOptions: {
        launch: {
          devtools: true,
        },
        context: {
          geolocation: {
            latitude: 45,
            longitude: -30,
          },
          reducedMotion: 'reduce',
        },
      },
    },
  },
});

如需获得类型提示,请将 @vitest/browser/providers/playwright 添加到 tsconfig.json 文件中的 compilerOptions.types。 == WebdriverIO 您可以通过 providerOptions 字段配置 Vitest 在启动浏览器时应使用哪些选项:

ts
export default defineConfig({
  test: {
    browser: {
      browser: 'chrome',
      providerOptions: {
        region: 'eu',
        capabilities: {
          browserVersion: '27.0',
          platformName: 'Windows 10',
        },
      },
    },
  },
});

如需获得类型提示,请将 @vitest/browser/providers/webdriverio 添加到 tsconfig.json 文件中的 compilerOptions.types。 :::

浏览器选项类型 ​

Vitest 中的浏览器选项取决于提供程序。如果您传递 --browser 但未在配置文件中指定其名称,Vitest 会报错。可用选项:

  • webdriverio 支持以下浏览器:
    • firefox
    • chrome
    • edge
    • safari
  • playwright 支持以下浏览器:
    • firefox
    • webkit
    • chromium

浏览器兼容性 ​

Vitest 使用 Vite 开发服务器运行您的测试,因此我们仅支持 esbuild.target 选项(默认为 esnext)中指定的功能。

默认情况下,Vite 针对支持原生 ES Modules、原生 ESM 动态导入和 import.meta 的浏览器。除此之外,我们还利用 BroadcastChannel 在 iframe 之间进行通信:

  • Chrome >=87
  • Firefox >=78
  • Safari >=15.4
  • Edge >=88

运行测试 ​

当您在浏览器选项中指定浏览器名称时,Vitest 将尝试默认使用 preview 运行指定的浏览器,然后在其中运行测试。如果您不想使用 preview,可以通过使用 browser.provider 选项配置自定义浏览器提供程序。

要使用 CLI 指定浏览器,请使用 --browser 标志,后跟浏览器名称,如下所示:

sh
npx vitest --browser=chrome

或者您可以使用点表示法向 CLI 提供浏览器选项:

sh
npx vitest --browser.name=chrome --browser.headless

默认情况下,Vitest 将自动打开浏览器 UI 进行开发。测试将在中央的 iframe 中运行。您可以通过选择首选尺寸、在测试中调用 page.viewport 或在配置中设置默认值来配置视口。

无头模式 ​

无头模式是浏览器模式中可用的另一个选项。在无头模式下,浏览器会在后台运行,没有用户界面,这使得它对于运行自动化测试非常有用。Vitest 中的无头选项可以设置为布尔值以启用或禁用无头模式。

使用无头模式时,Vitest 不会自动打开 UI。如果您想继续使用 UI 但让测试在无头模式下运行,您可以安装 @vitest/ui 包并在运行 Vitest 时传递 --ui 标志。

以下是启用无头模式的配置示例:

ts
export default defineConfig({
  test: {
    browser: {
      provider: 'playwright',
      enabled: true,
      headless: true,
    },
  },
});

您还可以使用 CLI 中的 --browser.headless 标志设置无头模式,如下所示:

sh
npx vitest --browser.name=chrome --browser.headless

在这种情况下,Vitest 将使用 Chrome 浏览器在无头模式下运行。

WARNING

无头模式默认不可用。您需要使用 playwright 或 webdriverio 提供程序才能启用此功能。

示例 ​

Vitest 提供了一些开箱即用的软件包,用于渲染几种流行框架的组件:

  • vitest-browser-vue 用于渲染 vue 组件
  • vitest-browser-svelte 用于渲染 svelte 组件
  • vitest-browser-react 用于渲染 react 组件

如果您的框架没有被支持,请随时创建您自己的软件包 - 它只是框架渲染器和 page.elementLocator API 的简单包装器。我们将在本页上添加指向它的链接。请确保其名称以 vitest-browser- 开头。

除了渲染组件和定位元素之外,您还需要进行断言。Vitest 内置了 @testing-library/jest-dom 库,以提供广泛的 DOM 断言。详情请参阅断言 API。

ts
import { expect } from 'vitest';
import { page } from '@vitest/browser/context';
// 元素是否正确渲染
await expect.element(page.getByText('Hello World')).toBeInTheDocument();

Vitest 提供了一个上下文 API,其中包含一些在测试中可能对您有用的实用程序。例如,如需进行交互,例如单击元素或在输入框中输入文本,您可以使用 @vitest/browser/context 中的 userEvent。请参阅交互性 API 了解更多信息。

ts
import { page, userEvent } from '@vitest/browser/context';
await userEvent.fill(page.getByLabelText(/username/i), 'Alice');
// 或者直接使用 locator.fill
await page.getByLabelText(/username/i).fill('Alice');
ts
import { render } from 'vitest-browser-vue';
import Component from './Component.vue';

test('properly handles v-model', async () => {
  const screen = render(Component);

  // 验证初始状态。
  await expect
    .element(screen.getByText('Hi, my name is Alice'))
    .toBeInTheDocument();

  // 通过查询关联的标签获取输入 DOM 节点。
  const usernameInput = screen.getByLabelText(/username/i);

  // 在输入框中输入名称。这已自动验证输入是否正确填充,
  // 无需手动检查值。
  await usernameInput.fill('Bob');

  await expect
    .element(screen.getByText('Hi, my name is Bob'))
    .toBeInTheDocument();
});
ts
import { render } from 'vitest-browser-svelte';
import { expect, test } from 'vitest';

import Greeter from './greeter.svelte';

test('greeting appears on click', async () => {
  const screen = render(Greeter, { name: 'World' });

  const button = screen.getByRole('button');
  await button.click();
  const greeting = screen.getByText(/hello world/iu);

  await expect.element(greeting).toBeInTheDocument();
});
tsx
import { render } from 'vitest-browser-react';
import Fetch from './fetch';

test('loads and displays greeting', async () => {
  // 将 React 元素渲染到 DOM 中
  const screen = render(<Fetch url="/greeting" />);

  await screen.getByText('Load Greeting').click();
  // 如果找不到元素,则等待一段时间再抛出错误
  const heading = screen.getByRole('heading');

  // 断言警告消息是否正确
  await expect.element(heading).toHaveTextContent('hello there');
  await expect.element(screen.getByRole('button')).toBeDisabled();
});

Vitest 并非原生支持所有框架,但您可以使用外部工具运行这些框架的测试。我们也鼓励社区创建自己的 vitest-browser 包装器 - 如果您有,请随时将其添加到上面的示例中。

对于不受支持的框架,我们建议使用 testing-library 包:

  • @testing-library/preact 用于渲染 preact 组件
  • @solidjs/testing-library 用于渲染 solid 组件
  • @marko/testing-library 用于渲染 marko 组件

WARNING

testing-library 提供了一个包 @testing-library/user-event。我们不建议直接使用它,因为它模拟事件而不是实际触发它们 - 相反,请使用从 @vitest/browser/context 导入的 userEvent,它在底层使用 Chrome DevTools Protocol 或 Webdriver(取决于提供程序)。

tsx
// 基于 @testing-library/preact 示例
// https://testing-library.com/docs/preact-testing-library/example

import { h } from 'preact';
import { page } from '@vitest/browser/context';
import { render } from '@testing-library/preact';

import HiddenMessage from '../hidden-message';

test('shows the children when the checkbox is checked', async () => {
  const testMessage = 'Test Message';

  const { baseElement } = render(<HiddenMessage>{testMessage}</HiddenMessage>);

  const screen = page.elementLocator(baseElement);

  // .query() 将返回元素,如果找不到则返回 null。
  // .element() 将返回元素,如果找不到则抛出错误。
  expect(screen.getByText(testMessage).query()).not.toBeInTheDocument();

  // 查询可以接受正则表达式,以使您的选择器更具弹性,
  // 能够应对内容调整和更改。
  await screen.getByLabelText(/show/i).click();

  await expect.element(screen.getByText(testMessage)).toBeInTheDocument();
});
tsx
// 基于 @testing-library/solid API
// https://testing-library.com/docs/solid-testing-library/api

import { render } from '@testing-library/solid';

it('uses params', async () => {
  const App = () => (
    <>
      <Route
        path="/ids/:id"
        component={() => (
          <p>
            Id:
            {useParams()?.id}
          </p>
        )}
      />
      <Route path="/" component={() => <p>Start</p>} />
    </>
  );
  const { baseElement } = render(() => <App />, { location: 'ids/1234' });
  const screen = page.elementLocator(baseElement);

  await expect.screen(screen.getByText('Id: 1234')).toBeInTheDocument();
});
ts
// 基于 @testing-library/marko API
// https://testing-library.com/docs/marko-testing-library/api

import { render, screen } from '@marko/testing-library';
import Greeting from './greeting.marko';

test('renders a message', async () => {
  const { baseElement } = await render(Greeting, { name: 'Marko' });
  const screen = page.elementLocator(baseElement);
  await expect.element(screen.getByText(/Marko/)).toBeInTheDocument();
  await expect.element(container.firstChild).toMatchInlineSnapshot(`
    <h1>Hello, Marko!</h1>
  `);
});

限制 ​

线程阻塞对话框 ​

使用 Vitest Browser 时,需要注意的是,不能原生使用 alert 或 confirm 等线程阻塞对话框。这是因为它们会阻塞网页,这意味着 Vitest 无法继续与页面通信,导致执行挂起。

在这种情况下,Vitest 为这些 API 提供了带有默认返回值的默认模拟。这确保了如果用户意外使用同步弹出式 Web API,执行不会挂起。但是,仍然建议用户模拟这些 Web API 以获得更好的体验。请参阅模拟了解更多信息。

Pager
上一页Why Browser Mode?
下一页Context API

基于 MIT 许可证 发布。

版权所有 (c) 2021-Present Vitest Team

https://v2.vitest.dev/guide/

基于 MIT 许可证 发布。

版权所有 (c) 2021-Present Vitest Team