Playwright操作(Actions)

この章では、Playwright におけるナビゲーションやクリックに関連する操作と、操作の背後にある自動待機メカニズムについて紹介します。


Actionとは

Action(操作)は、Playwright でユーザーの操作をシミュレートするメソッドです。例: ボタンのクリック、テキスト入力、ドロップダウンの選択。

各 Action の実行前に、Playwright は自動的にターゲット要素が次の状態になるのを待ちます:操作可能な状態。


Actionability(可操作性)チェック

各操作を実行する前に、Playwright はターゲット要素に対して一連のチェックを行います:

手順チェック条件説明
1. Attached要素がDOMツリーにマウントされている要素がページ内に存在する
2. Visible要素が表示されている(非表示ではないdisplay:none 或 visibility:hidden)ユーザーは要素を見ることができる
3. Stable要素の位置が安定している(アニメーション終了)アニメーション中の誤操作を防ぐ
4. Receives Events要素が他の要素に覆われていないクリックが要素に届くことを保証する
5. Enabled要素が無効になっていない(無効ではないdisabled)ユーザーは対話できる

いずれかのステップが失敗した場合、Playwright はタイムアウトになるまで待機して再試行します。

この5つのステップのチェックは Playwright が自動で行うため、追加の待機コードを書く必要はありません。これが Playwright が不安定なテストを大幅に減らせる根本的な理由です。


強制操作 { force: true }

場合によっては、可操作性チェックをバイパスする必要があります。例えば、マスクで隠されたボタンをクリックする、非表示要素の状態をテストするなどです。

例

// 強制クリック、すべての可操作性チェックをスキップ
await page.getByRole('button', { name: '提交' }).click({ force: true });

force: trueこれはテストで実際のユーザーができない操作を再現するものであり、ほとんどの場合使用すべきではありません。もしテストで必要になる場合、force: true、まずインタラクションデザインの問題がないか確認してください。


ナビゲーション操作

page.goto() ページ遷移

例

// 基本ナビゲーション
await page.goto('https://www.example.com/');

// DOMContentLoaded(ページ構造の読み込み完了)を待機
await page.goto('https://www.example.com/', { waitUntil: 'domcontentloaded' });

// ネットワークがアイドル状態(すべての非同期データの読み込み完了)を待機
await page.goto('https://www.example.com/', {
  waitUntil: 'networkidle',    // ネットワークアイドル
  timeout: 60000,              // タイムアウト60秒
  referer: 'https://google.com', // Referer 参照元
});

page.goBack() / goForward() / reload()

例

// 1ページ戻る
await page.goBack();

// 1ページ進む
await page.goForward();

// ページをリロード
await page.reload();

クリック操作

locator.click() クリック

例

// 基本クリック
await page.getByRole('button', { name: '登录' }).click();

// オプション付きクリック
await page.getByRole('button', { name: '登录' }).click({
  button: 'left',     // マウスボタン:'left' | 'right' | 'middle'
  clickCount: 1,      // クリック回数
  delay: 100,         // 押下と解放の間の遅延(ミリ秒)
  timeout: 5000,      // タイムアウト時間
  modifiers: [],      // 修飾キー:['Alt', 'Control', 'Meta', 'Shift']
});

locator.dblclick() ダブルクリック

例

// 要素をダブルクリック
await page.getByText('双击编辑').dblclick();

右クリック

例

// 右クリック(コンテキストメニューを開く)
await page.getByText('右键菜单').click({ button: 'right' });

修飾キーを押しながらクリック

例

// Ctrl + クリック(複数選択)
await page.getByRole('option').click({ modifiers: ['Control'] });

// Shift + クリック(範囲選択 / 新しいウィンドウで開く)
await page.getByRole('link').click({ modifiers: ['Shift'] });

座標クリック

例

// 要素の特定位置をクリック(要素の左上基準)
await page.locator('canvas').click({
  position: { x: 100, y: 50 },
});

locator.hover() ホバー

例

// マウスホバー(ホバー効果やドロップダウンメニューをトリガー)
await page.getByRole('link', { name: '教程' }).hover();

// ホバー後に表示されたサブメニューをクリック
await page.getByRole('link', { name: 'Playwright 教程' }).click();

クリック vs ホバーの使用シーンの違い

操作適用シーン
click()ボタンのクリック、リンク遷移、チェックボックスの切り替え
dblclick()編集モードへの移行、ダブルクリックでのテキスト選択
click({ button: 'right' })ブラウザのネイティブコンテキストメニューを開く
hover()ホバーメニューやツールチップの表示をトリガー
click({ position })Canvas操作、カスタムグラフィックスのインタラクション

テキスト入力操作

locator.fill() クリアして入力

fill()入力欄をクリアしてから新しい値を入力します。入力操作で最も一般的で推奨される方法です。

例

// 入力欄をクリアして新しい値を入力
await page.getByLabel('用户名').fill('サンプル_user');
await page.getByLabel('密码').fill('secure_password');
await page.getByPlaceholder('搜索サンプル教程').fill('Playwright');

locator.type() 一文字ずつ入力

type()1文字ずつ入力し、実際のキーボード入力をシミュレートします。各キー入力の間に間隔を設定できます。

例

// 一文字ずつ入力(各文字間に100msの遅延)
await page.getByLabel('搜索').type('Playwright', { delay: 100 });

fill vs type の違い

