testa_appium_driver 0.1.11 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +15 -15
  3. data/.idea/deployment.xml +21 -21
  4. data/.idea/inspectionProfiles/Project_Default.xml +8 -8
  5. data/.idea/misc.xml +5 -5
  6. data/.idea/modules.xml +7 -7
  7. data/.idea/runConfigurations/Android_Test.xml +41 -41
  8. data/.idea/runConfigurations.xml +9 -9
  9. data/.idea/sshConfigs.xml +12 -12
  10. data/.idea/vcs.xml +5 -5
  11. data/.idea/webServers.xml +20 -20
  12. data/.rspec +3 -3
  13. data/.rubocop.yml +13 -13
  14. data/CHANGELOG.md +5 -5
  15. data/CODE_OF_CONDUCT.md +102 -102
  16. data/Gemfile +12 -12
  17. data/LICENSE.txt +21 -21
  18. data/README.md +378 -378
  19. data/Rakefile +12 -12
  20. data/bin/console +17 -17
  21. data/bin/setup +8 -8
  22. data/lib/testa_appium_driver/android/class_selectors.rb +437 -437
  23. data/lib/testa_appium_driver/android/driver.rb +69 -69
  24. data/lib/testa_appium_driver/android/locator/attributes.rb +113 -113
  25. data/lib/testa_appium_driver/android/locator.rb +141 -141
  26. data/lib/testa_appium_driver/android/scroll_actions/uiautomator_scroll_actions.rb +61 -61
  27. data/lib/testa_appium_driver/android/selenium_element.rb +7 -7
  28. data/lib/testa_appium_driver/common/bounds.rb +149 -149
  29. data/lib/testa_appium_driver/common/constants.rb +36 -36
  30. data/lib/testa_appium_driver/common/exceptions/strategy_mix_exception.rb +11 -11
  31. data/lib/testa_appium_driver/common/helpers.rb +270 -270
  32. data/lib/testa_appium_driver/common/locator/scroll_actions.rb +397 -397
  33. data/lib/testa_appium_driver/common/locator.rb +610 -610
  34. data/lib/testa_appium_driver/common/scroll_actions/json_wire_scroll_actions.rb +3 -3
  35. data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +237 -237
  36. data/lib/testa_appium_driver/common/scroll_actions.rb +246 -246
  37. data/lib/testa_appium_driver/common/selenium_element.rb +19 -19
  38. data/lib/testa_appium_driver/driver.rb +312 -312
  39. data/lib/testa_appium_driver/ios/driver.rb +48 -48
  40. data/lib/testa_appium_driver/ios/locator/attributes.rb +80 -80
  41. data/lib/testa_appium_driver/ios/locator.rb +70 -70
  42. data/lib/testa_appium_driver/ios/selenium_element.rb +6 -6
  43. data/lib/testa_appium_driver/ios/type_selectors.rb +187 -187
  44. data/lib/testa_appium_driver/version.rb +5 -5
  45. data/lib/testa_appium_driver.rb +6 -6
  46. data/testa_appium_driver.gemspec +41 -41
  47. data/testa_appium_driver.iml +27 -78
  48. metadata +3 -3
