Skip to Content

Browserアクション

Browserアクションはchromedp を通して実際のChromeを操作します。ページを開き、内容を読み、入力し、要素を待ち、スクリーンショットを撮ります。Probeを実行する環境にChromeかChromiumが必要です。

外部アクションとしてmozership/probe-browser で公開しています。Probe v1.21.0までは組み込みアクションでした。ワークフローが初めて使うときにProbeがダウンロードし、固定したコミットのaction.ymlが示すSHA-256と一致する実行ファイルだけを実行します。Probe v1.21.0以降が必要です。各リリース のノートの先頭に、コピーして使うusesの行があります。

このアクションはページが何をするかを判定できないため、ガードを守りません。--read-onlyや--allow-hostの下では、--allow-actionで指定しない限り、このアクションを使うステップを拒否します。

基本的な構文

browserステップでは、行う操作をactionsに順番に並べます。ステップごとに新しいブラウザを起動し、操作を実行して閉じます。そのためクッキーやログイン状態は次のステップに引き継がれません。一連の流れは1つのステップにまとめます。

steps: - name: Read the heading uses: github.com/mozership/probe-browser@42dda412d5d183c091f8baf071237cc090f16052 # v0.1.0 with: actions: - name: navigate url: "{{vars.url}}/" - name: text id: heading selector: h1 test: res.code == 0 && res.results.heading == "Welcome"

パラメータ

以下はwithの直下に書きます。

パラメータ型デフォルト説明
actionsList必須順に実行する操作。アクションを参照
timeout期間の文字列、または秒数5sステップ全体の制限時間。ブラウザの起動とすべての操作を含む。30s、30、"30"はどれも30秒。それ以外の値や0以下の値はエラーになる
headlessBooleantrueウィンドウを表示せずにChromeを動かす
window_wInteger1920ウィンドウの幅(ピクセル)
window_hInteger1080ウィンドウの高さ(ピクセル)
evidence_dirString一時ディレクトリ操作が失敗したときにページを保存する場所。失敗時のページを参照

Chromeの起動にもtimeoutの一部を使い、1秒以上かかることもよくあります。短すぎる制限では、最初のページを開く前に時間切れになることがあります。

アクション

actionsの各要素は、nameで操作を指定し、次のフィールドを取ります。

フィールド使うアクション説明
nameすべて下の表にある操作の名前
id結果を返すアクションres.resultsやres.filepathsで結果を引くキー。省くとアクション名がキーになるため、同じ種類のアクションを後に置くと前の結果を置き換える
urlnavigate開くアドレス
selector要素に対するアクションCSSセレクタ
valuetype、send_keys、select使うテキスト
attributeget_attribute読む属性をhrefか[href]で指定する。リストの場合は最初の要素だけを読む
qualityfull_screenshot1から99はその品質のJPEGで保存する。それ以外は、省略、0、100以上、負の数も含めてPNGで保存する
pathスクリーンショット非推奨。画像をこのパスにも書き出す。代わりにres.filepathsを使う

要素を探すアクションは、要素が現れるまで待ちます。先にtimeoutが尽きるとステップは失敗します。多くは要素が表示されるまでも待ちます。

移動と待機

ページを開くか、次の操作に必要な状態になるまでステップを待たせます。

アクション内容
navigateurlを開き、ページの読み込みを待つ。net::ERR_CONNECTION_REFUSEDのようにブラウザがネットワークのエラーを返すとすぐに失敗する。応答のないアドレスではtimeoutまで待つ
wait_visibleselectorが表示されるまで待つ
wait_not_visibleselectorが表示されなくなるまで待つ
wait_enabledselectorが表示され、有効になるまで待つ
wait_readyページのbodyの準備ができるまで待つ。selectorは使わない

ページの読み取り

以下は文字列をres.resultsに、idまたはアクション名をキーにして入れます。

アクション結果
textselectorのテキスト
wait_textselectorが表示されるまで待ち、そのテキスト
valueinputなどのフォーム項目の値
get_attributeselectorの、attributeの最初の属性の値。要素がその属性を持たなければ空文字列
get_html表示されたselectorの外側のHTML

操作

利用者と同じようにページを操作します。結果は返しません。

アクション内容
click表示されたselectorをクリックする
double_click表示されたselectorをダブルクリックする
type、send_keysselectorの内容を消してからvalueを入力する
submitselectorが属するフォームを送信する
focusselectorにフォーカスを移す
scrollselectorが見える位置までスクロールする
selectselectorのvalue属性をvalueに設定する。<select>の選択肢は選ばないため、選ぶ場合は選択肢をクリックする
hoverselectorにmouseoverイベントを送る。待たず、一致する要素がなければ何もしない
right_clickselectorにcontextmenuイベントを送る。待たず、一致する要素がなければ何もしない

スクリーンショット

以下は画像をファイルに保存し、そのパスをres.filepathsに、idまたはアクション名をキーにして入れます。ファイル名の拡張子は形式に合わせて.pngか.jpgになります。

アクション画像
capture_screenshotウィンドウに見えている範囲。PNG
full_screenshotページ全体。PNG。qualityが1から99ならJPEG
screenshot表示されたselectorだけ。PNG

