testa_appium_driver 0.1.13 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +23 -0
  3. data/.gitignore +2 -3
  4. data/.rubocop.yml +5 -13
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +76 -0
  7. data/appium-driver.iml +74 -0
  8. data/lib/testa_appium_driver/android/class_selectors.rb +7 -7
  9. data/lib/testa_appium_driver/android/driver.rb +1 -0
  10. data/lib/testa_appium_driver/android/locator/attributes.rb +29 -25
  11. data/lib/testa_appium_driver/android/locator.rb +1 -1
  12. data/lib/testa_appium_driver/android/selenium_element.rb +6 -2
  13. data/lib/testa_appium_driver/common/constants.rb +2 -1
  14. data/lib/testa_appium_driver/common/locator/scroll_actions.rb +33 -33
  15. data/lib/testa_appium_driver/common/locator.rb +66 -78
  16. data/lib/testa_appium_driver/common/scroll_actions/json_wire_scroll_actions.rb +1 -1
  17. data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +87 -20
  18. data/lib/testa_appium_driver/common/scroll_actions.rb +43 -23
  19. data/lib/testa_appium_driver/common/selenium_element.rb +2 -2
  20. data/lib/testa_appium_driver/driver.rb +41 -20
  21. data/lib/testa_appium_driver/ios/locator/attributes.rb +24 -20
  22. data/lib/testa_appium_driver/ios/locator.rb +1 -0
  23. data/lib/testa_appium_driver/ios/selenium_element.rb +3 -2
  24. data/lib/testa_appium_driver/ios/type_selectors.rb +2 -2
  25. data/lib/testa_appium_driver/version.rb +1 -1
  26. data/testa_appium_driver.gemspec +2 -2
  27. metadata +11 -18
  28. data/.idea/deployment.xml +0 -22
  29. data/.idea/inspectionProfiles/Project_Default.xml +0 -9
  30. data/.idea/misc.xml +0 -6
  31. data/.idea/modules.xml +0 -8
  32. data/.idea/runConfigurations/Android_Test.xml +0 -42
  33. data/.idea/runConfigurations.xml +0 -10
  34. data/.idea/sshConfigs.xml +0 -13
  35. data/.idea/vcs.xml +0 -6
  36. data/.idea/webServers.xml +0 -21
  37. data/testa_appium_driver.iml +0 -41
@@ -1,7 +1,6 @@
1
1
  require_relative 'locator/scroll_actions'
2
2
 
3
-
4
- module TestaAppiumDriver
3
+ module ::TestaAppiumDriver
5
4
  #noinspection RubyTooManyInstanceVariablesInspection,RubyTooManyMethodsInspection
6
5
  class Locator
7
6
  include Helpers
@@ -29,7 +28,6 @@ module TestaAppiumDriver
29
28
 
30
29
  attr_accessor :index_for_multiple
31
30
 
32
-
33
31
  # locator parameters are:
34
32
  # single: true or false
35
33
  # scrollable_locator: [TestaAppiumDriver::Locator, nil] for scrolling if needed later
@@ -59,19 +57,17 @@ module TestaAppiumDriver
59
57
  end
60
58
 
61
59
  selectors[:id] = selectors[:name] unless selectors[:name].nil?
62
- if from_element.instance_of?(Selenium::WebDriver::Element)
63
- @xpath_selector = "//*" # to select current element
64
- @xpath_selector += hash_to_xpath(@driver.device, selectors, single)[1..-1]
60
+ if from_element.instance_of?(::Selenium::WebDriver::Element) || from_element.instance_of?(::Appium::Core::Element) || from_element.instance_of?(::TestaAppiumDriver::Locator)
61
+ @xpath_selector = "."
62
+ @xpath_selector += hash_to_xpath(@driver.device, selectors, single)
65
63
  else
66
64
  @xpath_selector = hash_to_xpath(@driver.device, selectors, single)
67
65
  end
68
66
 
69
-
70
67
  @from_element = from_element
71
68
  @default_find_strategy = params[:default_find_strategy]
72
69
  @default_scroll_strategy = params[:default_scroll_strategy]
73
70
 
74
-
75
71
  @can_use_id_strategy = is_only_id_selector?(selectors)
76
72
  if @can_use_id_strategy
77
73
  if @driver.device == :android
