LoginSignup
2
0

More than 5 years have passed since last update.

WebdriverIOでクリックできない要素を強制的にクリックする

Last updated at Posted at 2019-01-05

WebdriverIOの click() は、指定された要素に別の要素が重なってクリック出来ない場合、次のようなメッセージを出力してテストに失敗します。

Element is not clickable at point (x, x). Other element would receive the click: ..."

これは公式ドキュメントでも言及されており、回避方法が紹介されています。WebdriverIOの問題というより、Webdriverの仕様によるもののようです。

To work around this, try to find the overlaying element and remove it via execute command so it doesn't interfere the click. You also can try to scroll to the element yourself using scroll with an offset appropriate for your scenario.

かぶさってる要素を execute で取り除くか、テストシナリオ内で明示的にスクロールして被らないようにしろ、ということですね。または、 browser.waitUntil() でかぶさってる要素が消えるのを待つ方法もあります。
スクロールやwaitで解決するならそれでよさそうですが、 execute で無理やり取り除くくらいなら、対象の要素のclickイベントを直接発火させてしまってもあんまり変わらないのでは……?

ということで、browser.execute() でやってみたのがこちらです。
やることは単純で、XPathで要素を取得し、clickイベントを発火するスクリプトをブラウザ上で実行するだけです。

async function forceClick(locator) {

  const elements = await $(locator)
  const selector = elements.selector

  browser.execute(function (el) {
    (
      function(expression, parentElement) {
        var r = []
        var x = document.evaluate(expression, parentElement ||
                document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
        for (var i = 0, l = x.snapshotLength; i < l; i++) {
        r.push(x.snapshotItem(i))
        }
        return r
      } 
    )(el)[0].click()
  }, selector)
}

forceClick(locator)

こちらは完全に余談ですが、自分はCodeceptJSを使っているので、以下のようなカスタムヘルパを定義して使っています。


class ForceClick extends Helper {

  async forceClick(locator) {
    const helper = this.helpers['WebDriver']
    const elements = await helper._locateClickable(locator)
    const selector = elements[0].selector

    helper.executeScript(function (el) {
      (
        function(expression, parentElement) {
          var r = []
          var x = document.evaluate(expression, parentElement || 
                  document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
          for (var i = 0, l = x.snapshotLength; i < l; i++) {
            r.push(x.snapshotItem(i))
          }
          return r
        } 
      )(el)[0].click()
    }, selector)
  }
}


module.exports = ForceClick;

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0