Gayle
Gayle

Reputation: 3092

Stale Element Reference Error

Using the page-object gem and Watir webdriver, we occasionally come across a Selenium::WebDriver::Error::StaleElementReferenceError on a page that loads some basic stuff, makes an ajax request, and repopulates with more info (for the illusion of speed on the page).

This happens because there will be an HTML element there, it disappears quickly and reappears again before the user is really aware of it.

We use page-object's ".when_present" method to wait until the object's on the page the first time before accessing it. However, even after the code finds the element, usually it will get the stale element error because the original HTML element gone and the other one has reappeared by the time it tries to access it.

We found a way using just straight Watir (not page-object) around this. We basically catch the StaleElementReferenceError inside of a Watir::Wait.until block. If it gets an exception, the block returns false, and the Wait.until tries again until it either becomes true, or times out eventually. What we've found is that this usually gets the Stale Element the first time (on line 3 below), returns false from the rescue, Wait.until executes the block again, and the 2nd time it's true and the test moves on and passes.

1  Watir::Wait.until {
2    begin
3      tds = page.my_element.when_present.element.tds
4      table_data_classes = tds.map{|cell| cell.attribute_value("class") }
5
6      # Should have at least one with a class of "xyz"
7      xyz = table_data_classes.select{|data| data.include?("xyz")}
8      xyz.size > 0 
9    rescue Selenium::WebDriver::Error::StaleElementReferenceError
10     false
11   end
12 }

I'm really just wondering if there's any kind of page-object wrapper for this kind of thing. I couldn't find anything. If not, that's ok because the above works. Just curious.

Thanks

Upvotes: 4

Views: 2043

Answers (1)

Cheezy
Cheezy

Reputation: 789

Gayle, great question. At this time there is no specific handling of a retry if the StaleElementReferenceError occurs in the page-object gem. I have heard from another person that they periodically get this error and it is something I could look into. What version of watir-webdriver are you using?

There is a way to duplicate the code you have above using page-object. I am not sure if the above code you provided is inside of your page or if it is somewhere else (like step definitions or some other place). Here's what I would do using the page-object gem:

Inside of your PageObject class

def has_element_with_class(clz)
  wait_until
    begin
      cells = my_element.when_present.cell_elements
      cells.any? { |cell| cell.attribute('class').include? clz }
    rescue Selenium::WebDriver::Error::StaleElementReferenceError
      false
  end
end

I am simply getting all of the cells (tds) nested within my_element into an array. I am calling the any? method on that array which will return true if any of the blocks returns true and otherwise false. This has the same effect as all of the code you have above. If the error happens then you will continue another time.

Upvotes: 3

Related Questions