@@ -81,7 +77,6 @@ module TestaAppiumDriver
81
77
  end
82
78
  end
83
79
 
84
-
85
80
  @strategy = params[:strategy]
86
81
  @strategy_reason = params[:strategy_reason]
87
82
 
@@ -90,9 +85,6 @@ module TestaAppiumDriver
90
85
  init(params, selectors, single)
91
86
  end
92
87
 
93
-
94
-
95
-
96
88
  def is_only_id_selector?(selectors)
97
89
  # since, name and id is the same thing for iOS,
98
90
  if @driver.device == :android
@@ -103,7 +95,6 @@ module TestaAppiumDriver
103
95
  end
104
96
  end
105
97
 
106
-
107
98
  # method missing is used to fetch the element before executing additional commands like click, send_key, count
108
99
  def method_missing(method, *args, &block)
109
100
  r = execute.send(method, *args, &block)
@@ -111,7 +102,6 @@ module TestaAppiumDriver
111
102
  r
112
103
  end
113
104
 
114
-
115
105
  # @param [Boolean] skip_cache if true it will skip cache check and store
116
106
  # @param [Selenium::WebDriver::Element] force_cache_element, for internal use where we have already the element, and want to execute custom locator methods on it
117
107
  # @return [Selenium::WebDriver::Element, Array]
@@ -122,17 +112,12 @@ module TestaAppiumDriver
122
112
  # elements[2] will be resolved with xpath because we are looking for multiple elements from element
123
113
  # and since we are looking for instance 2, [](instance) method will return new "empty locator"
124
114
  # we are executing click on that "empty locator" so we have to return the instance 2 of elements for the click
125
- if @xpath_selector == "//*[1]" && !@from_element.nil? && @image_selector.nil?
126
- return @from_element if @from_element.instance_of?(Selenium::WebDriver::Element)
115
+ if @xpath_selector == ".//*[1]" && !@from_element.nil? && @image_selector.nil?
116
+ return @from_element if @from_element.instance_of?(::Selenium::WebDriver::Element) || @from_element.instance_of?(::Appium::Core::Element)
127
117
  return @from_element.execute(skip_cache: skip_cache, force_cache_element: force_cache_element, ignore_implicit_wait: ignore_implicit_wait) if @from_element.instance_of?(TestaAppiumDriver::Locator)
128
118
  return @from_element
129
119
  end
130
120
 
131
-
132
-
133
-
134
-
135
-
136
121
  r = @driver.execute(@from_element, @single, strategies_and_selectors, skip_cache: skip_cache, ignore_implicit_wait: ignore_implicit_wait)
137
122
  r = r[@index_for_multiple] if !@index_for_multiple.nil? && !@single
138
123
  r
@@ -149,30 +134,28 @@ module TestaAppiumDriver
149
134
  if found
150
135
  if block_given? # block is given
151
136
  block.call(self) # use call to execute the block
152
- else # the value of block_argument becomes nil if you didn't give a block
137
+ else
138
+ # the value of block_argument becomes nil if you didn't give a block
153
139
  # block was not given
154
140
  end
155
141
  end
156
142
  self
157
143
  end
158
144
 
159
-
160
145
  # @param [Integer] timeout in seconds
161
146
  # @return [TestaAppiumDriver::Locator]
162
147
  def wait_until_exists(timeout = nil)
163
- args = {timeout: timeout}
148
+ args = { timeout: timeout }
164
149
  _wait(:until, args)
165
150
  end
166
151
 
167
-
168
152
  # @param [Integer] timeout in seconds
169
153
  # @return [TestaAppiumDriver::Locator]
170
154
  def wait_while_exists(timeout = nil)
171
- args = {timeout: timeout}
155
+ args = { timeout: timeout }
172
156
  _wait(:while, args)
173
157
  end
174
158
 
175
-
176
159
  def wait_while(timeout = nil, args = {})
177
160
  args[:timeout] = timeout
178
161
  _wait(:while, args)
@@ -183,13 +166,13 @@ module TestaAppiumDriver
183
166
  _wait(:until, args)
184
167
  end
185
168
 
186
-
187
169
  # all timeouts are disabled before check, and enabled after check
188
170
  # @return [boolean] true if it exists in the page regardless if visible or not
