testa_appium_driver 0.1.21 → 0.1.24

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 (34) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +23 -0
  3. data/.gitignore +17 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +6 -0
  6. data/Gemfile.lock +1 -1
  7. data/bin/console +17 -0
  8. data/bin/setup +8 -0
  9. data/lib/testa_appium_driver/android/class_selectors.rb +438 -0
  10. data/lib/testa_appium_driver/android/driver.rb +71 -0
  11. data/lib/testa_appium_driver/android/locator/attributes.rb +115 -0
  12. data/lib/testa_appium_driver/android/locator.rb +142 -0
  13. data/lib/testa_appium_driver/android/scroll_actions/uiautomator_scroll_actions.rb +62 -0
  14. data/lib/testa_appium_driver/android/selenium_element.rb +12 -0
  15. data/lib/testa_appium_driver/common/bounds.rb +150 -0
  16. data/lib/testa_appium_driver/common/constants.rb +38 -0
  17. data/lib/testa_appium_driver/common/exceptions/strategy_mix_exception.rb +12 -0
  18. data/lib/testa_appium_driver/common/helpers.rb +272 -0
  19. data/lib/testa_appium_driver/common/locator/scroll_actions.rb +390 -0
  20. data/lib/testa_appium_driver/common/locator.rb +640 -0
  21. data/lib/testa_appium_driver/common/scroll_actions/json_wire_scroll_actions.rb +4 -0
  22. data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +380 -0
  23. data/lib/testa_appium_driver/common/scroll_actions.rb +275 -0
  24. data/lib/testa_appium_driver/common/selenium_element.rb +19 -0
  25. data/lib/testa_appium_driver/driver.rb +338 -0
  26. data/lib/testa_appium_driver/ios/driver.rb +49 -0
  27. data/lib/testa_appium_driver/ios/locator/attributes.rb +89 -0
  28. data/lib/testa_appium_driver/ios/locator.rb +73 -0
  29. data/lib/testa_appium_driver/ios/selenium_element.rb +8 -0
  30. data/lib/testa_appium_driver/ios/type_selectors.rb +201 -0
  31. data/lib/testa_appium_driver.rb +4 -0
  32. data/testa_appium_driver.gemspec +6 -2
  33. metadata +39 -11
  34. data/appium-driver.iml +0 -79
