Reputation: 1636
I am forming a collection of links based on the title
attribute using the following syntax
in_frame(name: 'example frame') do |frame|
links(:example_link, {title: 'This is an example title', frame: frame})
end
SNIPPET - 1
Then i try to click each link (there are 2 in the collection) and get some info from the window that pops up
self.example_link_elements.each do |one_link|
one_link.click
@browser.window(index: 1).use do
# do something here
@browser.window.close
end
end
SNIPPET - 2
This runs fine for the first link, but it throws Element is no longer valid (Selenium::WebDriver::Error::StaleElementReferenceError)
error for the second iteration at the one_link.click
statement!! I tried to do it this way then
2.times do |i|
self.example_link_elements[i].click
@browser.window(index: 1).use do
# do something here
@browser.window.close
end
end
end
The above mentioned snippet works fine!! I don't understand why the first snippet would throw that error!! Can any body shed light on the reason for the first snippet acting up?!
UPDATE
To make sure I understand it, I just coded up the following test page
<html>
<body>
<a target="_blank" href="http://www.google.com">click here</a>
<a target="_blank" href="http://www.google.com">click here</a>
</body>
</html>
and ran the following ruby code on it
require 'watir-webdriver'
require 'page-object'
class MyPageObject
include PageObject
def initialize(browser, visit)
@browser = browser
super browser, visit
end
def goto
@browser.goto "file:///C:/Users/raveej1/Desktop/test.html"
end
end
browser = Watir::Browser.new :firefox
page = MyPageObject.new browser, true
page.class.send(:links, :search_link, text: "click here")
page.search_link_elements.each_with_index do |p, p_index|
p.click
browser.window(index: 1).use do
page.class.send(:link, :singin_link, text: "Sign in")
page.singin_link
browser.window.close
end
end
It worked!! I believe it is exactly the same way as snippet 1. Why do the two pages act differently?!!
Upvotes: 1
Views: 352
Reputation: 46836
The documentation for the Selenium Element#click (which is what one_link.click
eventually calls) says:
Click this element. If this causes a new page to load, this method will attempt to block until the page has loaded. At this point, you should discard all references to this element and any further operations performed on this element will raise a StaleElementReferenceError unless you know that the element and the page will still be present. If click() causes a new page to be loaded via an event or is done by sending a native event then the method will not wait for it to be loaded and the caller should verify that a new page has been loaded.
In your case, opening the popup window means your reference to elements is going to be considered stale.
The different behaviour you are seeing is due to how you are referencing the elements.
In your first code snippet:
In your second code snippet:
As you can see, your second code snippet is always using a fresh reference to elements, which is why you do not get the StaleReferenceError.
Upvotes: 1