[解決済み] WebDriverのclick()とJavaScriptのclick()の比較
質問
ストーリーは?
この StackOverflow で、selenium WebDriver の "click" コマンドで要素をクリックできない、スクリプトを実行して JavaScript でクリックすれば回避できる、というユーザーの報告を見かけました。
Pythonでの例。
element = driver.find_element_by_id("myid")
driver.execute_script("arguments[0].click();", element)
WebDriverJS/Protractor での例です。
var elm = $("#myid");
browser.executeScript("arguments[0].click();", elm.getWebElement());
質問です。
通常のWebDriverクリックでは動作しないのに、"via JavaScript"クリックでは動作するのはなぜですか?また、この回避策の欠点は何ですか(もしあれば)?
私自身、なぜそうしなければならないのか、それがどのような問題につながるのかを十分に理解しないまま、この回避策を使ってしまいました。
解決方法は?
とは対照的に 現在受け入れられている回答 WebDriverにクリックをさせるか、JavaScriptで行うかの違いについては、PhantomJSに特化したものはありません。
違い
この2つの方法の本質的な違いは、すべてのブラウザに共通するもので、非常に簡単に説明することができます。
-
WebDriverです。 WebDriver がクリックを実行するとき、実際のユーザーがブラウザを使用するときに起こることを可能な限りシミュレートしようとします。 例えば、"Click me"というボタンである要素Aと、"Click me"というボタンである要素Bがあるとします。
div
を持つ、透明な要素であり、その寸法とzIndex
次に、WebDriver に A をクリックするように指示します。WebDriver はクリックをシミュレートして、B がクリックを受けるようにします。 最初 . なぜか?なぜなら、BはAをカバーしており、もしユーザーがAをクリックしようとしたら、Bが先にイベントを取得することになるからです。Aが最終的にクリックイベントを取得するかどうかは、Bがそのイベントをどう処理するかによります。いずれにせよ、この場合のWebDriverでの動作は、実際のユーザーがAをクリックしようとしたときと同じになります。 -
JavaScriptです。では、JavaScriptを使って
A.click()
. この方法では、ユーザーがAをクリックしようとしたときに実際に起こることを再現することはできません。 JavaScriptが送信するclick
イベントは直接 A に送られ、B は何のイベントも受け取りません。
WebDriverのクリックが効かないのにJavaScriptのクリックが効くのはなぜ?
上で述べたように、WebDriverは実際のユーザーがブラウザを使用しているときに起こることを可能な限りシミュレートしようとします。実際、DOMはユーザーが操作できない要素を含むことができ、WebDriverはこれらの要素をクリックすることを許可しません。先ほどのオーバーラップのケースに加え、不可視の要素もクリックすることができません。Stack Overflowの質問でよく見かけるケースは、DOMにすでに存在するが、他の要素が操作されたときだけ見えるようになるGUI要素と対話しようとしている人です。これは、ドロップダウンメニューで時々起こります。メニュー項目を選択する前に、まずドロップダウンメニューを表示するボタンをクリックする必要があります。メニューが表示される前に誰かがメニュー項目をクリックしようとすると、WebDriver はその要素を操作できないと断ります。 もし、その人がJavaScriptでそれを行おうとしたら、イベントは可視性に関係なく、要素に直接配信されるので、うまくいきます。
クリック操作にJavaScriptを使うべき場合とは?
Seleniumを使用している場合 アプリケーションのテスト この質問に対する私の答えは ほとんどないですね。 概して、Seleniumのテストは、ユーザーがブラウザで行うことを再現する必要があります。ドロップダウンメニューを例にとると、テストはまずドロップダウンを表示するボタンをクリックし、次にメニュー項目をクリックします。もしボタンが見えない、あるいはボタンがメニュー項目を表示しないなど、GUIに問題があれば、テストは失敗し、バグを検出したことになります。 JavaScriptを使ってクリックしまくると、自動テストでこれらのバグを検出することができません。
私が「ほとんどない」と言ったのは、JavaScriptを使うことが意味のある例外があるかもしれないからです。しかし、それは非常にまれなことです。
のためにSeleniumを使用している場合 スクレイピングサイト であれば、ユーザーの行動を再現することはそれほど重要ではありません。そのため、GUIをバイパスするためにJavaScriptを使用することは、それほど問題ではありません。
関連
-
Vueのフォームイベントのデータバインディングの説明
-
[解決済み】gulp anythingを実行するたびに、アサーションエラーが発生します。- タスク関数を指定する必要があります
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] あるJavaScriptファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] JavaScriptでメールアドレスを検証するのに最適な方法は何ですか?
-
[解決済み] JavaScriptでタイムスタンプを取得する方法は?
-
[解決済み】JavaScriptの比較では、どちらの等号演算子(== vs ===)を使うべきですか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
-
[解決済み】オブジェクトからプロパティを削除する(JavaScript)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
親子コンポーネント通信を解決する3つのVueスロット
-
Vueがechartsのtooltipにクリックイベントを追加するケーススタディ
-
jsを使った簡単な照明スイッチのコード
-
vueのグローバルがscss(mixin)を導入。
-
vueはopenlayersを使用してスカイマップとガオードマップをロードする
-
vue ディレクティブ v-html と v-text
-
[解決済み】awaitは非同期関数でのみ有効です。
-
[解決済み】Node.jsで "Cannot find module "エラーを解決するには?
-
[解決済み】React-Redux: アクションはプレーンオブジェクトでなければならない。非同期アクションにはカスタムミドルウェアを使用する
-
[解決済み】<select>で現在選択されている<option>をJavaScriptで取得するにはどうすればよいですか?