189
171
  def exists?
190
172
  found = true
191
173
  begin
192
- execute(skip_cache: true, ignore_implicit_wait: true)
174
+ r = execute(skip_cache: true, ignore_implicit_wait: true)
175
+ return r.count.positive? if r.is_a?(Array)
193
176
  rescue StandardError
194
177
  found = false
195
178
  end
@@ -235,7 +218,7 @@ module TestaAppiumDriver
235
218
  else
236
219
  from_element = self.dup
237
220
  from_element.index_for_multiple = instance
238
- params = {}.merge({single: true, scrollable_locator: @scrollable_locator})
221
+ params = {}.merge({ single: true, scrollable_locator: @scrollable_locator })
239
222
  #params[:strategy] = FIND_STRATEGY_XPATH
240
223
  #params[:strategy_reason] = "retrieved instance of a array"
241
224
  params[:default_find_strategy] = @default_find_strategy
@@ -244,33 +227,32 @@ module TestaAppiumDriver
244
227
  end
245
228
  end
246
229
 
247
-
248
230
  # @param [TestaAppiumDriver::Locator, Selenium::WebDriver::Element, Array] other
249
231
  #noinspection RubyNilAnalysis,RubyUnnecessaryReturnStatement
250
232
  def ==(other)
251
233
  elements = execute
252
- other = other.execute if other.kind_of?(TestaAppiumDriver::Locator)
234
+ other = other.execute if other.is_a?(TestaAppiumDriver::Locator)
253
235
 
254
- if elements.kind_of?(Array)
255
- return false unless other.kind_of?(Array)
236
+ if elements.is_a?(Array)
237
+ return false unless other.is_a?(Array)
256
238
  return false if other.count != elements.count
257
239
  return (elements - other).empty?
258
240
  else
259
- return false if other.kind_of?(Array)
241
+ return false if other.is_a?(Array)
260
242
  return elements == other
261
243
  end
262
244
  end
263
245
 
264
246
  def as_json
265
247
  {
266
- strategy: @strategy,
267
- default_strategy: @default_find_strategy,
268
- single: @single,
269
- uiautomator: defined?(self.ui_selector) ? ui_selector : nil,
270
- xpath: @xpath_selector,
271
- scroll_orientation: @scroll_orientation,
272
- resolved: strategies_and_selectors,
273
- index_for_multiple: @index_for_multiple
248
+ strategy: @strategy,
249
+ default_strategy: @default_find_strategy,
250
+ single: @single,
251
+ uiautomator: defined?(self.ui_selector) ? ui_selector : nil,
252
+ xpath: @xpath_selector,
253
+ scroll_orientation: @scroll_orientation,
254
+ resolved: strategies_and_selectors,
255
+ index_for_multiple: @index_for_multiple
274
256
  }
275
257
  end
276
258
 
@@ -282,7 +264,6 @@ module TestaAppiumDriver
282
264
  [self.to_s]
283
265
  end
284
266
 
285
-
286
267
  # @return [TestaAppiumDriver::Locator]
287
268
  def as_scrollable(orientation: :vertical, top: nil, bottom: nil, right: nil, left: nil)
288
269
  @scroll_orientation = orientation
@@ -297,43 +278,50 @@ module TestaAppiumDriver
297
278
  self
298
279
  end
299
280
 
300
-
301
281
  def first_and_last_leaf
302
282
  @driver.first_and_last_leaf(execute)
303
283
  end
304
284
 
285
+ def first_and_last_child
286
+ @driver.first_and_last_child(execute)
287
+ end
305
288
 
306
- def tap(x = nil, y = nil)
307
- click(x, y)
289
+ def double_click(x = nil, y = nil)
290
+ click(x, y, double: true)
308
291
  end
309
292
 
310
293
  # if both x or y, or both are not given, will click in the center of the element
311
294
  # @param x If positive integer, will offset the click from the left side, if negative integer, will offset the click from the right. If float value is given, it will threat it as percentage offset, giving it 0.5 will click in the middle
312
295
  # @param y If positive integer, will offset the click from the bottom side, if negative integer, will offset the click from the top. If float value is given, it will threat it as percentage offset, giving it 0.5 will click in the middle
