瀏覽器模式 實驗性
此頁面提供 Vitest API 中實驗性瀏覽器模式功能的相關資訊。此功能允許您在瀏覽器中原生執行測試,並可存取 window 和 document 等瀏覽器全域變數。此功能目前仍在開發中,未來的 API 可能會有所變更。
TIP
如果您正在尋找 expect、vi 或任何通用 API(例如測試專案或型別測試)的相關文件,請參閱「入門指南」。


安裝
為簡化設定流程,您可以使用 vitest init browser 命令來安裝所需的依賴套件並建立瀏覽器配置。
npx vitest init browseryarn exec vitest init browserpnpx vitest init browserbunx vitest init browser手動安裝
您也可以手動安裝套件。預設情況下,瀏覽器模式無需任何額外的 E2E 提供者即可在本地執行測試,因為它會重複使用您現有的瀏覽器實例。
npm install -D vitest @vitest/browseryarn add -D vitest @vitest/browserpnpm add -D vitest @vitest/browserbun add -D vitest @vitest/browserWARNING
然而,要在 CI 環境中執行測試,您需要安裝 playwright 或 webdriverio。我們也建議在本地測試時切換到其中一個提供者,而非使用預設的 preview 提供者,因為 preview 依賴於模擬事件,而非使用 Chrome 開發者工具協議。
如果您尚未採用這些工具,建議從 Playwright 開始,因為它支援平行執行,能顯著加快測試速度。此外,Playwright 使用 Chrome 開發者工具協議,這通常比 WebDriver 更快。
::: tabs key:provider == Playwright Playwright 是一個用於 Web 測試和自動化的框架。
npm install -D vitest @vitest/browser playwrightyarn add -D vitest @vitest/browser playwrightpnpm add -D vitest @vitest/browser playwrightbun add -D vitest @vitest/browser playwright== WebdriverIO
WebdriverIO 允許您使用 WebDriver 協議在本地執行測試。
npm install -D vitest @vitest/browser webdriverioyarn add -D vitest @vitest/browser webdriveriopnpm add -D vitest @vitest/browser webdriveriobun add -D vitest @vitest/browser webdriverio配置
要在 Vitest 設定中啟用瀏覽器模式,請在 Vitest 設定檔中將 browser.enabled 選項設定為 true。以下是使用 browser 選項的設定範例:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
browser: {
provider: 'playwright', // 或 'webdriverio'
enabled: true,
// 至少需要一個實例
instances: [{ browser: 'chromium' }],
},
},
});INFO
Vitest 分配連接埠 63315 以避免與開發伺服器衝突,允許您同時執行兩者。您可以使用 browser.api 選項更改此設定。
自 Vitest 2.1.5 起,CLI 不再自動顯示 Vite URL。您可以在監聽模式下執行時按「b」來顯示 URL。
如果您之前沒有使用過 Vite,請確保您已安裝並在設定中指定了您的框架外掛程式。某些框架可能需要額外的設定才能運作 - 請查閱其 Vite 相關文件以確保。
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});import { defineConfig } from 'vitest/config';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});import { defineConfig } from 'vitest/config';
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
plugins: [svelte()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});import { defineConfig } from 'vitest/config';
import solidPlugin from 'vite-plugin-solid';
export default defineConfig({
plugins: [solidPlugin()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});import { defineConfig } from 'vitest/config';
import marko from '@marko/vite';
export default defineConfig({
plugins: [marko()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});如果您需要使用基於 Node 的執行器執行某些測試,您可以定義一個 projects 選項,其中包含不同測試策略的獨立設定:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
projects: [
{
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,
instances: [{ browser: 'chromium' }],
},
},
},
],
},
});瀏覽器選項類型
Vitest 中的瀏覽器選項取決於所選的提供者。如果您傳遞 --browser 但未在設定檔中指定其名稱,Vitest 將會失敗。可用選項:
webdriverio支援以下瀏覽器:firefoxchromeedgesafari
playwright支援以下瀏覽器:firefoxwebkitchromium
TypeScript
預設情況下,TypeScript 無法識別提供者選項和額外的 expect 屬性。如果您沒有使用任何提供者,請確保 @vitest/browser/matchers 在您的測試、設定檔 或 設定檔 中有被引用,以便取得額外的 expect 定義。如果您使用自訂提供者,請確保將 @vitest/browser/providers/playwright 或 @vitest/browser/providers/webdriverio 添加到同一個檔案中,以便 TypeScript 可以取得自訂選項的定義:
/// <reference types="@vitest/browser/matchers" />/// <reference types="@vitest/browser/providers/playwright" />/// <reference types="@vitest/browser/providers/webdriverio" />或者,您也可以將它們添加到 tsconfig.json 檔案中的 compilerOptions.types 選項。請注意,在此選項中指定任何內容將會禁用 @types/* 套件的自動載入。
{
"compilerOptions": {
"types": ["@vitest/browser/matchers"]
}
}{
"compilerOptions": {
"types": ["@vitest/browser/providers/playwright"]
}
}{
"compilerOptions": {
"types": ["@vitest/browser/providers/webdriverio"]
}
}瀏覽器相容性
Vitest 使用 Vite 開發伺服器 來執行您的測試,因此我們只支援 esbuild.target 選項中指定的功能(預設為 esnext)。
預設情況下,Vite 針對支援原生 ES 模組、原生 ESM 動態導入 和 import.meta 的瀏覽器。除此之外,我們還利用 BroadcastChannel 在 iframe 之間進行通訊:
- Chrome >=87
- Firefox >=78
- Safari >=15.4
- Edge >=88
執行測試
當您在瀏覽器選項中指定瀏覽器名稱時,Vitest 將預設嘗試使用 preview 執行指定的瀏覽器,然後在那裡執行測試。如果您不想使用 preview,可以透過 browser.provider 選項設定自訂瀏覽器提供者。
要使用 CLI 指定瀏覽器,請使用 --browser 旗標,後跟瀏覽器名稱,如下所示:
npx vitest --browser=chromium或者您可以使用點符號將瀏覽器選項提供給 CLI:
npx vitest --browser.headlessWARNING
自 Vitest 3.2 起,如果您在設定中沒有 browser 選項但指定了 --browser 旗標,Vitest 將會失敗,因為它無法假定該設定是用於瀏覽器而不是 Node.js 測試。
預設情況下,Vitest 將自動開啟瀏覽器 UI 進行開發。您的測試將在中央的 iframe 中執行。您可以透過選擇偏好的尺寸、在測試中呼叫 page.viewport 或在設定中設定預設值來設定視窗大小。
無頭模式
無頭模式是瀏覽器模式中另一個可用的選項。在無頭模式下,瀏覽器在後台執行,沒有使用者介面,這使得它對於執行自動化測試非常有用。Vitest 中的 headless 選項可以設定為布林值以啟用或禁用無頭模式。
使用無頭模式時,Vitest 不會自動開啟 UI。如果您想繼續使用 UI 但讓測試以無頭模式執行,您可以安裝 @vitest/ui 套件並在執行 Vitest 時傳入 --ui 旗標。
以下是啟用無頭模式的設定範例:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
browser: {
provider: 'playwright',
enabled: true,
headless: true,
},
},
});您也可以使用 CLI 中的 --browser.headless 旗標設定無頭模式,如下所示:
npx vitest --browser.headless在這種情況下,Vitest 將使用 Chrome 瀏覽器以無頭模式執行。
WARNING
無頭模式預設不可用。您需要使用 playwright 或 webdriverio 提供者才能啟用此功能。
範例
預設情況下,您不需要任何外部套件即可使用瀏覽器模式:
import { expect, test } from 'vitest';
import { page } from '@vitest/browser/context';
import { render } from './my-render-function.js';
test('properly handles form inputs', async () => {
render(); // 掛載 DOM 元素
// 驗證初始狀態。
await expect
.element(page.getByText('Hi, my name is Alice'))
.toBeInTheDocument();
// 透過查詢相關標籤來取得輸入 DOM 元素。
const usernameInput = page.getByLabelText(/username/i);
// 將名稱輸入到輸入欄位中。這已經驗證了輸入是否正確填寫,
// 無需手動檢查值。
await usernameInput.fill('Bob');
await expect
.element(page.getByText('Hi, my name is Bob'))
.toBeInTheDocument();
});然而,Vitest 也提供了開箱即用的套件,用於渲染多種流行框架的組件:
vitest-browser-vue用於渲染 vue 組件vitest-browser-svelte用於渲染 svelte 組件vitest-browser-react用於渲染 react 組件
其他框架的社群套件:
vitest-browser-lit用於渲染 lit 組件vitest-browser-preact用於渲染 preact 組件
如果您的框架未列出,請隨時建立您自己的套件 - 它只是框架渲染器和 page.elementLocator API 的簡單包裝。我們將在此頁面上添加連結。請確保其名稱以 vitest-browser- 開頭。
除了渲染組件和定位元素之外,您還需要進行斷言。Vitest 分支了 @testing-library/jest-dom 函式庫,以提供開箱即用的各種 DOM 斷言。請參閱 斷言 API 以了解更多資訊。
import { expect } from 'vitest';
import { page } from '@vitest/browser/context';
// 元素已正確渲染
await expect.element(page.getByText('Hello World')).toBeInTheDocument();Vitest 暴露了一個 Context API,其中包含一小部分在測試中可能對您有用的工具。例如,如果您需要進行互動,例如點擊元素或在輸入欄位中輸入文字,您可以使用來自 @vitest/browser/context 的 userEvent。請參閱 互動 API 以了解更多資訊。
import { page, userEvent } from '@vitest/browser/context';
await userEvent.fill(page.getByLabelText(/username/i), 'Alice');
// 或直接 locator.fill
await page.getByLabelText(/username/i).fill('Alice');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();
});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();
});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();
});import { render } from 'vitest-browser-lit';
import { html } from 'lit';
import './greeter-button';
test('greeting appears on click', async () => {
const screen = render(html`<greeter-button name="World"></greeter-button>`);
const button = screen.getByRole('button');
await button.click();
const greeting = screen.getByText(/hello world/iu);
await expect.element(greeting).toBeInTheDocument();
});import { render } from 'vitest-browser-preact';
import { createElement } from 'preact';
import Greeting from '.Greeting';
test('greeting appears on click', async () => {
const screen = render(<Greeting />);
const button = screen.getByRole('button');
await button.click();
const greeting = screen.getByText(/hello world/iu);
await expect.element(greeting).toBeInTheDocument();
});Vitest 並非開箱即用支援所有框架,但您可以使用外部工具來執行這些框架的測試。我們也鼓勵社群建立自己的 vitest-browser 包裝函式 - 如果您有,請隨時將其添加到上述範例中。
對於不支援的框架,我們建議使用 testing-library 套件:
@solidjs/testing-library用於渲染 solid 組件@marko/testing-library用於渲染 marko 組件
您也可以在 browser-examples 儲存庫中查看更多範例。
WARNING
testing-library 提供了一個套件 @testing-library/user-event。我們不建議直接使用它,因為它模擬事件而不是實際觸發它們 - 相反,請使用從 @vitest/browser/context 導入的 userEvent,它在底層使用 Chrome 開發者工具協議或 Webdriver(取決於提供者)。
// 基於 @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();
});// 基於 @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();
expect(container.firstChild).toMatchInlineSnapshot(`
<h1>Hello, Marko!</h1>
`);
});限制
執行緒阻塞對話框
使用 Vitest 瀏覽器時,請務必注意無法原生使用 alert 或 confirm 等阻塞式對話框。這是因為它們會阻塞網頁,這表示 Vitest 無法繼續與頁面溝通,導致執行掛起。
在這種情況下,Vitest 提供了預設的模擬,並為這些 API 提供了預設的回傳值。這確保了如果使用者意外使用同步彈出視窗網頁 API,執行不會掛起。然而,仍然建議使用者模擬這些網頁 API 以獲得更好的體驗。請參閱 模擬 以了解更多資訊。