Alpha
Alpha

Reputation: 14026

How to determine that element is clickable using Selenium WebDriver with Ruby?

On my web page, page loads but sub-tabs of page aren't clickable for 20 seconds (sometimes more than this). Page contents are -

<nav id="subTabHeaders">
 <div class="selected" data-name="ab">AB</div>
 <div class="" data-name="cd">CD</div>
 <div class="" data-name="ef">EF</div>
 <div class="" data-name="gh">GH</div>
</nav>

I've to click on sub-tab, hence I tried this in following way - Put sleep & then element.click But sleep is not ideal way to deal because sometimes it may happen that sub-tab element is clickable before or after the time given to sleep.

Using sleep, I did following -

element = WAIT.until { driver.find_element(:xpath, ".//*[@id='subTabHeaders']/div[3]")}
sleep 20
element.click

If element is clickable after more than the sleep time & we click on element immediate after sleep time expires, (I mean (using above code) suppose element becomes clickable after 30 seconds but we click on element immediate after 20 seconds), actual click action doesn't happen & also click doesn't return any error.

Is there Ruby method to check whether element is clickable or not? So that we'll get to know when to click.

Upvotes: 4

Views: 16210

Answers (4)

Phil Hudson
Phil Hudson

Reputation: 3901

Here is what I use - to test if the link is clickable, else go to another URL:

    if (logOutLink.Exists() && ExpectedConditions.ElementToBeClickable(logOutLink).Equals(true))
    {
        logOutLink.Click();
    }
    else
    {
        Browser.Goto("/");
    }

Upvotes: 0

tgf
tgf

Reputation: 3256

From the ruby bindings page: (see driver examples)

# wait for a specific element to show up
wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
wait.until { driver.find_element(:id => "foo") }

So ordinarily you could do something like:

wait = Selenium::WebDriver::Wait.new(:timeout => 40)
wait.until do
  element = driver.find_element(:xpath, ".//*[@id='subTabHeaders']/div[3]")
  element.click
end

Or more succinctly

wait = Selenium::WebDriver::Wait.new(:timeout => 40)
wait.until { driver.find_element(:xpath, ".//*[@id='subTabHeaders']/div[3]").click }

However, since you say that the click doesn't raise an error, it sounds like the click is in fact working, just your page isn't really ready to display that tab. I'm guessing there's some async javascript going on here.
So what you can try is inside the wait block, check that the click caused the desired change. I'm guessing, but you could try something like:

wait = Selenium::WebDriver::Wait.new(:timeout => 40)
wait.until do
  driver.find_element(:xpath, ".//*[@id='subTabHeaders']/div[3]").click
  driver.find_element(:xpath, ".//*[@id='subTabHeaders']/div[3][@class='selected']")
end

The important thing here is that #until will wait and repeat until the block gets a true result or the timeout is exceeded.

Upvotes: 4

Michael Durrant
Michael Durrant

Reputation: 96454

How about

WebDriverWait wait = new WebDriverWait(driver,30);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(subTabHeaders)));

Upvotes: 1

Arup Rakshit
Arup Rakshit

Reputation: 118261

Hope it would help you:

begin

    element = WAIT.until { driver.find_element(:xpath, ".//*[@id='subTabHeaders']/div[3]")}
    sleep 20
    element.click

rescue Selenium::WebDriver::Error::StaleElementReferenceError

    p "Indicates that a reference to an element is now “stale” - the element no longer appears in the DOM of the page."

end

OR

you could try this one:

begin

    wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
    wait.until { driver.title.include? "page title" }
    driver.find_element(:xpath, ".//*[@id='subTabHeaders']/div[3]")}.click

rescue Selenium::WebDriver::Error::StaleElementReferenceError

    p "element is not present"

end

Upvotes: 0

Related Questions