ブラウザモード 実験的機能
このページでは、Vitest API の実験的なブラウザモード機能について説明します。この機能により、テストをブラウザでネイティブに実行し、window や document などのブラウザのグローバルオブジェクトにアクセスできるようになります。この機能は現在開発中であり、将来的に 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 プロバイダーは Chrome DevTools Protocol を使用する代わりにイベントをシミュレートするため、ローカルでのテストにはどちらかのプロバイダーに切り替えることを推奨します。
これらのツールをまだ使用していない場合は、Playwright から始めることをお勧めします。Playwright は並列実行をサポートしており、テストの実行を高速化できるためです。さらに、Playwright が使用する Chrome DevTools Protocol は、一般的に 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 の設定でブラウザモードを有効にするには、--browser フラグを使用するか、Vitest 設定ファイルで browser.enabled フィールドを true に設定します。以下は、browser フィールドを使用した設定例です。
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 関連のドキュメントを確認してください。
import { defineConfig } from 'vitest/config';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
test: {
browser: {
enabled: true,
provider: 'playwright',
name: 'chromium',
},
},
});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',
},
},
});import { defineConfig } from 'vitest/config';
import solidPlugin from 'vite-plugin-solid';
export default defineConfig({
plugins: [solidPlugin()],
test: {
browser: {
enabled: true,
provider: 'playwright',
name: 'chromium',
},
},
});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 ベースのランナーを使用して一部のテストを実行する必要がある場合は、異なるテスト戦略のために個別の設定を持つ ワークスペース ファイルを定義できます。
// 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 Vitest がブラウザを起動し、ページコンテキストを作成する方法は、providerOptions フィールドで設定できます。
export default defineConfig({
test: {
browser: {
providerOptions: {
launch: {
devtools: true,
},
context: {
geolocation: {
latitude: 45,
longitude: -30,
},
reducedMotion: 'reduce',
},
},
},
},
});型ヒントを得るには、tsconfig.json ファイルの compilerOptions.types に @vitest/browser/providers/playwright を追加します。 == WebdriverIO Vitest がブラウザを起動する際に使用するオプションは、providerOptions フィールドで設定できます。
export default defineConfig({
test: {
browser: {
browser: 'chrome',
providerOptions: {
region: 'eu',
capabilities: {
browserVersion: '27.0',
platformName: 'Windows 10',
},
},
},
},
});型ヒントを得るには、tsconfig.json ファイルの compilerOptions.types に @vitest/browser/providers/webdriverio を追加します。 :::
ブラウザオプションの型
Vitest のブラウザオプションはプロバイダーに依存します。--browser を渡し、設定ファイルでその名前を指定しない場合、Vitest は失敗します。利用可能なオプション:
webdriverioは以下のブラウザをサポートしています:firefoxchromeedgesafari
playwrightは以下のブラウザをサポートしています:firefoxwebkitchromium
ブラウザの互換性
Vitest は Vite 開発サーバー を使用してテストを実行するため、esbuild.target オプション (esnext がデフォルト) で指定された機能のみをサポートします。
デフォルトでは、Vite はネイティブの ES Modules、ネイティブの ESM dynamic import、および import.meta をサポートするブラウザをターゲットとします。それに加えて、iframe 間で通信するために BroadcastChannel を使用します。
- Chrome >=87
- Firefox >=78
- Safari >=15.4
- Edge >=88
テストの実行
ブラウザオプションでブラウザ名を指定すると、Vitest はデフォルトで指定されたブラウザを preview を使用して実行しようとし、そこでテストを実行します。preview を使用したくない場合は、browser.provider オプションを使用してカスタムブラウザプロバイダーを設定できます。
CLI を使用してブラウザを指定するには、--browser フラグの後にブラウザ名を指定します。
npx vitest --browser=chromeまたは、ドット記法でブラウザオプションを CLI に提供することもできます。
npx vitest --browser.name=chrome --browser.headlessデフォルトでは、Vitest は開発時にブラウザ UI を自動的に開きます。テストは中央の iframe 内で実行されます。ビューポートは、好みの寸法を選択するか、テスト内で page.viewport を呼び出すか、設定でデフォルト値を設定することで設定できます。
ヘッドレス
ヘッドレスモードは、ブラウザモードで利用できるもう1つのオプションです。ヘッドレスモードでは、ブラウザはユーザーインターフェースなしでバックグラウンドで実行されるため、自動テストの実行に役立ちます。Vitest のヘッドレスオプションは、ヘッドレスモードを有効または無効にする真偽値で設定できます。
ヘッドレスモードを使用する場合、Vitest は UI を自動的に開きません。UI を引き続き使用しながらテストをヘッドレスで実行したい場合は、@vitest/ui パッケージをインストールし、Vitest の実行時に --ui フラグを渡します。
ヘッドレスモードを有効にする設定例を次に示します。
export default defineConfig({
test: {
browser: {
provider: 'playwright',
enabled: true,
headless: true,
},
},
});CLI で --browser.headless フラグを使用してヘッドレスモードを設定することもできます。
npx vitest --browser.name=chrome --browser.headlessこの場合、Vitest は Chrome ブラウザを使用してヘッドレスモードで実行されます。
WARNING
ヘッドレスモードはデフォルトでは利用できません。この機能を有効にするには、playwright または webdriverio プロバイダーのいずれかを使用する必要があります。
例
Vitest は、いくつかの人気のあるフレームワークのコンポーネントをすぐにレンダリングするためのパッケージを提供しています。
- vue コンポーネントをレンダリングするための
vitest-browser-vue - svelte コンポーネントをレンダリングするための
vitest-browser-svelte - react コンポーネントをレンダリングするための
vitest-browser-react
お使いのフレームワークがリストにない場合は、ご自身のパッケージを作成することも可能です。これはフレームワークレンダラーと page.elementLocator API のシンプルなラッパーとなります。このページにリンクを追加します。名前が vitest-browser- で始まるようにしてください。
コンポーネントのレンダリングと要素の特定に加えて、アサーションも行う必要があります。Vitest は、幅広い DOM アサーションをすぐに利用できるように、@testing-library/jest-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();
});Vitest はすべてのフレームワークをそのままサポートしているわけではありませんが、これらのフレームワークでテストを実行するために外部ツールを使用できます。また、コミュニティが独自の vitest-browser ラッパーを作成することを奨励しています。もし作成された場合は、上記の例に追加していただけると幸いです。
サポートされていないフレームワークの場合、testing-library パッケージの使用をお勧めします。
- preact コンポーネントをレンダリングするための
@testing-library/preact - solid コンポーネントをレンダリングするための
@solidjs/testing-library - marko コンポーネントをレンダリングするための
@marko/testing-library
WARNING
testing-library は @testing-library/user-event パッケージを提供しています。これはイベントを実際にトリガーするのではなくシミュレートするため、直接使用することは推奨されません。代わりに、内部で Chrome DevTools Protocol または Webdriver (プロバイダーによる) を使用する @vitest/browser/context からインポートされた userEvent を使用してください。
// @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();
});// @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();
await expect.element(container.firstChild).toMatchInlineSnapshot(`
<h1>Hello, Marko!</h1>
`);
});制限事項
スレッドブロックダイアログ
Vitest Browser を使用する場合、alert や confirm のようなスレッドブロックダイアログはネイティブでは使用できない点に注意が必要です。これらのダイアログはウェブページをブロックし、Vitest がページとの通信を継続できなくなるため、実行がハングアップする原因となります。
このような状況では、Vitest はこれらの API のデフォルト戻り値を持つデフォルトのモックを提供します。これにより、ユーザーが誤って同期ポップアップ Web API を使用した場合でも、実行がハングアップするのを防ぎます。ただし、より良いエクスペリエンスのために、これらの Web API をモックすることを推奨します。詳細については、モックをご参照ください。