Watir"元素不再附加到DOM"错误

时间:2015-12-02 12:38:36

标签: javascript ruby selenium-webdriver automated-tests watir-webdriver

我遇到了一个问题,我已经创建了一个问题,我会随机地解决这个问题,因为有一些java脚本在运行,它会定期刷新元素。我不确定如何阻止此错误发生,这是我的测试代码;

编辑:正如我所知,我已从变量中删除了元素并直接调用它们,但错误仍然存​​在,这是我更新的代码和错误消息(包括行号)

47 When(/^I click the create room button$/) do

  49 Watir::Wait.for_condition(10, 2, "Waiting for room data to load") {
    50 @browser.iframe(:id, 'iconsole-plugin-session_iframe__').div(:id, 'lobby_rooms').div(:id, 'room_list').present?
  51 }

  53 rooms = []

  55 @browser.iframe(:id, 'iconsole-plugin-session_iframe__').div(:id, 'lobby_rooms').div(:id, 'room_list').as.each do |room |
    56 rooms << room.attribute_value('data-room-id')
  57 end

  59 puts roomvalue = rooms.size.to_i

  61 @current_rooms = rooms

  63 roomvalue

  65 Watir::Wait.for_condition(10, 2, "Waiting for button to be present") {
    66 @browser.iframe(:id, 'iconsole-plugin-session_iframe__').button(:id, 'create_room_form_button').present?
  67 }
  68 @browser.iframe(:id, 'iconsole-plugin-session_iframe__').button(:id, 'create_room_form_button').click
69 end

我得到的错误是;

Element is no longer attached to the DOM - {:element=>#<Selenium::WebDriver::Element:0x68d78665e583d27c id="{80a6296c-fc63-4d63-917c-9a2bf35bb429}">} (Watir::Exception::UnknownObjectException)
  ./features/step_definitions/multiplayer_fe_steps.rb:56:in `block (2 levels) in <top (required)>'
  ./features/step_definitions/multiplayer_fe_steps.rb:55:in `/^I click the create room button$/'
  features/multiplayer_fe.feature:21:in `When I click the create room button'

感谢钢铁提供的答案,但是即使将元素直接放入等待语句中我也会遇到同样的错误,还有什么我可以尝试解决这个问题吗?

编辑:我已尝试将lamda用于我的列表,但是,当我这样做时,我会得到一个不同的错误,说明未定义的方法&#39; as&#39;在我的.as.each做|房间|

2 个答案:

答案 0 :(得分:0)

我不太了解Watir,但我怀疑问题在于您将引用存储在变量中。也许试试这个:

Watir::Wait.for_condition(10, 2, "Waiting for room data to load") {
  @browser.iframe(:id, 'iconsole-plugin-session_iframe__').div(:id, 'lobby_rooms').present?
}

Watir::Wait.for_condition(10, 2, "Waiting for button to be present") {
 @browser.iframe(:id, 'iconsole-plugin-session_iframe__').button(:id, 'create_room_form_button').present?
}
@browser.iframe(:id, 'iconsole-plugin-session_iframe__').button(:id, 'create_room_form_button').click

问题在于每次调用@ browser.find_element时......你都在重新审视DOM。存储变量时,您没有存储要查找的过程,而是存储实际的元素,是否存在。当您尝试调用不再存在的找到的元素变量时,您将获得此Selenium StaleObjectError。

在这里走出另一个边缘,但你也可能尝试在Proc或Lambda中包装那些调用,而不是变量。

createpress = -> { @browser.iframe(:id, 'iconsole-plugin-session_iframe__').button(:id, 'create_room_form_button') }

然后,当您想要触发它时,请将其命名为:

create_press.call.present?

这非常冗长和重复。如果你曾经去过Capybara,你可以尝试使用Dill gem将这些元素包装在小部件中,就像触发器一样。 https://github.com/mojotech/dill

答案 1 :(得分:0)

您的代码......

@browser.iframe(:id, 'iconsole-plugin-session_iframe__').div(:id, 'lobby_rooms').div(:id, 'room_list').as

....,在您声明它的那一刻,是一个包含链接元素列表的静态数组。

如果在迭代该元素列表时,DOM会更新,那么这些元素就会变得陈旧。这就是你得到这个错误的原因。

至于如何解决迭代更新链接元素列表的潜在问题......

您可能做的一件事是获取列表的大小,然后直接引用链接:

count = @browser.iframe(:id, 'iconsole-plugin-session_iframe__').div(:id, 'lobby_rooms').div(:id, 'room_list').as

count.times do |x|
  rooms << @browser.iframe(:id, 'iconsole-plugin-session_iframe__').div(:id, 'lobby_rooms').div(:id, 'room_list').a(index: x-1).attribute_value('data-room-id')
end