@@ -0,0 +1,380 @@
1
+ module ::TestaAppiumDriver
2
+ module W3cScrollActions
3
+ # @return [Array]
4
+ def w3c_scroll_each(direction, &block)
5
+ default_deadzone!
6
+ if direction.nil?
7
+ scroll_to_start
8
+ if @scrollable.scroll_orientation == :vertical
9
+ direction = :down
10
+ else
11
+ direction = :right
12
+ end
13
+ end
14
+
15
+ case direction
16
+ when :up
17
+ align_with = :bottom
18
+ when :down
19
+ align_with = :top
20
+ when :right
21
+ align_with = :left
22
+ when :left
23
+ align_with = :right
24
+ else
25
+ align_with = :top
26
+ end
27
+
28
+ if @driver.ios?
29
+ # if true
30
+ w3c_scroll_each_ios(direction, align_with, &block)
31
+ else
32
+ w3c_scroll_each_android(direction, align_with, &block)
33
+ end
34
+ end
35
+
36
+ def w3c_scroll_each_android(direction, align_with, &block)
37
+ elements = []
38
+ begin
39
+
40
+ iterations = 0
41
+ ignore_element_ids = []
42
+ previous_element = nil
43
+
44
+ until is_end_of_scroll?
45
+ # # $__.puts "-- new iteration"
46
+ # # $__.puts "-------------"
47
+ aligned_items = 0
48
+ new_ignore_element_ids = []
49
+ matches = @locator.execute(skip_cache: true)
50
+ matches.each_with_index do |m, index|
51
+ # # $__.puts "Matches: #{matches.count}"
52
+ # # $__.puts "M: #{m.id}"
53
+ if ignore_element_ids.include?(m.id)
54
+ previous_element = m
55
+ next
56
+ end
57
+
58
+ sa = self.dup
59
+ sa.locator = m
60
+ sa.w3c_align(align_with, false, 1, speed_coef: 2.0)
61
+ is_aligned = sa.is_aligned?(align_with, m)
62
+
63
+ # add the previous to ignore if current is not aligned (probably means we cannot scroll any further)
64
+ new_ignore_element_ids << previous_element.id if !is_aligned && !previous_element.nil?
65
+
66
+ aligned_items += 1 if is_aligned
67
+
68
+ # add last element to ignore
69
+ new_ignore_element_ids << m.id if matches.count == index + 1
70
+
71
+ elements << m
72
+ if block_given? # block is given
73
+ @locator.driver.invalidate_cache
74
+ block.call(m) # use call to execute the block
75
+ else
76
+ # the value of block_argument becomes nil if you didn't give a block
77
+ # block was not given
78
+ end
79
+ previous_element = m
80
+ end
81
+
82
+ iterations += 1
83
+ break if !@max_scrolls.nil? && iterations == @max_scrolls
84
+
85
+ if aligned_items.zero?
86
+ self.send("page_#{direction}")
87
+ else
88
+ ignore_element_ids = new_ignore_element_ids.dup
89
+ end
90
+ end
91
+ rescue StandardError => e
92
+ raise e
93
+ end
94
+
95
+ elements
96
+ end
97
+
98
+ def w3c_scroll_each_ios(direction, align_with, &block)
99
+ elements = []
100
+ elements_in_current_iteration = []
101
+ begin
102
+ iterations = 0
103
+
104
+ loop do
105
+ elements_in_last_iteration = elements_in_current_iteration
106
+ elements_in_current_iteration = []
107
+ elements_count_before_iteration = elements.count
108
+
109
+ new_element_in_this_iteration_found = false
110
+ matches = @locator.execute(skip_cache: true)
111
+ matches.each do |m|
112
+ elements_in_current_iteration << m.id
113
+
114
+ element_found_in_last_iteration = elements_in_last_iteration.include?(m.id)
115
+
116
+ # ignore all elements from last iteration until first new element is found
117
+ if !new_element_in_this_iteration_found && element_found_in_last_iteration
118
+ next
119
+ end
120
+
121
+ # new element in this iteration is found,
122
+ # process all remaining elements regardless if it is found in last iteration or not
123
+ new_element_in_this_iteration_found = true
124
+
125
+ sa = self.dup
126
+ sa.locator = m
127
+ sa.w3c_align(align_with, false, 1, speed_coef: 2.0)
128
+
129
+ elements << m.id
130
+ if block_given? # block is given
131
+ @locator.driver.invalidate_cache
132
+ block.call(m) # use call to execute the block
133
+ else
134
+ # the value of block_argument becomes nil if you didn't give a block
135
+ # block was not given
136
+ end
137
+ end
138
+
139
+ iterations += 1
140
+ break if !@max_scrolls.nil? && iterations == @max_scrolls
141
+
142
+ if matches.count.positive?
143
+ # if there are elements on screen, but there are no new elements
144
+ # then we have reached the end of scrolling
145
+ if elements.count == elements_count_before_iteration
146
+ return elements
147
+ end
148
+ else
149
+ # there are no matching elements. to detect end of scroll,
150
+ # first and last leaf is compared before with first and last leaf of previous iteration
151
+ if is_end_of_scroll?
152
+ return elements
153
+ end
154
+ end
155
+
156
+ # if there are more than 1 match on screen,
157
+ # the page is scrolled by aligning elements 1 by one,
158
+ # but if there is only 1, or none elements.
159
+ # then scroll the page manually
160
+ self.send("page_#{direction}") if matches.count < 2
161
+ end
162
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
163
+ # if boundElementsByIndex is enabled, we can get stale element reference while doing scroll each
164
+ retry
165
+ rescue StandardError => e
166
+ raise e
167
+ end
168
+
169
+ elements
170
+ end
171
+
172
+ def w3c_align(with, scroll_to_find, max_attempts, speed_coef: 1.25)
173
+ default_deadzone!
174
+
175
+ @locator.scroll_to if scroll_to_find
176
+
177
+ if @locator.instance_of?(TestaAppiumDriver::Locator)
178
+ element = @locator.execute
179
+ else
180
+ element = @locator
181
+ end
182
+
183
+ max_attempts = 3 if max_attempts.nil? || max_attempts <= 0
184
+ # $ctx.puts("Is aligned: #{is_aligned?(with, element)}")
185
+ timeout = 0
186
+ stale_retries = 0
187
+ begin
188
+ until is_aligned?(with, element) || timeout == max_attempts
189
+ # $ctx.puts("align roudn: #{timeout}")
190
+ w3c_attempt_align(with, speed_coef)
191
+ timeout += 1
192
+ end
193
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
194
+ # if boundElementsByIndex is enabled, we can get stale element reference while doing scroll each
195
+ stale_retries += 1
196
+ element = @locator.execute if @locator.instance_of?(TestaAppiumDriver::Locator)
197
+ retry if stale_retries < 2
198
+ end
199
+ # $ctx.puts("end align")
200
+ end
201
+
202
+ def w3c_attempt_align(with, speed_coef)
203
+ case with
204
+ when :top
205
+ y0 = @bounds.bottom_right.y - @deadzone[:bottom]
206
+ y1 = y0 - @align_offset
207
+ x0 = @bounds.width / 2
208
+ x1 = x0
209
+ scroll_direction = :down
210
+ when :bottom
211
+ y0 = @bounds.top_left.y + @deadzone[:top]
212
+ y1 = y0 + @align_offset
213
+ x0 = @bounds.width / 2
214
+ x1 = x0
215
+ scroll_direction = :up
216
+ when :left
217
+ x0 = @bounds.bottom_right.x - @deadzone[:right]
218
+ x1 = x0 - @align_offset
219
+ y0 = @bounds.height / 2
220
+ y1 = y0
221
+ scroll_direction = :right
222
+ when :right
223
+ x0 = @bounds.top_left.x + @deadzone[:top]
224
+ x1 = x0 + @align_offset
225
+ y0 = @bounds.height / 2
226
+ y1 = y0
227
+ scroll_direction = :left
228
+ else
229
+ raise "Unsupported align with option: #{with}"
230
+ end
231
+
232
+ x1, y1 = apply_w3c_correction(x1, y1, scroll_direction) if @driver.device == :android
233
+ w3c_action(x0, y0, x1, y1, SCROLL_ACTION_TYPE_SCROLL, speed_coef: speed_coef)
234
+ end
235
+
236
+ def w3c_scroll_to(direction)
237
+ rounds = 0
238
+ max_scrolls_reached = false
239
+ end_of_scroll_reached = false
240
+ # $ctx.puts("starting scroll to")
241
+ until (@driver.android? && @locator.exists?) ||
242
+ (@driver.ios? && @locator.exists? && @locator.in_viewport?) || end_of_scroll_reached
243
+ # $ctx.puts("Scroll to round: #{rounds}")
244
+ end_of_scroll_reached = is_end_of_scroll?
245
+ case direction
246
+ when :down
247
+ page_down
248
+ when :right
249
+ page_right
250
+ when :left
251
+ page_left
252
+ when :up
253
+ page_up
254
+ else
255
+ scroll_to_start
256
+ @previous_elements = nil
257
+ if @scrollable.scroll_orientation == :vertical
258
+ direction = :down
259
+ else
260
+ direction = :right
261
+ end
262
+ end
263
+
264
+ rounds += 1
265
+
266
+ max_scrolls_reached = true if rounds == @max_scrolls
267
+ break if rounds == @max_scrolls
268
+ end
269
+ # $ctx.puts("end scroll to")
270
+ raise Selenium::WebDriver::Error::NoSuchElementError if max_scrolls_reached || end_of_scroll_reached
271
+ end
272
+
273
+ def w3c_scroll_to_start_or_end(type)
274
+ default_deadzone!
275
+
276
+ @previous_elements = nil
277
+
278
+ if type == :start
279
+ if @scrollable.scroll_orientation == :vertical
280
+ method = "fling_up"
281
+ else
282
+ method = "fling_left"
283
+ end
284
+ else
285
+ if @scrollable.scroll_orientation == :vertical
286
+ method = "fling_down"
287
+ else
288
+ method = "fling_right"
289
+ end
290
+ end
291
+
292
+ iterations = 0
293
+ until is_end_of_scroll? || iterations >= 3
294
+ self.send(method)
295
+ iterations += 1
296
+ end
297
+
298
+ # reset the flag for end of scroll elements
299
+ @previous_elements = nil
300
+ end
301
+
302
+ def w3c_page_or_fling(type, direction)
303
+ default_deadzone!
304
+
305
+ if direction == :down || direction == :up
306
+ if direction == :down
307
+ y0 = @bounds.bottom_right.y - @deadzone[:bottom].to_i
308
+ y1 = @bounds.top_left.y + @deadzone[:top].to_i
309
+ else
310
+ y0 = @bounds.top_left.y + @deadzone[:top].to_i
311
+ y1 = @bounds.bottom_right.y - @deadzone[:bottom].to_i
312
+ end
313
+ x0 = @bounds.top_left.x + (@bounds.width - @deadzone[:left].to_i - @deadzone[:right].to_i) / 2
314
+ x0 = @bounds.top_left.x if x0 < @bounds.top_left.x
315
+ x0 = @bounds.bottom_right.x if x0 > @bounds.bottom_right.x
316
+ x1 = x0
317
+ else
318
+ if direction == :right
319
+ x0 = @bounds.bottom_right.x - @deadzone[:right].to_i
320
+ x1 = @bounds.top_left.x + @deadzone[:left].to_i
321
+ else
322
+ x0 = @bounds.top_left.x + @deadzone[:left].to_i
323
+ x1 = @bounds.bottom_right.x - @deadzone[:right].to_i
324
+ end
325
+
326
+ y0 = @bounds.top_left.y + (@bounds.height - @deadzone[:top].to_i - @deadzone[:bottom].to_i) / 2
327
+ y0 = @bounds.top_left.y if y0 < @bounds.top_left.y
328
+ y0 = @bounds.bottom_right.y if y0 > @bounds.bottom_right.y
329
+ y1 = y0
330
+ end
331
+ x1, y1 = apply_w3c_correction(x1, y1, direction) if @driver.device == :android
332
+
333
+ speed_coef = 1
334
+ speed_coef = 1.5 if type == SCROLL_ACTION_TYPE_SCROLL
335
+
336
+ w3c_action(x0, y0, x1, y1, type, speed_coef: speed_coef)
337
+ end
338
+
339
+ def w3c_action(x0, y0, x1, y1, type, speed_coef: 1.0)
340
+ speed_coef = 1 / speed_coef
341
+ if type == SCROLL_ACTION_TYPE_SCROLL
342
+ duration = 1.8 * speed_coef
343
+ elsif type == SCROLL_ACTION_TYPE_FLING
344
+ duration = 0.1 * speed_coef
345
+ elsif type == SCROLL_ACTION_TYPE_DRAG
346
+ duration = 3.5 * speed_coef
347
+ else
348
+ raise "Unknown scroll action type #{type}"
349
+ end
350
+
351
+ action_builder = @driver.action
352
+ f1 = action_builder.add_pointer_input(:touch, "finger1")
353
+ f1.create_pointer_move(duration: 0, x: x0, y: y0, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
354
+ f1.create_pointer_down(:left)
355
+
356
+ f1.create_pointer_move(duration: duration, x: x1, y: y1, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
357
+ unless type == SCROLL_ACTION_TYPE_FLING
358
+ # with this move we prevent flinging/overscroll
359
+ overscroll_pause = @driver.ios? ? 1 : 0.5
360
+ f1.create_pointer_move(duration: overscroll_pause, x: x1, y: y1, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
361
+ end
362
+ f1.create_pointer_up(:left)
363
+ puts "Scroll execute[w3c_action]: #{type}: {x0: #{x0}, y0: #{y0}} => (duration: #{duration}) => {x1: #{x1}, y1: #{y1}}"
364
+ # $ctx.puts "Scroll execute[w3c_action]: #{type}: {x0: #{x0}, y0: #{y0}} => (duration: #{duration}) => {x1: #{x1}, y1: #{y1}}"
365
+ @driver.perform_actions [f1]
366
+ end
367
+
368
+ def apply_w3c_correction(x1, y1, direction)
369
+ y1 -= SCROLL_CORRECTION_W3C if direction == :down
370
+ y1 += SCROLL_CORRECTION_W3C if direction == :up
371
+ x1 -= SCROLL_CORRECTION_W3C if direction == :right
372
+ x1 += SCROLL_CORRECTION_W3C if direction == :left
373
+ [x1, y1]
374
+ end
375
+
376
+ def w3c_drag_to(x0, y0, x1, y1)
377
+ w3c_action(x0, y0, x1, y1, SCROLL_ACTION_TYPE_DRAG)
378
+ end
379
+ end
380
+ end
@@ -0,0 +1,275 @@
1
+ require_relative 'scroll_actions/json_wire_scroll_actions'
2
+ require_relative 'scroll_actions/w3c_scroll_actions'
3
+
4
+ module ::TestaAppiumDriver
5
+
6
+ # Class for handling scroll actions
7
+ class ScrollActions
8
+ include W3cScrollActions
9
+ include JsonWireScrollActions
10
+
11
+ attr_accessor :locator
12
+ # @param [TestaAppiumDriver::Locator, nil] scrollable container that will be used to determine the bounds for scrolling
13
+ # @param [Hash] params
14
+ # acceptable params
15
+ # - locator - element that should be found with scrolling actions
16
+ # - deadzone - [Hash] that stores top, bottom, left and right deadzone values. If deadzone[:top] is 200 then 200px from top of the scrollable container will not be used for scrolling
17
+ # - max_scrolls - [Integer] maximum number of scrolls before exception is thrown
18
+ # - default_scroll_strategy - defines which scroll strategy will be used if a scroll action is valid for multiple strategies
19
+ def initialize(scrollable, params = {})
20
+ @scrollable = scrollable
21
+ @locator = params[:locator]
22
+ # TODO: raise error if locator is for multiple, but not for scroll each, chekc other cases aswell
23
+ @deadzone = params[:deadzone]
24
+ @max_scrolls = params[:max_scrolls]
25
+ @default_scroll_strategy = params[:default_scroll_strategy]
26
+ @driver = @locator.driver
27
+
28
+ if @scrollable.nil?
29
+ # if we dont have a scrollable element or if we do have it, but it is not compatible with uiautomator
30
+ # then find first scrollable in document
31
+ @scrollable = @driver.scrollable
32
+ end
33
+
34
+ @strategy = nil
35
+ if @scrollable.strategy == FIND_STRATEGY_XPATH || # uiautomator cannot resolve scrollable from a xpath locator
36
+ !@deadzone.nil? ||
37
+ !@scrollable.from_element.instance_of?(TestaAppiumDriver::Driver) # uiautomator cannot resolve nested scrollable
38
+ @strategy = SCROLL_STRATEGY_W3C
39
+ end
40
+
41
+ @bounds = @scrollable.bounds
42
+ end
43
+
44
+ def align(with, scroll_to_find, max_attempts)
45
+ w3c_align(with, scroll_to_find, max_attempts)
46
+ @locator
47
+ end
48
+
49
+ # @return [Array]
50
+ def scroll_each(&block)
51
+ w3c_scroll_each(nil, &block)
52
+ end
53
+
54
+ def scroll_each_down(&block)
55
+ w3c_scroll_each(:down, &block)
56
+ end
57
+
58
+ def scroll_each_up(&block)
59
+ w3c_scroll_each(:up, &block)
60
+ end
61
+
62
+ def scroll_each_right(&block)
63
+ w3c_scroll_each(:right, &block)
64
+ end
65
+
66
+ def scroll_each_left(&block)
67
+ w3c_scroll_each(:left, &block)
68
+ end
69
+
70
+ def resolve_strategy
71
+ if @strategy.nil?
72
+ @default_scroll_strategy
73
+ else
74
+ @strategy
75
+ end
76
+ end
77
+
78
+ def scroll_to
79
+ if @locator.strategy != FIND_STRATEGY_XPATH && resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
80
+ uiautomator_scroll_to
81
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
82
+ w3c_scroll_to(nil)
83
+ end
84
+ end
85
+
86
+ def scroll_down_to
87
+ w3c_scroll_to(:down)
88
+ end
89
+
90
+ def scroll_up_to
91
+ w3c_scroll_to(:up)
92
+ end
93
+
94
+ def scroll_right_to
95
+ w3c_scroll_to(:right)
96
+ end
97
+
98
+ def scroll_left_to
99
+ w3c_scroll_to(:left)
100
+ end
101
+
102
+ def page_next
103
+ if @scrollable.scroll_orientation == :vertical
104
+ page_down
105
+ else
106
+ page_left
107
+ end
108
+ end
109
+
110
+ def page_back
111
+ if @scrollable.scroll_orientation == :vertical
112
+ page_up
113
+ else
114
+ page_right
115
+ end
116
+ end
117
+
118
+ def page_down
119
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
120
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :down)
121
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
122
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :down)
123
+ end
124
+ end
125
+
126
+ def page_right
127
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
128
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :right)
129
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
130
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :right)
131
+ end
132
+ end
133
+
134
+ def page_up
135
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
136
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :up)
137
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
138
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :up)
139
+ end
140
+ end
141
+
142
+ def page_left
143
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
144
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :left)
145
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
146
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :left)
147
+ end
148
+ end
149
+
150
+ def scroll_to_start
151
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
152
+ uiautomator_scroll_to_start_or_end(:start)
153
+
154
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
155
+ w3c_scroll_to_start_or_end(:start)
156
+ end
157
+ end
158
+
159
+ def scroll_to_end
160
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
161
+ uiautomator_scroll_to_start_or_end(:end)
162
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
163
+ w3c_scroll_to_start_or_end(:end)
164
+ end
165
+ end
166
+
167
+ def fling_down
168
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
169
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_FLING, :down)
170
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
171
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_FLING, :down)
172
+ end
173
+ end
174
+
175
+ def fling_right
176
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
177
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_FLING, :right)
178
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
179
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_FLING, :right)
180
+ end
181
+ end
182
+
183
+ def fling_up
184
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
185
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_FLING, :up)
186
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
187
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_FLING, :up)
188
+ end
189
+ end
190
+
191
+ def fling_left
192
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
193
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_FLING, :left)
194
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
195
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_FLING, :left)
196
+ end
197
+ end
198
+
199
+ def drag_to(x, y)
200
+ b = @locator.bounds
201
+ coords = b.center
202
+ w3c_drag_to(coords.x, coords.y, x, y)
203
+ end
204
+
205
+
206
+
207
+
208
+ def is_aligned?(with, element)
209
+ align_bounds = @locator.bounds(force_cache_element: element)
210
+ case with
211
+ when :top
212
+ @align_offset = align_bounds.top_left.y - @bounds.top_left.y - @deadzone[:top]
213
+ when :bottom
214
+ @align_offset = @bounds.bottom_right.y - @deadzone[:bottom] - align_bounds.bottom_right.y
215
+ when :right
216
+ @align_offset = @bounds.bottom_right.x - @deadzone[:right] - align_bounds.bottom_right.x
217
+ when :left
218
+ @align_offset = align_bounds.top_left.x - @bounds.top_left.x - @deadzone[:left]
219
+ else
220
+ raise "Unsupported align with option: #{with}"
221
+ end
222
+ @align_offset < SCROLL_ALIGNMENT_THRESHOLD
223
+ end
224
+
225
+
226
+
227
+ def is_end_of_scroll?
228
+ # if @driver.device == :android
229
+
230
+ old_elements = @previous_elements
231
+ @previous_elements = @scrollable.first_and_last_leaf
232
+
233
+
234
+ # $__.puts "old: #{old_elements}"
235
+ # $__.puts "new: #{@previous_elements}"
236
+ # $__.puts "end_of_scroll? #{ old_elements == @previous_elements}"
237
+ old_elements == @previous_elements
238
+ # else
239
+ # # for ios, check location of first and last elements
240
+ # old_elements = @previous_elements
241
+ # @previous_elements = @scrollable.first_and_last_child&.map(&:location)
242
+ # # $__.puts "old:"
243
+ # # $__.puts old_elements
244
+ # # $__.puts "prev:"
245
+ # # $__.puts @previous_elements
246
+ # old_elements == @previous_elements
247
+ # end
248
+ end
249
+
250
+ def default_deadzone!
251
+ @deadzone = {} if @deadzone.nil?
252
+ if @deadzone[:top].nil?
253
+ @deadzone[:top] = 1
254
+ else
255
+ @deadzone[:top] = @deadzone[:top].to_f
256
+ end
257
+ if @deadzone[:bottom].nil?
258
+ @deadzone[:bottom] = 1
259
+ else
260
+ @deadzone[:bottom] = @deadzone[:bottom].to_f
261
+ end
262
+ if @deadzone[:right].nil?
263
+ @deadzone[:right] = 1
264
+ else
265
+ @deadzone[:right] = @deadzone[:right].to_f
266
+ end
267
+ if @deadzone[:left].nil?
268
+ @deadzone[:left] = 1
269
+ else
270
+ @deadzone[:left] = @deadzone[:left].to_f
271
+ end
272
+ end
273
+
274
+ end
275
+ end
@@ -0,0 +1,19 @@
1
+ module ::Appium
2
+ module Core
3
+ class Element
4
+ # sets the testa appium driver instance for the current phone
5
+ def self.set_driver(driver, udid)
6
+ udid = "unknown" if udid.nil?
7
+ @@drivers ||= {}
8
+ @@drivers[udid] = driver
9
+ end
10
+
11
+ # @return [TestaAppiumDriver::Driver] testa appium driver instance for the current phone
12
+ def get_driver
13
+ udid = @bridge.capabilities.instance_variable_get(:@capabilities)["udid"]
14
+ udid = "unknown" if udid.nil?
15
+ @@drivers[udid]
16
+ end
17
+ end
18
+ end
19
+ end