testa_appium_driver 0.1.1 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  module TestaAppiumDriver
2
- module AndroidAttributeModule
2
+ module Attributes
3
3
 
4
4
  #noinspection RubyNilAnalysis
5
5
  def attribute(name, *args)
@@ -98,7 +98,7 @@ module TestaAppiumDriver
98
98
  end
99
99
 
100
100
  class Locator
101
- include TestaAppiumDriver::AndroidAttributeModule
101
+ include TestaAppiumDriver::Attributes
102
102
 
103
103
 
104
104
  # element index in parent element, starts from 0
@@ -75,7 +75,7 @@ module TestaAppiumDriver
75
75
  end
76
76
 
77
77
 
78
- # @return [Locator] existing locator element
78
+ # @return [Locator] new child locator element
79
79
  def add_child_selector(params)
80
80
  params, selectors = extract_selectors_from_params(params)
81
81
  single = params[:single]
@@ -2,7 +2,7 @@ module Selenium
2
2
  module WebDriver
3
3
  class Element
4
4
  include TestaAppiumDriver::ClassSelectors
5
- include TestaAppiumDriver::AndroidAttributeModule
5
+ include TestaAppiumDriver::Attributes
6
6
  end
7
7
  end
8
8
  end
@@ -2,6 +2,7 @@ module TestaAppiumDriver
2
2
  #noinspection RubyTooManyMethodsInspection
3
3
  class Locator
4
4
 
5
+ # performs a long tap on the retrieved element
5
6
  # @param [Float] duration in seconds
6
7
  def long_tap(duration = LONG_TAP_DURATION)
7
8
  action_builder = @driver.action
@@ -15,173 +16,238 @@ module TestaAppiumDriver
15
16
  @driver.perform_actions [f1]
16
17
  end
17
18
 
18
- # @return [Array] array of [Selenium::WebDriver::Element]
19
- def each(deadzone: nil, skip_scroll_to_start: false, &block)
19
+
20
+ # scrolls to the start of the scrollable containers and scrolls to the end,
21
+ # everytime a locator element is found the given block is executed
22
+ # @return [Array<Selenium::WebDriver::Element>]
23
+ def each(top: nil, bottom: nil, right: nil, left: nil, direction: nil, &block)
24
+ deadzone = _process_deadzone(top, bottom, right, left)
20
25
  raise "Each can only be performed on multiple elements locator" if @single
21
26
  deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
22
27
  sa = ScrollActions.new(@scrollable_locator,
23
28
  locator: self,
24
29
  deadzone: deadzone,
25
30
  default_scroll_strategy: @default_scroll_strategy)
26
- sa.each(skip_scroll_to_start, &block)
31
+ if direction.nil?
32
+ sa.each(&block)
33
+ else
34
+ sa.send("each_#{direction}", &block)
35
+ end
36
+ end
37
+
38
+ # scrolls down from the current page view (without prior scrolling to the top) and
39
+ # everytime a locator element is found the given block is executed
40
+ # @return [Array<Selenium::WebDriver::Element>]
41
+ def each_down(top: nil, bottom: nil, right: nil, left: nil, &block)
42
+ each(top: top, bottom: bottom, right: right, left: left, direction: :down, &block)
43
+ end
44
+
45
+ # scrolls up from the current page view (without prior scrolling to the bottom) and
46
+ # everytime a locator element is found the given block is executed
47
+ # @return [Array<Selenium::WebDriver::Element>]
48
+ def each_up(top: nil, bottom: nil, right: nil, left: nil, &block)
49
+ each(top: top, bottom: bottom, right: right, left: left, direction: :up, &block)
50
+ end
51
+
52
+ # scrolls right from the current page view (without prior scrolling to the left) and
53
+ # everytime a locator element is found the given block is executed
54
+ # @return [Array<Selenium::WebDriver::Element>]
55
+ def each_right(top: nil, bottom: nil, right: nil, left: nil, &block)
56
+ each(top: top, bottom: bottom, right: right, left: left, direction: :right, &block)
57
+ end
58
+
59
+ # scrolls left from the current page view (without prior scrolling to the right) and
60
+ # everytime a locator element is found the given block is executed
61
+ # @return [Array<Selenium::WebDriver::Element>]
62
+ def each_left(top: nil, bottom: nil, right: nil, left: nil, &block)
63
+ each(top: top, bottom: bottom, right: right, left: left, direction: :left, &block)
27
64
  end