313
- def click(x = nil, y = nil)
314
- if !x.nil? && !y.nil?
296
+ def click(x = nil, y = nil, double: false, by_coords: false)
297
+ if !x.nil? && !y.nil? || double || by_coords
298
+
299
+ x = 0.5 if x.nil?
300
+ y = 0.5 if y.nil?
315
301
 
316
302
  b = self.bounds
317
- if x.kind_of? Integer
303
+ if x.is_a?(Integer)
318
304
  if x >= 0
319
305
  x = b.top_left.x + x
320
306
  else
321
307
  x = b.bottom_right.x + x
322
308
  end
323
- elsif x.kind_of? Float
324
- x = b.top_left.x + b.width*x
309
+ elsif x.is_a?(Float) && x <= 1.0 && x >= 0
310
+ x = b.top_left.x + b.width * x
325
311
  else
326
- raise "x value #{x} not supported"
312
+ raise "x value #{x} not supported. Use integer as pixel or float (0..1) as percentage of element width"
327
313
  end
328
314
 
329
- if y.kind_of? Integer
315
+ if y.is_a?(Integer)
330
316
  if y >= 0
331
- y = b.bottom_right.y + y
317
+ y = b.top_left.y + y
332
318
  else
333
- y = b.top_left + y
319
+ y = b.bottom_right + y
334
320
  end
335
- elsif y.kind_of? Float
336
- y = b.bottom_right.y + b.height*y
321
+ elsif y.is_a?(Float) && y <= 1.0 && y >= 0
322
+ y = b.top_left.y + b.height * y
323
+ else
324
+ raise "y value #{x} not supported. Use integer as pixel or float (0..1) as percentage of element height"
337
325
  end
338
326
 
339
327
  action_builder = @driver.action
@@ -341,6 +329,11 @@ module TestaAppiumDriver
341
329
  f1.create_pointer_move(duration: 0, x: x, y: y, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
342
330
  f1.create_pointer_down(:left)
343
331
  f1.create_pointer_up(:left)
332
+ if double
333
+ f1.create_pause(0.1)
334
+ f1.create_pointer_down(:left)
335
+ f1.create_pointer_up(:left)
336
+ end
344
337
  @driver.perform_actions [f1]
345
338
  else
346
339
  if @driver.device == :android
@@ -348,13 +341,16 @@ module TestaAppiumDriver
348
341
  else
349
342
  # on ios, if element is not visible, first click will scroll to it
350
343
  # then on second click actually perform the click
351
- visible = visible?
344
+ #visible = visible?
352
345
  perform_driver_method(:click)
353
- perform_driver_method(:click) unless visible rescue nil
346
+ #perform_driver_method(:click) unless visible rescue nil
354
347
  end
355
348
  end
356
349
  end
357
350
 
351
+ alias_method :tap, :click
352
+ alias_method :double_tap, :double_click
353
+
358
354
  def send_key(*args)
359
355
  perform_driver_method(:send_keys, *args)
360
356
  end
@@ -363,12 +359,11 @@ module TestaAppiumDriver
363
359
  perform_driver_method(:clear)
364
360
  end
365
361
 
366
-
367
362
  # Return parent element
368
363
  # @return [TestaAppiumDriver::Locator]
369
364
  def parent
370
365
  raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "parent") if @strategy != FIND_STRATEGY_XPATH && !@strategy.nil?
371
- raise "Cannot add parent selector to a retrieved instance of a class array" if (@xpath_selector == "//*" || @xpath_selector == "//*[1]") && !@from_element.nil?
366
+ raise "Cannot add parent selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
372
367
 
373
368
  locator = self.dup
374
369
  locator.strategy = FIND_STRATEGY_XPATH
@@ -382,7 +377,7 @@ module TestaAppiumDriver
382
377
  # @return [TestaAppiumDriver::Locator]
383
378
  def children
384
379
  raise "Cannot add children selector to array" unless @single
385
- raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "children") if @strategy != FIND_STRATEGY_XPATH && @strategy != FIND_STRATEGY_CLASS_CHAIN && !@strategy.nil?
380
+ raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "children") if @strategy != FIND_STRATEGY_XPATH && @strategy != FIND_STRATEGY_CLASS_CHAIN && !@strategy.nil?
386
381
 
387
382
  locator = self.dup
388
383
  locator.strategy_reason = "children"