レスポンスオブジェクト

すべての操作が成功すると、ステップからは次の値を参照できます。

フィールド型説明
res.codeInteger0
res.resultsObject読み取りのアクションが返した値。キーはidまたはアクション名
res.filepathsObjectスクリーンショットの保存先。キーはidまたはアクション名
rt.durationStringステップにかかった時間。"663.268333ms"など
statusInteger0

操作が失敗した場合は、テストできるレスポンスはありません。ステップはエラーハンドリングのとおりアクションのエラーとして失敗します。

例

どの例も1つのステップです。1つのステップの操作は同じブラウザを共有し、次のステップは新しいブラウザで始まるためです。

ログイン

ログインと、それが成功したことの確認は同じブラウザで行う必要があるため、1つのステップにします。

secrets: - PASSWORD vars: url: "{{APP_URL}}" user: "{{USERNAME}}" password: "{{PASSWORD}}" jobs: - name: Sign in steps: - name: Log in and reach the dashboard uses: github.com/mozership/probe-browser@42dda412d5d183c091f8baf071237cc090f16052 # v0.1.0 with: timeout: 30s actions: - name: navigate url: "{{vars.url}}/login" - name: type selector: "#username" value: "{{vars.user}}" - name: type selector: "#password" value: "{{vars.password}}" - name: click selector: "button[type='submit']" - name: wait_visible selector: "#dashboard" - name: text id: greeting selector: "#dashboard h1" test: res.code == 0 && res.results.greeting contains vars.user

複数の値の読み取り

結果が互いに置き換わらないよう、読み取りのアクションにはそれぞれidを付けます。

- name: Product page uses: github.com/mozership/probe-browser@42dda412d5d183c091f8baf071237cc090f16052 # v0.1.0 with: actions: - name: navigate url: "{{vars.url}}/products/42" - name: text id: title selector: "h1" - name: text id: price selector: ".price" - name: get_attribute id: image selector: "img.product" attribute: [src] test: | res.code == 0 && res.results.title != "" && res.results.price startsWith "$" outputs: image_url: res.results.image

スクリーンショットを残す

保存した画像のパスはres.filepathsに入り、表示したり次に渡したりできます。

- name: Checkout page uses: github.com/mozership/probe-browser@42dda412d5d183c091f8baf071237cc090f16052 # v0.1.0 with: window_w: 1280 window_h: 800 actions: - name: navigate url: "{{vars.url}}/checkout" - name: full_screenshot id: page test: res.code == 0 echo: "Saved {{res.filepaths.page}}"

エラーハンドリング

アクションが完了できないと、ステップ全体がアクションのエラーとして失敗し、実行は終了ステータス3で終わります。セレクタが何にも一致しなくても空の結果にはなりません。wait_visible、text、clickなど要素を探すアクションは、ステップのtimeoutまで待ち続けます。ナビゲーションは、接続の拒否のようにブラウザがネットワークのエラーを返すとすぐに失敗しますが、応答のないアドレスではtimeoutまで待ちます。いずれの場合もテストできるresはなく、失敗のメッセージにブラウザのエラーが入ります。

失敗時のページ

アクションが失敗すると、Probeはその時点のページを保存します。ページ全体のPNGのスクリーンショットと、文書のHTMLです。2つのファイルはprobe-browser-failure-1947177907.pngと.htmlのように同じ名前を共有します。失敗のメッセージには、ページのURLとあわせて両方のファイルのパスが入ります。

action error in step_execute: action execution failed (caused by: ... context deadline exceeded (page at failure: url http://localhost:8090/, screenshot /tmp/probe-browser-failure-1947177907.png, html /tmp/probe-browser-failure-1947177907.html))

--reportで書き出すファイルでも、このメッセージが失敗のmessageになります。テストがfalseになるのはアクションの失敗ではないため、そのときはページを保存しません。残したい場合はcapture_screenshotアクションを加えます。

ファイルはシステムの一時ディレクトリに保存します。evidence_dirを指定するとそこに保存し、ディレクトリは必要に応じて作成します。CIのアーティファクトとしてアップロードする場合に便利です。ページには個人の情報が写りうるため、ファイルはProbeを実行したユーザーだけが読めるようにします。

- name: Checkout page uses: github.com/mozership/probe-browser@42dda412d5d183c091f8baf071237cc090f16052 # v0.1.0 with: evidence_dir: out/browser actions: - name: navigate url: "{{vars.url}}/checkout" - name: wait_visible selector: "#pay"

ページを読み取れるように、ブラウザはタイムアウトのあとも最大10秒残します。ブラウザが起動しなかった場合や、時間切れの時点でページがまだ読み込み中だった場合など、読み取れなかったときはその旨をメッセージに書き、何も保存しません。

CIでの実行

CIのランナーには、ブラウザと、手元より少し長い時間が必要です。

  • ランナーにChromeかChromiumを入れる。
  • headless: trueのままにするか、ウィンドウが必要ならXvfbなどのディスプレイを用意する。
  • コンテナで多く必要になるため、Chromeは--no-sandboxで起動する。信頼できるサイトだけを開く。
  • コールドスタートのランナーではChromeの起動が遅いため、timeoutに余裕を持たせる。
更新日時