testa_appium_driver 0.1.11 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +23 -0
  3. data/.gitignore +16 -16
  4. data/.rspec +3 -3
  5. data/.rubocop.yml +13 -13
  6. data/CHANGELOG.md +5 -5
  7. data/CODE_OF_CONDUCT.md +102 -102
  8. data/Gemfile +12 -12
  9. data/Gemfile.lock +74 -0
  10. data/LICENSE.txt +21 -21
  11. data/README.md +402 -378
  12. data/Rakefile +12 -12
  13. data/{testa_appium_driver.iml → appium-driver.iml} +71 -78
  14. data/bin/console +17 -17
  15. data/bin/setup +8 -8
  16. data/lib/testa_appium_driver/android/class_selectors.rb +437 -437
  17. data/lib/testa_appium_driver/android/driver.rb +70 -69
  18. data/lib/testa_appium_driver/android/locator/attributes.rb +117 -113
  19. data/lib/testa_appium_driver/android/locator.rb +141 -141
  20. data/lib/testa_appium_driver/android/scroll_actions/uiautomator_scroll_actions.rb +61 -61
  21. data/lib/testa_appium_driver/android/selenium_element.rb +11 -7
  22. data/lib/testa_appium_driver/common/bounds.rb +149 -149
  23. data/lib/testa_appium_driver/common/constants.rb +37 -36
  24. data/lib/testa_appium_driver/common/exceptions/strategy_mix_exception.rb +11 -11
  25. data/lib/testa_appium_driver/common/helpers.rb +270 -270
  26. data/lib/testa_appium_driver/common/locator/scroll_actions.rb +397 -397
  27. data/lib/testa_appium_driver/common/locator.rb +627 -610
  28. data/lib/testa_appium_driver/common/scroll_actions/json_wire_scroll_actions.rb +3 -3
  29. data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +304 -237
  30. data/lib/testa_appium_driver/common/scroll_actions.rb +253 -246
  31. data/lib/testa_appium_driver/common/selenium_element.rb +19 -19
  32. data/lib/testa_appium_driver/driver.rb +328 -312
  33. data/lib/testa_appium_driver/ios/driver.rb +48 -48
  34. data/lib/testa_appium_driver/ios/locator/attributes.rb +84 -80
  35. data/lib/testa_appium_driver/ios/locator.rb +71 -70
  36. data/lib/testa_appium_driver/ios/selenium_element.rb +6 -6
  37. data/lib/testa_appium_driver/ios/type_selectors.rb +187 -187
  38. data/lib/testa_appium_driver/version.rb +5 -5
  39. data/lib/testa_appium_driver.rb +6 -6
  40. data/testa_appium_driver.gemspec +41 -41
  41. metadata +9 -16
  42. data/.idea/deployment.xml +0 -22
  43. data/.idea/inspectionProfiles/Project_Default.xml +0 -9
  44. data/.idea/misc.xml +0 -6
  45. data/.idea/modules.xml +0 -8
  46. data/.idea/runConfigurations/Android_Test.xml +0 -42
  47. data/.idea/runConfigurations.xml +0 -10
  48. data/.idea/sshConfigs.xml +0 -13
  49. data/.idea/vcs.xml +0 -6
  50. data/.idea/webServers.xml +0 -21
@@ -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 scroll_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.scroll_each(&block)
33
+ else
34
+ sa.send("scroll_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 scroll_each_down(top: nil, bottom: nil, right: nil, left: nil, &block)
42
+ scroll_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 scroll_each_up(top: nil, bottom: nil, right: nil, left: nil, &block)
49
+ scroll_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 scroll_each_right(top: nil, bottom: nil, right: nil, left: nil, &block)
56
+ scroll_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 scroll_each_left(top: nil, bottom: nil, right: nil, left: nil, &block)
63
+ scroll_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, max_attempts: 3)
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, max_attempts)
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, max_attempts: 3)
89
+ align(:top, top: top, bottom: bottom, right: right, left: left, max_attempts: max_attempts)
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, max_attempts: 3)
98
+ align(:bottom, top: top, bottom: bottom, right: right, left: left, max_attempts: max_attempts)
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, max_attempts: 3)
107
+ align(:left, top: top, bottom: bottom, right: right, left: left, max_attempts: max_attempts)
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, max_attempts: 3)
116
+ align(:right, top: top, bottom: bottom, right: right, left: left, max_attempts: max_attempts)
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, max_attempts: 3)
125
+ align(with, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true, max_attempts: max_attempts)
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, max_attempts: 3)
134
+ align(:top, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true, max_attempts: max_attempts)
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, max_attempts: 3)
143
+ align(:bottom, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true, max_attempts: max_attempts)
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, max_attempts: 3)
152
+ align(:left, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true, max_attempts: max_attempts)
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, max_attempts: 3)
161
+ align(:right, top: top, bottom: bottom, right: right, left: left, scroll_to_find: true, max_attempts: max_attempts)
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?(::Appium::Core::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) || to.kind_of?(::Appium::Core::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