Vitest 4 のブラウザモード - jsdom を卒業して実ブラウザでテストする

Vitest 4 のブラウザモード - jsdom を卒業して実ブラウザでテストする

作成日:
更新日:

ユニットテストやコンポーネントテストを書くとき、長らく定番だったのは jsdom や happy-dom のような擬似的なDOM環境でした。Node.js 上で「ブラウザのフリ」をする仕組みです。手軽な一方、「テストは通るのに実ブラウザだと挙動が違う」という擬似DOM特有のズレに悩まされることもありました。

2025年10月22日にリリースされた Vitest 4 で、その答えになるブラウザモード(Browser Mode)が experimental(実験的)から安定版になりました。Playwright 経由で実際のブラウザを使ってテストを走らせる機能です。

この記事では、Vitest 4 のブラウザモードを、設定方法・移行のポイント・新しいアサーションとともに整理します。テスト環境構築の総論は Vitest × Playwright でのテスト環境記事を、Playwright の普段使いは Playwright CLI で普段の Chrome に attach する記事も合わせてどうぞ。

ブラウザモードとは何か

ブラウザモードは、Vitest のテストをNode.js ではなく本物のブラウザの中で実行する仕組みです。windowdocument といったブラウザのグローバルに、擬似実装ではなく実物としてアクセスできます。

方式DOM の正体長所短所
jsdom / happy-domJS による擬似実装軽い・速い・設定が楽実ブラウザとの挙動差。一部API未実装
ブラウザモード実ブラウザ(Playwright 等)実環境に忠実。レイアウト・可視性も測れる起動コストがやや高い

「擬似DOMで十分なテスト」と「実ブラウザでしか正確に測れないテスト」は別物です。要素の可視性、スクロール、実際のCSS適用、IntersectionObserver の挙動などは、擬似DOMだと再現しきれません。ブラウザモードはここを埋めます。

プロバイダは3種類

ブラウザモードは、実ブラウザを操作する「プロバイダ」を選べます。

プロバイダ対応ブラウザ備考
PlaywrightChromium / Firefox / WebKit並列実行に対応。CI で推奨
WebdriverIOChrome / Firefox / Edge / SafariWebDriver ベース
Preview(開発用の軽量オプション)手元の確認用。CI には Playwright/WebdriverIO 推奨

すでに E2E で Playwright を使っているプロジェクトなら、プロバイダも Playwright で揃えるのが自然です。

設定方法

最小構成はこうです。vitest.config.tstest.browser を設定します。

vitest.config.ts(ブラウザモード)
import { defineConfig } from 'vitest/config'
import { playwright } from '@vitest/browser-playwright'
 
export default defineConfig({
  test: {
    browser: {
      enabled: true,
      provider: playwright(),
      instances: [
        { browser: 'chromium' },
      ],
    },
  },
})

IMPORTANT

Vitest 4 では、プロバイダが別パッケージに分離されました。Playwright を使うなら @vitest/browser-playwright を追加でインストールします(WebdriverIO は @vitest/browser-webdriverio、Preview は @vitest/browser-preview)。また、ブラウザ用ユーティリティの import 元は、旧来の @vitest/browser/context ではなく vitest/browser に変わりました。3系から上げる場合はここでつまずきやすい点です。

instances に複数のブラウザを並べれば、Chromium・Firefox・WebKit を横断してテストできます。

複数ブラウザで実行
instances: [
  { browser: 'chromium' },
  { browser: 'firefox' },
  { browser: 'webkit' },
]

Vitest 4 のブラウザ関連の新機能

ブラウザモードの安定化に加え、Vitest 4 ではブラウザテストが一段強化されました。

toMatchScreenshot: ビジュアルリグレッションテスト

スクリーンショット比較が組み込みになりました。toMatchScreenshot で、意図しない見た目の変化を検知できます。

見た目の変化を検知する
import { page } from 'vitest/browser'
import { expect, test } from 'vitest'
 
