http://vaderpi.com/blog/?p=630
I have been working with over the last couple of days. I quickly became frustrated with numerous errors claiming that the element I wanted to perform an operation on did not exist. I found the Watir::Waiter class and started using it extensively. So extensively, that I decided to write a little monkey patch to make my life easier.
The application that I am working with performs a lot of client-side DOM manipulation. This can create instances where my script was asking Watir to perform operations on DOM objects that didn’t exist. To defend against that, every time that I called click or set or select on various DOM objects, I wrote two additional statements. One to make sure the browser had finished whatever it was working on, and one to make sure that the element I was about to interact with actually existed.
The code looked something like this.
@browser = Watir::Browser.new
@browser.goto("http://localhost")
@browser.wait
Watir::Waiter.wait_until { @browser.text_field(:name, /UserName/).exists? }
@browser.text_field(:name, /UserName/).set("Admin")
@browser.wait
Watir::Waiter.wait_until { @browser.text_field(:name, /Password/).exists? }
@browser.text_field(:name, /Password/).set("Password")
@browser.wait
Watir::Waiter.wait_until { @browser.button(:name, /Submit/).exists? }
@browser.button(:name, /Submit/).click
While that works, I got really sick of having to re-type the selector for the DOM element that I wanted to muck with. What I wanted to do was write code that looked something like this.
@browser = Watir::Browser.new
@browser.goto("http://localhost")
@browser.text_field(:name, /UserName/).wait_to_set("Admin")
@browser.text_field(:name, /Password/).wait_to_set("Password")
@browser.button(:name, /Submit/).wait_to_click
Wow. That is much more concise and easier to understand. Even a non-programmer can understand what is happening now.
To make this code actually work, I decided to write a quick monkey patch that adds a “wait_to_” alternative for every method that can be called on input elements and links. These methods call @browser.wait, ask Watir::Waiter to wait for the element to exist, and then call the requested method.
I called my monkey patch Watir Wait. (Get it? I crack myself up! :)) Take a peek and let me know what you think. If I get enough positive feedback, I’ll rework this into a proper patch and submit it to the Watir team for inclusion.
require 'watir'
require 'watir/container'
require 'watir/element'
require 'watir/input_elements'
require 'watir/link'
def support_wait_to_methods
timeout_in_seconds = 30
original_method_missing = self.instance_method(:method_missing)
define_method(:method_missing) do |symbol, *args|
name = symbol.id2name
if name =~ /^wait_to_/
new_symbol = name.gsub("wait_to_", "").to_sym
self.wait
Watir::Waiter.wait_until(timeout_in_seconds) do
exists_and_contains_option_if_select?(new_symbol, args)
end
self.send(new_symbol, *args)
else
original_method_missing.bind(self).call(symbol, args)
end
end
def exists_and_contains_option_if_select?(symbol, args)
result = false
if self.exist?
result = true
# I really don't like sticking this here. It violates my
# desgin sense, but I am going to leave it here for now
# because I am lazy. This will get reworked if I roll this
# into a proper patch.
if symbol == :select
self.locate
result = self.include?(args[0])
end
end
result
end
end
class Watir::InputElement
support_wait_to_methods
end
class Watir::Link
support_wait_to_methods
end
116

被折叠的 条评论
为什么被折叠?



