testa_appium_driver 0.1.6 → 0.1.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb79ce18b9e98f651e83630eff7efe2d71d77031231f88c04521e7d4f1baf483
4
- data.tar.gz: 94d1b8a88844c8726b1b87cd500ca07842b7b92190df7ef223f2cac4f929c9d9
3
+ metadata.gz: 2dadb5244c71161bcdf995e9b057951ee4a5e979be496e65e828f7188baa85dc
4
+ data.tar.gz: bd5d23887285a260d5231525ad09d42f33219ac655432a74ba044b9b57805647
5
5
  SHA512:
6
- metadata.gz: 9c2abf9c966c5e8d192c52e48226fcf0d73994315b3d865e48ce03f41aced48f3785dcaf7d46fd26b6e21fa51e0035cae6b00e416fffde3ae1ab0a5cf703b982
7
- data.tar.gz: e7e087b4b4227eb4d355df738f53d4ea72903b80fe51d3408c8c7ec6ac855a2066f40882dbae55de3418a1827895bcbefa14aa9b3322d767e22cd94393c1a67c
6
+ metadata.gz: 463e52be3a9a6764bbcbc068a46cb0cdc5f6ff41e0651cd95b9bc26da6b2210ba8c90f6651e8f6a153b76b0d173905a8d4a3a3d8b68055ea1e07653af3f4ecf1
7
+ data.tar.gz: 7b6ba6de823bbfcc993e712fe11f846cabd3e263b63a23ebfab5bc08c980eeee2c27c9ed0b85690505ed1441e137b3495661a65ecec81db1c6bd8d3755de6638
data/.gitignore CHANGED
@@ -13,4 +13,4 @@
13
13
  /.idea/deployment.xml
14
14
  /.idea/workspace.xml
15
15
  /.idea/misc.xml
16
- Gemfile.lock
16
+ Gemfile.lock
data/.idea/deployment.xml CHANGED
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <project version="4">
3
- <component name="PublishConfigData" autoUpload="On explicit save action" serverName="supertesta.com" autoUploadExternalChanges="true">
3
+ <component name="PublishConfigData" autoUpload="On explicit save action" serverName="supertesta.com" preserveTimestamps="false" autoUploadExternalChanges="true">
4
4
  <serverData>
5
5
  <paths name="supertesta.com">
6
6
  <serverdata>
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="RunConfigurationProducerService">
4
+ <option name="ignoredProducers">
5
+ <set>
6
+ <option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
7
+ </set>
8
+ </option>
9
+ </component>
10
+ </project>
data/README.md CHANGED
@@ -202,12 +202,18 @@ siblings selector can only be used with xpath strategy.
202
202
  - search_views
203
203
  - spinner
204
204
  - spinners
205
+ - switch
206
+ - switches
205
207
  - toast
206
208
  - toasts
207
209
  - toolbar
208
210
  - toolbars
209
211
  - text_view
210
212
  - text_views
213
+ - web_view
214
+ - web_views
215
+ - card_view
216
+ - card_views
211
217
 
212
218
  Adjacent selectors
213
219
  - from_parent
@@ -323,11 +329,15 @@ Type Selector arguments
323
329
 
324
330
  # Scroll actions
325
331
  - each
326
- - align!
327
- - align_top!
328
- - align_bottom!
329
- - align_left!
330
- - align_right!
332
+ - each_down
333
+ - each_up
334
+ - each_left
335
+ - each_right
336
+ - align! (if does not exist, will scroll to find)
337
+ - align_top! (if does not exist, will scroll to find)
338
+ - align_bottom! (if does not exist, will scroll to find)
339
+ - align_left! (if does not exist, will scroll to find)
340
+ - align_right! (if does not exist, will scroll to find)
331
341
  - align
332
342
  - align_top
333
343
  - align_bottom
@@ -355,6 +365,9 @@ Type Selector arguments
355
365
  - as_scrollable
356
366
  - wait_until_exists
357
367
  - wait_while_exists
368
+ - wait_until
369
+ - wait_while
370
+ - when_exists
358
371
  - exists?
359
372
  - long_tap
360
373
 
@@ -24,6 +24,9 @@ module TestaAppiumDriver
24
24
  # @param selectors [Hash]
25
25
  # @return [TestaAppiumDriver::Locator] first element
26
26
  def element(selectors = {})
27
+ unless selectors[:image].nil?
28
+ selectors[:strategy] = FIND_STRATEGY_IMAGE
29
+ end
27
30
  add_selector(selectors)
28
31
  end
29
32
 
@@ -31,24 +34,9 @@ module TestaAppiumDriver
31
34
  # @param params [Hash]
32
35
  # @return [TestaAppiumDriver::Locator] all elements that match given selectors
33
36
  def elements(params = {})
