Outline
Salesforceなどのように、Shadow DOMを用いたサイトを自動化するのは厄介だ。
T-DASHでは、Shadow DOMを使った要素を識別することができない(※ 2024/09/01 現在)
そこをなんとかする。
技術的情報
Document:querySelector()とShadowRootを用いて要素を特定する
具体例
まず、簡単なShadow DOMのボタンを定義しているサイトを用いる。
このサイトの「This button is inside a Shadow DOM」のボタンを要素特定してみる。
Developer toolで XPathを取得すると、以下の値になる
//*[@id="my-btn"]
しかし、これは「Here's a basic button example.」の上のボタンだけヒットして、とれません
では、以下のようにボタンのtextを指定してみるとどうなるか?
//button[text()="This button is inside a Shadow DOM."]
この場合、ヒットされません。
つまり、単純にXPathでは、Shadow DOMの中身を特定できないということです。
では、querySelector や ShadowRootを使ってどうやって取得するか?
querySelectorはXPathと類似で要素を効率よく検索するMethodである。
CSS selectorを指定して、それが一番最初にあるものを返します。
ShadowRootはDOMツリーとは別にレンダリングされるDOMサブツリーのルートノードを指定します。
では、selectorはどうやって取得するか?
2パターンあります
- 対象のHTMLで”selectorをコピー”する
- selectorの階層の情報を参照する(構成は "タグ" "selector" である)
では、具体的に「This button is inside a Shadow DOM」のボタンを querySelector で特定してみる。
① Shadow DOMの親階層を指定する
document.querySelector('#shadow-host')
② Shadow DOMのroot nodeであることを指定します
document.querySelector('#shadow-host').shadowRoot
③ buttonを特定します
document.querySelector('#shadow-host').shadowRoot.querySelector('#my-btn')
では、実際にこの記載で正しく特定できているかを、developer toolのコンソールを使って確認することができます。
コンソールで先ほどのqueryを記載して、リターンを押すと、対象のボタンが取れることが確認できると思います。
document.querySelector('#shadow-host').shadowRoot.querySelector('#my-btn')
こちら、robot frameworkで実際に処理したいときどうするか
*** Settings ***
Library SeleniumLibrary
*** Test Cases ***
Open Browser and Access practice demo
Open Browser https://practice.expandtesting.com/shadowdom chrome
Click Element dom:document.querySelector('#shadow-host').shadowRoot.querySelector('#my-btn')
Click Element locator
こちらが、「locatorで指定された要素をクリックする」命令である。
locatorとして、xpath=${xpath} の形式で、xpathを指定するのがよくつかわれるパターン。
今回、locatorとして、domで指定する
T-DASHの手順
カスタム動作
以下設定内容を selenium.yamlのファイル名で保存する
ACT-CAT-CUSTOM-a7b47e3f-ab46-4e69-8133-bcc13b702cd0:
action_category_name: Selenium
icon: ''
color: '#3b16c1'
custom_data:
file_name: Selenium
pip_list: []
library_list: []
actions:
ACT-CUSTOM-c92d773f-f636-4ff9-af5f-d9f329f507df:
action_name: マウスで指定したlocatorをクリックする
action_type: operation
action_format: マウスでlocator「設定値1」をクリックする
action_note: ''
action_args:
- value1
action_def:
- - Click Element
- ${value1}
ACT-CUSTOM-b33c3edc-c60d-41da-bffd-487c5745629a:
action_name: Locatorをマウスオーバーする
action_type: operation
action_format: Locator「設定値1」をマウスオーバーする
action_note: ''
action_args:
- value1
action_def:
- - Mouse Over
- ${value1}
次に、作成された selenium.yamlをT-DASHの動作定義 -> カスタム動作 -> カスタム動作をインポート にてインポートする
2つのカスタム動作は、Selenium keywordsの操作をそのまま利用している。
ただ、locatorを引数で指定できるようにしている。
この引数に、先ほどのdomの情報を入力することで、domで定義したlocationをクリック、マウスオーバーできるようになる。
スクリプト
ブラウザを開き、対象のボタンをマウスオーバーし、クリックするだけである。
※尚、「秒待機」をいれているのは、このサイトは広告がたまにでるため、その広告を閉じるために設けている。
また、この練習サイトは、ボタンをクリックしても遷移はしません(動作が期待通りかわからない)。ただ、マウスオーバーすると、ボタンの色が変わるため、「マウスオーバー」処理を入れている。
テスト結果
スクリーンショットを確認すると、「This button is inside a Shadow DOM」のボタンの色が変わっており、そのボタンを特定していることが確認できる。