ボタンが画面にあっても無効のままならクリックできません。クリックできても、集計結果の表示がまだという場合もあります。Playwrightの待機で詰まったときは、どの状態を待っているかを分けると調べやすくなります。
ボタンを操作できることと、操作後の結果が完成したことは別の条件です。待機時間だけを延ばす前に、要素の指定と期待する状態を確認します。
クリックの自動待機が見るもの
Playwrightはクリックなどの操作前に、要素が一つに定まり、表示され、安定し、イベントを受け取り、有効であるかなどを確認します。必要な条件を満たさないままタイムアウトへ達すると、その操作は失敗します。
この待機だけで、クリック後に始まる業務処理の完了まで保証されるわけではありません。結果の文字や行数など、その後の状態を別に確認します。
遅れて有効になるボタンの例
次をwait-example.htmlとしてUTF-8で保存します。二つの遅延は待機を試すための架空の設定です。
<!doctype html>
<html lang="ja">
<head><meta charset="utf-8"><title>待機条件の練習</title></head>
<body>
<button id="run" type="button" disabled>集計</button>
<p role="status">未実行</p>
<script>
const button = document.querySelector('#run');
setTimeout(() => { button.disabled = false; }, 200);
button.addEventListener('click', () => {
setTimeout(() => {
document.querySelector('[role="status"]').textContent = '完了';
}, 300);
});
</script>
</body>
</html>
固定秒数を使わず二つの条件を確かめる
Playwrightと対応ブラウザーがある環境で、次をHTMLと同じフォルダーから実行します。
from pathlib import Path
from playwright.sync_api import sync_playwright, expect, TimeoutError as PlaywrightTimeoutError
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
try:
page = browser.new_page()
page.goto(Path("wait-example.html").resolve().as_uri())
try:
page.get_by_role("button", name="集計").click(timeout=3000)
status = page.get_by_role("status")
expect(status).to_have_text("完了", timeout=3000)
print(status.inner_text())
except (PlaywrightTimeoutError, AssertionError):
print("URL:", page.url)
print("ボタン数:", page.get_by_role("button", name="集計").count())
raise
finally:
browser.close()
正常な入力では「完了」と表示されます。ローカルのHTMLで、正常、有効にならないボタン、結果の文字が異なる場合の三ケースを確認しました。clickの待機と、to_have_textでの結果確認は、それぞれ最大3秒という別の設定です。全処理が合計3秒以内で必ず終わる、という指定ではありません。
expectの照合は状態が変わるまで再試行します。結果が出ないままならAssertionErrorになり、操作そのもののTimeoutErrorとは区別できます。このコードはどちらの場合も確認用のURLと件数を出し、例外をそのまま伝えます。
失敗した条件から戻る
ボタン数がゼロなら、名前が違う、別のフレーム内にある、ページが切り替わった、といった可能性を確認します。二つ以上なら、同じ名前がある領域のどこを操作するかを絞ります。一つでも無効のままなら、操作可能になる前提を調べます。
結果の文字だけが合わない場合は、実際の文言、空白、エラー表示、処理の完了条件を確認します。待機時間を増やしても、違う文字を待っていれば一致しません。force=Trueで操作条件を飛ばす方法も、正しい状態を確認できたことの代わりにはなりません。
この練習ではdisabledを外さないHTMLや、結果を「失敗」に変えるHTMLも用意すると、待機がどこで止まるかを分けて確かめられます。取得結果を空の値で埋めて続行するより、どの条件が成立しなかったかを残す方が修正につながります。
関連する作業
基本のブラウザー操作と、Seleniumで条件を待つ例も合わせて確認できます。