34
- params[:single] = false
35
- add_selector(params)
36
- end
37
-
38
-
39
- # first element that has scrollable: true
40
- # @param selectors [Hash]
41
- # @return [TestaAppiumDriver::Locator] first scrollable element
42
- def scrollable(selectors = {})
43
- selectors[:scrollable] = true
44
- add_selector(selectors)
45
- end
46
-
47
- # all elements that have scrollable: true
48
- # @param params [Hash]
49
- # @return [TestaAppiumDriver::Locator] first scrollable element
50
- def scrollables(params = {})
51
- params[:scrollable] = true
37
+ unless params[:image].nil?
38
+ params[:strategy] = FIND_STRATEGY_IMAGE
39
+ end
52
40
  params[:single] = false
53
41
  add_selector(params)
54
42
  end
@@ -399,5 +387,52 @@ module TestaAppiumDriver
399
387
  add_selector(params)
400
388
  end
401
389
 
390
+
391
+ # first androidx.cardview.widget.CardView element that match given selectors
392
+ # @return [TestaAppiumDriver::Locator]
393
+ def card_view(params = {})
394
+ params[:class] = "androidx.cardview.widget.CardView"
395
+ add_selector(params)
396
+ end
397
+
398
+ # all androidx.cardview.widget.CardView elements that match given selectors
399
+ # @return [TestaAppiumDriver::Locator]
400
+ def card_views(params = {})
401
+ params[:class] = "androidx.cardview.widget.CardView"
402
+ params[:single] = false
403
+ add_selector(params)
404
+ end
405
+
406
+ # first android.widget.Switch element that match given selectors
407
+ # @return [TestaAppiumDriver::Locator]
408
+ def switch(params = {})
409
+ params[:class] = "android.widget.Switch"
410
+ add_selector(params)
411
+ end
412
+
413
+ # all android.widget.Switch elements that match given selectors
414
+ # @return [TestaAppiumDriver::Locator]
415
+ def switches(params = {})
416
+ params[:class] = "android.widget.Switch"
417
+ params[:single] = false
418
+ add_selector(params)
419
+ end
420
+
421
+
422
+ # first android.webkit.WebView element that match given selectors
423
+ # @return [TestaAppiumDriver::Locator]
424
+ def web_view(params = {})
425
+ params[:class] = "android.webkit.WebView"
426
+ add_selector(params)
427
+ end
428
+
429
+ # all android.webkit.WebView elements that match given selectors
430
+ # @return [TestaAppiumDriver::Locator]
431
+ def web_views(params = {})
432
+ params[:class] = "android.webkit.WebView"
433
+ params[:single] = false
434
+ add_selector(params)
435
+ end
436
+
402
437
  end
403
438
  end
@@ -24,6 +24,23 @@ module TestaAppiumDriver
24
24
  end
25
25
 
26
26
 
27
+ def scrollable
28
+ locator = Locator.new(self, self, {single: true})
29
+ locator.xpath_selector = "//androidx.recyclerview.widget.RecyclerView|//android.widget.ScrollView|//android.widget.ListView|//android.widget.HorizontalScrollView"
30
+ locator.ui_selector = "new UiSelector().scrollable(true).instance(0)"
31
+ locator
32
+ end
33
+
34
+
35
+ def scrollables
36
+ locator = Locator.new(self, self, {single: false})
37
+ locator.xpath_selector = "//androidx.recyclerview.widget.RecyclerView|//android.widget.ScrollView|//android.widget.ListView|//android.widget.HorizontalScrollView"
38
+ locator.ui_selector = "new UiSelector().scrollable(true)"
39
+ locator
40
+ end
41
+
42
+
43
+
27
44
  private
28
45
  def handle_testa_opts
29
46
  if @testa_opts[:default_find_strategy].nil?
@@ -48,6 +48,10 @@ module TestaAppiumDriver
48
48
  if @strategy.nil? || @strategy == FIND_STRATEGY_XPATH
49
49
  ss.push({"#{FIND_STRATEGY_XPATH}": @xpath_selector})
50
50
  end
51
+
52
+ if @strategy == FIND_STRATEGY_IMAGE
53
+ ss.push({"#{FIND_STRATEGY_IMAGE}": @image_selector})
54
+ end
51
55
  ss
52
56
  end
53
57
 
@@ -93,6 +97,8 @@ module TestaAppiumDriver
93
97
  add_xpath_child_selectors(locator, selectors, single)
94
98
  elsif @strategy == FIND_STRATEGY_UIAUTOMATOR
95
99
  locator = add_uiautomator_child_selector(locator, selectors, single)
100
+ elsif @strategy == FIND_STRATEGY_IMAGE
101
+ locator = add_image_child_selector(locator, selectors, single)
96
102
  else
