Неизвестное свойство или метод: `readyState'Код ошибки HRESULT:0x80010108 Вызванный объект отключился от своих клиентов. (NoMethodError)
unknown property or method: `readyState'
HRESULT error code:0x80010108
The object invoked has disconnected from its clients. (NoMethodError)
C:/Opt/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-4.3.0/lib/watir-classic/browser.rb:603:in `method_missing'
C:/Opt/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-4.3.0/lib/watir-classic/browser.rb:603:in `block in wait'
C:/Opt/Ruby/Ruby193/lib/ruby/1.9.1/timeout.rb:69:in `timeout'
C:/Opt/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-4.3.0/lib/watir-classic/browser.rb:597:in `wait'
C:/Opt/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-4.3.0/lib/watir-classic/container.rb:56:in `wait'
C:/Opt/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-4.3.0/lib/watir-classic/container.rb:56:in `wait'
C:/Opt/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-4.3.0/lib/watir-classic/element.rb:210:in `block in fire_event'
C:/Opt/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-4.3.0/lib/watir-classic/element.rb:489:in `perform_action'
C:/Opt/Ruby/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-4.3.0/lib/watir-classic/element.rb:210:in `fire_event'
C:/Jenkins/workspace/UI_Automation_Dev/trunk/Automation/ocelot/lib/ocelot/extensions.rb:400:in `method_missing'
Я получаю вышеуказанную ошибку при выполнении в виртуальном узле через Jenkins. Когда я запускаю то же самое на моей локальной машине вручную, ошибки не возникает. Вот блок, где выкидывается ошибка.
browser.frame(id: 'Iframe1').table(id: 'reviewHeader').td(id: 'RESAVE').when_present.click #clicking Save button
sleep(3) # Wait after Save so the 3rd party app. window closes
browser.window(title: /user/).use # Switch back to the main app window
browser.wait_for_page_load
Здесь я нажимаю кнопку сохранения, которая закрывает вкладку. Затем я сплю в течение 3 секунд. Затем я использую окно с заголовком "пользователь" и жду, пока страница загрузится. Ошибка появляется после того, как я нажимаю кнопку Сохранить; он не переключается на окно. Я даже пытался дать больше / меньше времени сна, но это не сработало. Кстати, я использую Watir Classic.
1 ответ
Воспроизведение исключения
Глядя на то, где произошло исключение, я смог смоделировать исключение с помощью:
1. Создание и открытие окна с HTML (это главное окно):
<html>
<head><title>user</title></head>
<body><a href="popup.htm" target="_blank">popup</a></body>
</html>
2. Создание и открытие окна с именем файла "popup.htm" и HTML (это всплывающее окно):
<html>
<head><title>popup</title></head>
<body><a href="#" id="RESAVE">Re-save</a></body>
</html>
3. Запустите следующий скрипт Watir с ручным взаимодействием:
browser = Watir::Browser.attach(:url, /popup/)
Watir::Browser::READYSTATES = {complete: 5}
browser.link.click # while this is running, which is 300 seconds, manually close the popup
#=> `method_missing': unknown property or method: `readyState' (NoMethodError)
#=> HRESULT error code:0x80010108
#=> The object invoked has disconnected from its clients.
Решение
Исключение происходит в этой части Browser#wait
метод, в частности, @ie.readyState
команда:
begin
while @ie.busy
sleep interval
end
until READYSTATES.has_value?(@ie.readyState)
sleep interval
end
until @ie.document
sleep interval
end
documents_to_wait_for = [@ie.document]
rescue WIN32OLERuntimeError # IE window must have been closed
@down_load_time = ::Time.now - start_load_time
return @down_load_time
end
Код был написан, чтобы спасти закрываемое окно. Тем не менее, я не уверен, почему он включает в себя только WIN32OLERuntimeError
когда мы получаем NoMethodError
, Учитывая возраст этого кода, возможно, что базовый WIN32OLE со временем изменил свой тип возврата, или это может быть просто другим возможным исключением. В любом случае, обезьяна исправляет wait
метод также обрабатывать NoMethodError
обратимся к исключению.
require 'watir-classic'
module Watir
class Browser
def wait(no_sleep=false)
@xml_parser_doc = nil
@down_load_time = 0.0
interval = 0.05
start_load_time = ::Time.now
Timeout::timeout(5*60) do
begin
while @ie.busy
sleep interval
end
until READYSTATES.has_value?(@ie.readyState)
sleep interval
end
until @ie.document
sleep interval
end
documents_to_wait_for = [@ie.document]
rescue WIN32OLERuntimeError, NoMethodError # this is the only line modified
# IE window must have been closed
@down_load_time = ::Time.now - start_load_time
return @down_load_time
end
while doc = documents_to_wait_for.shift
begin
until READYSTATES.has_key?(doc.readyState.to_sym)
sleep interval
end
@url_list << doc.location.href unless @url_list.include?(doc.location.href)
doc.frames.length.times do |n|
begin
documents_to_wait_for << doc.frames[n.to_s].document
rescue WIN32OLERuntimeError, NoMethodError
end
end
rescue WIN32OLERuntimeError
end
end
end
@down_load_time = ::Time.now - start_load_time
run_error_checks
sleep @pause_after_wait unless no_sleep
@down_load_time
end
end
end
Если проблема возникает только на этом одном шаге одного сценария, самое безопасное решение может состоять в том, чтобы просто спасти исключение в одном месте:
begin
browser.frame(id: 'Iframe1').table(id: 'reviewHeader').td(id: 'RESAVE').when_present.click #clicking Save button
rescue NoMethodError
# window was likely closed
end