我正在使用以下语法
基于title
属性构建链接集合
in_frame(name: 'example frame') do |frame|
links(:example_link, {title: 'This is an example title', frame: frame})
end
SNIPPET - 1
然后我尝试点击每个链接(集合中有2个)并从弹出的窗口中获取一些信息
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
这对于第一个链接运行正常,但它会在Element is no longer valid (Selenium::WebDriver::Error::StaleElementReferenceError)
语句的第二次迭代中抛出one_link.click
错误!我试着这样做,然后
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
上面提到的片段工作正常!!我不明白为什么第一个片段会抛出这个错误!!任何机构都可以了解第一个代码片段的原因吗?!
更新
为了确保理解,我只是编写了以下测试页
<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>
并在其上运行以下ruby代码
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
有效!!我相信它与片段1完全相同。为什么这两个页面的行为不同?!!
答案 0 :(得分:1)
documentation for the Selenium Element#click(one_link.click
最终调用的内容)说:
单击此元素。如果这导致加载新页面,则此方法 将尝试阻止,直到页面加载。在这一点上,你 应放弃对此元素的所有引用以及任何进一步的引用 对此元素执行的操作将引发一个 StaleElementReferenceError除非你知道元素和 页面仍然存在。如果click()导致加载新页面 通过事件或通过发送本机事件完成,然后方法将 not 等待它被加载,调用者应该验证是否已加载新页面。
在您的情况下,打开弹出窗口意味着您对元素的引用将被视为陈旧。
您看到的不同行为是由于您引用元素的方式。
在您的第一个代码段中:
在您的第二个代码段中:
正如您所看到的,您的第二个代码段总是使用对元素的新引用,这就是您没有得到StaleReferenceError的原因。