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 +4 -4
- data/.gitignore +1 -1
- data/.idea/deployment.xml +1 -1
- data/.idea/runConfigurations.xml +10 -0
- data/README.md +18 -5
- data/lib/testa_appium_driver/android/class_selectors.rb +53 -18
- data/lib/testa_appium_driver/android/driver.rb +17 -0
- data/lib/testa_appium_driver/android/locator.rb +11 -0
- data/lib/testa_appium_driver/android/scroll_actions/uiautomator_scroll_actions.rb +0 -14
- data/lib/testa_appium_driver/common/constants.rb +1 -0
- data/lib/testa_appium_driver/common/helpers.rb +5 -1
- data/lib/testa_appium_driver/common/locator/scroll_actions.rb +16 -0
- data/lib/testa_appium_driver/common/locator.rb +76 -10
- data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +2 -32
- data/lib/testa_appium_driver/driver.rb +62 -15
- data/lib/testa_appium_driver/ios/driver.rb +13 -0
- data/lib/testa_appium_driver/ios/locator.rb +3 -1
- data/lib/testa_appium_driver/ios/type_selectors.rb +0 -13
- data/lib/testa_appium_driver/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dadb5244c71161bcdf995e9b057951ee4a5e979be496e65e828f7188baa85dc
|
4
|
+
data.tar.gz: bd5d23887285a260d5231525ad09d42f33219ac655432a74ba044b9b57805647
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 463e52be3a9a6764bbcbc068a46cb0cdc5f6ff41e0651cd95b9bc26da6b2210ba8c90f6651e8f6a153b76b0d173905a8d4a3a3d8b68055ea1e07653af3f4ecf1
|
7
|
+
data.tar.gz: 7b6ba6de823bbfcc993e712fe11f846cabd3e263b63a23ebfab5bc08c980eeee2c27c9ed0b85690505ed1441e137b3495661a65ecec81db1c6bd8d3755de6638
|
data/.gitignore
CHANGED
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
|
-
-
|
327
|
-
-
|
328
|
-
-
|
329
|
-
-
|
330
|
-
-
|
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[:
|
35
|
-
|
36
|
-
|
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
|
|
@@ -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
|
-
|
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 == "
|
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.
|
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
|
-
|
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
|
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.
|
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.
|
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
|
97
|
-
|
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
|
-
|
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
|
-
|
149
|
+
r
|
136
150
|
end
|
137
151
|
|
138
152
|
# disables implicit wait
|
139
153
|
def disable_implicit_wait
|
140
|
-
|
141
|
-
|
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"
|
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
|
-
|
154
|
-
@
|
155
|
-
|
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"
|
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
|
-
|
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"
|
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.
|
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-
|
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"
|