97
103
  # both paths are valid
98
104
  add_xpath_child_selectors(locator, selectors, single)
@@ -127,5 +133,10 @@ module TestaAppiumDriver
127
133
  locator
128
134
  end
129
135
  end
136
+
137
+ def add_image_child_selector(locator, selectors, single)
138
+ params = selectors.merge({single: single, scrollable_locator: locator.scrollable_locator})
139
+ Locator.new(@driver, self, params)
140
+ end
130
141
  end
131
142
  end
@@ -4,8 +4,6 @@ module TestaAppiumDriver
4
4
  private
5
5
 
6
6
  def uiautomator_scroll_to_start_or_end(type)
7
- @driver.disable_wait_for_idle
8
- @driver.disable_implicit_wait
9
7
 
10
8
  scrollable_selector = @scrollable.ui_selector(false)
11
9
  orientation = @scrollable.scroll_orientation == :vertical ? ".setAsVerticalList()" : ".setAsHorizontalList()"
@@ -19,18 +17,12 @@ module TestaAppiumDriver
19
17
  end
20
18
 
21
19
 
22
- @driver.enable_implicit_wait
23
- @driver.enable_wait_for_idle
24
20
  end
25
21
 
26
22
 
27
23
  def uiautomator_scroll_to
28
24
  raise "UiAutomator scroll cannot work with specified direction" unless @direction.nil?
29
25
 
30
-
31
- @driver.disable_wait_for_idle
32
- @driver.disable_implicit_wait
33
-
34
26
  scrollable_selector = @scrollable.ui_selector(false)
35
27
  element_selector = @locator.ui_selector(false)
36
28
  orientation_command = @scrollable.scroll_orientation == :vertical ? ".setAsVerticalList()" : ".setAsHorizontalList()"
@@ -41,15 +33,11 @@ module TestaAppiumDriver
41
33
  rescue
42
34
  # Ignored
43
35
  ensure
44
- @driver.enable_implicit_wait
45
- @driver.enable_wait_for_idle
46
36
  end
47
37
  end
48
38
 
49
39
 
50
40
  def uiautomator_page_or_fling(type, direction)
51
- @driver.disable_wait_for_idle
52
- @driver.disable_implicit_wait
53
41
 
54
42
  scrollable_selector = @scrollable.ui_selector(false)
55
43
  orientation = direction == :up || direction == :down ? ".setAsVerticalList()" : ".setAsHorizontalList()"
@@ -67,8 +55,6 @@ module TestaAppiumDriver
67
55
  rescue
68
56
  # Ignored
69
57
  end
70
- @driver.enable_implicit_wait
71
- @driver.enable_wait_for_idle
72
58
  end
73
59
 
74
60
 
@@ -6,6 +6,7 @@ module TestaAppiumDriver
6
6
  FIND_STRATEGY_XPATH = :xpath
7
7
  FIND_STRATEGY_ID = :id
8
8
  FIND_STRATEGY_NAME = :name
9
+ FIND_STRATEGY_IMAGE = :image
9
10
 
10
11
  SCROLL_STRATEGY_UIAUTOMATOR = :uiautomator
11
12
  SCROLL_STRATEGY_W3C = :w3c
@@ -120,7 +120,9 @@ module TestaAppiumDriver
120
120
  command = "#{ command }[@focused=\"#{ hash[:focused] }\"]" unless hash[:focused].nil?
121
121
  command = "#{ command }[@index=\"#{ hash[:index] }\"]" unless hash[:index].nil?
122
122
  command = "#{ command }[@selected=\"#{ hash[:selected] }\"]" unless hash[:selected].nil?
123
- command = "#{ command }[@scrollable=\"#{ hash[:scrollable] }\"]" unless hash[:scrollable].nil?
123
+
124
+ # it seems like you cannot query by scrollable
125
+ # command = "#{ command }[@scrollable=\"#{ hash[:scrollable] }\"]" unless hash[:scrollable].nil?
124
126
  else
125
127
 
126
128
  hash[:type] = hash[:class] unless hash[:class].nil?
@@ -205,6 +207,8 @@ module TestaAppiumDriver
205
207
  :visible,
206
208
  :name,
207
209
  :value,
210
+
211
+ :image
208
212
  ].include?(key) }
209
213
  params = Hash[params.to_a - selectors.to_a]
210
214
 
@@ -250,6 +250,22 @@ module TestaAppiumDriver
250
250
  _fling(:right, _process_deadzone(top, bottom, right, left))
251
251
  end
252
252
 