@@ -399,7 +394,6 @@ module TestaAppiumDriver
399
394
  locator
400
395
  end
401
396
 
402
-
403
397
  # Return first child element
404
398
  # @return [TestaAppiumDriver::Locator]
405
399
  def child
@@ -421,12 +415,11 @@ module TestaAppiumDriver
421
415
  locator
422
416
  end
423
417
 
424
-
425
418
  # @return [TestaAppiumDriver::Locator]
426
419
  def siblings
427
420
  raise "Cannot add siblings selector to array" unless @single
428
421
  raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "siblings") if @strategy != FIND_STRATEGY_XPATH && !@strategy.nil?
429
- raise "Cannot add siblings selector to a retrieved instance of a class array" if (@xpath_selector == "//*" || @xpath_selector == "//*[1]") && !@from_element.nil?
422
+ raise "Cannot add siblings selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
430
423
 
431
424
  locator = self.dup
432
425
  locator.strategy = FIND_STRATEGY_XPATH
@@ -442,7 +435,7 @@ module TestaAppiumDriver
442
435
  def preceding_siblings
443
436
  raise "Cannot add preceding_siblings selector to array" unless @single
444
437
  raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "preceding_siblings") if @strategy != FIND_STRATEGY_XPATH && !@strategy.nil?
445
- raise "Cannot add preceding_siblings selector to a retrieved instance of a class array" if (@xpath_selector == "//*" || @xpath_selector == "//*[1]") && !@from_element.nil?
438
+ raise "Cannot add preceding_siblings selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
446
439
 
447
440
  locator = self.dup
448
441
  locator.strategy = FIND_STRATEGY_XPATH
@@ -458,7 +451,7 @@ module TestaAppiumDriver
458
451
  def preceding_sibling
459
452
  raise "Cannot add preceding_sibling selector to array" unless @single
460
453
  raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "preceding_sibling") if @strategy != FIND_STRATEGY_XPATH && !@strategy.nil?
461
- raise "Cannot add preceding siblings selector to a retrieved instance of a class array" if (@xpath_selector == "//*" || @xpath_selector == "//*[1]") && !@from_element.nil?
454
+ raise "Cannot add preceding siblings selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
462
455
 
463
456
  locator = self.dup
464
457
  locator.strategy = FIND_STRATEGY_XPATH
@@ -472,12 +465,11 @@ module TestaAppiumDriver
472
465
  locator
473
466
  end
474
467
 
475
-
476
468
  # @return [TestaAppiumDriver::Locator]
477
469
  def following_siblings
478
470
  raise "Cannot add following_siblings selector to array" unless @single
479
471
  raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "following_siblings") if @strategy != FIND_STRATEGY_XPATH && !@strategy.nil?
480
- raise "Cannot add following_siblings selector to a retrieved instance of a class array" if (@xpath_selector == "//*" || @xpath_selector == "//*[1]") && !@from_element.nil?
472
+ raise "Cannot add following_siblings selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
481
473
 
482
474
  locator = self.dup
483
475
  locator.strategy = FIND_STRATEGY_XPATH
@@ -493,7 +485,7 @@ module TestaAppiumDriver
493
485
  def following_sibling
494
486
  raise "Cannot add following_sibling selector to array" unless @single
495
487
  raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "following_sibling") if @strategy != FIND_STRATEGY_XPATH && !@strategy.nil?
496
- raise "Cannot add following_sibling selector to a retrieved instance of a class array" if (@xpath_selector == "//*" || @xpath_selector == "//*[1]") && !@from_element.nil?
488
+ raise "Cannot add following_sibling selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
497
489
 
498
490
  locator = self.dup
499
491
  locator.strategy = FIND_STRATEGY_XPATH
@@ -507,7 +499,6 @@ module TestaAppiumDriver
507
499
  locator
508
500
  end
509
501
 
510
-
511
502
  private
512
503
 
513
504
  def _wait(type, args)
@@ -528,10 +519,8 @@ module TestaAppiumDriver
528
519
  args.delete(:interval)
529
520
  args.delete(:timeout)
530
521
 
531
-
532
-
533
522
  start_time = Time.now.to_f
534
- if type == :while
523
+ if type == :while
535
524
  while exists? && _attributes_match(args)