メソッド動作適用シーン
fill()クリアしてから一度に入力ほとんどのシーン(推奨)
type()一文字ずつ入力し、各キーイベントをトリガー入力候補(オートコンプリート)やリアルタイム検索をトリガーする必要がある場合

ほとんどの場合はこちらを使用fill()それで十分です。入力ボックスにリアルタイム検索(keydown/keyup イベント)がある場合のみ、使用する必要があります。type()。

locator.clear() クリア

例

// 入力ボックスの内容をクリア
await page.getByLabel('ユーザー名').clear();

選択操作

locator.check() / uncheck() チェックボックス

例

// チェックボックスをオンにする
await page.getByLabel('サービス規約に同意する').check();

// チェックを外す
await page.getByLabel('メール通知を受け取る').uncheck();

// チェック状態を設定する
await page.getByLabel('ログイン状態を保存').setChecked(true);   // チェックされていることを確認
await page.getByLabel('ログイン状態を保存').setChecked(false);  // チェックされていないことを確認

locator.selectOption() ドロップダウン選択

例

// value 属性で選択
await page.getByLabel('都市').selectOption('beijing');

// 表示テキストで選択
await page.getByLabel('都市').selectOption({ label: '上海' });

// 複数選択ドロップダウン
await page.getByLabel('興味タグ').selectOption([
  { label: 'プログラミング' },
  { value: 'design' },
]);

// インデックスで選択(0番目、2番目)
await page.getByLabel('都市').selectOption({ index: 0 });

キーボード操作

page.keyboard.press() キー押下

例

// Enter を押して離す
await page.keyboard.press('Enter');

// すべて選択(Control + A)
await page.keyboard.press('Control+A');

// コピー&ペースト
await page.keyboard.press('Control+C');
await page.keyboard.press('Control+V');

// 元に戻す
await page.keyboard.press('Control+Z');

page.keyboard.down() / up() 押下/解放

例

// Shift を押したまま離さない
await page.keyboard.down('Shift');

// その間に他のキーを押す(Shift を押しながら他のキーを押すのと同じ)
await page.keyboard.press('ArrowRight');  // Shift + 右矢印(テキスト選択)
await page.keyboard.press('ArrowRight');

// Shift を離す
await page.keyboard.up('Shift');

特殊キー名

キー名対応するキー
EnterEnter
EscapeEsc 終了
TabTab フォーカス移動
BackspaceBackspace 削除
DeleteDelete キー
ArrowUp/Down/Left/Right矢印キー
PageUp/PageDownページキー
Home/End行頭/行末
Control/Alt/Shift/Meta修飾キー

page.keyboard.type() キーボードでテキスト入力

例

// フォーカス中の要素にテキストを入力
await page.keyboard.type('サンプル チュートリアル', { delay: 50 });

page.keyboard.insertText() 直接挿入

例

// フォーカス位置にテキストを直接挿入(キーボードイベントをシミュレートせず最速)
await page.keyboard.insertText('高速挿入テキスト');

マウス操作

座標クリックと移動

例

// ビューポート座標 (100, 200) をクリック
await page.mouse.click(100, 200);

// 座標でダブルクリック
await page.mouse.dblclick(100, 200);

// マウスを座標まで移動
await page.mouse.move(100, 200);

// 押下 / 解放
await page.mouse.down();
await page.mouse.up();

マウスホイール

例

// 下に 500px スクロール
await page.mouse.wheel(0, 500);

// 左に 200px スクロール
await page.mouse.wheel(200, 0);

locator.dragTo() ドラッグ&ドロップ

例

// 要素 A を要素 B にドラッグ
const source = page.getByText('ドラッグして');
const target = page.getByTestId('drop-zone');
await source.dragTo(target);

// オプション付きドラッグ
await source.dragTo(target, {
  sourcePosition: { x: 0, y: 0 },   // ドラッグ開始点(ソース要素からの相対位置)
  targetPosition: { x: 10, y: 10 }, // ドラッグ終了点(ターゲット要素からの相対位置)
});

page.mouse vs locator.click の使い分け

方法適用シーン
locator.click()ページ要素をクリック(大半のシーン)
page.mouse.click()特定の座標をクリック(Canvas、チャートなど DOM がないシーン)

ファイルアップロード

locator.setInputFiles() 単一ファイル/複数ファイル

例

// 単一ファイルをアップロード
await page
  .getByLabel('ファイルを選択')
  .setInputFiles('path/to/document.pdf');

// 複数ファイルをアップロード
await page
  .getByLabel('ファイルを選択')
  .setInputFiles([
    'path/to/file1.png',
    'path/to/file2.png',
  ]);

// 選択済みファイルをクリア
await page.getByLabel('ファイルを選択').setInputFiles([]);

ファイルパスは現在の作業ディレクトリ(プロジェクトルート)からの相対パスです。


ファイルダウンロード

例

// ダウンロードイベントの待機を開始(ダウンロードをトリガーする操作の前に呼び出す必要がある)
const downloadPromise = page.waitForEvent('download');

// ダウンロードをトリガーする操作を実行
await page.getByRole('button', { name: 'レポートをダウンロード' }).click();

// ダウンロード完了を待機
const download = await downloadPromise;

// 推奨ファイル名を取得
console.log(download.suggestedFilename());

// 指定パスに保存
await download.saveAs('downloads/report.pdf');
その他の拡張