253
+ def drag_up_by(amount)
254
+ drag_by(amount, direction: :top)
255
+ end
256
+
257
+ def drag_down_by(amount)
258
+ drag_by(amount, direction: :bottom)
259
+ end
260
+
261
+ def drag_left_by(amount)
262
+ drag_by(amount, direction: :left)
263
+ end
264
+
265
+ def drag_right_by(amount)
266
+ drag_by(amount, direction: :right)
267
+ end
268
+
253
269
 
254
270
  # @param [TestaAppiumDriver::Locator, Hash, Selenium::WebDriver::Element, String] to
255
271
  #noinspection RubyYardParamTypeMatch,RubyScope
@@ -17,6 +17,8 @@ module TestaAppiumDriver
17
17
  attr_accessor :last_selector_adjacent
18
18
  attr_accessor :can_use_id_strategy
19
19
 
20
+ attr_accessor :image_selector
21
+
20
22
  attr_accessor :from_element
21
23
  attr_accessor :scroll_orientation
22
24
  attr_accessor :scroll_deadzone
@@ -41,12 +43,21 @@ module TestaAppiumDriver
41
43
  # @type [TestaAppiumDriver::Driver]
42
44
  @driver = driver
43
45
  @index_for_multiple = nil
46
+ @image_selector = nil
44
47
 
45
48
  params, selectors = extract_selectors_from_params(params)
46
49
  single = params[:single]
47
50
 
48
51
  @single = single
49
52
 
53
+ if selectors[:image].nil?
54
+ if from_element.instance_of?(TestaAppiumDriver::Locator) && !from_element.image_selector.nil?
55
+ raise "Cannot chain non-image selectors to image selectors"
56
+ end
57
+ else
58
+ handle_image_selector(selectors, params)
59
+ end
60
+
50
61
  selectors[:id] = selectors[:name] unless selectors[:name].nil?
51
62
  if from_element.instance_of?(Selenium::WebDriver::Element)
52
63
  @xpath_selector = "//*" # to select current element
@@ -80,6 +91,8 @@ module TestaAppiumDriver
80
91
  end
81
92
 
82
93
 
94
+
95
+
83
96
  def is_only_id_selector?(selectors)
84
97
  # since, name and id is the same thing for iOS,
85
98
  if @driver.device == :android
@@ -95,7 +108,6 @@ module TestaAppiumDriver
95
108
  def method_missing(method, *args, &block)
96
109
  r = execute.send(method, *args, &block)
97
110
  @driver.invalidate_cache
98
- r = r[@index_for_multiple] if !@index_for_multiple.nil? && !@single
99
111
  r
100
112
  end
101
113
 
@@ -103,14 +115,16 @@ module TestaAppiumDriver
103
115
  # @param [Boolean] skip_cache if true it will skip cache check and store
104
116
  # @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
105
117
  # @return [Selenium::WebDriver::Element, Array]
106
- def execute(skip_cache: false, force_cache_element: nil)
118
+ def execute(skip_cache: false, force_cache_element: nil, ignore_implicit_wait: false)
107
119
  return force_cache_element unless force_cache_element.nil?
108
120
  # if we are looking for current element, then return from_element
109
121
  # for example when we have driver.element.elements[1].click
110
122
  # elements[2] will be resolved with xpath because we are looking for multiple elements from element
111
123
  # and since we are looking for instance 2, [](instance) method will return new "empty locator"
112
124
  # we are executing click on that "empty locator" so we have to return the instance 2 of elements for the click
113
- if @xpath_selector == "//*/*[1]" && @from_element.instance_of?(Selenium::WebDriver::Element)
125
+ if @xpath_selector == "//*[1]" && !@from_element.nil? && @image_selector.nil?
126
+ return @from_element if @from_element.instance_of?(Selenium::WebDriver::Element)
127
+ 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)
114
128
  return @from_element
115
129
  end
116
130
 
@@ -119,11 +133,30 @@ module TestaAppiumDriver
119
133
 
120
134
 
121
135
 
122
- r = @driver.execute(@from_element, @single, strategies_and_selectors, skip_cache)
136
+ r = @driver.execute(@from_element, @single, strategies_and_selectors, skip_cache, ignore_implicit_wait)
123
137
  r = r[@index_for_multiple] if !@index_for_multiple.nil? && !@single
124
138
  r
125
139
  end
126
140
 
141
+ def when_exists(timeout = nil, &block)
142
+ timeout = @driver.get_timeouts["implicit"] / 1000 if timeout.nil?
143
+ found = false
144
+ begin
145
+ wait_until_exists(timeout)
146
+ found = true
147
+ rescue
148
+ #ignored
149
+ end
150
+ if found
151
+ if block_given? # block is given
152
+ block.call(self) # use call to execute the block
153
+ else # the value of block_argument becomes nil if you didn't give a block
154
+ # block was not given
155
+ end
156
+ end
157
+ self
158
+ end
159
+
127
160
 
128
161
  # @param [Integer] timeout in seconds
