Playwright JavaScript 実行

この章では、Playwright で JavaScript コードを実行する方法を紹介します。ページコンテキストでの実行、引数の受け渡し、初期化スクリプトの注入を含みます。


page.evaluate() ページコンテキストでの実行

page.evaluate()ページの JavaScript 環境でコードを実行し、DOM やページのグローバル変数にアクセスできます。

例

test('ページデータを取得', async ({ page }) => {
  await page.goto('https://www.example.com/');

  // ページタイトルを取得(ページコンテキストで実行)
  const title = await page.evaluate(() => {
    return document.title;
  });
  console.log('ページタイトル:', title);

  // ページ内のすべてのリンク数を取得
  const linkCount = await page.evaluate(() => {
    return document.querySelectorAll('a').length;
  });
  console.log('リンク数:', linkCount);

  // ページのスクロール位置を取得
  const scrollY = await page.evaluate(() => {
    return window.scrollY;
  });
});

evaluate に引数を渡す

page.evaluate()の2番目の引数はページ内の関数に渡されます。

例

test('ページに引数を渡す', async ({ page }) => {
  await page.goto('https://www.example.com/');

  // 単一の引数を渡す
  const result1 = await page.evaluate((name) => {
    return `Hello, ${name}!`;
  }, 'サンプル');

  // オブジェクトの引数を渡す
  const userInfo = { name: 'サンプル', role: 'admin' };
  const result2 = await page.evaluate((user) => {
    return `${user.name}の役割は $ です。{user.role}`;
  }, userInfo);

  // 複数の引数を渡す(分割代入を使用)
  const result3 = await page.evaluate(
    ({ x, y }) => {
      return x + y;
    },
    { x: 10, y: 20 }
  );
  console.log('10 + 20 =', result3); // 30
});

渡された引数は JSON にシリアライズされてページコンテキストに送信されるため、関数や DOM 要素などシリアライズできないオブジェクトは渡せません。

戻り値も同様にシリアライズされます。


locator.evaluate() 要素コンテキストでの実行

locator.evaluate()一致した要素のコンテキストでコードを実行します。引数にはその要素の DOM ノードへの参照が含まれます。

例

test('要素の DOM 属性を取得', async ({ page }) => {
  await page.goto('https://www.example.com/');

  // 特定の要素の textContent を取得
  const text = await page
    .getByRole('heading', { name: 'サンプル' })
    .evaluate(node => node.textContent);

  // 要素のスタイル属性を取得
  const color = await page
    .getByRole('button', { name: '検索' })
    .evaluate(node => getComputedStyle(node).backgroundColor);
});

locator.evaluateAll() 一致するすべての要素を走査

evaluateAll()一致するすべての要素に対して同じコードを実行し、配列を返します。

例

test('すべてのリスト項目のテキストを取得', async ({ page }) => {
  await page.goto('https://www.example.com/');

  // すべてのメニュー項目のテキストを取得
  const menuItems = await page
    .getByRole('navigation')
    .locator('a')
    .evaluateAll(links => links.map(link => link.textContent));

  console.log('メニュー項目:', menuItems);
  // ['ホーム', 'チュートリアル', 'ツール', ...]
});

page.addInitScript() 初期化スクリプトの注入

addInitScript()ページが読み込まれる前に JavaScript コードを注入でき、ページスクリプトの実行前にブラウザ環境を変更できます。

例

test('初期化スクリプトを注入', async ({ page }) => {
  // ページ読み込み前に navigator プロパティを変更
  await page.addInitScript(() => {
    // WebDriver 検出を上書き
    Object.defineProperty(navigator, 'webdriver', {
      get: () => false,
    });

    // window 上のグローバル変数をモック
    window.サンプル_CONFIG = {
      env: 'test',
      version: '1.0.0',
    };
  });

  await page.goto('https://www.example.com/');

  // 注入した変数が有効であることを確認
  const config = await page.evaluate(() => window.サンプル_CONFIG);
  console.log(config); // { env: 'test', version: '1.0.0' }
});

addInitScript()一般的な用途:

用途説明
ブラウザ API のモック上書きnavigator.webdriver、navigator.language 等
カスタム設定の注入テスト環境変数の設定、データソースのモックなど
機能の無効化Service Worker の停止、ログの無効化など
Polyfillページが依存しているがテスト環境にない機能を追加する

ElementHandle の用途と制限

ElementHandle は DOM 要素への直接参照であり、Playwright の初期バージョンで広く使用されていました。

現在、ほとんどのシナリオでは、LocatorLocator を ElementHandle の代わりに使用します。

例

// ElementHandle 方式(旧式、非推奨)
const handle = await page.$('.my-element');
await handle.click();

// Locator 方式(新式、推奨)
await page.locator('.my-element').click();

ElementHandle は、取得が必要な場合にのみboundingBox()または複雑な DOM 操作を行う場合に使用します。

その他の拡張