testa_appium_driver 0.1.7 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.idea/deployment.xml +1 -1
- data/lib/testa_appium_driver/android/locator/attributes.rb +1 -3
- data/lib/testa_appium_driver/android/locator.rb +1 -1
- data/lib/testa_appium_driver/android/scroll_actions/uiautomator_scroll_actions.rb +0 -1
- data/lib/testa_appium_driver/common/constants.rb +1 -0
- data/lib/testa_appium_driver/common/helpers.rb +27 -0
- data/lib/testa_appium_driver/common/locator/scroll_actions.rb +5 -4
- data/lib/testa_appium_driver/common/locator.rb +74 -16
- data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +3 -4
- data/lib/testa_appium_driver/common/scroll_actions.rb +5 -14
- data/lib/testa_appium_driver/driver.rb +69 -40
- data/lib/testa_appium_driver/ios/locator.rb +16 -2
- data/lib/testa_appium_driver/ios/type_selectors.rb +36 -2
- data/lib/testa_appium_driver/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c55e4e3d29193b3bc89ea292de2c36d093897208050494204da865ea4902d6c
|
4
|
+
data.tar.gz: 35014def9a47f5fcfb1242cd1c897a4c13add7f1e9359b66170c2057aa450e3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3562a893791f45303d3cf4cbb3d2b1d1510122ae296e9fb257ce25bd83a9388efacd69ebc9e149219fc5a02fc42f80a9c05f0be72241909b6cd142abfec48e8b
|
7
|
+
data.tar.gz: 741a8b9d2b1683484e0100d01c53966d63f9eeacb19ca188589e32b62990ee1cc822d8306e6e23baf34f93ac0a34b929ce5342fdbe1d4a80f3be0e87acf7d28c
|
data/.idea/deployment.xml
CHANGED
@@ -7,7 +7,6 @@ module TestaAppiumDriver
|
|
7
7
|
|
8
8
|
@driver = get_driver if self.instance_of?(Selenium::WebDriver::Element)
|
9
9
|
|
10
|
-
@driver.disable_wait_for_idle
|
11
10
|
if elements.kind_of?(Selenium::WebDriver::Element)
|
12
11
|
r = elements.send(:attribute, name.to_s)
|
13
12
|
r = TestaAppiumDriver::Bounds.from_android(r, @driver) if name.to_s == "bounds"
|
@@ -15,7 +14,6 @@ module TestaAppiumDriver
|
|
15
14
|
r = elements.map { |e| e.send(:attribute, name.to_s) }
|
16
15
|
r.map! { |b| TestaAppiumDriver::Bounds.from_android(b, @driver) } if name.to_s == "bounds"
|
17
16
|
end
|
18
|
-
@driver.enable_wait_for_idle
|
19
17
|
r
|
20
18
|
end
|
21
19
|
|
@@ -110,7 +108,7 @@ module TestaAppiumDriver
|
|
110
108
|
children = self.dup.parent.children.execute
|
111
109
|
index = children.index(this)
|
112
110
|
raise "Index not found" if index.nil?
|
113
|
-
index
|
111
|
+
index.to_i
|
114
112
|
end
|
115
113
|
end
|
116
114
|
end
|
@@ -106,7 +106,7 @@ module TestaAppiumDriver
|
|
106
106
|
end
|
107
107
|
|
108
108
|
if is_scrollable_selector?(selectors, single)
|
109
|
-
locator.scrollable_locator =
|
109
|
+
locator.scrollable_locator = locator
|
110
110
|
if selectors[:class] == "android.widget.HorizontalScrollView"
|
111
111
|
locator.scrollable_locator.scroll_orientation = :horizontal
|
112
112
|
else
|
@@ -38,7 +38,6 @@ module TestaAppiumDriver
|
|
38
38
|
|
39
39
|
|
40
40
|
def uiautomator_page_or_fling(type, direction)
|
41
|
-
|
42
41
|
scrollable_selector = @scrollable.ui_selector(false)
|
43
42
|
orientation = direction == :up || direction == :down ? ".setAsVerticalList()" : ".setAsHorizontalList()"
|
44
43
|
if type == SCROLL_ACTION_TYPE_SCROLL
|
@@ -157,6 +157,33 @@ module TestaAppiumDriver
|
|
157
157
|
command
|
158
158
|
end
|
159
159
|
|
160
|
+
|
161
|
+
def hash_to_class_chain(hash, single = true)
|
162
|
+
command = "**/"
|
163
|
+
|
164
|
+
hash[:type] = hash[:class] unless hash[:class].nil?
|
165
|
+
hash[:label] = hash[:text] unless hash[:text].nil?
|
166
|
+
hash[:name] = hash[:id] unless hash[:id].nil?
|
167
|
+
if hash[:type] && hash[:type].kind_of?(String)
|
168
|
+
command = "#{ command }#{hash[:type] }"
|
169
|
+
else
|
170
|
+
command = "#{command}*"
|
171
|
+
end
|
172
|
+
|
173
|
+
command = "#{ command }[`enabled == #{ hash[:enabled] }`]" unless hash[:enabled].nil?
|
174
|
+
command = "#{ command }[`label == \"#{ %(#{hash[:label] }) }\"`]" if hash[:label] && hash[:label].kind_of?(String)
|
175
|
+
command = "#{ command }[`label CONTAINS \"#{ %(#{hash[:label].source }) }\"`]" if hash[:label] && hash[:label].kind_of?(Regexp)
|
176
|
+
command = "#{ command }[`name == \"#{ %(#{hash[:name] }) }\"`]" if hash[:name] && hash[:name].kind_of?(String)
|
177
|
+
command = "#{ command }[`name CONTAINS \"#{ %(#{hash[:name].source }) }\"`]" if hash[:name] && hash[:name].kind_of?(Regexp)
|
178
|
+
command = "#{ command }[`value == \"#{ %(#{hash[:value] }) }\"`]" if hash[:value] && hash[:value].kind_of?(String)
|
179
|
+
command = "#{ command }[`value CONTAINS \"#{ %(#{hash[:value].source }) }\"`]" if hash[:value] && hash[:value].kind_of?(Regexp)
|
180
|
+
command = "#{ command }[`visible == #{ hash[:visible] }`]" unless hash[:visible].nil?
|
181
|
+
|
182
|
+
command += "[1]" if single
|
183
|
+
|
184
|
+
command
|
185
|
+
end
|
186
|
+
|
160
187
|
# check if selectors are for a scrollable element
|
161
188
|
# @param [Boolean] single should the command return first instance or all of matched elements
|
162
189
|
# @param [Hash] selectors for fetching elements
|
@@ -70,6 +70,7 @@ module TestaAppiumDriver
|
|
70
70
|
# The retry mechanism allows alignment even for dynamic layouts when elements are hidden/show when scrolling to certain direction
|
71
71
|
# @return [TestaAppiumDriver::Locator]
|
72
72
|
def align(with = :top, top: nil, bottom: nil, right: nil, left: nil, scroll_to_find: false)
|
73
|
+
deadzone = _process_deadzone(top, bottom, right, left)
|
73
74
|
deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
|
74
75
|
sa = ScrollActions.new(@scrollable_locator,
|
75
76
|
locator: self,
|
@@ -289,7 +290,7 @@ module TestaAppiumDriver
|
|
289
290
|
x = to[:x]
|
290
291
|
y = to[:y]
|
291
292
|
end
|
292
|
-
_drag_to(x, y)
|
293
|
+
_drag_to(bounds.center.x, bounds.center.y, x, y)
|
293
294
|
end
|
294
295
|
|
295
296
|
def drag_by(amount, direction: :top)
|
@@ -308,7 +309,7 @@ module TestaAppiumDriver
|
|
308
309
|
else
|
309
310
|
raise "Unknown direction #{direction}"
|
310
311
|
end
|
311
|
-
_drag_to(x, y)
|
312
|
+
_drag_to(b.center.x, b.center.y, x, y)
|
312
313
|
end
|
313
314
|
|
314
315
|
|
@@ -326,11 +327,11 @@ module TestaAppiumDriver
|
|
326
327
|
deadzone
|
327
328
|
end
|
328
329
|
|
329
|
-
def _drag_to(
|
330
|
+
def _drag_to(x0, y0, x1, y1)
|
330
331
|
sa = ScrollActions.new(@scrollable_locator,
|
331
332
|
locator: self,
|
332
333
|
default_scroll_strategy: @default_scroll_strategy)
|
333
|
-
sa.drag_to(
|
334
|
+
sa.drag_to(x0, y0, x1, y1)
|
334
335
|
self
|
335
336
|
end
|
336
337
|
|
@@ -133,13 +133,12 @@ module TestaAppiumDriver
|
|
133
133
|
|
134
134
|
|
135
135
|
|
136
|
-
r = @driver.execute(@from_element, @single, strategies_and_selectors, skip_cache, ignore_implicit_wait)
|
136
|
+
r = @driver.execute(@from_element, @single, strategies_and_selectors, skip_cache: skip_cache, ignore_implicit_wait: ignore_implicit_wait)
|
137
137
|
r = r[@index_for_multiple] if !@index_for_multiple.nil? && !@single
|
138
138
|
r
|
139
139
|
end
|
140
140
|
|
141
141
|
def when_exists(timeout = nil, &block)
|
142
|
-
timeout = @driver.get_timeouts["implicit"] / 1000 if timeout.nil?
|
143
142
|
found = false
|
144
143
|
begin
|
145
144
|
wait_until_exists(timeout)
|
@@ -161,7 +160,6 @@ module TestaAppiumDriver
|
|
161
160
|
# @param [Integer] timeout in seconds
|
162
161
|
# @return [TestaAppiumDriver::Locator]
|
163
162
|
def wait_until_exists(timeout = nil)
|
164
|
-
timeout = @driver.get_timeouts["implicit"] / 1000 if timeout.nil?
|
165
163
|
args = {timeout: timeout}
|
166
164
|
_wait(:until, args)
|
167
165
|
end
|
@@ -170,7 +168,6 @@ module TestaAppiumDriver
|
|
170
168
|
# @param [Integer] timeout in seconds
|
171
169
|
# @return [TestaAppiumDriver::Locator]
|
172
170
|
def wait_while_exists(timeout = nil)
|
173
|
-
timeout = @driver.get_timeouts["implicit"] / 1000 if timeout.nil?
|
174
171
|
args = {timeout: timeout}
|
175
172
|
_wait(:while, args)
|
176
173
|
end
|
@@ -221,13 +218,20 @@ module TestaAppiumDriver
|
|
221
218
|
|
222
219
|
def [](instance)
|
223
220
|
raise "Cannot add index selector to non-Array" if @single
|
224
|
-
if ((@strategy.nil? && !@last_selector_adjacent) || @strategy == FIND_STRATEGY_UIAUTOMATOR) && instance >= 0
|
221
|
+
if ((@strategy.nil? && !@last_selector_adjacent && @driver.device == :android) || @strategy == FIND_STRATEGY_UIAUTOMATOR) && instance >= 0
|
225
222
|
locator = self.dup
|
226
223
|
locator.strategy = FIND_STRATEGY_UIAUTOMATOR
|
227
224
|
locator.ui_selector = "#{@ui_selector}.instance(#{instance})"
|
228
225
|
locator.single = true
|
229
226
|
locator.can_use_id_strategy = false
|
230
227
|
locator
|
228
|
+
elsif (@driver.device == :ios && !@last_selector_adjacent && @strategy.nil?) || @strategy == FIND_STRATEGY_CLASS_CHAIN
|
229
|
+
locator = self.dup
|
230
|
+
locator.strategy = FIND_STRATEGY_CLASS_CHAIN
|
231
|
+
locator.class_chain_selector += "[#{instance + 1}]"
|
232
|
+
locator.single = true
|
233
|
+
locator.can_use_id_strategy = false
|
234
|
+
locator
|
231
235
|
else
|
232
236
|
from_element = self.dup
|
233
237
|
from_element.index_for_multiple = instance
|
@@ -262,10 +266,8 @@ module TestaAppiumDriver
|
|
262
266
|
strategy: @strategy,
|
263
267
|
default_strategy: @default_find_strategy,
|
264
268
|
single: @single,
|
265
|
-
context: @from_element.nil? ? nil : @from_element.to_s,
|
266
269
|
uiautomator: defined?(self.ui_selector) ? ui_selector : nil,
|
267
270
|
xpath: @xpath_selector,
|
268
|
-
scrollable: @scrollable_locator.nil? ? nil : @scrollable_locator.to_s,
|
269
271
|
scroll_orientation: @scroll_orientation,
|
270
272
|
resolved: strategies_and_selectors,
|
271
273
|
index_for_multiple: @index_for_multiple
|
@@ -301,12 +303,56 @@ module TestaAppiumDriver
|
|
301
303
|
end
|
302
304
|
|
303
305
|
|
304
|
-
def tap
|
305
|
-
click
|
306
|
+
def tap(x = nil, y = nil)
|
307
|
+
click(x, y)
|
306
308
|
end
|
307
309
|
|
308
|
-
|
309
|
-
|
310
|
+
# if both x or y, or both are not given, will click in the center of the element
|
311
|
+
# @param x If positive integer, will offset the click from the left side, if negative integer, will offset the click from the right. If float value is given, it will threat it as percentage offset, giving it 0.5 will click in the middle
|
312
|
+
# @param y If positive integer, will offset the click from the bottom side, if negative integer, will offset the click from the top. If float value is given, it will threat it as percentage offset, giving it 0.5 will click in the middle
|
313
|
+
def click(x = nil, y = nil)
|
314
|
+
if !x.nil? && !y.nil?
|
315
|
+
|
316
|
+
b = self.bounds
|
317
|
+
if x.kind_of? Integer
|
318
|
+
if x >= 0
|
319
|
+
x = b.top_left.x + x
|
320
|
+
else
|
321
|
+
x = b.bottom_right.x + x
|
322
|
+
end
|
323
|
+
elsif x.kind_of? Float
|
324
|
+
x = b.top_left.x + b.width*x
|
325
|
+
else
|
326
|
+
raise "x value #{x} not supported"
|
327
|
+
end
|
328
|
+
|
329
|
+
if y.kind_of? Integer
|
330
|
+
if y >= 0
|
331
|
+
y = b.bottom_right.y + y
|
332
|
+
else
|
333
|
+
y = b.top_left + y
|
334
|
+
end
|
335
|
+
elsif y.kind_of? Float
|
336
|
+
y = b.bottom_right.y + b.height*y
|
337
|
+
end
|
338
|
+
|
339
|
+
action_builder = @driver.action
|
340
|
+
f1 = action_builder.add_pointer_input(:touch, "finger1")
|
341
|
+
f1.create_pointer_move(duration: 0, x: x, y: y, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
|
342
|
+
f1.create_pointer_down(:left)
|
343
|
+
f1.create_pointer_up(:left)
|
344
|
+
@driver.perform_actions [f1]
|
345
|
+
else
|
346
|
+
if @driver.device == :android
|
347
|
+
perform_driver_method(:click)
|
348
|
+
else
|
349
|
+
# on ios, if element is not visible, first click will scroll to it
|
350
|
+
# then on second click actually perform the click
|
351
|
+
visible = visible?
|
352
|
+
perform_driver_method(:click)
|
353
|
+
perform_driver_method(:click) unless visible rescue nil
|
354
|
+
end
|
355
|
+
end
|
310
356
|
end
|
311
357
|
|
312
358
|
def send_key(*args)
|
@@ -336,15 +382,20 @@ module TestaAppiumDriver
|
|
336
382
|
# @return [TestaAppiumDriver::Locator]
|
337
383
|
def children
|
338
384
|
raise "Cannot add children selector to array" unless @single
|
339
|
-
raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "children") if @strategy != FIND_STRATEGY_XPATH && !@strategy.nil?
|
385
|
+
raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "children") if @strategy != FIND_STRATEGY_XPATH && @strategy != FIND_STRATEGY_CLASS_CHAIN && !@strategy.nil?
|
340
386
|
|
341
387
|
locator = self.dup
|
342
|
-
locator.strategy = FIND_STRATEGY_XPATH
|
343
388
|
locator.strategy_reason = "children"
|
344
389
|
locator.xpath_selector += "/*"
|
345
390
|
locator.single = false
|
346
391
|
locator.last_selector_adjacent = true
|
347
392
|
locator.can_use_id_strategy = false
|
393
|
+
|
394
|
+
if @driver.device == :android
|
395
|
+
locator.strategy = FIND_STRATEGY_XPATH
|
396
|
+
else
|
397
|
+
locator.class_chain_selector += "/*"
|
398
|
+
end
|
348
399
|
locator
|
349
400
|
end
|
350
401
|
|
@@ -353,14 +404,20 @@ module TestaAppiumDriver
|
|
353
404
|
# @return [TestaAppiumDriver::Locator]
|
354
405
|
def child
|
355
406
|
raise "Cannot add children selector to array" unless @single
|
356
|
-
raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "child") if @strategy != FIND_STRATEGY_XPATH && !@strategy.nil?
|
407
|
+
raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_XPATH, "child") if @strategy != FIND_STRATEGY_XPATH && @strategy != FIND_STRATEGY_CLASS_CHAIN && !@strategy.nil?
|
357
408
|
|
358
409
|
locator = self.dup
|
359
|
-
|
410
|
+
|
360
411
|
locator.strategy_reason = "child"
|
361
412
|
locator.xpath_selector += "/*[1]"
|
362
413
|
locator.single = true
|
363
414
|
locator.can_use_id_strategy = false
|
415
|
+
|
416
|
+
if @driver.device == :android
|
417
|
+
locator.strategy = FIND_STRATEGY_XPATH
|
418
|
+
else
|
419
|
+
locator.class_chain_selector += "/*[1]"
|
420
|
+
end
|
364
421
|
locator
|
365
422
|
end
|
366
423
|
|
@@ -461,7 +518,8 @@ module TestaAppiumDriver
|
|
461
518
|
message = args[:message] unless args[:message].nil?
|
462
519
|
|
463
520
|
if args[:timeout].nil?
|
464
|
-
timeout = @driver.get_timeouts["implicit"] / 1000
|
521
|
+
#timeout = @driver.get_timeouts["implicit"] / 1000
|
522
|
+
timeout = 10
|
465
523
|
else
|
466
524
|
timeout = args[:timeout]
|
467
525
|
end
|
@@ -23,6 +23,7 @@ module TestaAppiumDriver
|
|
23
23
|
until is_end_of_scroll?
|
24
24
|
matches = @locator.execute(skip_cache: true)
|
25
25
|
matches.each_with_index do |m|
|
26
|
+
next if elements.include?(m)
|
26
27
|
elements << m
|
27
28
|
if block_given? # block is given
|
28
29
|
block.call(m) # use call to execute the block
|
@@ -228,10 +229,8 @@ module TestaAppiumDriver
|
|
228
229
|
|
229
230
|
|
230
231
|
|
231
|
-
def w3c_drag_to(
|
232
|
-
x0
|
233
|
-
y0 = @bounds.center.y
|
234
|
-
w3c_action(x0, y0, x, y, SCROLL_ACTION_TYPE_DRAG)
|
232
|
+
def w3c_drag_to(x0, y0, x1, y1)
|
233
|
+
w3c_action(x0, y0, x1, y1, SCROLL_ACTION_TYPE_DRAG)
|
235
234
|
end
|
236
235
|
|
237
236
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require_relative 'scroll_actions/json_wire_scroll_actions'
|
2
2
|
require_relative 'scroll_actions/w3c_scroll_actions'
|
3
3
|
|
4
|
-
|
5
4
|
module TestaAppiumDriver
|
6
5
|
|
7
6
|
# Class for handling scroll actions
|
@@ -21,7 +20,6 @@ module TestaAppiumDriver
|
|
21
20
|
@default_scroll_strategy = params[:default_scroll_strategy]
|
22
21
|
@driver = @locator.driver
|
23
22
|
|
24
|
-
|
25
23
|
if @scrollable.nil?
|
26
24
|
# if we dont have a scrollable element or if we do have it, but it is not compatible with uiautomator
|
27
25
|
# then find first scrollable in document
|
@@ -30,16 +28,14 @@ module TestaAppiumDriver
|
|
30
28
|
|
31
29
|
@strategy = nil
|
32
30
|
if @scrollable.strategy == FIND_STRATEGY_XPATH || # uiautomator cannot resolve scrollable from a xpath locator
|
33
|
-
|
34
|
-
|
31
|
+
!@deadzone.nil? ||
|
32
|
+
!@scrollable.from_element.instance_of?(TestaAppiumDriver::Driver) # uiautomator cannot resolve nested scrollable
|
35
33
|
@strategy = SCROLL_STRATEGY_W3C
|
36
34
|
end
|
37
35
|
|
38
|
-
|
39
36
|
@bounds = @scrollable.bounds
|
40
37
|
end
|
41
38
|
|
42
|
-
|
43
39
|
def align(with, scroll_to_find)
|
44
40
|
w3c_align(with, scroll_to_find)
|
45
41
|
@locator
|
@@ -66,7 +62,6 @@ module TestaAppiumDriver
|
|
66
62
|
w3c_each(:left, &block)
|
67
63
|
end
|
68
64
|
|
69
|
-
|
70
65
|
def resolve_strategy
|
71
66
|
if @strategy.nil?
|
72
67
|
@default_scroll_strategy
|
@@ -75,7 +70,6 @@ module TestaAppiumDriver
|
|
75
70
|
end
|
76
71
|
end
|
77
72
|
|
78
|
-
|
79
73
|
def scroll_to
|
80
74
|
if @locator.strategy != FIND_STRATEGY_XPATH && resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
|
81
75
|
uiautomator_scroll_to
|
@@ -116,7 +110,6 @@ module TestaAppiumDriver
|
|
116
110
|
end
|
117
111
|
end
|
118
112
|
|
119
|
-
|
120
113
|
def page_down
|
121
114
|
if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
|
122
115
|
uiautomator_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :down)
|
@@ -149,10 +142,10 @@ module TestaAppiumDriver
|
|
149
142
|
end
|
150
143
|
end
|
151
144
|
|
152
|
-
|
153
145
|
def scroll_to_start
|
154
146
|
if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
|
155
147
|
uiautomator_scroll_to_start_or_end(:start)
|
148
|
+
|
156
149
|
elsif resolve_strategy == SCROLL_STRATEGY_W3C
|
157
150
|
w3c_scroll_to_start_or_end(:start)
|
158
151
|
end
|
@@ -198,11 +191,10 @@ module TestaAppiumDriver
|
|
198
191
|
end
|
199
192
|
end
|
200
193
|
|
201
|
-
def drag_to(
|
202
|
-
w3c_drag_to(
|
194
|
+
def drag_to(x0, y0, x1, y1)
|
195
|
+
w3c_drag_to(x0, y0, x1, y1)
|
203
196
|
end
|
204
197
|
|
205
|
-
|
206
198
|
private
|
207
199
|
|
208
200
|
def is_end_of_scroll?
|
@@ -211,7 +203,6 @@ module TestaAppiumDriver
|
|
211
203
|
old_elements == @previous_elements
|
212
204
|
end
|
213
205
|
|
214
|
-
|
215
206
|
def default_deadzone!
|
216
207
|
@deadzone = {} if @deadzone.nil?
|
217
208
|
if @deadzone[:top].nil?
|
@@ -29,9 +29,6 @@ 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
|
34
|
-
|
35
32
|
core = Appium::Core.for(opts)
|
36
33
|
extend_for(core.device, core.automation_name)
|
37
34
|
@device = core.device
|
@@ -43,6 +40,9 @@ module TestaAppiumDriver
|
|
43
40
|
invalidate_cache
|
44
41
|
|
45
42
|
|
43
|
+
disable_wait_for_idle
|
44
|
+
disable_implicit_wait
|
45
|
+
|
46
46
|
Selenium::WebDriver::Element.set_driver(self, opts[:caps][:udid])
|
47
47
|
end
|
48
48
|
|
@@ -69,11 +69,9 @@ module TestaAppiumDriver
|
|
69
69
|
# @param [Array<Hash>] strategies_and_selectors array of usable strategies and selectors
|
70
70
|
# @param [Boolean] skip_cache to skip checking and storing cache
|
71
71
|
# @return [Selenium::WebDriver::Element, Array] element is returned if single is true, array otherwise
|
72
|
-
def execute(from_element, single, strategies_and_selectors, skip_cache
|
72
|
+
def execute(from_element, single, strategies_and_selectors, skip_cache: false, ignore_implicit_wait: false)
|
73
73
|
|
74
74
|
# if user wants to wait for element to exist, he can use wait_until_present
|
75
|
-
disable_wait_for_idle
|
76
|
-
disable_implicit_wait
|
77
75
|
start_time = Time.now.to_f
|
78
76
|
ss_index = 0
|
79
77
|
|
@@ -126,15 +124,13 @@ module TestaAppiumDriver
|
|
126
124
|
puts "Using cache from #{@cache[:time].strftime("%H:%M:%S.%L")}, strategy: #{@cache[:strategy]}"
|
127
125
|
end
|
128
126
|
rescue => e
|
129
|
-
if (start_time + @implicit_wait_ms/1000 < Time.now.to_f && !ignore_implicit_wait) || ss_index < strategies_and_selectors.count
|
127
|
+
#if (start_time + @implicit_wait_ms/1000 < Time.now.to_f && !ignore_implicit_wait) || ss_index < strategies_and_selectors.count
|
128
|
+
if ss_index < strategies_and_selectors.count
|
130
129
|
sleep EXISTS_WAIT if ss_index >= strategies_and_selectors.count
|
131
130
|
retry
|
132
131
|
else
|
133
132
|
raise e
|
134
133
|
end
|
135
|
-
ensure
|
136
|
-
enable_implicit_wait
|
137
|
-
enable_wait_for_idle
|
138
134
|
end
|
139
135
|
|
140
136
|
execute_result
|
@@ -151,43 +147,23 @@ module TestaAppiumDriver
|
|
151
147
|
|
152
148
|
# disables implicit wait
|
153
149
|
def disable_implicit_wait
|
154
|
-
|
155
|
-
@implicit_wait_ms = @
|
150
|
+
@implicit_wait_ms = @driver.get_timeouts["implicit"].to_i
|
151
|
+
@implicit_wait_ms = @implicit_wait_ms/1000 if @implicit_wait_ms > 100000
|
156
152
|
@implicit_wait_uiautomator_ms = @driver.get_settings["waitForSelectorTimeout"]
|
157
153
|
@driver.manage.timeouts.implicit_wait = 0
|
158
|
-
@driver.update_settings({waitForSelectorTimeout:
|
159
|
-
@implicit_wait_disabled = true
|
160
|
-
end
|
154
|
+
@driver.update_settings({waitForSelectorTimeout: 1})
|
161
155
|
end
|
162
156
|
|
163
|
-
# enables implicit wait, can be called only after disabling implicit wait
|
164
|
-
def enable_implicit_wait
|
165
|
-
raise "Implicit wait is not disabled" unless @implicit_wait_disabled
|
166
|
-
# get_timeouts always returns in milliseconds, but we should set in seconds
|
167
|
-
@driver.manage.timeouts.implicit_wait = @implicit_wait_ms / 1000
|
168
|
-
@driver.update_settings({waitForSelectorTimeout: @implicit_wait_uiautomator_ms})
|
169
|
-
@implicit_wait_disabled = false
|
170
|
-
end
|
171
157
|
|
172
158
|
# disables wait for idle, only executed for android devices
|
173
159
|
def disable_wait_for_idle
|
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
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
# enables wait for idle, only executed for android devices
|
184
|
-
def enable_wait_for_idle
|
185
160
|
if @device == :android
|
186
|
-
|
187
|
-
@driver.update_settings({waitForIdleTimeout:
|
161
|
+
@wait_for_idle_timeout = @driver.settings.get["waitForIdleTimeout"]
|
162
|
+
@driver.update_settings({waitForIdleTimeout: 1})
|
188
163
|
end
|
189
164
|
end
|
190
165
|
|
166
|
+
|
191
167
|
def set_find_by_image_settings(settings)
|
192
168
|
settings.delete(:image)
|
193
169
|
@default_find_image_settings = {}
|
@@ -233,6 +209,33 @@ module TestaAppiumDriver
|
|
233
209
|
@driver.hide_keyboard
|
234
210
|
end
|
235
211
|
|
212
|
+
def home_key
|
213
|
+
@driver.press_keycode(3)
|
214
|
+
end
|
215
|
+
def tab_key
|
216
|
+
@driver.press_keycode(61)
|
217
|
+
end
|
218
|
+
|
219
|
+
def dpad_up_key
|
220
|
+
@driver.press_keycode(19)
|
221
|
+
end
|
222
|
+
|
223
|
+
def dpad_down_key
|
224
|
+
@driver.press_keycode(20)
|
225
|
+
end
|
226
|
+
|
227
|
+
def dpad_right_key
|
228
|
+
@driver.press_keycode(22)
|
229
|
+
end
|
230
|
+
|
231
|
+
def dpad_left_key
|
232
|
+
@driver.press_keycode(23)
|
233
|
+
end
|
234
|
+
|
235
|
+
def enter_key
|
236
|
+
@driver.press_keycode(66)
|
237
|
+
end
|
238
|
+
|
236
239
|
def press_keycode(code)
|
237
240
|
@driver.press_keycode(code)
|
238
241
|
end
|
@@ -241,16 +244,42 @@ module TestaAppiumDriver
|
|
241
244
|
@driver.long_press_keycode(code)
|
242
245
|
end
|
243
246
|
|
247
|
+
def click(x, y)
|
248
|
+
ws = driver.window_size
|
249
|
+
window_width = ws.width.to_i
|
250
|
+
window_height = ws.height.to_i
|
251
|
+
if x.kind_of? Integer
|
252
|
+
if x < 0
|
253
|
+
x = window_width + x
|
254
|
+
end
|
255
|
+
elsif x.kind_of? Float
|
256
|
+
x = window_width*x
|
257
|
+
else
|
258
|
+
raise "x value #{x} not supported"
|
259
|
+
end
|
260
|
+
|
261
|
+
if y.kind_of? Integer
|
262
|
+
if y < 0
|
263
|
+
y = window_height + y
|
264
|
+
end
|
265
|
+
elsif y.kind_of? Float
|
266
|
+
y = window_height*y
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
action_builder = @driver.action
|
271
|
+
f1 = action_builder.add_pointer_input(:touch, "finger1")
|
272
|
+
f1.create_pointer_move(duration: 0, x: x, y: y, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
|
273
|
+
f1.create_pointer_down(:left)
|
274
|
+
f1.create_pointer_up(:left)
|
275
|
+
@driver.perform_actions [f1]
|
276
|
+
end
|
244
277
|
|
245
278
|
|
246
279
|
|
247
280
|
# @return [Array<Selenium::WebDriver::Element] array of 2 elements, the first element without children and the last element without children in the current page
|
248
281
|
def first_and_last_leaf(from_element = @driver)
|
249
|
-
disable_wait_for_idle
|
250
|
-
disable_implicit_wait
|
251
282
|
elements = from_element.find_elements(xpath: "//*[not(*)]")
|
252
|
-
enable_implicit_wait
|
253
|
-
enable_wait_for_idle
|
254
283
|
return nil if elements.count == 0
|
255
284
|
[elements[0], elements[-1]]
|
256
285
|
end
|
@@ -3,6 +3,7 @@ require_relative 'locator/attributes'
|
|
3
3
|
module TestaAppiumDriver
|
4
4
|
class Locator
|
5
5
|
include TypeSelectors
|
6
|
+
attr_accessor :class_chain_selector
|
6
7
|
|
7
8
|
def init(params, selectors, single)
|
8
9
|
if is_scrollable_selector?(selectors, single)
|
@@ -19,6 +20,9 @@ module TestaAppiumDriver
|
|
19
20
|
params[:scrollable_locator] = self.dup
|
20
21
|
end
|
21
22
|
|
23
|
+
@class_chain_selector = hash_to_class_chain(selectors, single)
|
24
|
+
|
25
|
+
|
22
26
|
@scrollable_locator = params[:scrollable_locator] if params[:scrollable_locator]
|
23
27
|
end
|
24
28
|
|
@@ -29,7 +33,7 @@ module TestaAppiumDriver
|
|
29
33
|
if @can_use_id_strategy
|
30
34
|
ss.push({"#{FIND_STRATEGY_NAME}": @can_use_id_strategy})
|
31
35
|
end
|
32
|
-
|
36
|
+
ss.push({"#{FIND_STRATEGY_CLASS_CHAIN}": @class_chain_selector}) if @strategy.nil? || @strategy == FIND_STRATEGY_CLASS_CHAIN
|
33
37
|
ss.push({"#{FIND_STRATEGY_XPATH}": @xpath_selector}) if @strategy.nil? || @strategy == FIND_STRATEGY_XPATH
|
34
38
|
ss.push({"#{FIND_STRATEGY_IMAGE}": @image_selector}) if @strategy == FIND_STRATEGY_IMAGE
|
35
39
|
ss
|
@@ -45,13 +49,23 @@ module TestaAppiumDriver
|
|
45
49
|
|
46
50
|
locator = self.dup
|
47
51
|
add_xpath_child_selectors(locator, selectors, single)
|
52
|
+
if @strategy.nil? || @strategy == FIND_STRATEGY_CLASS_CHAIN
|
53
|
+
add_class_chain_child_selectors(locator, selectors, single)
|
54
|
+
end
|
55
|
+
|
48
56
|
if is_scrollable_selector?(selectors, single)
|
49
57
|
locator.scrollable_locator.scroll_orientation = :vertical
|
50
|
-
locator.scrollable_locator =
|
58
|
+
locator.scrollable_locator = locator
|
51
59
|
end
|
52
60
|
|
53
61
|
locator.last_selector_adjacent = false
|
54
62
|
locator
|
55
63
|
end
|
64
|
+
|
65
|
+
|
66
|
+
def add_class_chain_child_selectors(locator, selectors, single)
|
67
|
+
locator.single = false unless single # switching from single result to multiple
|
68
|
+
locator.class_chain_selector += "/" + hash_to_class_chain(selectors, single)
|
69
|
+
end
|
56
70
|
end
|
57
71
|
end
|
@@ -5,10 +5,15 @@ module TestaAppiumDriver
|
|
5
5
|
# @return [TestaAppiumDriver::Locator]
|
6
6
|
def add_selector(*args, &block)
|
7
7
|
# if class selector is executed from driver, create new locator instance
|
8
|
-
if self.kind_of?(TestaAppiumDriver::Driver) || self.
|
8
|
+
if self.kind_of?(TestaAppiumDriver::Driver) || self.instance_of?(Selenium::WebDriver::Element)
|
9
9
|
args.last[:default_find_strategy] = @default_find_strategy
|
10
10
|
args.last[:default_scroll_strategy] = @default_scroll_strategy
|
11
|
-
|
11
|
+
if self.instance_of?(Selenium::WebDriver::Element)
|
12
|
+
driver = self.get_driver
|
13
|
+
else
|
14
|
+
driver = self
|
15
|
+
end
|
16
|
+
Locator.new(driver, self, *args)
|
12
17
|
else
|
13
18
|
# class selector is executed from locator, just add child selector criteria
|
14
19
|
self.add_child_selector(*args)
|
@@ -150,5 +155,34 @@ module TestaAppiumDriver
|
|
150
155
|
params[:single] = false
|
151
156
|
add_selector(params)
|
152
157
|
end
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
# @return [TestaAppiumDriver::Locator]
|
162
|
+
def text_field(params = {})
|
163
|
+
params[:type] = "XCUIElementTypeTextField"
|
164
|
+
add_selector(params)
|
165
|
+
end
|
166
|
+
|
167
|
+
# @return [TestaAppiumDriver::Locator]
|
168
|
+
def text_fields(params = {})
|
169
|
+
params[:type] = "XCUIElementTypeTextField"
|
170
|
+
params[:single] = false
|
171
|
+
add_selector(params)
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
# @return [TestaAppiumDriver::Locator]
|
176
|
+
def secure_text_field(params = {})
|
177
|
+
params[:type] = "XCUIElementTypeSecureTextField"
|
178
|
+
add_selector(params)
|
179
|
+
end
|
180
|
+
|
181
|
+
# @return [TestaAppiumDriver::Locator]
|
182
|
+
def secure_text_fields(params = {})
|
183
|
+
params[:type] = "XCUIElementTypeSecureTextField"
|
184
|
+
params[:single] = false
|
185
|
+
add_selector(params)
|
186
|
+
end
|
153
187
|
end
|
154
188
|
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.
|
4
|
+
version: 0.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- karlo.razumovic
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appium_lib_core
|