129
162
  # @return [TestaAppiumDriver::Locator]
@@ -157,16 +190,12 @@ module TestaAppiumDriver
157
190
  # all timeouts are disabled before check, and enabled after check
158
191
  # @return [boolean] true if it exists in the page regardless if visible or not
159
192
  def exists?
160
- @driver.disable_wait_for_idle
161
- @driver.disable_implicit_wait
162
193
  found = true
163
194
  begin
164
- execute(skip_cache: true)
195
+ execute(skip_cache: true, ignore_implicit_wait: true)
165
196
  rescue StandardError
166
197
  found = false
167
198
  end
168
- @driver.enable_implicit_wait
169
- @driver.enable_wait_for_idle
170
199
  found
171
200
  end
172
201
 
@@ -200,7 +229,8 @@ module TestaAppiumDriver
200
229
  locator.can_use_id_strategy = false
201
230
  locator
202
231
  else
203
- from_element = self.index_for_multiple = instance
232
+ from_element = self.dup
233
+ from_element.index_for_multiple = instance
204
234
  params = {}.merge({single: true, scrollable_locator: @scrollable_locator})
205
235
  #params[:strategy] = FIND_STRATEGY_XPATH
206
236
  #params[:strategy_reason] = "retrieved instance of a array"
@@ -482,6 +512,42 @@ module TestaAppiumDriver
482
512
  locator.single = false unless single # switching from single result to multiple
483
513
  locator.xpath_selector += hash_to_xpath(@driver.device, selectors, single)
484
514
  end
515
+
516
+
517
+ def handle_image_selector(selectors, params)
518
+ image_match_threshold = 0.4
519
+ image_match_threshold = params[:imageMatchThreshold] unless params[:imageMatchThreshold].nil?
520
+ image_match_threshold = params[:threshold] unless params[:threshold].nil?
521
+ fix_image_find_screenshot_dims = true
522
+ fix_image_find_screenshot_dims = params[:fixImageFindScreenshotDims] unless params[:fixImageFindScreenshotDims].nil?
523
+ fix_image_template_size = false
524
+ fix_image_template_size = params[:fixImageTemplateSize] unless params[:fixImageTemplateSize].nil?
525
+ fix_image_template_scale = false
526
+ fix_image_template_scale = params[:fixImageTemplateScale] unless params[:fixImageTemplateScale].nil?
527
+ default_image_template_scale = 1.0
528
+ default_image_template_scale = params[:defaultImageTemplateScale] unless params[:defaultImageTemplateScale].nil?
529
+ check_for_image_element_staleness = true
530
+ check_for_image_element_staleness = params[:checkForImageElementStaleness] unless params[:checkForImageElementStaleness].nil?
531
+ auto_update_image_element_position = false
532
+ auto_update_image_element_position = params[:autoUpdateImageElementPosition] unless params[:autoUpdateImageElementPosition].nil?
533
+ image_element_tap_strategy = "w3cActions"
534
+ image_element_tap_strategy = params[:imageElementTapStrategy] unless params[:imageElementTapStrategy].nil?
535
+ get_matched_image_result = false
536
+ get_matched_image_result = params[:getMatchedImageResult] unless params[:getMatchedImageResult].nil?
537
+
538
+ @image_selector = {
539
+ image: selectors[:image],
540
+ imageMatchThreshold: image_match_threshold,
541
+ fixImageFindScreenshotDims: fix_image_find_screenshot_dims,
542
+ fixImageTemplateSize: fix_image_template_size,
543
+ fixImageTemplateScale: fix_image_template_scale,
544
+ defaultImageTemplateScale: default_image_template_scale,
545
+ checkForImageElementStaleness: check_for_image_element_staleness,
546
+ autoUpdateImageElementPosition: auto_update_image_element_position,
547
+ imageElementTapStrategy: image_element_tap_strategy,
548
+ getMatchedImageResult: get_matched_image_result,
549
+ }
550
+ end
485
551
  end
486
552
 
487
553
  end
@@ -6,8 +6,6 @@ module TestaAppiumDriver
6
6
  def w3c_each(direction, &block)
7
7
  elements = []
8
8
  begin
9
- @driver.disable_wait_for_idle
10
- @driver.disable_implicit_wait
11
9
  default_deadzone!
12
10
 
13
11
  iterations = 0
@@ -38,15 +36,12 @@ module TestaAppiumDriver
38
36
  end
39
37
  rescue => e
40
38
  raise e
41
- ensure
42
- @driver.enable_implicit_wait
43
- @driver.enable_wait_for_idle
39
+
44
40
  end
45
41
  elements
46
42
  end
47
43
 
48
44
  def w3c_align(with, scroll_to_find)