@@ -1,398 +1,398 @@
1
- module TestaAppiumDriver
2
- #noinspection RubyTooManyMethodsInspection
3
- class Locator
4
-
5
- # performs a long tap on the retrieved element
6
- # @param [Float] duration in seconds
7
- def long_tap(duration = LONG_TAP_DURATION)
8
- action_builder = @driver.action
9
- b = bounds
10
- f1 = action_builder.add_pointer_input(:touch, "finger1")
11
- f1.create_pointer_move(duration: 0, x: b.center.x, y: b.center.y, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
12
- f1.create_pointer_down(:left)
13
- f1.create_pause(duration)
14
- f1.create_pointer_up(:left)
15
- puts "long tap execute: {x: #{b.center.x}, y: #{b.center.y}}"
16
- @driver.perform_actions [f1]
17
- end
18
-
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)
25
- raise "Each can only be performed on multiple elements locator" if @single
26
- deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
27
- sa = ScrollActions.new(@scrollable_locator,
28
- locator: self,
29
- deadzone: deadzone,
30
- default_scroll_strategy: @default_scroll_strategy)
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)
64
- end
65
-
66
-
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
71
- # @return [TestaAppiumDriver::Locator]
72
- def align(with = :top, top: nil, bottom: nil, right: nil, left: nil, scroll_to_find: false)
73
- deadzone = _process_deadzone(top, bottom, right, left)
74
- deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
75
- sa = ScrollActions.new(@scrollable_locator,
76
- locator: self,
77
- deadzone: deadzone,
78
- default_scroll_strategy: @default_scroll_strategy)
79
- sa.align(with, scroll_to_find)
80
- self
81
- end
82
-
83
- # Aligns element on top of the scrollable container, if the element does not exists it will scroll to find it
84
- # The element is aligned if the the distance from the top of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
85
- # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
86
- # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
87
- # @return [TestaAppiumDriver::Locator]
88
- def align_top(top: nil, bottom: nil, right: nil, left: nil)
89
- align(:top, top: top, bottom: bottom, right: right, left: left)
90
- end
91
-
92
- # Aligns element on bottom of the scrollable container, if the element does not exists it will scroll to find it
93
- # The element is aligned if the the distance from the bottom of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
94
- # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
95
- # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
96
- # @return [TestaAppiumDriver::Locator]
97
- def align_bottom(top: nil, bottom: nil, right: nil, left: nil)
98
- align(:bottom, top: top, bottom: bottom, right: right, left: left)
99
- end
100
-
101
- # Aligns element on left of the scrollable container, if the element does not exists it will scroll to find it
102
- # The element is aligned if the the distance from the left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
103
- # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
104
- # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
105
- # @return [TestaAppiumDriver::Locator]
106
- def align_left(top: nil, bottom: nil, right: nil, left: nil)
107
- align(:left, top: top, bottom: bottom, right: right, left: left)
108
- end
109
-
110
- # Aligns element on right of the scrollable container, if the element does not exists it will scroll to find it
111
- # The element is aligned if the the distance from the right of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
112
- # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
113
- # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
114
- # @return [TestaAppiumDriver::Locator]
115
- def align_right(top: nil, bottom: nil, right: nil, left: nil)
116
- align(:right, top: top, bottom: bottom, right: right, left: left)
117
- end
118
-
119
- # Aligns element (by default) on top of the scrollable container, if the element does not exists it raise an exception
120
- # 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]
121
- # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
122
- # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
123
- # @return [TestaAppiumDriver::Locator]
124
- def align!(with = :top, top: nil, bottom: nil, right: nil, left: nil)
125
- align(with, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
126
- end
127
-
128
- # Aligns element on top of the scrollable container, if the element does not exists it raise an exception
129
- # The element is aligned if the the distance from the top of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
130
- # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
131
- # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
132
- # @return [TestaAppiumDriver::Locator]
133
- def align_top!(top: nil, bottom: nil, right: nil, left: nil)
134
- align(:top, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
135
- end
136
-
137
- # Aligns element on bottom of the scrollable container, if the element does not exists it raise an exception
138
- # The element is aligned if the the distance from the bottom of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
139
- # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
140
- # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
141
- # @return [TestaAppiumDriver::Locator]
142
- def align_bottom!(top: nil, bottom: nil, right: nil, left: nil)
143
- align(:bottom, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
144
- end
145
-
146
- # Aligns element on left of the scrollable container, if the element does not exists it raise an exception
147
- # The element is aligned if the the distance from the left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
148
- # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
149
- # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
150
- # @return [TestaAppiumDriver::Locator]
151
- def align_left!(top: nil, bottom: nil, right: nil, left: nil)
152
- align(:left, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
153
- end
154
-
155
- # Aligns element on right of the scrollable container, if the element does not exists it raise an exception
156
- # The element is aligned if the the distance from the right of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
157
- # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
158
- # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
159
- # @return [TestaAppiumDriver::Locator]
160
- def align_right!(top: nil, bottom: nil, right: nil, left: nil)
161
- align(:right, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
162
- end
163
-
164
-
165
- # First scrolls to the beginning of the scrollable container and then scrolls down until element is found or end is reached
166
- # @return [TestaAppiumDriver::Locator]
167
- def scroll_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil, direction: nil)
168
- if direction
169
- _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, direction)
170
- else
171
- _scroll_to(_process_deadzone(top, bottom, right, left), max_scrolls)
172
- end
173
- end
174
-
175
-
176
- # Scrolls down until element is found or end is reached
177
- # @return [TestaAppiumDriver::Locator]
178
- def scroll_down_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
179
- _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :down)
180
- end
181
-
182
- # Scrolls up until element is found or end is reached
183
- # @return [TestaAppiumDriver::Locator]
184
- def scroll_up_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
185
- _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :up)
186
- end
187
-
188
- # Scrolls right until element is found or end is reached
189
- # @return [TestaAppiumDriver::Locator]
190
- def scroll_right_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
191
- _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :right)
192
- end
193
-
194
-
195
- # Scrolls left until element is found or end is reached
196
- # @return [TestaAppiumDriver::Locator]
197
- def scroll_left_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
198
- _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :left)
199
- end
200
-
201
- # Scrolls to the start of the scrollable container (top on vertical container, left on horizontal)
202
- # @return [TestaAppiumDriver::Locator]
203
- def scroll_to_start(top: nil, bottom: nil, right: nil, left: nil)
204
- _scroll_to_start_or_end(:start, _process_deadzone(top, bottom, right, left))
205
- end
206
-
207
- # Scrolls to the end of the scrollable container (bottom on vertical container, right on horizontal)
208
- # @return [TestaAppiumDriver::Locator]
209
- def scroll_to_end(top: nil, bottom: nil, right: nil, left: nil)
210
- _scroll_to_start_or_end(:end, _process_deadzone(top, bottom, right, left))
211
- end
212
-
213
-
214
- # @return [TestaAppiumDriver::Locator]
215
- def page_down(top: nil, bottom: nil, right: nil, left: nil)
216
- _page(:down, _process_deadzone(top, bottom, right, left))
217
- end
218
-
219
- # @return [TestaAppiumDriver::Locator]
220
- def page_up(top: nil, bottom: nil, right: nil, left: nil)
221
- _page(:up, _process_deadzone(top, bottom, right, left))
222
- end
223
-
224
- # @return [TestaAppiumDriver::Locator]
225
- def page_left(top: nil, bottom: nil, right: nil, left: nil)
226
- _page(:left, _process_deadzone(top, bottom, right, left))
227
- end
228
-
229
- # @return [TestaAppiumDriver::Locator]
230
- def page_right(top: nil, bottom: nil, right: nil, left: nil)
231
- _page(:right, _process_deadzone(top, bottom, right, left))
232
- end
233
-
234
- # @return [TestaAppiumDriver::Locator]
235
- def fling_down(top: nil, bottom: nil, right: nil, left: nil)
236
- _fling(:down, _process_deadzone(top, bottom, right, left))
237
- end
238
-
239
- # @return [TestaAppiumDriver::Locator]
240
- def fling_up(top: nil, bottom: nil, right: nil, left: nil)
241
- _fling(:up, _process_deadzone(top, bottom, right, left))
242
- end
243
-
244
- # @return [TestaAppiumDriver::Locator]
245
- def fling_left(top: nil, bottom: nil, right: nil, left: nil)
246
- _fling(:left, _process_deadzone(top, bottom, right, left))
247
- end
248
-
249
- # @return [TestaAppiumDriver::Locator]
250
- def fling_right(top: nil, bottom: nil, right: nil, left: nil)
251
- _fling(:right, _process_deadzone(top, bottom, right, left))
252
- end
253
-
254
- def drag_up_by(amount)
255
- drag_by(amount, direction: :top)
256
- end
257
-
258
- def drag_down_by(amount)
259
- drag_by(amount, direction: :bottom)
260
- end
261
-
262
- def drag_left_by(amount)
263
- drag_by(amount, direction: :left)
264
- end
265
-
266
- def drag_right_by(amount)
267
- drag_by(amount, direction: :right)
268
- end
269
-
270
-
271
- # @param [TestaAppiumDriver::Locator, Hash, Selenium::WebDriver::Element, String] to
272
- #noinspection RubyYardParamTypeMatch,RubyScope
273
- def drag_to(to)
274
- if !to.kind_of?(Selenium::WebDriver::Element) && !to.kind_of?(TestaAppiumDriver::Locator) && !to.kind_of?(Hash)
275
- raise "Parameter not accepted, acceptable instances of [TestaAppiumDriver::Locator, Hash, Selenium::WebDriver::Element]"
276
- end
277
- if to.kind_of?(Selenium::WebDriver::Element)
278
- bounds = TestaAppiumDriver::Bounds.from_android(to.bounds, @driver)
279
- x = bounds.center.x
280
- y = bounds.center.y
281
- end
282
- if to.kind_of?(TestaAppiumDriver::Locator)
283
- bounds = to.bounds
284
- x = bounds.center.x
285
- y = bounds.center.y
286
- end
287
- if to.kind_of?(Hash)
288
- raise "Missing x coordinate" if to[:x].nil?
289
- raise "Missing y coordinate" if to[:y].nil?
290
- x = to[:x]
291
- y = to[:y]
292
- end
293
- _drag_to(bounds.center.x, bounds.center.y, x, y)
294
- end
295
-
296
- def drag_by(amount, direction: :top)
297
- b = bounds
298
- x = b.center.x
299
- y = b.center.y
300
- case direction
301
- when :top
302
- y -= amount.to_i
303
- when :bottom
304
- y += amount.to_i
305
- when :left
306
- x -= amount.to_i
307
- when :right
308
- x += amount.to_i
309
- else
310
- raise "Unknown direction #{direction}"
311
- end
312
- _drag_to(b.center.x, b.center.y, x, y)
313
- end
314
-
315
-
316
-
317
- private
318
- def _process_deadzone(top, bottom, right, left)
319
- deadzone = nil
320
- if !top.nil? || !bottom.nil? || !right.nil? || !left.nil?
321
- deadzone = {}
322
- deadzone[:top] = top unless top.nil?
323
- deadzone[:bottom] = bottom unless bottom.nil?
324
- deadzone[:right] = right unless right.nil?
325
- deadzone[:left] = left unless left.nil?
326
- end
327
- deadzone
328
- end
329
-
330
- def _drag_to(x0, y0, x1, y1)
331
- sa = ScrollActions.new(@scrollable_locator,
332
- locator: self,
333
- default_scroll_strategy: @default_scroll_strategy)
334
- sa.drag_to(x0, y0, x1, y1)
335
- self
336
- end
337
-
338
-
339
- def _page(direction, deadzone)
340
- deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
341
- sa = ScrollActions.new(@scrollable_locator,
342
- locator: self,
343
- deadzone: deadzone,
344
- direction: direction.to_sym,
345
- default_scroll_strategy: @default_scroll_strategy)
346
- sa.send("page_#{direction}")
347
- self
348
- end
349
-
350
- def _fling(direction, deadzone)
351
- deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
352
- sa = ScrollActions.new(@scrollable_locator,
353
- locator: self,
354
- deadzone: deadzone,
355
- direction: direction.to_sym,
356
- default_scroll_strategy: @default_scroll_strategy)
357
- sa.send("fling_#{direction}")
358
- self
359
- end
360
-
361
- def _scroll_to_start_or_end(type, deadzone)
362
- deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
363
- sa = ScrollActions.new(@scrollable_locator,
364
- locator: self,
365
- deadzone: deadzone,
366
- default_scroll_strategy: @default_scroll_strategy)
367
- if type == :start
368
- sa.scroll_to_start
369
- else
370
- sa.scroll_to_end
371
- end
372
- self
373
- end
374
-
375
- def _scroll_to(deadzone, max_scrolls)
376
- deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
377
- sa = ScrollActions.new(@scrollable_locator,
378
- locator: self,
379
- deadzone: deadzone,
380
- max_scrolls: max_scrolls,
381
- default_scroll_strategy: @default_scroll_strategy)
382
- sa.scroll_to
383
- self
384
- end
385
-
386
- def _scroll_dir_to(deadzone, max_scrolls, direction)
387
- deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
388
- sa = ScrollActions.new(@scrollable_locator,
389
- locator: self,
390
- deadzone: deadzone,
391
- max_scrolls: max_scrolls,
392
- default_scroll_strategy: @default_scroll_strategy)
393
-
394
- sa.send("scroll_#{direction}_to")
395
- self
396
- end
397
- end
1
+ module TestaAppiumDriver
2
+ #noinspection RubyTooManyMethodsInspection
3
+ class Locator
4
+
5
+ # performs a long tap on the retrieved element
6
+ # @param [Float] duration in seconds
7
+ def long_tap(duration = LONG_TAP_DURATION)
8
+ action_builder = @driver.action
9
+ b = bounds
10
+ f1 = action_builder.add_pointer_input(:touch, "finger1")
11
+ f1.create_pointer_move(duration: 0, x: b.center.x, y: b.center.y, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
12
+ f1.create_pointer_down(:left)
13
+ f1.create_pause(duration)
14
+ f1.create_pointer_up(:left)
15
+ puts "long tap execute: {x: #{b.center.x}, y: #{b.center.y}}"
16
+ @driver.perform_actions [f1]
17
+ end
18
+
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)
25
+ raise "Each can only be performed on multiple elements locator" if @single
26
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
27
+ sa = ScrollActions.new(@scrollable_locator,
28
+ locator: self,
29
+ deadzone: deadzone,
30
+ default_scroll_strategy: @default_scroll_strategy)
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)
64
+ end
65
+
66
+
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
71
+ # @return [TestaAppiumDriver::Locator]
72
+ def align(with = :top, top: nil, bottom: nil, right: nil, left: nil, scroll_to_find: false)
73
+ deadzone = _process_deadzone(top, bottom, right, left)
74
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
75
+ sa = ScrollActions.new(@scrollable_locator,
76
+ locator: self,
77
+ deadzone: deadzone,
78
+ default_scroll_strategy: @default_scroll_strategy)
79
+ sa.align(with, scroll_to_find)
80
+ self
81
+ end
82
+
83
+ # Aligns element on top of the scrollable container, if the element does not exists it will scroll to find it
84
+ # The element is aligned if the the distance from the top of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
85
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
86
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
87
+ # @return [TestaAppiumDriver::Locator]
88
+ def align_top(top: nil, bottom: nil, right: nil, left: nil)
89
+ align(:top, top: top, bottom: bottom, right: right, left: left)
90
+ end
91
+
92
+ # Aligns element on bottom of the scrollable container, if the element does not exists it will scroll to find it
93
+ # The element is aligned if the the distance from the bottom of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
94
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
95
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
96
+ # @return [TestaAppiumDriver::Locator]
97
+ def align_bottom(top: nil, bottom: nil, right: nil, left: nil)
98
+ align(:bottom, top: top, bottom: bottom, right: right, left: left)
99
+ end
100
+
101
+ # Aligns element on left of the scrollable container, if the element does not exists it will scroll to find it
102
+ # The element is aligned if the the distance from the left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
103
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
104
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
105
+ # @return [TestaAppiumDriver::Locator]
106
+ def align_left(top: nil, bottom: nil, right: nil, left: nil)
107
+ align(:left, top: top, bottom: bottom, right: right, left: left)
108
+ end
109
+
110
+ # Aligns element on right of the scrollable container, if the element does not exists it will scroll to find it
111
+ # The element is aligned if the the distance from the right of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
112
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
113
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
114
+ # @return [TestaAppiumDriver::Locator]
115
+ def align_right(top: nil, bottom: nil, right: nil, left: nil)
116
+ align(:right, top: top, bottom: bottom, right: right, left: left)
117
+ end
118
+
119
+ # Aligns element (by default) on top of the scrollable container, if the element does not exists it raise an exception
120
+ # 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]
121
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
122
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
123
+ # @return [TestaAppiumDriver::Locator]
124
+ def align!(with = :top, top: nil, bottom: nil, right: nil, left: nil)
125
+ align(with, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
126
+ end
127
+
128
+ # Aligns element on top of the scrollable container, if the element does not exists it raise an exception
129
+ # The element is aligned if the the distance from the top of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
130
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
131
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
132
+ # @return [TestaAppiumDriver::Locator]
133
+ def align_top!(top: nil, bottom: nil, right: nil, left: nil)
134
+ align(:top, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
135
+ end
136
+
137
+ # Aligns element on bottom of the scrollable container, if the element does not exists it raise an exception
138
+ # The element is aligned if the the distance from the bottom of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
139
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
140
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
141
+ # @return [TestaAppiumDriver::Locator]
142
+ def align_bottom!(top: nil, bottom: nil, right: nil, left: nil)
143
+ align(:bottom, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
144
+ end
145
+
146
+ # Aligns element on left of the scrollable container, if the element does not exists it raise an exception
147
+ # The element is aligned if the the distance from the left of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
148
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
149
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
150
+ # @return [TestaAppiumDriver::Locator]
151
+ def align_left!(top: nil, bottom: nil, right: nil, left: nil)
152
+ align(:left, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
153
+ end
154
+
155
+ # Aligns element on right of the scrollable container, if the element does not exists it raise an exception
156
+ # The element is aligned if the the distance from the right of the scrollable container is less than [TestaAppiumDriver::SCROLL_ALIGNMENT_THRESHOLD]
157
+ # If the distance is greater than the threshold, it will attempt to realign it up to 2 more times.
158
+ # The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
159
+ # @return [TestaAppiumDriver::Locator]
160
+ def align_right!(top: nil, bottom: nil, right: nil, left: nil)
161
+ align(:right, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true)
162
+ end
163
+
164
+
165
+ # First scrolls to the beginning of the scrollable container and then scrolls down until element is found or end is reached
166
+ # @return [TestaAppiumDriver::Locator]
167
+ def scroll_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil, direction: nil)
168
+ if direction
169
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, direction)
170
+ else
171
+ _scroll_to(_process_deadzone(top, bottom, right, left), max_scrolls)
172
+ end
173
+ end
174
+
175
+
176
+ # Scrolls down until element is found or end is reached
177
+ # @return [TestaAppiumDriver::Locator]
178
+ def scroll_down_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
179
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :down)
180
+ end
181
+
182
+ # Scrolls up until element is found or end is reached
183
+ # @return [TestaAppiumDriver::Locator]
184
+ def scroll_up_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
185
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :up)
186
+ end
187
+
188
+ # Scrolls right until element is found or end is reached
189
+ # @return [TestaAppiumDriver::Locator]
190
+ def scroll_right_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
191
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :right)
192
+ end
193
+
194
+
195
+ # Scrolls left until element is found or end is reached
196
+ # @return [TestaAppiumDriver::Locator]
197
+ def scroll_left_to(top: nil, bottom: nil, right: nil, left: nil, max_scrolls: nil)
198
+ _scroll_dir_to(_process_deadzone(top, bottom, right, left), max_scrolls, :left)
199
+ end
200
+
201
+ # Scrolls to the start of the scrollable container (top on vertical container, left on horizontal)
202
+ # @return [TestaAppiumDriver::Locator]
203
+ def scroll_to_start(top: nil, bottom: nil, right: nil, left: nil)
204
+ _scroll_to_start_or_end(:start, _process_deadzone(top, bottom, right, left))
205
+ end
206
+
207
+ # Scrolls to the end of the scrollable container (bottom on vertical container, right on horizontal)
208
+ # @return [TestaAppiumDriver::Locator]
209
+ def scroll_to_end(top: nil, bottom: nil, right: nil, left: nil)
210
+ _scroll_to_start_or_end(:end, _process_deadzone(top, bottom, right, left))
211
+ end
212
+
213
+
214
+ # @return [TestaAppiumDriver::Locator]
215
+ def page_down(top: nil, bottom: nil, right: nil, left: nil)
216
+ _page(:down, _process_deadzone(top, bottom, right, left))
217
+ end
218
+
219
+ # @return [TestaAppiumDriver::Locator]
220
+ def page_up(top: nil, bottom: nil, right: nil, left: nil)
221
+ _page(:up, _process_deadzone(top, bottom, right, left))
222
+ end
223
+
224
+ # @return [TestaAppiumDriver::Locator]
225
+ def page_left(top: nil, bottom: nil, right: nil, left: nil)
226
+ _page(:left, _process_deadzone(top, bottom, right, left))
227
+ end
228
+
229
+ # @return [TestaAppiumDriver::Locator]
230
+ def page_right(top: nil, bottom: nil, right: nil, left: nil)
231
+ _page(:right, _process_deadzone(top, bottom, right, left))
232
+ end
233
+
234
+ # @return [TestaAppiumDriver::Locator]
235
+ def fling_down(top: nil, bottom: nil, right: nil, left: nil)
236
+ _fling(:down, _process_deadzone(top, bottom, right, left))
237
+ end
238
+
239
+ # @return [TestaAppiumDriver::Locator]
240
+ def fling_up(top: nil, bottom: nil, right: nil, left: nil)
241
+ _fling(:up, _process_deadzone(top, bottom, right, left))
242
+ end
243
+
244
+ # @return [TestaAppiumDriver::Locator]
245
+ def fling_left(top: nil, bottom: nil, right: nil, left: nil)
246
+ _fling(:left, _process_deadzone(top, bottom, right, left))
247
+ end
248
+
249
+ # @return [TestaAppiumDriver::Locator]
250
+ def fling_right(top: nil, bottom: nil, right: nil, left: nil)
251
+ _fling(:right, _process_deadzone(top, bottom, right, left))
252
+ end
253
+
254
+ def drag_up_by(amount)
255
+ drag_by(amount, direction: :top)
256
+ end
257
+
258
+ def drag_down_by(amount)
259
+ drag_by(amount, direction: :bottom)
260
+ end
261
+
262
+ def drag_left_by(amount)
263
+ drag_by(amount, direction: :left)
264
+ end
265
+
266
+ def drag_right_by(amount)
267
+ drag_by(amount, direction: :right)
268
+ end
269
+
270
+
271
+ # @param [TestaAppiumDriver::Locator, Hash, Selenium::WebDriver::Element, String] to
272
+ #noinspection RubyYardParamTypeMatch,RubyScope
273
+ def drag_to(to)
274
+ if !to.kind_of?(Selenium::WebDriver::Element) && !to.kind_of?(TestaAppiumDriver::Locator) && !to.kind_of?(Hash)
275
+ raise "Parameter not accepted, acceptable instances of [TestaAppiumDriver::Locator, Hash, Selenium::WebDriver::Element]"
276
+ end
277
+ if to.kind_of?(Selenium::WebDriver::Element)
278
+ bounds = TestaAppiumDriver::Bounds.from_android(to.bounds, @driver)
279
+ x = bounds.center.x
280
+ y = bounds.center.y
281
+ end
282
+ if to.kind_of?(TestaAppiumDriver::Locator)
283
+ bounds = to.bounds
284
+ x = bounds.center.x
285
+ y = bounds.center.y
286
+ end
287
+ if to.kind_of?(Hash)
288
+ raise "Missing x coordinate" if to[:x].nil?
289
+ raise "Missing y coordinate" if to[:y].nil?
290
+ x = to[:x]
291
+ y = to[:y]
292
+ end
293
+ _drag_to(bounds.center.x, bounds.center.y, x, y)
294
+ end
295
+
296
+ def drag_by(amount, direction: :top)
297
+ b = bounds
298
+ x = b.center.x
299
+ y = b.center.y
300
+ case direction
301
+ when :top
302
+ y -= amount.to_i
303
+ when :bottom
304
+ y += amount.to_i
305
+ when :left
306
+ x -= amount.to_i
307
+ when :right
308
+ x += amount.to_i
309
+ else
310
+ raise "Unknown direction #{direction}"
311
+ end
312
+ _drag_to(b.center.x, b.center.y, x, y)
313
+ end
314
+
315
+
316
+
317
+ private
318
+ def _process_deadzone(top, bottom, right, left)
319
+ deadzone = nil
320
+ if !top.nil? || !bottom.nil? || !right.nil? || !left.nil?
321
+ deadzone = {}
322
+ deadzone[:top] = top unless top.nil?
323
+ deadzone[:bottom] = bottom unless bottom.nil?
324
+ deadzone[:right] = right unless right.nil?
325
+ deadzone[:left] = left unless left.nil?
326
+ end
327
+ deadzone
328
+ end
329
+
330
+ def _drag_to(x0, y0, x1, y1)
331
+ sa = ScrollActions.new(@scrollable_locator,
332
+ locator: self,
333
+ default_scroll_strategy: @default_scroll_strategy)
334
+ sa.drag_to(x0, y0, x1, y1)
335
+ self
336
+ end
337
+
338
+
339
+ def _page(direction, deadzone)
340
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
341
+ sa = ScrollActions.new(@scrollable_locator,
342
+ locator: self,
343
+ deadzone: deadzone,
344
+ direction: direction.to_sym,
345
+ default_scroll_strategy: @default_scroll_strategy)
346
+ sa.send("page_#{direction}")
347
+ self
348
+ end
349
+
350
+ def _fling(direction, deadzone)
351
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
352
+ sa = ScrollActions.new(@scrollable_locator,
353
+ locator: self,
354
+ deadzone: deadzone,
355
+ direction: direction.to_sym,
356
+ default_scroll_strategy: @default_scroll_strategy)
357
+ sa.send("fling_#{direction}")
358
+ self
359
+ end
360
+
361
+ def _scroll_to_start_or_end(type, deadzone)
362
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
363
+ sa = ScrollActions.new(@scrollable_locator,
364
+ locator: self,
365
+ deadzone: deadzone,
366
+ default_scroll_strategy: @default_scroll_strategy)
367
+ if type == :start
368
+ sa.scroll_to_start
369
+ else
370
+ sa.scroll_to_end
371
+ end
372
+ self
373
+ end
374
+
375
+ def _scroll_to(deadzone, max_scrolls)
376
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
377
+ sa = ScrollActions.new(@scrollable_locator,
378
+ locator: self,
379
+ deadzone: deadzone,
380
+ max_scrolls: max_scrolls,
381
+ default_scroll_strategy: @default_scroll_strategy)
382
+ sa.scroll_to
383
+ self
384
+ end
385
+
386
+ def _scroll_dir_to(deadzone, max_scrolls, direction)
387
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
388
+ sa = ScrollActions.new(@scrollable_locator,
389
+ locator: self,
390
+ deadzone: deadzone,
391
+ max_scrolls: max_scrolls,
392
+ default_scroll_strategy: @default_scroll_strategy)
393
+
394
+ sa.send("scroll_#{direction}_to")
395
+ self
396
+ end
397
+ end
398
398
  end