28
65
 
29
66
 
30
67
  # Aligns element (by default) on top of the scrollable container, if the element does not exists it will scroll to find it
68
+ # The element is aligned if the the distance from the top/bottom/right/left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
69
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
70
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
31
71
  # @return [TestaAppiumDriver::Locator]
32
- def align(with = :top, deadzone: nil, raise: false)
72
+ def align(with = :top, top: nil, bottom: nil, right: nil, left: nil, scroll_to_find: false)
33
73
  deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
34
74
  sa = ScrollActions.new(@scrollable_locator,
35
75
  locator: self,
36
76
  deadzone: deadzone,
37
- default_scroll_strategy: @default_scroll_strategy,
38
- raise: raise)
39
- sa.align(with)
77
+ default_scroll_strategy: @default_scroll_strategy)
78
+ sa.align(with, scroll_to_find)
40
79
  self
41
80
  end
42
81
 
43
82
  # Aligns element on top of the scrollable container, if the element does not exists it will scroll to find it
83
+ # The element is aligned if the the distance from the top of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
84
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
85
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
44
86
  # @return [TestaAppiumDriver::Locator]
45
- def align_top(deadzone: nil)
46
- align(:top, deadzone: deadzone)
87
+ def align_top(top: nil, bottom: nil, right: nil, left: nil)
88
+ align(:top, top: top, bottom: bottom, right: right, left: left)
47
89
  end
48
90
 
49
91
  # Aligns element on bottom of the scrollable container, if the element does not exists it will scroll to find it
92
+ # The element is aligned if the the distance from the bottom of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
93
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
94
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
50
95
  # @return [TestaAppiumDriver::Locator]
51
- def align_bottom(deadzone: nil)
52
- align(:bottom, deadzone: deadzone)
96
+ def align_bottom(top: nil, bottom: nil, right: nil, left: nil)
97
+ align(:bottom, top: top, bottom: bottom, right: right, left: left)
53
98
  end
54
99
 
55
100
  # Aligns element on left of the scrollable container, if the element does not exists it will scroll to find it
101
+ # The element is aligned if the the distance from the left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
102
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
103
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
56
104
  # @return [TestaAppiumDriver::Locator]
57
- def align_left(deadzone: nil)
58
- align(:left, deadzone: deadzone)
105
+ def align_left(top: nil, bottom: nil, right: nil, left: nil)
106
+ align(:left, top: top, bottom: bottom, right: right, left: left)
59
107
  end
60
108
 
61
109
  # Aligns element on right of the scrollable container, if the element does not exists it will scroll to find it
110
+ # The element is aligned if the the distance from the right of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
111
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
112
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
62
113
  # @return [TestaAppiumDriver::Locator]
63
- def align_right(deadzone: nil)
64
- align(:right, deadzone: deadzone)
114
+ def align_right(top: nil, bottom: nil, right: nil, left: nil)
115
+ align(:right, top: top, bottom: bottom, right: right, left: left)
65
116
  end
66
117
 
67
118
  # Aligns element (by default) on top of the scrollable container, if the element does not exists it raise an exception
119
+ # The element is aligned if the the distance from the top/bottom/right/left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
120
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
121
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
68
122
  # @return [TestaAppiumDriver::Locator]
