【问题标题】:Is there a way to determine if an element is clickable in Chrome Browser using Selenium and Watir?有没有办法使用 Selenium 和 Watir 确定 Chrome 浏览器中的元素是否可点击?
【发布时间】:2018-11-11 16:08:36
【问题描述】:

据我了解,由于使用 Selenium Webdriver 和 Chromedriver 实现点击事件的方式,这个问题仅在使用 Chrome 浏览器执行 Web 测试自动化时才真正相关。作为序言,我使用并且知道通过使用 Watir 元素函数“present?”来查找元素,据我所知,它本质上是“visible?”的组合。和“存在?”。我还可以在需要时找到一个具有 Webdriver 元素功能的元素,以识别一个元素是否存在,如果不存在则对异常进行救援。我要确定的是以下内容:

有时,由于缺乏对页面的响应能力,可能会找到一些页面元素并通过所有验证测试以确认其存在,但由于上述缺乏页面响应能力而无法实际与之交互。使用 Chrome 浏览器(带有 Chromedriver)尝试与这些元素交互将导致错误:

irb(main):003:0> @browser.button(:id, "button_login").present? => 真的 irb(main):004:0> @browser.button(:id, "button_login").click Selenium::WebDriver::Error::UnknownError: 未知错误: 元素 ... 在点 (915, nt 会收到点击:

...
(会话信息:chrome=66.0.3359.181) (驱动程序信息:chromedriver=2.38.552522 (437e6fbedfa8762dec75e2c5b3ddb86763dc9dcb),平台=Windows NT 6.3.9600 x86_64) 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/response.rb:69:in 'assert_ok' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/response.rb:32:in 'initialize' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/common.rb:83:in 'new' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/common.rb:83:in 'create_response' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/default.rb:107:in 'request' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/common.rb:61:in 'call' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/bridge.rb:170:in 'execute' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/oss/bridge.rb:579:in 'execute' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/oss/bridge.rb:328:in 'click_element' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/common/element.rb:74:in 'click' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.4.1/lib/watir/elements/element.rb:131:in 'block in click' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.4.1/lib/watir/elements/element.rb:656:in 'element_call' 来自 C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.4.1/lib/watir/elements/element.rb:122:in 'click' 来自 (irb):4 来自 C:/Ruby23/bin/irb.cmd:19:in ''

我知道此时我可以进行救援,但这需要我实际单击该元素。本质上我想写一个特殊的功能“可点击?”这将返回布尔输出,而无需实际单击元素并可能离开页面。我不希望使用 --ctrl+click 类型尝试此操作,如果新窗口返回 true,则关闭窗口,将焦点设置在第一个窗口上,救援返回 false - 工作流。

【问题讨论】:

    标签: ruby selenium-webdriver selenium-chromedriver watir


    【解决方案1】:

    Watir 6.15.0+

    Element#obscured? 已添加以检查这种情况。你现在可以这样做:

    browser.element(id: 'target').wait_while(&:obscured?).click
    

    等待 6.15.0 之前的版本

    对于旧版本,您需要采用不同的方法。

    我会尝试等待重叠元素消失。如果重叠类似于最终会消失的重叠,则相对简单 - 例如:

    browser.element(id: 'overlapping_element').wait_while(&:present?)
    

    如果重叠元素被移动而不是消失,或者您不知道重叠元素,您可以尝试近似重叠元素检查。当 Chrome 单击一个元素时,它会获取元素的中心位置,然后在该点单击。如果此时的顶级元素不是您的元素,则会引发异常。以下等待将执行此检查,直到没有重叠元素:

    target = browser.button
    target_children = target.elements.to_a
    browser.wait_until do
      location = target.location
      size = target.size
      center = [location.x + size.width/2, location.y + size.height/2]
      element_at_point = browser.execute_script("return document.elementFromPoint(#{center[0]}, #{center[1]});")
      [target, target_children].flatten.include?(element_at_point)
    end
    target.click
    

    请注意,我以前不必这样做,所以我不知道是否存在极端情况。似乎适用于 Chrome 和 Firefox。

    【讨论】:

    • 但是它在 Java selenium 绑定中可用,为什么它在 Ruby Selenium 绑定中不可用?
    • @Rajagopalan,对不起,我对 Java 绑定了解不多。快速搜索表明elementToBeClickable 只是检查该元素是否可见并已启用。我不认为在这种情况下就足够了,another answer 也建议这样做。
    • 我可以告诉你,在 Java 绑定中,这会以同样的方式失败。您必须编写一个执行 #2 的方法。对所有元素都做到 #1 非常困难。
    • @JeffC,检查元素是否重叠比预期的要简单(参见更新的答案)。好吧,至少找到一个在简单情况下有效的解决方案。你知道这种方法是否会有边缘情况吗?
    • @JeffC,document.elementFromPoint 应该将元素放在顶部。如果顶部的元素不是目标元素或其子元素之一,则目标元素将不可点击。
    【解决方案2】:

    我可以建议您等待此按钮显示在网页上。我遇到了同样的问题(我在测试中使用了 XPath)。修复它:

    首先我定义了 2 个辅助方法,因为我不得不重复使用它们很多。一种用于搜索页面上的确切元素(此方法通常需要一段时间才能返回结果,因此您无需sleep浏览器)另一种用于单击具有给定“id”的按钮。

    module Helpers
      module Common
        def wait_for_element_id(value)
          find(:xpath, "(//*[@id='#{value}'])[1]")
        end
    
        def click_button_with_id(value)
          first(:xpath, "//button[@id='#{value}']").click
        end
      end
    end
    

    在您的测试之后,您可以使用以下辅助方法:

    it 'clicks on the login button and magic is executed' do
      logout(user)
      wait_for_element_id('button_login')
      click_button_with_id('button_login')
    
      expect(magic).to be_executed
    end
    

    我也不确定,但由于浏览器窗口大小(未显示按钮,因为大小太小)或测试的“无头”模式,您也可能遇到同样的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-06
      • 2014-01-27
      • 1970-01-01
      • 2012-09-18
      • 2012-11-23
      相关资源
      最近更新 更多