10

I'm using Capybara with Ruby 1.9.3 using the selenium driver in order to get information off a website. After clicking through a couple of pages I visit the page I want and I put:

 all(:css, 'td').each { |td| a_info << td }
 a_info.each {|t| puts t.text }

The error I then get after about 10 seconds of waiting:

[remote server] resource://fxdriver/modules/web_element_cache.js:5628:in `unknown': Element not found in the cache - perhaps the page has changed since it was looked up (Selenium::WebDriver::Error::StaleElementReferenceError)

Followed a lot more remote server errors. I've given the page 10-30 seconds of sleep time and it's still not loading and when I do print page.html, I see a javascript script and then all the td's that I'm trying to get info from. I know that the error means an element being found is not the current one but it seems like all the elements have been loaded already so I'm not sure why they wouldn't exist anymore. I've scoured the internet for hours looking for this and would love any kind of help from possible solutions to try and the next steps for trying to figure it out. I can provide any extra information needed, just let me know.

Anoel
  • 1,053
  • 1
  • 10
  • 20

3 Answers3

17

It happens when you make a scope and into that you change the page, for example, but keeps making assertions inside it, like the following:

within 'selector' do
  expect(page).to have_link 'Link'

  visit 'page'

  expect(page).to have_link 'I do not know this whitin, I am stale.'

  find('I do not know this within, I am stale.').click
end

Just reopen you scope again over to keep working on the old one.

within 'selector' do
  expect(page).to have_link 'Link'
end

visit 'page'

within 'selector' do
  expect(page).to have_link 'Now i am fresh'

  find('#now-i-am-fresh').click
end
  • This solved it for me. It had to do with the `within`. – Neil Jun 08 '17 at 20:54
  • 1
    That's exactly my case. The tests tried to wait for a modal to close within the modal scope. The assertion was basically meaningless (always false), but if the modal closed too fast, that assertion triggered this exception. Must have been introduced by some refactoring. – x-yuri Aug 03 '18 at 14:15
  • I had the same problem without selenium, just using capybara: always got a Capybara::RackTest::Errors::StaleElementReferenceError. closing the scope solved it. – bjelli May 03 '19 at 19:26
5

This is my least favorite error. I'm gonna refer you to this exact question on stack overflow asked about a year before Random "Element is no longer attached to the DOM" StaleElementReferenceException

Community
  • 1
  • 1
Greg
  • 5,422
  • 1
  • 27
  • 32
  • Those answers aren't helping because I'm not waiting for an element, I'm just trying to get all the td elements off the page that have already loaded. That's why I'm confused on what to do. – Anoel Sep 04 '12 at 17:46
  • re-read the stack overflow error I sent you; that will give you the reason why you are having your problems. Here is the definition of the error youre getting: [Error](http://selenium.googlecode.com/svn/trunk/docs/api/rb/Selenium/WebDriver/Error/StaleElementReferenceError.html). Waiting 30 seconds wont help you. Maybe try an implicit wait, or modify your code to find a td element put its text down and then move onto the next td. Or if you like use some kind of html parser to find your information. Selenium isn't the best tool for what you're trying to do. – Greg Sep 04 '12 at 18:26
0

In presented code you are printing text on console, but maybe in your real code you are clicking on these links inside each loop which is wrong.

Solution

Try first to extract href attributes and then go through them in loop. Code:

a_href = a_node.collect {|a| a[:href] }
a_href.each { |a| visit(a) }

I'm not sure if it fits to your situation, give more info in comments.

Иван Бишевац
  • 13,811
  • 21
  • 66
  • 93
  • That is the real code I put there. I'm not trying to follow links, just collect information from a page. – Anoel Sep 04 '12 at 17:42
  • Maybe some javascript is executed and there aren't all td's you collected in previous step. Why you don't try to collect td.text in first each method? – Иван Бишевац Sep 04 '12 at 19:39