536
525
  raise message if start_time + timeout < Time.now.to_f
537
526
  sleep interval
@@ -548,7 +537,7 @@ module TestaAppiumDriver
548
537
  def _attributes_match(attributes)
549
538
  all_match = true
550
539
  attributes.each do |key, value|
551
- unless attribute(key) == value
540
+ unless testa_attribute(key) == value
552
541
  all_match = false
553
542
  break
554
543
  end
@@ -559,7 +548,7 @@ module TestaAppiumDriver
559
548
  #noinspection RubyNilAnalysis
560
549
  def perform_driver_method(name, *args)
561
550
  elements = execute
562
- if elements.kind_of?(Array)
551
+ if elements.is_a?(Array)
563
552
  elements.map { |e| e.send(name, *args) }
564
553
  else
565
554
  elements.send(name, *args)
@@ -571,7 +560,6 @@ module TestaAppiumDriver
571
560
  locator.xpath_selector += hash_to_xpath(@driver.device, selectors, single)
572
561
  end
573
562
 
574
-
575
563
  def handle_image_selector(selectors, params)
576
564
  image_match_threshold = 0.4
577
565
  image_match_threshold = params[:imageMatchThreshold] unless params[:imageMatchThreshold].nil?
@@ -1,4 +1,4 @@
1
1
  module TestaAppiumDriver
2
- class ScrollActions
2
+ module JsonWireScrollActions
3
3
  end
4
4
  end
@@ -1,7 +1,7 @@
1
- module TestaAppiumDriver
2
- class ScrollActions
1
+ module ::TestaAppiumDriver
2
+ module W3cScrollActions
3
+
3
4
 
4
- private
5
5
  # @return [Array]
6
6
  def w3c_scroll_each(direction, &block)
7
7
  elements = []
@@ -19,48 +19,105 @@ module TestaAppiumDriver
19
19
  direction = :right
20
20
  end
21
21
  end
22
+ case direction
23
+ when :up
24
+ align_with = :bottom
25
+ when :down
26
+ align_with = :top
27
+ when :right
28
+ align_with = :left
29
+ when :left
30
+ align_with = :right
31
+ else
32
+ align_with = :top
33
+ end
34
+
35
+
36
+
37
+ ignore_element_ids = []
38
+ previous_element = nil
22
39
 
23
40
  until is_end_of_scroll?
41
+ aligned_items = 0
42
+ new_ignore_element_ids = []
24
43
  matches = @locator.execute(skip_cache: true)
25
- matches.each_with_index do |m|
26
- next if elements.include?(m)
44
+ matches.each_with_index do |m, index|
45
+ if ignore_element_ids.include?(m.id)
46
+ previous_element = m
47
+ next
48
+ end
49
+
50
+ sa = self.dup
51
+ sa.locator = m
52
+ sa.w3c_align(align_with, false, 1, speed_coef: 2.0)
53
+ is_aligned = sa.is_aligned?(align_with, m)
54
+ if !is_aligned && !previous_element.nil?
55
+ new_ignore_element_ids << previous_element.id
56
+ end
57
+
58
+ if is_aligned
59
+ aligned_items += 1
60
+ end
61
+
62
+ if matches.count == index + 1
63
+ new_ignore_element_ids << m.id
64
+ end
65
+
27
66
  elements << m
28
67
  if block_given? # block is given
68
+ @locator.driver.invalidate_cache
29
69
  block.call(m) # use call to execute the block
30
70
  else # the value of block_argument becomes nil if you didn't give a block
31
71
  # block was not given
32
72
  end
73
+ previous_element = m
33
74
  end
75
+
34
76
  iterations += 1
35
77
  break if !@max_scrolls.nil? && iterations == @max_scrolls
36
- self.send("page_#{direction}")
78
+
79
+ if aligned_items == 0
80
+ self.send("page_#{direction}")
81
+ else
82
+ ignore_element_ids = new_ignore_element_ids.dup
83
+ end
84
+
85
+
86
+
37
87
  end
38
88
  rescue => e
39
89
  raise e
40
-
41
90
  end
91
+
42
92
  elements
43
93
  end
44
94
 
45
- def w3c_align(with, scroll_to_find)
95
+ def w3c_align(with, scroll_to_find, max_attempts, speed_coef: 1.25)
46
96
  default_deadzone!
