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'
I am getting the above error when executing in a virtual node through Jenkins. When I run the same in my local machine manually, there's no error. Here's the block where its throwing the error.
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
Here I click the save button, which closes the tab. Then, I sleep for 3 seconds. Then, I use the window having title 'user', and I wait until the page is loaded. The error shows up after I click the Save button; it does not switch to the window. I even tried giving more/less sleep time, but it didn't work. BTW I am using Watir Classic.
Reproducing the Exception
Looking at where the exception occurred, I was able to simulate the exception by:
1. Creating and opening a window with HTML (this is the main window):
<html>
<head><title>user</title></head>
<body><a href="popup.htm" target="_blank">popup</a></body>
</html>
2. Creating and opening a window with a file name of "popup.htm" and HTML (this is the popup window):
<html>
<head><title>popup</title></head>
<body><a href="#" id="RESAVE">Re-save</a></body>
</html>
3. Running the following Watir script with manual interaction:
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.
Solution
The exception is occurring in this part of the Browser#wait
method, specifically the @ie.readyState
command:
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
The code was written to rescue the window being closed. However, I am not sure why it only includes WIN32OLERuntimeError
when we are getting a NoMethodError
. Given the age of this code, it is possible that the underlying WIN32OLE has changed its return type over time or it could just be another possible exception. At any rate, monkey patching the wait
method to also handle NoMethodError
will address the exception.
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
If the problem only occurs on this one step of a single script, the safest solution might just be to rescue the exception in the one spot:
begin
browser.frame(id: 'Iframe1').table(id: 'reviewHeader').td(id: 'RESAVE').when_present.click #clicking Save button
rescue NoMethodError
# window was likely closed
end
User contributions licensed under CC BY-SA 3.0