简体   繁体   中英

Is there a way to determine if an element is clickable in Chrome Browser using Selenium and Watir?

As I understand it, this question is really only relevant when performing web test automation using Chrome browser due to the manner in which a click event is implemented with Selenium Webdriver and Chromedriver. To preface, I use and am aware of finding an element through the use of the Watir element function "present?", which as I understand is essentially a combination of "visible?" and "exists?". I could also, at need find an element with Webdriver element functions to identify if an element is present with a rescue for an exception if it is not. What I am trying to determine is the following:

At times, due to a lack of responsiveness to a page, there will be page elements that will be found and pass all validation tests for it's existence, but cannot actively actually be interacted with due to the aforementioned lack of page responsiveness. Using Chrome browser (with Chromedriver) attempts to interact with these elements will result in the error:

irb(main):003:0> @browser.button(:id, "button_login").present? => true irb(main):004:0> @browser.button(:id, "button_login").click Selenium::WebDriver::Error::UnknownError: unknown error: Element ... is not clickable at point (915, nt would receive the click:

...
(Session info: chrome=66.0.3359.181) (Driver info: chromedriver=2.38.552522 (437e6fbedfa8762dec75e2c5b3ddb86763dc9dcb),platform=Windows NT 6.3.9600 x86_64) from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/response.rb:69:in 'assert_ok' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/response.rb:32:in 'initialize' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/common.rb:83:in 'new' from 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' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/default.rb:107:in 'request' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/http/common.rb:61:in 'call' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdrive r/remote/bridge.rb:170:in 'execute' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/remote/oss/bridge.rb:579:in 'execute' from 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' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/selenium-webdriver-3.4.4/lib/selenium/webdriver/common/element.rb:74:in 'click' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.4.1/lib/watir/elements/element.rb:131:in 'block in click' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.4.1/lib/watir/elements/element.rb:656:in 'element_call' from C:/Ruby23/lib/ruby/gems/2.3.0/gems/watir-6.4.1/lib/watir/elements/element.rb:122:in 'click' from (irb):4 from C:/Ruby23/bin/irb.cmd:19:in ''

I know I can rescue at this point, but that entails that I actually click the element. Essentially I want to write a special function "clickable?" that will return a boolean output without actually clicking the element and possibly navigating away from the page. I would prefer not to attempt this with a type of --ctrl+click, if new window return true, close window, set focus on first window, rescue return false-- workflow.

Watir 6.15.0+

Element#obscured? has been added to check for this scenario. You can now do:

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

Watir pre-6.15.0

For older versions, you will need to take a different approach.

I would try waiting for the overlapping element to go away. If the overlapping is something like an overlay that will eventually disappear, it's relatively straightforward - eg:

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

If the overlapping element gets moved rather than disappears or you don't know the overlapping element, you could try approximating the overlapping element check. When Chrome clicks an element, it gets the element's center location and then clicks at that point. If there the top-level element at that point is not your element, the exception is thrown. The following wait will do this check until there is no overlapping element:

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

Note that I haven't had to do this before, so I don't know if there are edge cases. Seemed to work with Chrome and Firefox.

I can suggest you to wait this button to show on the web page. I experienced the same problem (I was using XPath in my tests). To fix it:

Firstly I defined 2 helper methods because I had to reuse them a lot. One for searching of a exact element on the page(this method is usually takes a while to return a result so you don't need to sleep the browser) and one for clicking a button with given "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

After that in your test you can use the helper methods like:

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

I am also not sure but you can also experience the same problem because of the browser window size (button is not shown because the size is too low) or because of the "headless" mode of your tests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM