testa_appium_driver 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|