testa_appium_driver 0.1.20 → 0.1.22

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