69
- def align!(with = :top, deadzone: nil)
70
- align(with, deadzone: deadzone, raise: true)
123
+ def align!(with = :top, top: nil, bottom: nil, right: nil, left: nil)
124
+ align(with, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
71
125
  end
72
126
 
73
127
  # Aligns element on top of the scrollable container, if the element does not exists it raise an exception
128
+ # The element is aligned if the the distance from the top of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
129
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
130
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
74
131
  # @return [TestaAppiumDriver::Locator]
75
- def align_top!(deadzone: nil)
76
- align(:top, deadzone: deadzone, raise: true)
132
+ def align_top!(top: nil, bottom: nil, right: nil, left: nil)
133
+ align(:top, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
77
134
  end
78
135
 
79
136
  # Aligns element on bottom of the scrollable container, if the element does not exists it raise an exception
137
+ # The element is aligned if the the distance from the bottom of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
138
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
139
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
80
140
  # @return [TestaAppiumDriver::Locator]
81
- def align_bottom!(deadzone: nil)
82
- align(:bottom, deadzone: deadzone, raise: true)
141
+ def align_bottom!(top: nil, bottom: nil, right: nil, left: nil)
142
+ align(:bottom, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
83
143
  end
84
144
 
85
145
  # Aligns element on left of the scrollable container, if the element does not exists it raise an exception
146
+ # The element is aligned if the the distance from the left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
147
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
148
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
86
149
  # @return [TestaAppiumDriver::Locator]
87
- def align_left!(deadzone: nil)
88
- align(:left, deadzone: deadzone, raise: true)
150
+ def align_left!(top: nil, bottom: nil, right: nil, left: nil)
151
+ align(:left, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
89
152
  end
90
153
 
91
154
  # Aligns element on right of the scrollable container, if the element does not exists it raise an exception
155
+ # The element is aligned if the the distance from the right of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
156
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
157
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
92
158
  # @return [TestaAppiumDriver::Locator]
93
- def align_right!(deadzone: nil)
94
- align(:right, deadzone: deadzone, raise: true)
159
+ def align_right!(top: nil, bottom: nil, right: nil, left: nil)
160
+ align(:right, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
95
161
  end
96
162
 
97
163
 
98
164
  # First scrolls to the beginning of the scrollable container and then scrolls down until element is found or end is reached
99
165
  # @return [TestaAppiumDriver::Locator]
100
- def scroll_to(deadzone: nil, max_scrolls: nil, direction: nil)
166
+ def scroll_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil, direction: nil)
101
167
  if direction
102
- _scroll_dir_to(deadzone, max_scrolls, direction)
168
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, direction)
103
169
  else
104
- _scroll_to(deadzone, max_scrolls)
170
+ _scroll_to(_process_deadzone(top, bottom, right, left), max_scrolls)
105
171
  end
106
172
  end
107
173
 
108
174
 
109
175
  # Scrolls down until element is found or end is reached
110
176
  # @return [TestaAppiumDriver::Locator]
111
- def scroll_down_to(deadzone: nil, max_scrolls: nil)
112
- _scroll_dir_to(deadzone, max_scrolls, :down)
177
+ def scroll_down_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
178
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :down)
113
179
  end
114
180
 
115
181
  # Scrolls up until element is found or end is reached
116
182
  # @return [TestaAppiumDriver::Locator]
117
- def scroll_up_to(deadzone: nil, max_scrolls: nil)
118
- _scroll_dir_to(deadzone, max_scrolls, :up)
183
+ def scroll_up_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
184
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :up)
119
185
  end
120
186
 
121
187
  # Scrolls right until element is found or end is reached
122
188
  # @return [TestaAppiumDriver::Locator]
123
- def scroll_right_to(deadzone: nil, max_scrolls: nil)
124
- _scroll_dir_to(deadzone, max_scrolls, :right)
189
+ def scroll_right_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
190
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :right)
125
191
  end
126
192
 
127
193
 
128
194
  # Scrolls left until element is found or end is reached
129
195
  # @return [TestaAppiumDriver::Locator]
130
- def scroll_left_to(deadzone: nil, max_scrolls: nil)
131
- _scroll_dir_to(deadzone, max_scrolls, :left)
196
+ def scroll_left_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
197
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :left)
132
198
  end
133
199
 
134
200
  # Scrolls to the start of the scrollable container (top on vertical container, left on horizontal)
135
201
  # @return [TestaAppiumDriver::Locator]
136
- def scroll_to_start(deadzone: nil)
137
- _scroll_to_start_or_end(:start, deadzone)
202
+ def scroll_to_start(top: nil, bottom: nil, right: nil, left: nil)
203
+ _scroll_to_start_or_end(:start, _process_deadzone(top, bottom, right, left))
138
204
  end
139
205
 
140
206
  # Scrolls to the end of the scrollable container (bottom on vertical container, right on horizontal)
141
207
  # @return [TestaAppiumDriver::Locator]