49
- @driver.disable_wait_for_idle
50
45
  default_deadzone!
51
46
 
52
47
 
@@ -54,20 +49,6 @@ module TestaAppiumDriver
54
49
  @locator.scroll_to if scroll_to_find
55
50
 
56
51
  element = @locator.execute
57
- @driver.disable_implicit_wait
58
-
59
- case with
60
- when :top
61
- page_down if is_aligned?(with, element)
62
- when :bottom
63
- page_up if is_aligned?(with, element)
64
- when :right
65
- page_right if is_aligned?(with, element)
66
- when :left
67
- page_left if is_aligned?(with, element)
68
- else
69
- raise "Unsupported align with option: #{with}"
70
- end
71
52
 
72
53
  timeout = 0
73
54
  until is_aligned?(with, element) || timeout == 3
@@ -75,8 +56,6 @@ module TestaAppiumDriver
75
56
  timeout += 1
76
57
  end
77
58
 
78
- @driver.enable_implicit_wait
79
- @driver.enable_wait_for_idle
80
59
  end
81
60
 
82
61
 
@@ -150,8 +129,6 @@ module TestaAppiumDriver
150
129
  end
151
130
 
152
131
  def w3c_scroll_to_start_or_end(type)
153
- @driver.disable_wait_for_idle
154
- @driver.disable_implicit_wait
155
132
  default_deadzone!
156
133
 
157
134
  @previous_elements = nil
@@ -179,15 +156,10 @@ module TestaAppiumDriver
179
156
 
180
157
  # reset the flag for end of scroll elements
181
158
  @previous_elements = nil
182
-
183
- @driver.enable_implicit_wait
184
- @driver.enable_wait_for_idle
185
159
  end
186
160
 
187
161
 
188
162
  def w3c_page_or_fling(type, direction)
189
- @driver.disable_wait_for_idle
190
- @driver.disable_implicit_wait
191
163
  default_deadzone!
192
164
 
193
165
  if direction == :down || direction == :up
@@ -216,8 +188,6 @@ module TestaAppiumDriver
216
188
 
217
189
  w3c_action(x0, y0, x1, y1, type)
218
190
 
219
- @driver.enable_implicit_wait
220
- @driver.enable_wait_for_idle
221
191
  end
222
192
 
223
193
 
@@ -258,7 +228,7 @@ module TestaAppiumDriver
258
228
 
259
229
 
260
230
 
261
- def drag_to(x, y)
231
+ def w3c_drag_to(x, y)
262
232
  x0 = @bounds.center.x
263
233
  y0 = @bounds.center.y
264
234
  w3c_action(x0, y0, x, y, SCROLL_ACTION_TYPE_DRAG)
@@ -29,6 +29,8 @@ module TestaAppiumDriver
29
29
  def initialize(opts = {})
30
30
  @testa_opts = opts[:testa_appium_driver] || {}
31
31
 
32
+ @wait_for_idle_disabled = false
33
+ @implicit_wait_disabled = false
32
34
 
33
35
  core = Appium::Core.for(opts)
34
36
  extend_for(core.device, core.automation_name)
@@ -67,7 +69,7 @@ module TestaAppiumDriver
67
69
  # @param [Array<Hash>] strategies_and_selectors array of usable strategies and selectors
68
70
  # @param [Boolean] skip_cache to skip checking and storing cache
69
71
  # @return [Selenium::WebDriver::Element, Array] element is returned if single is true, array otherwise
70
- def execute(from_element, single, strategies_and_selectors, skip_cache = false)
72
+ def execute(from_element, single, strategies_and_selectors, skip_cache = false, ignore_implicit_wait = false)
71
73
 
72
74
  # if user wants to wait for element to exist, he can use wait_until_present
73
75
  disable_wait_for_idle
@@ -79,13 +81,13 @@ module TestaAppiumDriver
79
81
 
80
82
 
81
83
  # resolve from_element unique id, so that we can cache it properly
82
- from_element_id = from_element.kind_of?(TestaAppiumDriver::Locator) ? from_element.strategy_and_selector[1] : nil
84
+ from_element_id = from_element.instance_of?(TestaAppiumDriver::Locator) ? from_element.strategies_and_selectors : nil
83
85
 
84
86
  begin
85
87
  ss = strategies_and_selectors[ss_index % strategies_and_selectors.count]
86
88
  ss_index +=1
87
89
 
88
- puts "Executing #{from_element_id ? "from #{from_element.strategy}: #{from_element.strategy_and_selector} => " : ""}#{ss.keys[0]}: #{ss.values[0]}"
90
+ puts "Executing #{from_element_id ? "from #{from_element.strategy}: #{from_element.strategies_and_selectors} => " : ""}#{ss.keys[0]}: #{ss.values[0]}"
89
91
 
