1
+ module Appium
2
+ module Common
3
+
4
+ # http://mudge.name/2011/01/26/passing-blocks-in-ruby-without-block.html
5
+ # Note that the Ruby timeout module is avoided. timeout has problems.
6
+ # https://coderwall.com/p/1novga
7
+
8
+ # Wait code from the selenium Ruby gem
9
+ # https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
10
+ def _generic_wait opts = { } , &block
11
+ valid_keys = [ :timeout , :interval , :message , :ignore , :return_if_true ]
12
+ invalid_keys = [ ]
13
+ opts . keys . each { |key | invalid_keys << key unless valid_keys . include? ( key ) }
14
+ # [:one, :two] => :one, :two
15
+ raise "Invalid keys #{ invalid_keys . to_s [ 1 ..-2 ] } . Valid keys are #{ valid_keys . to_s [ 1 ..-2 ] } " unless invalid_keys . empty?
16
+
17
+ timeout = opts . fetch ( :timeout , 30 )
18
+ interval = opts . fetch ( :interval , 0.5 )
19
+ message = opts [ :message ]
20
+ ignored = Array ( opts [ :ignore ] || ::Exception )
21
+ return_if_true = opts [ :return_if_true ]
22
+
23
+ end_time = Time . now + timeout
24
+ last_error = nil
25
+
26
+ until Time . now > end_time
27
+ begin
28
+ if return_if_true
29
+ result = block . call
30
+ return result if result
31
+ else
32
+ return block . call
33
+ end
34
+ rescue ::Errno ::ECONNREFUSED => e
35
+ raise e
36
+ rescue *ignored => last_error
37
+ # swallowed
38
+ end
39
+
40
+ sleep interval
41
+ end
42
+
43
+ if message
44
+ msg = message . dup
45
+ else
46
+ msg = "timed out after #{ timeout } seconds"
47
+ end
48
+
49
+ msg << " (#{ last_error . message } )" if last_error
50
+
51
+ raise Selenium ::WebDriver ::Error ::TimeOutError , msg
52
+ end
53
+
54
+ # process opts before calling _generic_wait
55
+ def _process_wait_opts opts
56
+ opts = { timeout : opts } if opts . is_a? ( Numeric )
57
+ raise 'opts must be a hash' unless opts . is_a? Hash
58
+ opts
59
+ end
60
+
61
+ # Check every interval seconds to see if block.call returns a truthy value.
62
+ # Note this isn't a strict boolean true, any truthy value is accepted.
63
+ # false and nil are considered failures.
64
+ # Give up after timeout seconds.
65
+ #
66
+ # Wait code from the selenium Ruby gem
67
+ # https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
68
+ #
69
+ # If only a number is provided then it's treated as the timeout value.
70
+ #
71
+ # @param [Hash] opts Options
72
+ # @option opts [Numeric] :timeout (5) Seconds to wait before timing out.
73
+ # @option opts [Numeric] :interval (0.2) Seconds to sleep between polls.
74
+ # @option opts [String] :message Exception message if timed out.
75
+ # @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
76
+ def wait_true opts = { } , &block
77
+ opts = _process_wait_opts ( opts ) . merge ( return_if_true : true )
78
+ _generic_wait opts , &block
79
+ end
80
+
81
+ # Check every interval seconds to see if block.call doesn't raise an exception.
82
+ # Give up after timeout seconds.
83
+ #
84
+ # Wait code from the selenium Ruby gem
85
+ # https://github.com/SeleniumHQ/selenium/blob/cf501dda3f0ed12233de51ce8170c0e8090f0c20/rb/lib/selenium/webdriver/common/wait.rb
86
+ #
87
+ # If only a number is provided then it's treated as the timeout value.
88
+ #
89
+ # @param [Hash] opts Options
90
+ # @option opts [Numeric] :timeout (5) Seconds to wait before timing out.
91
+ # @option opts [Numeric] :interval (0.2) Seconds to sleep between polls.
92
+ # @option opts [String] :message Exception message if timed out.
93
+ # @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Exception)
94
+ def wait opts = { } , &block
95
+ opts = _process_wait_opts ( opts ) . merge ( return_if_true : false )
96
+ _generic_wait opts , &block
97
+ end
98
+ end # module Common
99
+ end # module Appium
0 commit comments