142
- def scroll_to_end(deadzone: nil)
143
- _scroll_to_start_or_end(:end, deadzone)
208
+ def scroll_to_end(top: nil, bottom: nil, right: nil, left: nil)
209
+ _scroll_to_start_or_end(:end, _process_deadzone(top, bottom, right, left))
144
210
  end
145
211
 
146
212
 
147
213
  # @return [TestaAppiumDriver::Locator]
148
- def page_down(deadzone: nil)
149
- _page(:down, deadzone)
214
+ def page_down(top: nil, bottom: nil, right: nil, left: nil)
215
+ _page(:down, _process_deadzone(top, bottom, right, left))
150
216
  end
151
217
 
152
218
  # @return [TestaAppiumDriver::Locator]
153
- def page_up(deadzone: nil)
154
- _page(:up, deadzone)
219
+ def page_up(top: nil, bottom: nil, right: nil, left: nil)
220
+ _page(:up, _process_deadzone(top, bottom, right, left))
155
221
  end
156
222
 
157
223
  # @return [TestaAppiumDriver::Locator]
158
- def page_left(deadzone: nil)
159
- _page(:left, deadzone)
224
+ def page_left(top: nil, bottom: nil, right: nil, left: nil)
225
+ _page(:left, _process_deadzone(top, bottom, right, left))
160
226
  end
161
227
 
162
228
  # @return [TestaAppiumDriver::Locator]
163
- def page_right(deadzone: nil)
164
- _page(:right, deadzone)
229
+ def page_right(top: nil, bottom: nil, right: nil, left: nil)
230
+ _page(:right, _process_deadzone(top, bottom, right, left))
165
231
  end
166
232
 
167
233
  # @return [TestaAppiumDriver::Locator]
168
- def fling_down(deadzone: nil)
169
- _fling(:down, deadzone)
234
+ def fling_down(top: nil, bottom: nil, right: nil, left: nil)
235
+ _fling(:down, _process_deadzone(top, bottom, right, left))
170
236
  end
171
237
 
172
238
  # @return [TestaAppiumDriver::Locator]
173
- def fling_up(deadzone: nil)
174
- _fling(:up, deadzone)
239
+ def fling_up(top: nil, bottom: nil, right: nil, left: nil)
240
+ _fling(:up, _process_deadzone(top, bottom, right, left))
175
241
  end
176
242
 
177
243
  # @return [TestaAppiumDriver::Locator]
178
- def fling_left(deadzone: nil)
179
- _fling(:left, deadzone)
244
+ def fling_left(top: nil, bottom: nil, right: nil, left: nil)
245
+ _fling(:left, _process_deadzone(top, bottom, right, left))
180
246
  end
181
247
 
182
248
  # @return [TestaAppiumDriver::Locator]
183
- def fling_right(deadzone: nil)
184
- _fling(:right, deadzone)
249
+ def fling_right(top: nil, bottom: nil, right: nil, left: nil)
250
+ _fling(:right, _process_deadzone(top, bottom, right, left))
185
251
  end
186
252
 
187
253
 
@@ -232,6 +298,18 @@ module TestaAppiumDriver
232
298
 
233
299
 
234
300
  private
301
+ def _process_deadzone(top, bottom, right, left)
302
+ deadzone = nil
303
+ if !top.nil? || !bottom.nil? || !right.nil? || !left.nil?
304
+ deadzone = {}
305
+ deadzone[:top] = top unless top.nil?
306
+ deadzone[:bottom] = bottom unless bottom.nil?
307
+ deadzone[:right] = right unless right.nil?
308
+ deadzone[:left] = left unless left.nil?
309
+ end
310
+ deadzone
311
+ end
312
+
235
313
  def _drag_to(x, y)