47
97
 
48
98
 
49
99
 
50
100
  @locator.scroll_to if scroll_to_find
51
101
 
52
- element = @locator.execute
102
+ if @locator.instance_of?(TestaAppiumDriver::Locator)
103
+ element = @locator.execute
104
+ else
105
+ element = @locator
106
+ end
107
+
108
+
109
+ max_attempts = 3 if max_attempts.nil? || max_attempts <= 0
53
110
 
54
111
  timeout = 0
55
- until is_aligned?(with, element) || timeout == 3
56
- w3c_attempt_align(with)
112
+ until is_aligned?(with, element) || timeout == max_attempts
113
+ w3c_attempt_align(with, speed_coef)
57
114
  timeout += 1
58
115
  end
59
116
 
60
117
  end
61
118
 
62
119
 
63
- def w3c_attempt_align(with)
120
+ def w3c_attempt_align(with, speed_coef)
64
121
  case with
65
122
  when :top
66
123
  y0 = @bounds.bottom_right.y - @deadzone[:bottom]
@@ -91,7 +148,7 @@ module TestaAppiumDriver
91
148
  end
92
149
 
93
150
  x1, y1 = apply_w3c_correction(x1, y1, scroll_direction) if @driver.device == :android
94
- w3c_action(x0, y0, x1, y1, SCROLL_ACTION_TYPE_SCROLL)
151
+ w3c_action(x0, y0, x1, y1, SCROLL_ACTION_TYPE_SCROLL, speed_coef: speed_coef)
95
152
  end
96
153
 
97
154
 
@@ -171,7 +228,9 @@ module TestaAppiumDriver
171
228
  y0 = @bounds.top_left.y + @deadzone[:top].to_i
172
229
  y1 = @bounds.bottom_right.y - @deadzone[:bottom].to_i
173
230
  end
174
- x0 = @bounds.width / 2
231
+ x0 = @bounds.top_left.x + (@bounds.width - @deadzone[:left].to_i - @deadzone[:right].to_i)/ 2
232
+ x0 = @bounds.top_left.x if x0 < @bounds.top_left.x
233
+ x0 = @bounds.bottom_right.x if x0 > @bounds.bottom_right.x
175
234
  x1 = x0
176
235
  else
177
236
  if direction == :right
@@ -181,24 +240,32 @@ module TestaAppiumDriver
181
240
  x0 = @bounds.top_left.x + @deadzone[:left].to_i
182
241
  x1 = @bounds.bottom_right.x - @deadzone[:right].to_i
183
242
  end
184
- y0 = @bounds.height / 2
243
+
244
+ y0 = @bounds.top_left.y + (@bounds.height - @deadzone[:top].to_i - @deadzone[:bottom].to_i)/ 2
245
+ y0 = @bounds.top_left.y if y0 < @bounds.top_left.y
246
+ y0 = @bounds.bottom_right.y if y0 > @bounds.bottom_right.y
185
247
  y1 = y0
186
248
  end
187
249
  x1, y1 = apply_w3c_correction(x1, y1, direction) if @driver.device == :android
188
250
 
251
+ speed_coef = 1
252
+ if type == SCROLL_ACTION_TYPE_SCROLL
253
+ speed_coef = 1.5
254
+ end
189
255
 
190
- w3c_action(x0, y0, x1, y1, type)
256
+ w3c_action(x0, y0, x1, y1, type, speed_coef: speed_coef)
191
257
 
192
258
  end
193
259
 
194
260
 
195
- def w3c_action(x0, y0, x1, y1, type)
261
+ def w3c_action(x0, y0, x1, y1, type, speed_coef: 1.0)
262
+ speed_coef = 1/speed_coef
196
263
  if type == SCROLL_ACTION_TYPE_SCROLL
197
- duration = 1.8
264
+ duration = 1.8*speed_coef
198
265
  elsif type == SCROLL_ACTION_TYPE_FLING
199
- duration = 0.1
266
+ duration = 0.1*speed_coef
200
267
  elsif type == SCROLL_ACTION_TYPE_DRAG
201
- duration = 3.5
268
+ duration = 3.5*speed_coef
202
269
  else
203
270
  raise "Unknown scroll action type #{type}"
204
271
  end