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()
例
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' });
修飾キーを押しながらクリック
例
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文字ずつ入力し、実際のキーボード入力をシミュレートします。各キー入力の間に間隔を設定できます。
例
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() ドロップダウン選択
例
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() キー押下
例
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() 押下/解放
例
await page.keyboard.down('Shift');
// その間に他のキーを押す(Shift を押しながら他のキーを押すのと同じ)
await page.keyboard.press('ArrowRight'); // Shift + 右矢印(テキスト選択)
await page.keyboard.press('ArrowRight');
// Shift を離す
await page.keyboard.up('Shift');
特殊キー名
| キー名 | 対応するキー |
|---|---|
Enter | Enter |
Escape | Esc 終了 |
Tab | Tab フォーカス移動 |
Backspace | Backspace 削除 |
Delete | Delete キー |
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('高速挿入テキスト');
マウス操作
座標クリックと移動
例
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();
マウスホイール
例
await page.mouse.wheel(0, 500);
// 左に 200px スクロール
await page.mouse.wheel(200, 0);
locator.dragTo() ドラッグ&ドロップ
例
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');