236
314
  sa = ScrollActions.new(@scrollable_locator,
237
315
  locator: self,
@@ -239,6 +317,8 @@ module TestaAppiumDriver
239
317
  sa.drag_to(x, y)
240
318
  self
241
319
  end
320
+
321
+
242
322
  def _page(direction, deadzone)
243
323
  deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
244
324
  sa = ScrollActions.new(@scrollable_locator,
@@ -266,7 +346,6 @@ module TestaAppiumDriver
266
346
  sa = ScrollActions.new(@scrollable_locator,
267
347
  locator: self,
268
348
  deadzone: deadzone,
269
- direction: :left,
270
349
  default_scroll_strategy: @default_scroll_strategy)
271
350
  if type == :start
272
351
  sa.scroll_to_start
@@ -293,7 +372,6 @@ module TestaAppiumDriver
293
372
  locator: self,
294
373
  deadzone: deadzone,
295
374
  max_scrolls: max_scrolls,
296
- direction: direction,
297
375
  default_scroll_strategy: @default_scroll_strategy)
298
376
 
299
377
  sa.send("scroll_#{direction}_to")
@@ -12,6 +12,8 @@ module TestaAppiumDriver
12
12
  attr_accessor :driver
13
13
  attr_accessor :strategy
14
14
  attr_accessor :strategy_reason
15
+
16
+ # @type [Boolean] used to determine if last selector was one of siblings or children. Only in those selectors we can reliably use xpath array [instance] selector
15
17
  attr_accessor :last_selector_adjacent
16
18
  attr_accessor :can_use_id_strategy
17
19
 
@@ -68,7 +70,6 @@ module TestaAppiumDriver
68
70
  @strategy = params[:strategy]
69
71
  @strategy_reason = params[:strategy_reason]
70
72
 
71
- # @type [Boolean] used to determine if last selector was one of siblings or children. Only in those selectors we can reliably use xpath array [instance] selector
72
73
  @last_selector_adjacent = false
73
74
 
74
75
  init(params, selectors, single)
@@ -77,7 +78,9 @@ module TestaAppiumDriver
77
78
 
78
79
  # method missing is used to fetch the element before executing additional commands like click, send_key, count
79
80
  def method_missing(method, *args, &block)
80
- execute.send(method, *args, &block)
81
+ r = execute.send(method, *args, &block)
82
+ @driver.invalidate_cache
83
+ r
81
84
  end
82
85
 
83
86
 
@@ -96,6 +99,7 @@ module TestaAppiumDriver
96
99
  end
97
100
 
98
101
 
102
+
99
103
  strategy, selector = strategy_and_selector
100
104
 
101
105
 
@@ -105,10 +109,11 @@ module TestaAppiumDriver
105
109
 
106
110
  # @param [Integer] timeout in seconds
107
111
  # @return [TestaAppiumDriver::Locator]
108
- def wait_until_exists(timeout = @driver.get_timeouts["implicit"] / 1000)
112
+ def wait_until_exists(timeout = nil)
113
+ timeout = @driver.get_timeouts["implicit"] / 1000 if timeout.nil?
109
114
  start_time = Time.now.to_f
110
115
  until exists?
111
- raise "wait until exists timeout exceeded" if start_time + timeout > Time.now.to_f
116
+ raise "wait until exists timeout exceeded" if start_time + timeout < Time.now.to_f
112
117
  sleep EXISTS_WAIT
113
118
  end
114
119
  self
@@ -117,10 +122,11 @@ module TestaAppiumDriver
117
122
 
118
123
  # @param [Integer] timeout in seconds
119
124
  # @return [TestaAppiumDriver::Locator]
120
- def wait_while_exists(timeout = @driver.get_timeouts["implicit"] / 1000)
125
+ def wait_while_exists(timeout = nil)
126
+ timeout = @driver.get_timeouts["implicit"] / 1000 if timeout.nil?
121
127
  start_time = Time.now.to_f
122
128
  while exists?
123
- raise "wait until exists timeout exceeded" if start_time + timeout > Time.now.to_f
129
+ raise "wait until exists timeout exceeded" if start_time + timeout < Time.now.to_f
124
130
  sleep EXISTS_WAIT
125
131
  end
126
132
  self
@@ -209,7 +215,8 @@ module TestaAppiumDriver
209
215
  uiautomator: defined?(self.ui_selector) ? ui_selector : nil,
210
216
  xpath: @xpath_selector,
211
217
  scrollable: @scrollable_locator.nil? ? nil : @scrollable_locator.to_s,
212
- scroll_orientation: @scroll_orientation
218
+ scroll_orientation: @scroll_orientation,
219
+ resolved: strategy_and_selector
213
220
  }
214
221
  end
215
222