testa_appium_driver 0.1.13 → 0.1.14

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 +0 -2
  4. data/.rubocop.yml +1 -1
  5. data/Gemfile +1 -1
  6. data/Gemfile.lock +74 -0
  7. data/appium-driver.iml +72 -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 +42 -25
  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 +26 -19
  19. data/lib/testa_appium_driver/common/selenium_element.rb +2 -2
  20. data/lib/testa_appium_driver/driver.rb +33 -19
  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 +2 -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 +1 -1
  27. metadata +7 -14
  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
@@ -6,6 +6,7 @@ module TestaAppiumDriver
6
6
  class Locator
7
7
  include Helpers
8
8
 
9
+
9
10
  attr_accessor :xpath_selector
10
11
  attr_accessor :single
11
12
 
@@ -59,9 +60,9 @@ module TestaAppiumDriver
59
60
  end
60
61
 
61
62
  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]
63
+ if from_element.instance_of?(::Selenium::WebDriver::Element) || from_element.instance_of?(::Appium::Core::Element) || from_element.instance_of?(::TestaAppiumDriver::Locator)
64
+ @xpath_selector = "."
65
+ @xpath_selector += hash_to_xpath(@driver.device, selectors, single)
65
66
  else
66
67
  @xpath_selector = hash_to_xpath(@driver.device, selectors, single)
67
68
  end
@@ -122,8 +123,8 @@ module TestaAppiumDriver
122
123
  # elements[2] will be resolved with xpath because we are looking for multiple elements from element
123
124
  # and since we are looking for instance 2, [](instance) method will return new "empty locator"
124
125
  # 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)
126
+ if @xpath_selector == ".//*[1]" && !@from_element.nil? && @image_selector.nil?
127
+ return @from_element if @from_element.instance_of?(::Selenium::WebDriver::Element) || @from_element.instance_of?(::Appium::Core::Element)
127
128
  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
129
  return @from_element
129
130
  end
@@ -302,38 +303,44 @@ module TestaAppiumDriver
302
303
  @driver.first_and_last_leaf(execute)
303
304
  end
304
305
 
305
-
306
- def tap(x = nil, y = nil)
307
- click(x, y)
306
+ def double_click(x = nil, y = nil)
307
+ click(x,y, double: true)
308
308
  end
309
309
 
310
+
311
+
310
312
  # if both x or y, or both are not given, will click in the center of the element
311
313
  # @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
314
  # @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?
315
+ def click(x = nil, y = nil, double: false)
316
+ if !x.nil? && !y.nil? || double
317
+
318
+ x=0.5 if x.nil?
319
+ y=0.5 if y.nil?
315
320
 
316
321
  b = self.bounds
317
- if x.kind_of? Integer
322
+ if x.kind_of?(Integer)
318
323
  if x >= 0
319
324
  x = b.top_left.x + x
320
325
  else
321
326
  x = b.bottom_right.x + x
322
327
  end
323
- elsif x.kind_of? Float
328
+ elsif x.kind_of?(Float) && x <= 1.0 && x >= 0
324
329
  x = b.top_left.x + b.width*x
325
330
  else
326
- raise "x value #{x} not supported"
331
+ raise "x value #{x} not supported. Use integer as pixel or float (0..1) as percentage of element width"
327
332
  end
328
333
 
329
- if y.kind_of? Integer
334
+ if y.kind_of?(Integer)
330
335
  if y >= 0
331
- y = b.bottom_right.y + y
336
+ y = b.top_left.y + y
332
337
  else
333
- y = b.top_left + y
338
+ y = b.bottom_right + y
334
339
  end
335
- elsif y.kind_of? Float
336
- y = b.bottom_right.y + b.height*y
340
+ elsif y.kind_of?(Float) && y <= 1.0 && y >= 0
341
+ y = b.top_left.y + b.height*y
342
+ else
343
+ raise "y value #{x} not supported. Use integer as pixel or float (0..1) as percentage of element height"
337
344
  end
