lib/calabash-android/wait_helpers.rb in calabash-android-0.4.22.pre1 vs lib/calabash-android/wait_helpers.rb in calabash-android-0.4.22.pre3
- old
+ new
@@ -5,44 +5,69 @@
class WaitError < RuntimeError
end
+ # 'post_timeout' is the time to wait after a wait function returns true
+ DEFAULT_OPTS = {
+ :timeout => 30,
+ :retry_frequency => 0.3,
+ :post_timeout => 0,
+ :timeout_message => 'Timed out waiting...',
+ :screenshot_on_error => true
+ }.freeze
- def wait_for(options_or_timeout=
- {:timeout => 10,
- :retry_frequency => 0.2,
- :post_timeout => 0.1,
- :timeout_message => "Timed out waiting...",
- :screenshot_on_error => true}, &block)
+ def wait_for(options_or_timeout=DEFAULT_OPTS, &block)
#note Hash is preferred, number acceptable for backwards compat
- timeout=options_or_timeout
- post_timeout=0.1
- retry_frequency=0.2
+ default_timeout = 30
+ timeout = options_or_timeout || default_timeout
+ post_timeout=0
+ retry_frequency=0.3
timeout_message = nil
screenshot_on_error = true
if options_or_timeout.is_a?(Hash)
- timeout = options_or_timeout[:timeout] || 10
- retry_frequency = options_or_timeout[:retry_frequency] || 0.2
- post_timeout = options_or_timeout[:post_timeout] || 0.1
+ timeout = options_or_timeout[:timeout] || default_timeout
+ retry_frequency = options_or_timeout[:retry_frequency] || retry_frequency
+ post_timeout = options_or_timeout[:post_timeout] || post_timeout
timeout_message = options_or_timeout[:timeout_message]
- screenshot_on_error = options_or_timeout[:screenshot_on_error] || true
+ if options_or_timeout.key?(:screenshot_on_error)
+ screenshot_on_error = options_or_timeout[:screenshot_on_error]
+ end
end
begin
Timeout::timeout(timeout, WaitError) do
sleep(retry_frequency) until yield
end
sleep(post_timeout) if post_timeout > 0
rescue WaitError => e
- handle_error_with_options(e, timeout_message, screenshot_on_error)
+ msg = timeout_message || e
+ if screenshot_on_error
+ sleep(retry_frequency)
+ return screenshot_and_retry(msg, &block)
+ else
+ raise wait_error(msg)
+ end
rescue Exception => e
handle_error_with_options(e, nil, screenshot_on_error)
end
end
+ def screenshot_and_retry(msg, &block)
+ path = screenshot
+ res = yield
+ # Validate after taking screenshot
+ if res
+ FileUtils.rm_f(path)
+ return res
+ else
+ embed(path, 'image/png', msg)
+ raise wait_error(msg)
+ end
+ end
+
def wait_poll(opts, &block)
test = opts[:until]
if test.nil?
cond = opts[:until_exists]
raise "Must provide :until or :until_exists" unless cond
@@ -56,20 +81,25 @@
false
end
end
end
-#options for wait_for apply
+ #options for wait_for apply
def wait_for_elements_exist(elements_arr, options={})
+ if elements_arr.is_a?(String) || elements_arr.is_a?(Symbol)
+ elements_arr = [elements_arr.to_s]
+ end
options[:timeout_message] = options[:timeout_message] || "Timeout waiting for elements: #{elements_arr.join(",")}"
wait_for(options) do
elements_arr.all? { |q| element_exists(q) }
end
end
-
-#options for wait_for apply
+ #options for wait_for apply
def wait_for_elements_do_not_exist(elements_arr, options={})
+ if elements_arr.is_a?(String)
+ elements_arr = [elements_arr]
+ end
options[:timeout_message] = options[:timeout_message] || "Timeout waiting for no elements matching: #{elements_arr.join(",")}"
wait_for(options) do
elements_arr.none? { |q| element_exists(q) }
end
end
@@ -82,9 +112,63 @@
if screenshot_on_error
screenshot_and_raise msg
else
raise msg
end
+ end
+
+ def wait_error(msg)
+ (msg.is_a?(String) ? WaitError.new(msg) : msg)
+ end
+
+ # Performs a lambda action until the element (a query string) appears.
+ # The default action is to do nothing.
+ #
+ # Raises an error if no uiquery is specified. Same options as wait_for
+ # which are timeout, retry frequency, post_timeout, timeout_message, and
+ # screenshot on error.
+ #
+ # Example usage:
+ # until_element_exists("Button", :action => lambda { swipe("up") })
+ def until_element_exists(uiquery, opts = {})
+ extra_opts = { :until_exists => uiquery, :action => lambda { ; } }
+ opts = DEFAULT_OPTS.merge(extra_opts).merge(opts)
+ wait_poll(opts) do
+ opts[:action].call
+ end
+ end
+
+ # Performs a lambda action until the element (a query string) disappears.
+ # The default action is to do nothing.
+ #
+ # Raises an error if no uiquery is specified. Same options as wait_for
+ # which are timeout, retry frequency, post_timeout, timeout_message, and
+ # screenshot on error.
+ #
+ # Example usage:
+ # until_element_does_not_exist("Button", :action => lambda { swipe("up") })
+ def until_element_does_not_exist(uiquery, opts = {})
+ condition = lambda { element_exists(uiquery) ? false : true }
+ extra_opts = { :until => condition, :action => lambda { ; } }
+ opts = DEFAULT_OPTS.merge(extra_opts).merge(opts)
+ wait_poll(opts) do
+ opts[:action].call
+ end
+ end
+
+ # Performs a lambda action once the element exists.
+ # The default behavior is to touch the specified element.
+ #
+ # Raises an error if no uiquery is specified. Same options as wait_for
+ # which are timeout, retry frequency, post_timeout, timeout_message, and
+ # screenshot on error.
+ #
+ # Example usage: when_element_exists("Button", :timeout => 10)
+ def when_element_exists(uiquery, opts = {})
+ action = { :action => lambda { touch uiquery } }
+ opts = DEFAULT_OPTS.merge(action).merge(opts)
+ wait_for_elements_exist([uiquery], opts)
+ opts[:action].call
end
end
end