90
92
  if @cache[:selector] != ss.values[0] || # cache miss, selector is different
91
93
  @cache[:time] + 5 <= Time.now || # cache miss, older than 5 seconds
@@ -93,13 +95,24 @@ module TestaAppiumDriver
93
95
  @cache[:from_element_id] != from_element_id || # cache miss, search is started from different element
94
96
  skip_cache # cache is skipped
95
97
 
96
- if single
97
- execute_result = from_element.find_element(ss)
98
+ if ss.keys[0] == FIND_STRATEGY_IMAGE
99
+ set_find_by_image_settings(ss.values[0].dup)
100
+ if single
101
+ execute_result = from_element.find_element_by_image(ss.values[0][:image])
102
+ else
103
+ execute_result = from_element.find_elements_by_image(ss.values[0][:image])
104
+ end
105
+ restore_set_by_image_settings
98
106
  else
99
- execute_result = from_element.find_elements(ss)
107
+ if single
108
+ execute_result = from_element.find_element(ss)
109
+ else
110
+ execute_result = from_element.find_elements(ss)
111
+ end
100
112
  end
101
113
 
102
114
 
115
+
103
116
  unless skip_cache
104
117
  @cache[:selector] = ss.values[0]
105
118
  @cache[:strategy] = ss.keys[0]
@@ -113,7 +126,7 @@ module TestaAppiumDriver
113
126
  puts "Using cache from #{@cache[:time].strftime("%H:%M:%S.%L")}, strategy: #{@cache[:strategy]}"
114
127
  end
115
128
  rescue => e
116
- if start_time + @implicit_wait_ms/1000 < Time.now.to_f || ss_index < strategies_and_selectors.count
129
+ if (start_time + @implicit_wait_ms/1000 < Time.now.to_f && !ignore_implicit_wait) || ss_index < strategies_and_selectors.count
117
130
  sleep EXISTS_WAIT if ss_index >= strategies_and_selectors.count
118
131
  retry
119
132
  else
@@ -131,39 +144,71 @@ module TestaAppiumDriver
131
144
  # method missing is used to forward methods to the actual appium driver
132
145
  # after the method is executed, find element cache is invalidated
133
146
  def method_missing(method, *args, &block)
147
+ r = @driver.send(method, *args, &block)
134
148
  invalidate_cache
135
- @driver.send(method, *args, &block)
149
+ r
136
150
  end
137
151
 
138
152
  # disables implicit wait
139
153
  def disable_implicit_wait
140
- @implicit_wait_ms = @driver.get_timeouts["implicit"]
141
- @driver.manage.timeouts.implicit_wait = 0
154
+ unless @implicit_wait_disabled
155
+ @implicit_wait_ms = @driver.get_timeouts["implicit"]
156
+ @implicit_wait_uiautomator_ms = @driver.get_settings["waitForSelectorTimeout"]
157
+ @driver.manage.timeouts.implicit_wait = 0
158
+ @driver.update_settings({waitForSelectorTimeout: 0})
159
+ @implicit_wait_disabled = true
160
+ end
142
161
  end
143
162
 
144
163
  # enables implicit wait, can be called only after disabling implicit wait
145
164
  def enable_implicit_wait
146
- raise "Implicit wait is not disabled" if @implicit_wait_ms.nil?
165
+ raise "Implicit wait is not disabled" unless @implicit_wait_disabled
147
166
  # get_timeouts always returns in milliseconds, but we should set in seconds
148
167
  @driver.manage.timeouts.implicit_wait = @implicit_wait_ms / 1000
168
+ @driver.update_settings({waitForSelectorTimeout: @implicit_wait_uiautomator_ms})
169
+ @implicit_wait_disabled = false
149
170
  end
150
171
 
151
172
  # disables wait for idle, only executed for android devices
152
173
  def disable_wait_for_idle
153
- if @device == :android
154
- @wait_for_idle_timeout = @driver.settings.get["waitForIdleTimeout"]
155
- @driver.update_settings({waitForIdleTimeout: 0})
174
+ unless @wait_for_idle_disabled
175
+ if @device == :android
176
+ @wait_for_idle_timeout = @driver.settings.get["waitForIdleTimeout"]
177
+ @driver.update_settings({waitForIdleTimeout: 0})
178
+ end
179
+ @wait_for_idle_disabled = true
156
180
  end
157
181
  end
158
182
 
159
183
  # enables wait for idle, only executed for android devices
160
184
  def enable_wait_for_idle
161
185
  if @device == :android
162
- raise "Wait for idle is not disabled" if @wait_for_idle_timeout.nil?
186
+ raise "Wait for idle is not disabled" unless @wait_for_idle_disabled
163
187
  @driver.update_settings({waitForIdleTimeout: @wait_for_idle_timeout})