338
345
 
339
346
  action_builder = @driver.action
@@ -341,6 +348,11 @@ module TestaAppiumDriver
341
348
  f1.create_pointer_move(duration: 0, x: x, y: y, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
342
349
  f1.create_pointer_down(:left)
343
350
  f1.create_pointer_up(:left)
351
+ if double
352
+ f1.create_pause(0.1)
353
+ f1.create_pointer_down(:left)
354
+ f1.create_pointer_up(:left)
355
+ end
344
356
  @driver.perform_actions [f1]
345
357
  else
346
358
  if @driver.device == :android
@@ -355,6 +367,11 @@ module TestaAppiumDriver
355
367
  end
356
368
  end
357
369
 
370
+
371
+ alias_method :tap, :click
372
+ alias_method :double_tap, :double_click
373
+
374
+
358
375
  def send_key(*args)
359
376
  perform_driver_method(:send_keys, *args)
360
377
  end
@@ -368,7 +385,7 @@ module TestaAppiumDriver
368
385
  # @return [TestaAppiumDriver::Locator]
369
386
  def parent
370
387
  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?
388
+ raise "Cannot add parent selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
372
389
 
373
390
  locator = self.dup
374
391
  locator.strategy = FIND_STRATEGY_XPATH
@@ -426,7 +443,7 @@ module TestaAppiumDriver
426
443
  def siblings
427
444
  raise "Cannot add siblings selector to array" unless @single
428
445
  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?
446
+ raise "Cannot add siblings selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
430
447
 
431
448
  locator = self.dup
432
449
  locator.strategy = FIND_STRATEGY_XPATH
@@ -442,7 +459,7 @@ module TestaAppiumDriver
442
459
  def preceding_siblings
443
460
  raise "Cannot add preceding_siblings selector to array" unless @single
444
461
  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?
462
+ raise "Cannot add preceding_siblings selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
446
463
 
447
464
  locator = self.dup
448
465
  locator.strategy = FIND_STRATEGY_XPATH
@@ -458,7 +475,7 @@ module TestaAppiumDriver
458
475
  def preceding_sibling
459
476
  raise "Cannot add preceding_sibling selector to array" unless @single
460
477
  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?
478
+ raise "Cannot add preceding siblings selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
462
479
 
463
480
  locator = self.dup
464
481
  locator.strategy = FIND_STRATEGY_XPATH
@@ -477,7 +494,7 @@ module TestaAppiumDriver
477
494
  def following_siblings
478
495
  raise "Cannot add following_siblings selector to array" unless @single
479
496
  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?
497
+ raise "Cannot add following_siblings selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
481
498
 
482
499
  locator = self.dup
483
500
  locator.strategy = FIND_STRATEGY_XPATH
@@ -493,7 +510,7 @@ module TestaAppiumDriver
493
510
  def following_sibling
494
511
  raise "Cannot add following_sibling selector to array" unless @single
495
512
  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?
513
+ raise "Cannot add following_sibling selector to a retrieved instance of a class array" if (@xpath_selector == ".//*" || @xpath_selector == ".//*[1]") && !@from_element.nil?
497
514
 
498
515
  locator = self.dup
499
516
  locator.strategy = FIND_STRATEGY_XPATH
@@ -548,7 +565,7 @@ module TestaAppiumDriver
548
565
  def _attributes_match(attributes)
549
566
  all_match = true
550
567
  attributes.each do |key, value|
551
- unless attribute(key) == value
568
+ unless testa_attribute(key) == value
552
569
  all_match = false
553
570
  break
554
571
  end
@@ -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
+
87
+
37
88
  end
38
89
  rescue => e
39
90
  raise e
40
-
41
91
  end
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
@@ -5,6 +5,10 @@ module TestaAppiumDriver
5
5
 
6
6
  # Class for handling scroll actions
7
7
  class ScrollActions
8
+ include W3cScrollActions
9
+ include JsonWireScrollActions
10
+
11
+ attr_accessor :locator
8
12
  # @param [TestaAppiumDriver::Locator, nil] scrollable container that will be used to determine the bounds for scrolling
9
13
  # @param [Hash] params
10
14
  # acceptable params
@@ -15,6 +19,7 @@ module TestaAppiumDriver
15
19
  def initialize(scrollable, params = {})
16
20
  @scrollable = scrollable
17
21
  @locator = params[:locator]
22
+ # TODO: raise error if locator is for multiple, but not for scroll each, chekc other cases aswell
18
23
  @deadzone = params[:deadzone]
19
24
  @max_scrolls = params[:max_scrolls]
20
25
  @default_scroll_strategy = params[:default_scroll_strategy]
@@ -36,8 +41,8 @@ module TestaAppiumDriver
36
41
  @bounds = @scrollable.bounds
37
42
  end
38
43
 
39
- def align(with, scroll_to_find)
40
- w3c_align(with, scroll_to_find)
44
+ def align(with, scroll_to_find, max_attempts)
45
+ w3c_align(with, scroll_to_find, max_attempts)
41
46
  @locator
42
47
  end
43
48
 
@@ -195,7 +200,25 @@ module TestaAppiumDriver
195
200
  w3c_drag_to(x0, y0, x1, y1)
196
201
  end
197
202
 
198
- private
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
+
199
222
 
200
223
  def is_end_of_scroll?
201
224
  old_elements = @previous_elements
@@ -227,21 +250,5 @@ module TestaAppiumDriver
227
250
  end
228
251
  end
229
252
 
230
- def is_aligned?(with, element)
231
- align_bounds = @locator.bounds(force_cache_element: element)
232
- case with
233
- when :top
234
- @align_offset = align_bounds.top_left.y - @bounds.top_left.y + @deadzone[:top]
235
- when :bottom
236
- @align_offset = @bounds.bottom_right.y - @deadzone[:bottom] - align_bounds.bottom_right.y
237
- when :right
238
- @align_offset = @bounds.bottom_right.x - @deadzone[:right] - align_bounds.bottom_right.x
239
- when :left
240
- @align_offset = align_bounds.top_left.x - @bounds.top_left.x + @deadzone[:left]
241
- else
242
- raise "Unsupported align with option: #{with}"
243
- end
244
- @align_offset < SCROLL_ALIGNMENT_THRESHOLD
245
- end
246
253
  end
247
254
  end
@@ -1,5 +1,5 @@
1
- module Selenium
2
- module WebDriver
1
+ module ::Appium
2
+ module Core
3
3
  class Element
4
4
  # sets the testa appium driver instance for the current phone
5
5
  def self.set_driver(driver, udid)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'em/pure_ruby'
3
+ #require 'em/pure_ruby'
4
4
  require 'appium_lib_core'
5
5
 
6
6
  require_relative 'common/bounds'
@@ -27,25 +27,24 @@ module TestaAppiumDriver
27
27
  # - default_find_strategy: default strategy to be used for finding elements. Available strategies :uiautomator or :xpath
28
28
  # - default_scroll_strategy: default strategy to be used for scrolling. Available strategies: :uiautomator(android only), :w3c
29
29
  def initialize(opts = {})
30
- opts[:shouldEnforceXpath1] = false
31
30
 
32
31
  @testa_opts = opts[:testa_appium_driver] || {}
33
32
 
34
33
  core = Appium::Core.for(opts)
35
- extend_for(core.device, core.automation_name)
36
- @device = core.device
37
- @automation_name = core.automation_name
34
+ @driver = core.start_driver
35
+ @automation_name = @driver.capabilities["automationName"].downcase.to_sym
36
+ @device = @driver.capabilities.platform_name.downcase.to_sym
37
+
38
+ extend_for(@device, @automation_name)
38
39
 
39
40
  handle_testa_opts
40
41
 
41
- @driver = core.start_driver
42
42
  invalidate_cache
43
43
 
44
+ #disable_wait_for_idle
45
+ #disable_implicit_wait
44
46
 
45
- disable_wait_for_idle
46
- disable_implicit_wait
47
-
48
- Selenium::WebDriver::Element.set_driver(self, opts[:caps][:udid])
47
+ ::Appium::Core::Element.set_driver(self, @driver.capabilities["udid"])
49
48
  end
50
49
 
51
50
 
@@ -84,7 +83,11 @@ module TestaAppiumDriver
84
83
  from_element_id = from_element.instance_of?(TestaAppiumDriver::Locator) ? from_element.strategies_and_selectors : nil
85
84
 
86
85
  begin
86
+ begin
87
87
  ss = strategies_and_selectors[ss_index % strategies_and_selectors.count]
88
+ rescue ZeroDivisionError
89
+ puts "aa"
90
+ end
88
91
  ss_index +=1
89
92
 
90
93
  puts "Executing #{from_element_id ? "from #{from_element.strategy}: #{from_element.strategies_and_selectors} => " : ""}#{ss.keys[0]}: #{ss.values[0]}"
@@ -153,7 +156,7 @@ module TestaAppiumDriver
153
156
  @implicit_wait_ms = @implicit_wait_ms/1000 if @implicit_wait_ms > 100000
154
157
  @implicit_wait_uiautomator_ms = @driver.get_settings["waitForSelectorTimeout"]
155
158
  @driver.manage.timeouts.implicit_wait = 0
156
- @driver.update_settings({waitForSelectorTimeout: 1})
159
+ @driver.update_settings({waitForSelectorTimeout: 0})
157
160
  end
158
161
 
159
162
 
@@ -246,26 +249,28 @@ module TestaAppiumDriver
246
249
  @driver.long_press_keycode(code)
247
250
  end
248
251
 
249
- def click(x, y)
252
+ def click(x, y, double: false)
250
253
  ws = driver.window_size
251
254
  window_width = ws.width.to_i
252
255
  window_height = ws.height.to_i
253
- if x.kind_of? Integer
256
+ if x.kind_of?(Integer)
254
257
  if x < 0
255
258
  x = window_width + x
256
259
  end
257
- elsif x.kind_of? Float
260
+ elsif x.kind_of?(Float) && x <= 1.0 && x >= 0
258
261
  x = window_width*x
259
262
  else
260
- raise "x value #{x} not supported"
263
+ raise "x value #{x} not supported. Use integer as pixel or float (0..1) as percentage of screen"
261
264
  end
262
265
 
263
- if y.kind_of? Integer
266
+ if y.kind_of?(Integer)
264
267
  if y < 0
265
268
  y = window_height + y
266
269
  end
267
- elsif y.kind_of? Float
270
+ elsif y.kind_of?(Float) && y <= 1.0 && y >= 0
268
271
  y = window_height*y
272
+ else
273
+ raise "y value #{x} not supported. Use integer as pixel or float (0..1) as percentage of screen"
269
274
  end
270
275
 
271
276
 
@@ -274,14 +279,23 @@ module TestaAppiumDriver
274
279
  f1.create_pointer_move(duration: 0, x: x, y: y, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
275
280
  f1.create_pointer_down(:left)
276
281
  f1.create_pointer_up(:left)
282
+ if double
283
+ f1.create_pause(0.1)
284
+ f1.create_pointer_down(:left)
285
+ f1.create_pointer_up(:left)
286
+ end
277
287
  @driver.perform_actions [f1]
278
288
  end
279
289
 
290
+ def double_click(x,y)
291
+ click(x,y, double: true)
292
+ end
293
+
280
294
 
281
295
 
282
296
  # @return [Array<Selenium::WebDriver::Element] array of 2 elements, the first element without children and the last element without children in the current page
283
297
  def first_and_last_leaf(from_element = @driver)
284
- elements = from_element.find_elements(xpath: "//*[not(*)]")
298
+ elements = from_element.find_elements(xpath: ".//*[not(*)]")
285
299
  return nil if elements.count == 0
286
300
  [elements[0], elements[-1]]
287
301
  end
@@ -291,7 +305,7 @@ module TestaAppiumDriver
291
305
  case device
292
306
  when :android
293
307
  case automation_name
294
- when :uiautomator2
308
+ when :uiautomator2, :espresso, :Espresso
295
309
  require_relative 'android/driver'
296
310
  else
297
311
  raise "Testa appium driver not supported for #{automation_name} automation"
@@ -2,10 +2,17 @@ module TestaAppiumDriver
2
2
  module Attributes
3
3
 
4
4
  #noinspection RubyNilAnalysis
5
- def attribute(name, *args)
6
- elements = execute(*args)
5
+ def testa_attribute(name, *args)
7
6
 
8
- if elements.instance_of?(Selenium::WebDriver::Element)
7
+ if self.instance_of?(::Selenium::WebDriver::Element) || self.instance_of?(::Appium::Core::Element)
8
+ @driver = get_driver
9
+ elements = self
10
+ else
11
+ elements = execute(*args)
12
+ end
13
+
14
+
15
+ if elements.instance_of?(::Selenium::WebDriver::Element) || elements.instance_of?(::Appium::Core::Element)
9
16
  r = elements.send(:attribute, name.to_s)
10
17
  r = TestaAppiumDriver::Bounds.from_ios(r, @driver) if name.to_s == "rect"
11
18
  else
@@ -17,65 +24,62 @@ module TestaAppiumDriver
17
24
 
18
25
 
19
26
  def accessibility_container(*args)
20
- attribute("accessibilityContainer", *args)
27
+ testa_attribute("accessibilityContainer", *args)
21
28
  end
22
29
 
23
30
  def accessible?(*args)
24
- attribute("accessible", *args).to_s == "true"
31
+ testa_attribute("accessible", *args).to_s == "true"
25
32
  end
26
33
 
27
34
 
28
35
  def class_name(*args)
29
- attribute("class", *args)
36
+ testa_attribute("class", *args)
30
37
  end
31
38
 
32
39
  def enabled?(*args)
33
- attribute("enabled", *args).to_s == "true"
40
+ testa_attribute("enabled", *args).to_s == "true"
34
41
  end
35
42
 
36
43
  def frame(*args)
37
- attribute("frame", *args)
44
+ testa_attribute("frame", *args)
38
45
  end
39
46
 
40
47
  def index(*args)
41
- attribute("index", *args)
48
+ testa_attribute("index", *args)
42
49
  end
43
50
 
44
51
  def label(*args)
45
- attribute("label", *args)
52
+ testa_attribute("label", *args)
46
53
  end
47
54
 
48
55
  def name(*args)
49
- attribute("name", *args)
56
+ testa_attribute("name", *args)
50
57
  end
51
58
 
52
59
 
53
60
  def rect(*args)
54
- attribute("rect", *args)
61
+ testa_attribute("rect", *args)
55
62
  end
56
63
 
57
64
  def selected?(*args)
58
- attribute("selected", *args).to_s == "true"
65
+ testa_attribute("selected", *args).to_s == "true"
59
66
  end
60
67
 
61
68
  def type(*args)
62
- attribute("type", *args)
69
+ testa_attribute("type", *args)
63
70
  end
64
71
 
65
72
  def value(*args)
66
- attribute("value", *args)
73
+ testa_attribute("value", *args)
67
74
  end
68
75
 
69
76
  def visible?(*args)
70
- attribute("visible", *args).to_s == "true"
77
+ testa_attribute("visible", *args).to_s == "true"
71
78
  end
72
79
 
73
80
 
74
81
  alias_method :bounds, :rect
75
82
  alias_method :text, :label
76
83
  end
77
- #noinspection RubyYardReturnMatch
78
- class Locator
79
- include TestaAppiumDriver::Attributes
80
- end
84
+
81
85
  end