test('ボタンの見た目が変わっていない', async () => {
  // ... コンポーネントを描画 ...
  await expect(page.getByRole('button')).toMatchScreenshot()
})

これまで visual regression は専用ツールや Playwright 側で行うことが多かったのですが、コンポーネントテストの流れの中で書けるようになりました。

toBeInViewport: 可視性の判定

toBeInViewport マッチャは、IntersectionObserver API を使って要素がビューポート内に見えているかを判定します。「擬似DOMでは正確に測れない可視性」を、実ブラウザならではの精度でテストできます。

Playwright トレース対応

--browser.trace フラグや設定で Playwright のトレースを生成でき、テストレポートからトレースのリンクをたどって Playwright Trace Viewer で確認できます。失敗したブラウザテストの原因調査が格段に楽になります。

iframe 対応・ロケータ強化

page.frameLocator で iframe 内の要素を扱えるようになり(Playwright のみ)、すべてのロケータが length プロパティを持つようになって toHaveLength と組み合わせやすくなりました。

jsdom からの移行をどう考えるか

ここで現実的な話をします。本ブログ自身は、現時点で次の構成です。

本ブログの現在の vitest.config.ts(jsdom 方式)
export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',
    globals: true,
    setupFiles: ['./vitest.setup.ts'],
    include: ['**/__tests__/**/*.{test,spec}.{ts,tsx}'],
  },
})

Vitest は 4.0.18、Playwright も導入済みですが、ユニット・コンポーネントテストは今も environment: 'jsdom' で回しています。これは「悪い」わけではありません。全部をブラウザモードにする必要はないからです。

現実的な指針はこうです。

  • 純粋なロジック・データ整形のテスト: jsdom すら不要。Node 環境で最速。ブラウザモードにする意味は薄い
  • 一般的なコンポーネントの描画・イベント: jsdom で十分なことが多い。軽くて速い
  • 可視性・レイアウト・スクロール・実CSS依存・見た目の回帰: ここはブラウザモードの出番。toBeInViewporttoMatchScreenshot が効く

つまり「jsdom を全廃」ではなく、擬似DOMでは正確に測れないテストだけブラウザモードに切り出すのが筋の良い使い分けです。Vitest は同一プロジェクト内でワークスペース的に環境を分けられるので、「ロジックは Node、コンポーネントは jsdom、可視性まわりはブラウザ」と段階的に併用できます。

1つの設定ファイルで完結する強み

Vitest のブラウザモードの利点は、既存の Vite/Vitest 設定をそのまま使えることです。vite.config のプラグインやエイリアスがテストにもそのまま効くので、本番ビルドとテストで設定が二重管理になりません。

E2E は引き続き Playwright(playwright test)で、コンポーネント〜ユニットは Vitest(必要な部分だけブラウザモード)で、と役割分担しつつ、Vitest 側はブラウザ実行でも単一設定で完結する——この一貫性が2026年のテスト体験を軽くしています。

まとめ

  • Vitest 4(2025年10月22日)でブラウザモードが experimental から安定版に
  • ブラウザモードは jsdom/happy-dom の擬似DOMではなく、Playwright 等で実ブラウザを使ってテストする方式
  • 設定は test.browserenabled / provider / instances。Vitest 4 ではプロバイダが別パッケージ(@vitest/browser-playwright 等)に分離、import 元は vitest/browser に変更
  • 新機能: toMatchScreenshot(ビジュアルリグレッション)、toBeInViewport(可視性)、Playwright トレース、frameLocator
  • 全廃ではなく使い分けが筋: ロジックは Node、一般コンポーネントは jsdom、可視性・レイアウト・見た目はブラウザモード
  • 既存の Vite/Vitest 設定をそのまま使えるので、設定の二重管理が起きない

「テストは通るのに実ブラウザだと違う」を減らしたいなら、まずは可視性やレイアウトに絡む一部のテストだけブラウザモードに移してみるのが、コストを抑えた第一歩です。

参考リンク