164
188
  end
165
189
  end
166
190
 
191
+ def set_find_by_image_settings(settings)
192
+ settings.delete(:image)
193
+ @default_find_image_settings = {}
194
+ old_settings = @driver.get_settings
195
+ @default_find_image_settings[:imageMatchThreshold] = old_settings["imageMatchThreshold"]
196
+ @default_find_image_settings[:fixImageFindScreenshotDims] = old_settings["fixImageFindScreenshotDims"]
197
+ @default_find_image_settings[:fixImageTemplateSize] = old_settings["fixImageTemplateSize"]
198
+ @default_find_image_settings[:fixImageTemplateScale] = old_settings["fixImageTemplateScale"]
199
+ @default_find_image_settings[:defaultImageTemplateScale] = old_settings["defaultImageTemplateScale"]
200
+ @default_find_image_settings[:checkForImageElementStaleness] = old_settings["checkForImageElementStaleness"]
201
+ @default_find_image_settings[:autoUpdateImageElementPosition] = old_settings["autoUpdateImageElementPosition"]
202
+ @default_find_image_settings[:imageElementTapStrategy] = old_settings["imageElementTapStrategy"]
203
+ @default_find_image_settings[:getMatchedImageResult] = old_settings["getMatchedImageResult"]
204
+
205
+ @driver.update_settings(settings)
206
+ end
207
+
208
+ def restore_set_by_image_settings
209
+ @driver.update_settings(@default_find_image_settings) if @default_find_image_settings
210
+ end
211
+
167
212
 
168
213
  # @@return [String] current package under test
169
214
  def current_package
@@ -197,6 +242,8 @@ module TestaAppiumDriver
197
242
  end
198
243
 
199
244
 
245
+
246
+
200
247
  # @return [Array<Selenium::WebDriver::Element] array of 2 elements, the first element without children and the last element without children in the current page
201
248
  def first_and_last_leaf(from_element = @driver)
202
249
  disable_wait_for_idle
@@ -7,6 +7,19 @@ module TestaAppiumDriver
7
7
  include TypeSelectors
8
8
 
9
9
 
10
+
11
+ # @param params [Hash]
12
+ # @return [TestaAppiumDriver::Locator] first scrollable element
13
+ def scrollable(params = {})
14
+ scroll_view(params)
15
+ end
16
+
17
+ # @param params [Hash]
18
+ # @return [TestaAppiumDriver::Locator] first scrollable element
19
+ def scrollables(params = {})
20
+ scroll_views(params)
21
+ end
22
+
10
23
  private
11
24
  def handle_testa_opts
12
25
  if @testa_opts[:default_find_strategy].nil?
@@ -29,7 +29,9 @@ module TestaAppiumDriver
29
29
  if @can_use_id_strategy
30
30
  ss.push({"#{FIND_STRATEGY_NAME}": @can_use_id_strategy})
31
31
  end
32
- ss.push({"#{FIND_STRATEGY_XPATH}": @xpath_selector})
32
+
33
+ ss.push({"#{FIND_STRATEGY_XPATH}": @xpath_selector}) if @strategy.nil? || @strategy == FIND_STRATEGY_XPATH
34
+ ss.push({"#{FIND_STRATEGY_IMAGE}": @image_selector}) if @strategy == FIND_STRATEGY_IMAGE
33
35
  ss
34
36
  end
35
37
 
@@ -111,19 +111,6 @@ module TestaAppiumDriver
111
111
  end
112
112
 
113
113
 
114
- # @param params [Hash]
115
- # @return [TestaAppiumDriver::Locator] first scrollable element
116
- def scrollable(params = {})
117
- scroll_view(params)
118
- end
119
-
120
- # @param params [Hash]
121
- # @return [TestaAppiumDriver::Locator] first scrollable element
122
- def scrollables(params = {})
123
- scroll_views(params)
124
- end
125
-
126
-
127
114
  # @return [TestaAppiumDriver::Locator]
128
115
  def scroll_view(params = {})
129
116
  params[:type] = "XCUIElementTypeScrollView"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TestaAppiumDriver
4
- VERSION = "0.1.6"
4
+ VERSION = "0.1.7"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: testa_appium_driver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - karlo.razumovic
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-03 00:00:00.000000000 Z
11
+ date: 2021-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appium_lib_core
@@ -80,6 +80,7 @@ files:
80
80
  - ".idea/inspectionProfiles/Project_Default.xml"
81
81
  - ".idea/misc.xml"
82
82
  - ".idea/modules.xml"
83
+ - ".idea/runConfigurations.xml"
83
84
  - ".idea/runConfigurations/Android_Test.xml"
84
85
  - ".idea/sshConfigs.xml"
85
86
  - ".idea/vcs.xml"