1

我遇到了一个问题,我创建了一个测试,我会随机地得到这个问题,从我的理解是因为有java脚本运行定期刷新元素。我不确定如何阻止这个错误发生,这里是我的测试代码;Watir“元素不再附加到DOM”错误

编辑:诚如我已经移除变量的元素,并直接调用它们,但错误依然存在,这是我更新的代码和错误信息(包括行号)

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作为我的列表,但是当我这样做时,我会得到一个不同的错误,说'未定义的方法'为'.as.each do | room |

回答

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? 

这是相当冗长和重复。如果你曾经去过水豚,那么你可以尝试莳萝宝石将这些元素包裹在小工具中,这就像特效。 https://github.com/mojotech/dill

+0

由于钢所提供的答案,但是,即使元素被直接放入等待声明我得到同样的错误,还有什么我可以尝试解决问题? – Ethranes

+0

如果您使用了该代码,我可以再看一次。在代码中注意标记第63行,错误行?我还用一些更多的想法更新了我的答案,包括处理存储参考的第二个变量,以及为什么这是一个不好的模式。 – steel

+0

感谢钢铁公司,我在主要文章中更新了我的代码和错误 – Ethranes

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