Is element visible?

2.2k views Asked by At

I have an error when I try to check if some element is visible. My method is the following:

if find(:xpath, "//td[text()='#{subtab}']").visible?
  find(:xpath, "//td[text()='#{subtab}']").click
else
  find(:xpath, "//td[text()='#{tab}']").click
  find(:xpath, "//td[text()='#{subtab}']").click
end

In if find(:xpath, "//td[text()='#{subtab}']").visible?, I have:

Capybara::ElementNotFound:
       Unable to find xpath "//td[text()='Plan List2']"

but when the element is correctly visible, it works good.

3

There are 3 answers

0
Thomas Walpole On BEST ANSWER

By default capybara won't find non-displayed elements - if you really want find to return both visible and non-displayed elements you can do

find(:xpath, "//td[text()='#{subtab}']", visible: :all)

a better solution would be to do

if page.has_no_xpath?("//td[text()='#{subtab}']")
  # if the subtab is not visible click the tab
  find(:xpath, "//td[text()='#{tab}']").click
end
find(:xpath, "//td[text()='#{subtab}']").click
7
Raza Hussain On

Give a try with ':visible => true' with xpath, may be syntax error but just give you an idea.

if find(:xpath, "//td[text()='#{subtab}']", visible: false).visible?
      find(:xpath, "//td[text()='#{subtab}']").click
    else
      find(:xpath, "//td[text()='#{tab}']").click
      find(:xpath, "//td[text()='#{subtab}']").click
    end
8
Pippo On

EDIT: Looking better at your code, looks like what you want is just verify if the element is present, without waiting... so just ignore the wait portion (still useful if you encounter some related problem), and use the following (which was also suggested in the answer below) to verify if an element is present:

has_xpath?("//td[text()='#{subtab}']")

ORIGINAL:

The problem is that when you are fire the find method from capybara, it will attempt to map the element from your page. if the element is not present in the DOM, then it will never call the .visible? method...

Latest versions of Capybara removed wait_until functionality, so in this case you will need to implement a waiter yourself...

Below is an example of how you can work around that issue:

def wait_until 
  Timeout.timeout(20) do 
    sleep(0.1) until value = yield
  end
end

Then

wait_until { has_xpath?("//td[text()='#{subtab}']") }

The has_xpath? will return true or false based on the presence of the element in the DOM, you will loop through that check with the method above and it will only move to the next step until the check above returns true, then you can go ahead and use the .visible? method (although it might not be necessary after you assured the element is present in the DOM)....