lib/awetestlib/regression/waits.rb in awetestlib-0.1.28 vs lib/awetestlib/regression/waits.rb in awetestlib-0.1.29pre1

- old
+ new

@@ -1,470 +1,470 @@ -module Awetestlib - module Regression - # Methods for waiting until something has happened, or waiting while a condition exists, in the browser or DOM. - # sleep_for() is the basic technique. Its disadvantage is that it needs to be set for the longest likely wait time. - # The wait methods take advantage of the Watir and Watir Webdriver wait functionality to pause only as long as necessary for - # the element in question to be in the state needed. - module Waits - - # @!group Core - - # Sleep for *seconds* seconds before continuing execution of the script. - # A message is logged (but not reported) which, by default, includes a trace showing where in the script the sleep was invoked. - # @param [Fixnum] seconds The number of seconds to wait. - # @param [Boolean] dbg If true, includes a trace in the message - # @param [String] desc Contains a message or description intended to appear in the log and/or report output. - def sleep_for(seconds, dbg = true, desc = '') - trace = "\n#{get_debug_list}" if dbg - msg = build_message("Sleeping for #{seconds} seconds.", desc, trace) - info_to_log(msg) - sleep(seconds) - end - - # Wait while an element identified by attribute *how* with value *what* 1) exists, disappears, and exists again. - # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. - # @param [Symbol] how The element attribute used to identify the specific element. - # Valid values depend on the kind of element. - # Common values: :text, :id, :title, :name, :class, :href (:link only) - # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. - # @param [String] desc Contains a message or description intended to appear in the log and/or report output - # @param [Fixnum] timeout - # @return [Boolean] Returns true if disappears and reappears, each within the *timeout* limit - def wait_for_element_to_reappear(browser, how, what, desc = '', timeout = 20) - msg = "Element #{how}=#{what} exists. #{desc}" - wait_while(browser, "While: #{msg}", timeout) { browser.element(how, what).exists? } - wait_until(browser, "Until: #{msg}", timeout) { browser.element(how, what).exists? } - end - - # Wait until element of type *element*, identified by attribute *how* with value *what* exists on the page. - # Timeout is the default used by watir (60 seconds) - # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. - # @param [Symbol] element The kind of element to click. Must be one of the elements recognized by Watir. - # Some common values are :link, :button, :image, :div, :span. - # @param [Symbol] how The element attribute used to identify the specific element. - # Valid values depend on the kind of element. - # Common values: :text, :id, :title, :name, :class, :href (:link only) - # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. - # @param [String] desc Contains a message or description intended to appear in the log and/or report output - # @return [Boolean] True if element exists within timeout limit - def wait_until_exists(browser, element, how, what, desc = '') - msg = build_message("Wait until (:#{element} :#{how}=>'#{what}') exists.", desc) - start = Time.now.to_f - # TODO: try Watir::Wait.until { browser.element(how, what).exists? } instead of this (cumbersome) case statement - # TODO: above fails on frame - Watir::Wait.until { browser.exists? } - begin - case element - when :link - Watir::Wait.until { browser.link(how, what).exists? } - when :button - Watir::Wait.until { browser.button(how, what).exists? } - when :radio - Watir::Wait.until { browser.radio(how, what).exists? } - when :checkbox - Watir::Wait.until { browser.checkbox(how, what).exists? } - when :div - Watir::Wait.until { browser.div(how, what).exists? } - when :select_list - Watir::Wait.until { browser.select_list(how, what).exists? } - when :text_field - Watir::Wait.until { browser.text_field(how, what).exists? } - when :frame - Watir::Wait.until { browser.frame(how, what).exists? } - when :form - Watir::Wait.until { browser.form(how, what).exists? } - when :cell - Watir::Wait.until { browser.cell(how, what).exists? } - when :image - Watir::Wait.until { browser.image(how, what).exists? } - else - Watir::Wait.until { browser.element(how, what).exists? } - end - rescue => e - if e.class.to_s =~ /TimeOutException/ - failed_to_log("#{msg}: '#{$!}'") - return false - elsif not rescue_me(e, __method__, rescue_me_command(element, how, what, :exists?), "#{browser.class}") - raise e - end - end - stop = Time.now.to_f - #debug_to_log("#{__method__}: start:#{start} stop:#{stop}") - # sleep 1 - passed_to_log("#{msg} (#{stop - start} seconds)") - true - rescue - failed_to_log("Unable to complete #{msg}: '#{$!}'") - end - - # Wait _while_ expression in *&block* returns true. - # @example - # wait_while(browser, 'Textfield is enabled.', 10) { browser.text_field(:id, 'this text field').enabled?} - # - # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. - # @param [String] desc Contains a message or description intended to appear in the log and/or report output - # @param [Fixnum] timeout Maximum time to wait, in seconds. - # @param [Proc] &block A ruby expression that evaluates to true or false. The expression - # is usually a watir or watir-webdriver command like .exists?, enabled?, etc. on a - # specific DOM element. Note that *&block* is listed as the last parameter inside the signature - # parentheses, but is passed in curly braces outside the signature parentheses in the call. This is - # the way Ruby works. - # @return [Boolean] True if condition returns false within time limit. - def wait_while(browser, desc, timeout = 45, &block) - #TODO: Would like to be able to see the block code in the log message instead of the identification - msg = "Wait while #{desc}:" - start = Time.now.to_f - Watir::Wait.until { browser.exists? } - begin - #Watir::Wait.until(timeout) { block.call(nil) } - if block.call(nil) - Watir::Wait.while(timeout) { block.call(nil) } - end - rescue => e - if e.class.to_s =~ /TimeOutException/ or e.message =~ /timed out/ - failed_to_log("#{msg}: '#{$!}' ") - return false - elsif not rescue_me(e, __method__, "#{block.to_s}", "#{browser.class}") - raise e - end - end - stop = Time.now.to_f - #debug_to_log("#{__method__}: start:#{start} stop:#{stop} block: #{block.to_s}") - # sleep 1 - passed_to_log("#{msg} (#{"%.5f" % (stop - start)} seconds)") # {#{block.to_s}}") - true - rescue - failed_to_log("Unable to complete #{msg}. '#{$!}'") - end - - alias wait_while_true wait_while - - # Wait _until_ expression in *&block* returns true. - # @example - # wait_until(browser, 'Textfield is enabled.', 10) { browser.text_field(:id, 'this text field').exists?} - # - # @param (see #wait_while) - # @return [Boolean] True if condition in *&block* returns true within time limit. - def wait_until(browser, desc, timeout = 45, skip_pass = false, &block) - #TODO: Would like to be able to see the block code in the log message instead of the identification - msg = "Wait until #{desc}" - start = Time.now.to_f - Watir::Wait.until { browser.exists? } - begin - Watir::Wait.until(timeout) { block.call(nil) } - rescue => e - if e.class.to_s =~ /TimeOutException/ or e.message =~ /timed out/ - failed_to_log("#{msg} '#{$!}'") - return false - elsif not rescue_me(e, __method__, "#{block.to_s}", "#{browser.class}") - raise e - end - end - stop = Time.now.to_f - #debug_to_log("#{__method__}: start:#{start} stop:#{stop} block: #{block.to_s}") - # sleep 1 - passed_to_log("#{msg} (#{"%.5f" % (stop - start)} seconds)") unless skip_pass # {#{block.to_s}}") - true - rescue - failed_to_log("Unable to complete #{msg} '#{$!}'") - end - - alias wait_until_true wait_until - - # Wait _until_ element, identified by attribute *how* and its value *what*, exists. - # If it exists within *timeout* seconds then wait _until_ it is enabled. - # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. - # @param [Symbol] how The element attribute used to identify the specific element. - # Valid values depend on the kind of element. - # Common values: :text, :id, :title, :name, :class, :href (:link only) - # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. - # @param [String] desc Contains a message or description intended to appear in the log and/or report output - # @param [Fixnum] timeout Maximum time to wait, in seconds. - # @param [Boolean] verbose When set to true, more debug information is written to the log and - # all steps return pass/fail messages in the report. - # @return [Boolean] True if condition returns false within time limit. - def wait_until_ready(browser, how, what, desc = '', timeout = 90, verbose = false) - msg = "#{__method__.to_s.titleize}: element: #{how}='#{what}'" - msg << " #{desc}" if desc.length > 0 - proc_exists = Proc.new { browser.element(how, what).exists? } - proc_enabled = Proc.new { browser.element(how, what).enabled? } - case how - when :href - proc_exists = Proc.new { browser.link(how, what).exists? } - proc_enabled = Proc.new { browser.link(how, what).enabled? } - end - if verbose - if wait_until(browser, "#{msg} Element exists.", timeout) { proc_exists.call(nil) } - if wait_until(browser, "#{msg} Element enabled.", timeout) { proc_enabled.call(nil) } - passed_to_log(msg) - true - else - failed_to_log(msg) - end - else - failed_to_log(msg) - end - else - start = Time.now.to_f - Watir::Wait.until { browser.exists? } - if Watir::Wait.until(timeout) { proc_exists.call(nil) } - if Watir::Wait.until(timeout) { proc_enabled.call(nil) } - stop = Time.now.to_f - #debug_to_log("#{__method__}: start:#{"%.5f" % start} stop:#{"%.5f" % stop}") - passed_to_log("#{msg} (#{"%.5f" % (stop - start)} seconds)") - true - else - failed_to_log(msg) - end - else - failed_to_log(msg) - end - end - rescue - failed_to_log("Unable to #{msg}. '#{$!}'") - end - - # Wait _until_ element, identified by attribute *how* and its value *what*, exists. - # If it exists within *timeout* seconds then wait _until_ it is enabled. Report only failures. - # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. - # @param [Symbol] how The element attribute used to identify the specific element. - # Valid values depend on the kind of element. - # Common values: :text, :id, :title, :name, :class, :href (:link only) - # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. - # @param [String] desc Contains a message or description intended to appear in the log and/or report output - # @param [Fixnum] timeout Maximum time to wait, in seconds. - # @param [Boolean] quiet When set to true, only fail messages are logged and reported. - # @return [Boolean] True if condition returns false within time limit. - def wait_until_ready_quiet(browser, how, what, desc = '', timeout = 45, quiet = true) - msg = "#{__method__.to_s.titleize}: element: #{how}='#{what}'" - msg << " #{desc}" if desc.length > 0 - proc_exists = Proc.new { browser.element(how, what).exists? } - proc_enabled = Proc.new { browser.element(how, what).enabled? } - case how - when :href - proc_exists = Proc.new { browser.link(how, what).exists? } - proc_enabled = Proc.new { browser.link(how, what).enabled? } - end - start = Time.now.to_f - Watir::Wait.until { browser.exists? } - sleep_for(1) - if Watir::Wait.until(timeout) { proc_exists.call(nil) } - if Watir::Wait.until(timeout) { proc_enabled.call(nil) } - stop = Time.now.to_f - #debug_to_log("#{msg}: start:#{"%.5f" % start} stop:#{"%.5f" % stop}") - passed_to_log("#{msg} (#{"%.5f" % (stop - start)} seconds)") unless quiet - true - else - failed_to_log(msg) - end - else - failed_to_log(msg) - end - rescue - failed_to_log("Unable to #{msg}. '#{$!}'") - end - - def wait_until_text(browser, strg, desc = '', timeout = 60) - if not strg.class.to_s.match('String') - raise "#{__method__} requires String for search target. #{strg.class} is not supported." - end - wait_until(browser, "'#{strg}' #{desc}", timeout) { browser.text.include? strg } - end - - alias wait_until_by_text wait_until_text - - def wait_until_enabled(browser, what, how, value, desc = '') - # TODO: This can be simplified - start = Time.now.to_f - Watir::Wait.until { browser.exists? } - sleep_for(1) - begin - case what - when :link - Watir::Wait.until { browser.link(how, value).enabled? } - when :button - Watir::Wait.until { browser.button(how, value).enabled? } - when :radio - Watir::Wait.until { browser.radio(how, value).enabled? } - when :checkbox - Watir::Wait.until { browser.checkbox(how, value).enabled? } - when :div - Watir::Wait.until { browser.div(how, value).enabled? } - when :select_list - Watir::Wait.until { browser.select_list(how, value).enabled? } - when :text_field - Watir::Wait.until { browser.text_field(how, value).enabled? } - when :table - Watir::Wait.until { browser.table(how, value).enabled? } - else - Watir::Wait.until { browser.element(how, value).enabled? } - end - rescue => e - if e.class.to_s =~ /TimeOutException/ - failed_to_log("Wait until (#{what} :#{how}=>#{value}) enabled. #{desc}: '#{$!}' #{desc}") - return false - elsif not rescue_me(e, __method__, "#{block.to_s}", "#{browser.class}") - raise e - end - end - stop = Time.now.to_f - #debug_to_log("#{__method__}: start:#{start} stop:#{stop}") - # sleep 1 - passed_to_log("Wait until (#{what} :#{how}=>#{value}) enabled. #{desc} (#{stop - start} seconds)") - true - rescue - failed_to_log("Unable to complete wait until (#{what} :#{how}=>#{value}) enabled. #{desc}: '#{$!}'") - end - - def wait_until_visible(browser, element, how, what, desc = '') - start = Time.now.to_f - Watir::Wait.until { browser.exists? } - sleep_for(1) - Watir::Wait.until(20) { browser.element(how, what).exists? } - begin - case element - when :link - Watir::Wait.until { browser.link(how, what).visible? } - when :button - Watir::Wait.until { browser.button(how, what).visible? } - when :radio - Watir::Wait.until { browser.radio(how, what).visible? } - when :checkbox - Watir::Wait.until { browser.checkbox(how, what).visible? } - when :div - Watir::Wait.until { browser.div(how, what).visible? } - when :select_list - Watir::Wait.until { browser.select_list(how, what).visible? } - when :text_field - Watir::Wait.until { browser.text_field(how, what).visible? } - else - Watir::Wait.until { browser.element(how, what).visible? } - # raise "#{__method__}: Element #{what} not supported." - end - rescue => e - if e.class.to_s =~ /TimeOutException/ - failed_to_log("Wait until (#{what} :#{how}=>#{what}) visible. #{desc}: '#{$!}' #{desc}") - return false - elsif not rescue_me(e, __method__, rescue_me_command(element, how, what, :visible?), "#{browser.class}") - raise e - end - end - stop = Time.now.to_f - #debug_to_log("#{__method__}: start:#{start} stop:#{stop}") - # sleep 1 - passed_to_log("Wait until (#{element} :#{how}=>#{what}) visible. #{desc} (#{stop - start} seconds)") - true - rescue - failed_to_log("Unable to complete wait until (#{element} :#{how}=>#{what}) visible. #{desc}: '#{$!}'") - end - - # @!endgroup Core - - # @!group Altenatives - - # Wait for a specific text to appear in the *browser*. - # @note This is a last resort method when other wait or wait until avenues have been exhausted. - # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. - # @param [String, Regexp] text A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. - # @param [String] desc Contains a message or description intended to appear in the log and/or report output - # @param [Fixnum] threshold The number of seconds after which a warning is added to the report message. - # @param [Fixnum] interval The time between checks that the text exists. - # @return [Boolean] Returns true if the text appears before *how_long* has expired. - def hold_for_text(browser, how_long, text, desc = '', threshold = 20, interval = 0.25) - countdown = how_long - Watir::Wait.until { browser.exists? } - sleep_for(1) - while ((not browser.contains_text(text)) and countdown > 0) - sleep(interval) - countdown = countdown - interval - end - if countdown < how_long - waittime = how_long - countdown - passed_to_log("#{__method__} '#{text}' found after #{waittime} second(s) #{desc}") - if waittime > threshold - failed_to_log("#{__method__} '#{text}' took #{waittime} second(s). (threshold: #{threshold} seconds) #{desc}") - end - true - else - failed_to_log("#{__method__} '#{text}' not found after #{how_long} second(s) #{desc}") - false - end - rescue - failed_to_log("Unable to #{__method__} '#{text}'. '#{$!}' #{desc}") - end - - alias wait_for_text hold_for_text - - # Wait up to *how_long* seconds for DOM element *what_for* to exist in the page. - # @note This is a last resort method when other wait or wait until avenues have been exhausted. - # @param [Fixnum] how_long Timeout limit - # @param [Watir::Element] what_for A reference to a Dom element to wait for. - def wait_for_exists(how_long, what_for) - wait_for(how_long, what_for) - end - - # Wait up to *how_long* seconds for DOM element *what_for* to exist in the page. - # @note This is a last resort method when other wait or wait until avenues have - # been exhausted. - # @param [Fixnum] how_long Timeout limit - # @param [Watir::Element] what_for A reference to a Dom element to wait for. - def wait_for(how_long, what_for, interval = 0.25) - countdown = how_long - while ((not what_for.exists?) and countdown > 0) - sleep(interval) - puts what_for.inspect+':'+countdown.to_s - countdown = countdown - interval - end - if countdown - puts 'found '+what_for.inspect - passed_tolog("wait_for (#{how_long} found "+what_for.inspect) - else - puts 'Did not find '+what_for.inspect - failed_tolog("wait_for (#{how_long} did not find "+what_for.inspect) - end - countdown - end - - # Wait up to *how_long* seconds for DOM element identified by attribute *how* and its value - # *what* to exist in the page. - # @note This is a last resort method when other wait or wait until avenues have been exhausted. - # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. - # @param [Symbol] how The element attribute used to identify the specific element. - # Valid values depend on the kind of element. - # Common values: :text, :id, :title, :name, :class, :href (:link only) - # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. - # @param [Fixnum] wait Timeout limit. - # @param [Fixnum] interval How long to wait before checking again. - # @return [Boolean] True if element exists within *wait* time - def wait_the_hard_way(browser, how, what, wait = 6, interval = 0.25) - count = (wait / interval).to_i + 1 - tally = 0 - ok = (1 / interval).to_i + 1 - debug_to_log("#{__method__}: wait: #{wait} secs; interval: #{interval} secs; count; #{count}; thresh: #{ok}") - Watir::Wait.until { browser.exists? } - sleep_for(1) - (1..count).each do |x| - begin - if browser.element(how, what).exists? - tally += 1 - debug_to_log("#{x}: #{(x - 1) * interval}: #{what} exists.") - else - tally = 0 - debug_to_log("#{x}: #{(x - 1) * interval}: #{what} does not exist.") - end - rescue - tally = 0 - debug_to_log("#{x}: #{(x - 1) * interval}: #{what} rescue: #{$!}") - end - if tally >= ok - return true - end - sleep(interval) - end - end - - # @!endgroup Alternatives - - end - end -end - +module Awetestlib + module Regression + # Methods for waiting until something has happened, or waiting while a condition exists, in the browser or DOM. + # sleep_for() is the basic technique. Its disadvantage is that it needs to be set for the longest likely wait time. + # The wait methods take advantage of the Watir and Watir Webdriver wait functionality to pause only as long as necessary for + # the element in question to be in the state needed. + module Waits + + # @!group Core + + # Sleep for *seconds* seconds before continuing execution of the script. + # A message is logged (but not reported) which, by default, includes a trace showing where in the script the sleep was invoked. + # @param [Fixnum] seconds The number of seconds to wait. + # @param [Boolean] dbg If true, includes a trace in the message + # @param [String] desc Contains a message or description intended to appear in the log and/or report output. + def sleep_for(seconds, dbg = true, desc = '') + trace = "\n#{get_debug_list}" if dbg + msg = build_message("Sleeping for #{seconds} seconds.", desc, trace) + info_to_log(msg) + sleep(seconds) + end + + # Wait while an element identified by attribute *how* with value *what* 1) exists, disappears, and exists again. + # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. + # @param [Symbol] how The element attribute used to identify the specific element. + # Valid values depend on the kind of element. + # Common values: :text, :id, :title, :name, :class, :href (:link only) + # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. + # @param [String] desc Contains a message or description intended to appear in the log and/or report output + # @param [Fixnum] timeout + # @return [Boolean] Returns true if disappears and reappears, each within the *timeout* limit + def wait_for_element_to_reappear(browser, how, what, desc = '', timeout = 20) + msg = "Element #{how}=#{what} exists. #{desc}" + wait_while(browser, "While: #{msg}", timeout) { browser.element(how, what).exists? } + wait_until(browser, "Until: #{msg}", timeout) { browser.element(how, what).exists? } + end + + # Wait until element of type *element*, identified by attribute *how* with value *what* exists on the page. + # Timeout is the default used by watir (60 seconds) + # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. + # @param [Symbol] element The kind of element to click. Must be one of the elements recognized by Watir. + # Some common values are :link, :button, :image, :div, :span. + # @param [Symbol] how The element attribute used to identify the specific element. + # Valid values depend on the kind of element. + # Common values: :text, :id, :title, :name, :class, :href (:link only) + # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. + # @param [String] desc Contains a message or description intended to appear in the log and/or report output + # @return [Boolean] True if element exists within timeout limit + def wait_until_exists(browser, element, how, what, desc = '') + msg = build_message("Wait until (:#{element} :#{how}=>'#{what}') exists.", desc) + start = Time.now.to_f + # TODO: try Watir::Wait.until { browser.element(how, what).exists? } instead of this (cumbersome) case statement + # TODO: above fails on frame + Watir::Wait.until { browser.exists? } + begin + case element + when :link + Watir::Wait.until { browser.link(how, what).exists? } + when :button + Watir::Wait.until { browser.button(how, what).exists? } + when :radio + Watir::Wait.until { browser.radio(how, what).exists? } + when :checkbox + Watir::Wait.until { browser.checkbox(how, what).exists? } + when :div + Watir::Wait.until { browser.div(how, what).exists? } + when :select_list + Watir::Wait.until { browser.select_list(how, what).exists? } + when :text_field + Watir::Wait.until { browser.text_field(how, what).exists? } + when :frame + Watir::Wait.until { browser.frame(how, what).exists? } + when :form + Watir::Wait.until { browser.form(how, what).exists? } + when :cell + Watir::Wait.until { browser.cell(how, what).exists? } + when :image + Watir::Wait.until { browser.image(how, what).exists? } + else + Watir::Wait.until { browser.element(how, what).exists? } + end + rescue => e + if e.class.to_s =~ /TimeOutException/ + failed_to_log("#{msg}: '#{$!}'") + return false + elsif not rescue_me(e, __method__, rescue_me_command(element, how, what, :exists?), "#{browser.class}") + raise e + end + end + stop = Time.now.to_f + #debug_to_log("#{__method__}: start:#{start} stop:#{stop}") + # sleep 1 + passed_to_log("#{msg} (#{stop - start} seconds)") + true + rescue + failed_to_log("Unable to complete #{msg}: '#{$!}'") + end + + # Wait _while_ expression in *&block* returns true. + # @example + # wait_while(browser, 'Textfield is enabled.', 10) { browser.text_field(:id, 'this text field').enabled?} + # + # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. + # @param [String] desc Contains a message or description intended to appear in the log and/or report output + # @param [Fixnum] timeout Maximum time to wait, in seconds. + # @param [Proc] &block A ruby expression that evaluates to true or false. The expression + # is usually a watir or watir-webdriver command like .exists?, enabled?, etc. on a + # specific DOM element. Note that *&block* is listed as the last parameter inside the signature + # parentheses, but is passed in curly braces outside the signature parentheses in the call. This is + # the way Ruby works. + # @return [Boolean] True if condition returns false within time limit. + def wait_while(browser, desc, timeout = 45, &block) + #TODO: Would like to be able to see the block code in the log message instead of the identification + msg = "Wait while #{desc}:" + start = Time.now.to_f + Watir::Wait.until { browser.exists? } + begin + #Watir::Wait.until(timeout) { block.call(nil) } + if block.call(nil) + Watir::Wait.while(timeout) { block.call(nil) } + end + rescue => e + if e.class.to_s =~ /TimeOutException/ or e.message =~ /timed out/ + failed_to_log("#{msg}: '#{$!}' ") + return false + elsif not rescue_me(e, __method__, "#{block.to_s}", "#{browser.class}") + raise e + end + end + stop = Time.now.to_f + #debug_to_log("#{__method__}: start:#{start} stop:#{stop} block: #{block.to_s}") + # sleep 1 + passed_to_log("#{msg} (#{"%.5f" % (stop - start)} seconds)") # {#{block.to_s}}") + true + rescue + failed_to_log("Unable to complete #{msg}. '#{$!}'") + end + + alias wait_while_true wait_while + + # Wait _until_ expression in *&block* returns true. + # @example + # wait_until(browser, 'Textfield is enabled.', 10) { browser.text_field(:id, 'this text field').exists?} + # + # @param (see #wait_while) + # @return [Boolean] True if condition in *&block* returns true within time limit. + def wait_until(browser, desc, timeout = 45, skip_pass = false, &block) + #TODO: Would like to be able to see the block code in the log message instead of the identification + msg = "Wait until #{desc}" + start = Time.now.to_f + Watir::Wait.until { browser.exists? } + begin + Watir::Wait.until(timeout) { block.call(nil) } + rescue => e + if e.class.to_s =~ /TimeOutException/ or e.message =~ /timed out/ + failed_to_log("#{msg} '#{$!}'") + return false + elsif not rescue_me(e, __method__, "#{block.to_s}", "#{browser.class}") + raise e + end + end + stop = Time.now.to_f + #debug_to_log("#{__method__}: start:#{start} stop:#{stop} block: #{block.to_s}") + # sleep 1 + passed_to_log("#{msg} (#{"%.5f" % (stop - start)} seconds)") unless skip_pass # {#{block.to_s}}") + true + rescue + failed_to_log("Unable to complete #{msg} '#{$!}'") + end + + alias wait_until_true wait_until + + # Wait _until_ element, identified by attribute *how* and its value *what*, exists. + # If it exists within *timeout* seconds then wait _until_ it is enabled. + # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. + # @param [Symbol] how The element attribute used to identify the specific element. + # Valid values depend on the kind of element. + # Common values: :text, :id, :title, :name, :class, :href (:link only) + # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. + # @param [String] desc Contains a message or description intended to appear in the log and/or report output + # @param [Fixnum] timeout Maximum time to wait, in seconds. + # @param [Boolean] verbose When set to true, more debug information is written to the log and + # all steps return pass/fail messages in the report. + # @return [Boolean] True if condition returns false within time limit. + def wait_until_ready(browser, how, what, desc = '', timeout = 90, verbose = false) + msg = "#{__method__.to_s.titleize}: element: #{how}='#{what}'" + msg << " #{desc}" if desc.length > 0 + proc_exists = Proc.new { browser.element(how, what).exists? } + proc_enabled = Proc.new { browser.element(how, what).enabled? } + case how + when :href + proc_exists = Proc.new { browser.link(how, what).exists? } + proc_enabled = Proc.new { browser.link(how, what).enabled? } + end + if verbose + if wait_until(browser, "#{msg} Element exists.", timeout) { proc_exists.call(nil) } + if wait_until(browser, "#{msg} Element enabled.", timeout) { proc_enabled.call(nil) } + passed_to_log(msg) + true + else + failed_to_log(msg) + end + else + failed_to_log(msg) + end + else + start = Time.now.to_f + Watir::Wait.until { browser.exists? } + if Watir::Wait.until(timeout) { proc_exists.call(nil) } + if Watir::Wait.until(timeout) { proc_enabled.call(nil) } + stop = Time.now.to_f + #debug_to_log("#{__method__}: start:#{"%.5f" % start} stop:#{"%.5f" % stop}") + passed_to_log("#{msg} (#{"%.5f" % (stop - start)} seconds)") + true + else + failed_to_log(msg) + end + else + failed_to_log(msg) + end + end + rescue + failed_to_log("Unable to #{msg}. '#{$!}'") + end + + # Wait _until_ element, identified by attribute *how* and its value *what*, exists. + # If it exists within *timeout* seconds then wait _until_ it is enabled. Report only failures. + # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. + # @param [Symbol] how The element attribute used to identify the specific element. + # Valid values depend on the kind of element. + # Common values: :text, :id, :title, :name, :class, :href (:link only) + # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. + # @param [String] desc Contains a message or description intended to appear in the log and/or report output + # @param [Fixnum] timeout Maximum time to wait, in seconds. + # @param [Boolean] quiet When set to true, only fail messages are logged and reported. + # @return [Boolean] True if condition returns false within time limit. + def wait_until_ready_quiet(browser, how, what, desc = '', timeout = 45, quiet = true) + msg = "#{__method__.to_s.titleize}: element: #{how}='#{what}'" + msg << " #{desc}" if desc.length > 0 + proc_exists = Proc.new { browser.element(how, what).exists? } + proc_enabled = Proc.new { browser.element(how, what).enabled? } + case how + when :href + proc_exists = Proc.new { browser.link(how, what).exists? } + proc_enabled = Proc.new { browser.link(how, what).enabled? } + end + start = Time.now.to_f + Watir::Wait.until { browser.exists? } + sleep_for(1) + if Watir::Wait.until(timeout) { proc_exists.call(nil) } + if Watir::Wait.until(timeout) { proc_enabled.call(nil) } + stop = Time.now.to_f + #debug_to_log("#{msg}: start:#{"%.5f" % start} stop:#{"%.5f" % stop}") + passed_to_log("#{msg} (#{"%.5f" % (stop - start)} seconds)") unless quiet + true + else + failed_to_log(msg) + end + else + failed_to_log(msg) + end + rescue + failed_to_log("Unable to #{msg}. '#{$!}'") + end + + def wait_until_text(browser, strg, desc = '', timeout = 60) + if not strg.class.to_s.match('String') + raise "#{__method__} requires String for search target. #{strg.class} is not supported." + end + wait_until(browser, "'#{strg}' #{desc}", timeout) { browser.text.include? strg } + end + + alias wait_until_by_text wait_until_text + + def wait_until_enabled(browser, what, how, value, desc = '') + # TODO: This can be simplified + start = Time.now.to_f + Watir::Wait.until { browser.exists? } + sleep_for(1) + begin + case what + when :link + Watir::Wait.until { browser.link(how, value).enabled? } + when :button + Watir::Wait.until { browser.button(how, value).enabled? } + when :radio + Watir::Wait.until { browser.radio(how, value).enabled? } + when :checkbox + Watir::Wait.until { browser.checkbox(how, value).enabled? } + when :div + Watir::Wait.until { browser.div(how, value).enabled? } + when :select_list + Watir::Wait.until { browser.select_list(how, value).enabled? } + when :text_field + Watir::Wait.until { browser.text_field(how, value).enabled? } + when :table + Watir::Wait.until { browser.table(how, value).enabled? } + else + Watir::Wait.until { browser.element(how, value).enabled? } + end + rescue => e + if e.class.to_s =~ /TimeOutException/ + failed_to_log("Wait until (#{what} :#{how}=>#{value}) enabled. #{desc}: '#{$!}' #{desc}") + return false + elsif not rescue_me(e, __method__, "#{block.to_s}", "#{browser.class}") + raise e + end + end + stop = Time.now.to_f + #debug_to_log("#{__method__}: start:#{start} stop:#{stop}") + # sleep 1 + passed_to_log("Wait until (#{what} :#{how}=>#{value}) enabled. #{desc} (#{stop - start} seconds)") + true + rescue + failed_to_log("Unable to complete wait until (#{what} :#{how}=>#{value}) enabled. #{desc}: '#{$!}'") + end + + def wait_until_visible(browser, element, how, what, desc = '') + start = Time.now.to_f + Watir::Wait.until { browser.exists? } + sleep_for(1) + Watir::Wait.until(20) { browser.element(how, what).exists? } + begin + case element + when :link + Watir::Wait.until { browser.link(how, what).visible? } + when :button + Watir::Wait.until { browser.button(how, what).visible? } + when :radio + Watir::Wait.until { browser.radio(how, what).visible? } + when :checkbox + Watir::Wait.until { browser.checkbox(how, what).visible? } + when :div + Watir::Wait.until { browser.div(how, what).visible? } + when :select_list + Watir::Wait.until { browser.select_list(how, what).visible? } + when :text_field + Watir::Wait.until { browser.text_field(how, what).visible? } + else + Watir::Wait.until { browser.element(how, what).visible? } + # raise "#{__method__}: Element #{what} not supported." + end + rescue => e + if e.class.to_s =~ /TimeOutException/ + failed_to_log("Wait until (#{what} :#{how}=>#{what}) visible. #{desc}: '#{$!}' #{desc}") + return false + elsif not rescue_me(e, __method__, rescue_me_command(element, how, what, :visible?), "#{browser.class}") + raise e + end + end + stop = Time.now.to_f + #debug_to_log("#{__method__}: start:#{start} stop:#{stop}") + # sleep 1 + passed_to_log("Wait until (#{element} :#{how}=>#{what}) visible. #{desc} (#{stop - start} seconds)") + true + rescue + failed_to_log("Unable to complete wait until (#{element} :#{how}=>#{what}) visible. #{desc}: '#{$!}'") + end + + # @!endgroup Core + + # @!group Altenatives + + # Wait for a specific text to appear in the *browser*. + # @note This is a last resort method when other wait or wait until avenues have been exhausted. + # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. + # @param [String, Regexp] text A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. + # @param [String] desc Contains a message or description intended to appear in the log and/or report output + # @param [Fixnum] threshold The number of seconds after which a warning is added to the report message. + # @param [Fixnum] interval The time between checks that the text exists. + # @return [Boolean] Returns true if the text appears before *how_long* has expired. + def hold_for_text(browser, how_long, text, desc = '', threshold = 20, interval = 0.25) + countdown = how_long + Watir::Wait.until { browser.exists? } + sleep_for(1) + while ((not browser.contains_text(text)) and countdown > 0) + sleep(interval) + countdown = countdown - interval + end + if countdown < how_long + waittime = how_long - countdown + passed_to_log("#{__method__} '#{text}' found after #{waittime} second(s) #{desc}") + if waittime > threshold + failed_to_log("#{__method__} '#{text}' took #{waittime} second(s). (threshold: #{threshold} seconds) #{desc}") + end + true + else + failed_to_log("#{__method__} '#{text}' not found after #{how_long} second(s) #{desc}") + false + end + rescue + failed_to_log("Unable to #{__method__} '#{text}'. '#{$!}' #{desc}") + end + + alias wait_for_text hold_for_text + + # Wait up to *how_long* seconds for DOM element *what_for* to exist in the page. + # @note This is a last resort method when other wait or wait until avenues have been exhausted. + # @param [Fixnum] how_long Timeout limit + # @param [Watir::Element] what_for A reference to a Dom element to wait for. + def wait_for_exists(how_long, what_for) + wait_for(how_long, what_for) + end + + # Wait up to *how_long* seconds for DOM element *what_for* to exist in the page. + # @note This is a last resort method when other wait or wait until avenues have + # been exhausted. + # @param [Fixnum] how_long Timeout limit + # @param [Watir::Element] what_for A reference to a Dom element to wait for. + def wait_for(how_long, what_for, interval = 0.25) + countdown = how_long + while ((not what_for.exists?) and countdown > 0) + sleep(interval) + puts what_for.inspect+':'+countdown.to_s + countdown = countdown - interval + end + if countdown + puts 'found '+what_for.inspect + passed_tolog("wait_for (#{how_long} found "+what_for.inspect) + else + puts 'Did not find '+what_for.inspect + failed_tolog("wait_for (#{how_long} did not find "+what_for.inspect) + end + countdown + end + + # Wait up to *how_long* seconds for DOM element identified by attribute *how* and its value + # *what* to exist in the page. + # @note This is a last resort method when other wait or wait until avenues have been exhausted. + # @param [Watir::Browser] browser A reference to the browser window or container element to be tested. + # @param [Symbol] how The element attribute used to identify the specific element. + # Valid values depend on the kind of element. + # Common values: :text, :id, :title, :name, :class, :href (:link only) + # @param [String, Regexp] what A string or a regular expression to be found in the *how* attribute that uniquely identifies the element. + # @param [Fixnum] wait Timeout limit. + # @param [Fixnum] interval How long to wait before checking again. + # @return [Boolean] True if element exists within *wait* time + def wait_the_hard_way(browser, how, what, wait = 6, interval = 0.25) + count = (wait / interval).to_i + 1 + tally = 0 + ok = (1 / interval).to_i + 1 + debug_to_log("#{__method__}: wait: #{wait} secs; interval: #{interval} secs; count; #{count}; thresh: #{ok}") + Watir::Wait.until { browser.exists? } + sleep_for(1) + (1..count).each do |x| + begin + if browser.element(how, what).exists? + tally += 1 + debug_to_log("#{x}: #{(x - 1) * interval}: #{what} exists.") + else + tally = 0 + debug_to_log("#{x}: #{(x - 1) * interval}: #{what} does not exist.") + end + rescue + tally = 0 + debug_to_log("#{x}: #{(x - 1) * interval}: #{what} rescue: #{$!}") + end + if tally >= ok + return true + end + sleep(interval) + end + end + + # @!endgroup Alternatives + + end + end +end +