Playwrightの waitUntil: networkidle と domcontentloaded の違い

Playwright Testing E2E Frontend
結論

networkidle は非推奨です。domcontentloaded + expect(locator).toBeVisible() を使います。

// Playwright公式推奨:Flaky を防ぐ堅牢なページ遷移コード
import { test, expect } from '@playwright/test';

test('ユーザーダッシュボード表示テスト', async ({ page }) => {
  // 1. waitUntil には domcontentloaded を指定して即座に完了させる
  await page.goto('/dashboard', { waitUntil: 'domcontentloaded' });

  // 2. 目的の要素が可視化されるのを Locator 経由で自動待機(Actionability Check)
  const heading = page.getByRole('heading', { name: 'ダッシュボード' });
  await expect(heading).toBeVisible();
});

Playwright公式仕様:waitUntil オプションの評価比較

Playwright公式ドキュメント(playwright.dev/docs/api/class-page)において、page.goto()waitUntil パラメータは以下のように定義されています。

オプション名公式評価完了の判定タイミング特徴と注意点
'domcontentloaded'推奨DOMContentLoaded イベント発火時HTMLのパース完了時点で終了。高速でテストが最も安定
'load'標準 (デフォルト)load イベント発火時画像やスタイルシートを含む全アセットの読み込み完了
'networkidle'⚠️ 非推奨 (DISCOURAGED)少なくとも 500ms 間ネットワーク通信がゼロになった時バックグラウンド通信やアナリティクスでタイムアウト頻発

なぜ networkidle は非推奨で Flaky テストの主因になるのか?

Playwright開発チームが networkidle の使用を「DISCOURAGED(非推奨)」と警告している最大の理由は、現代のWebアプリケーションの通信構造にあります。

SPAや現代のWebサイトでは、以下のようなバックグラウンド通信が継続的に発生します:

  • SWR や React Query による裏でのデータ再取得
  • Google Analytics や Sentry へのメトリクス送信
  • 画像やアドバナーの遅延読み込み(Lazy Loading)

networkidle を指定すると、これらの通信によって「500ms 間ネットワークリクエスト数が0件」という条件が満たされず、TimeoutError: page.goto: Timeout 30000ms exceeded が多発してテストが落ちる事故が発生します。


正しいテスト待機手順

  1. page.goto(url, { waitUntil: 'domcontentloaded' }) でHTMLロード完了直後にテスト制御を戻す
  2. 通信完了を直接待つのではなく、表示したいコンポーネントの Locator を定義する
  3. await expect(page.getByTestId('user-profile')).toBeVisible() でアサーションを行う(Playwrightの自動リトライ機能が働く)