Reputation: 309
I have always learned that good coding means: do not repeat yourself. But these days I keep repeating myself, in an attempt to let my scrapers handle timeout errors.
For every link or button that I click, i add a rescue Exception => e and refresh the page.
For example
browser.link(:xpath, "//tr[@class='pager'][1]/td/a").when_present.click
turns into
begin
browser.link(:xpath, "//tr[@class='pager'][1]/td/a").wait_until_present
browser.link(:xpath, "//tr[@class='pager'][1]/td/a").click
rescue Exception => e
sleep (10)
puts "timed out, let's refresh"
browser.refresh
end
Perhaps there is a cleaner, non-repetitive solution. I've tried manipulating the Watir::wait but I could not get that to work..
class Watir::Wait
alias_method :__do_wait, :wait_until
def wait_until
begin
__do_wait{ yield }
rescue Exception => e
puts "timed out. let's refresh"
$browser.refresh
end
end
end
Upvotes: 3
Views: 3811
Reputation: 32
Sorry for my enlish, i'm french.... lol this script allows to refresh browser without to skip a step, for exemple when you have to login, you can't skip a step..... and if you have a website with too many connexion with a low bandwhith.....
I think that seeb would do this :
module Watir
class WhenPresentDecorator
def method_missing(m, *args, &block)
unless @element.respond_to?(m)
raise NoMethodError, "undefined method `#{m}' for #{@element.inspect}:# {@element.class}"
end
begin
while [email protected]?
sleep(10)
puts "timed out, let's refresh"
@element.browser.refresh
end
rescue
else
@element.__send__(m, *args, &block)
end
end
end # WhenPresentDecorator
end
Upvotes: 1
Reputation: 46836
If I understand your requirements correctly, I think you want to override the method_missing
handling of the WhenPresentDecorator.
require 'watir-webdriver'
module Watir
class WhenPresentDecorator
def method_missing(m, *args, &block)
unless @element.respond_to?(m)
raise NoMethodError, "undefined method `#{m}' for #{@element.inspect}:#{@element.class}"
end
begin
Watir::Wait.until(@timeout, @message) { @element.present? }
rescue
sleep(10)
puts "timed out, let's refresh"
@element.browser.refresh
else
@element.__send__(m, *args, &block)
end
end
end # WhenPresentDecorator
end
With this monkey patch, when_present
will wait for the element to be present. If the element is present, it will perform the action (ie click in your example). If the element is not present, it will catch the exception, ignore it, refresh the page and continue on to the next statement.
For example, given the following page that has a div tag that shows the time of page load:
<html>
<head>
<script>
function startTime()
{
var today=new Date();
var h=today.getHours();
var m=today.getMinutes();
var s=today.getSeconds();
document.getElementById('txt').innerHTML=h+":"+m+":"+s;
}
</script>
</head>
<body onload="startTime()">
<div id="txt"></div>
</body>
</html>
You can see that no exception occurs when accessing an element (link) that does exist. As well, the page refreshes after trying to find that element.
puts browser.div(:id => 'txt').text
#=> "22:48:25"
browser.link(:id => 'asdf').when_present.click
#=> "timed out, let's refresh"
puts browser.div(:id => 'txt').text
#=> "22:48:36"
Upvotes: 2