appium_lib 9.2.0 → 9.3.0
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/CHANGELOG.md +26 -0
- data/android_tests/lib/android/specs/common/device_touchaction.rb +1 -1
- data/android_tests/lib/android/specs/device/touch_actions.rb +40 -1
- data/android_tests/lib/android/specs/driver.rb +3 -1
- data/appium_lib.gemspec +1 -0
- data/docs/android_docs.md +361 -231
- data/docs/ios_docs.md +391 -251
- data/ios_tests/appium.txt +3 -1
- data/ios_tests/lib/ios/specs/common/helper.rb +1 -1
- data/ios_tests/lib/ios/specs/device/device.rb +1 -1
- data/ios_tests/lib/ios/specs/device/touch_actions.rb +53 -1
- data/ios_tests/lib/ios/specs/driver.rb +3 -1
- data/ios_tests/lib/ios/specs/ios/element/button.rb +1 -2
- data/ios_tests/lib/ios/specs/ios/element/text.rb +2 -2
- data/ios_tests/lib/ios/specs/ios/element/textfield.rb +3 -1
- data/ios_tests/lib/ios/specs/ios/patch.rb +1 -6
- data/lib/appium_lib/common/version.rb +2 -2
- data/lib/appium_lib/common/wait.rb +6 -6
- data/lib/appium_lib/device/device.rb +53 -49
- data/lib/appium_lib/device/multi_touch.rb +99 -27
- data/lib/appium_lib/device/touch_actions.rb +38 -20
- data/lib/appium_lib/driver.rb +58 -24
- data/lib/appium_lib/ios/element/button.rb +6 -6
- data/lib/appium_lib/ios/element/generic.rb +30 -10
- data/lib/appium_lib/ios/element/text.rb +8 -8
- data/lib/appium_lib/ios/element/textfield.rb +9 -6
- data/lib/appium_lib/ios/helper.rb +17 -18
- data/release_notes.md +15 -0
- metadata +22 -2
@@ -30,8 +30,11 @@ module Appium
|
|
30
30
|
end
|
31
31
|
|
32
32
|
# Move to the given co-ordinates.
|
33
|
-
#
|
34
|
-
#
|
33
|
+
#
|
34
|
+
# `move_to`'s `x` and `y` have two case. One is working as coordinate, the other is working as offset.
|
35
|
+
#
|
36
|
+
# @option opts [integer] :x x co-ordinate to move to if element isn't set. Works as an offset if x is set with Element.
|
37
|
+
# @option opts [integer] :y y co-ordinate to move to if element isn't set. Works as an offset if y is set with Element.
|
35
38
|
# @option opts [WebDriver::Element] Element to scope this move within.
|
36
39
|
def move_to(opts)
|
37
40
|
opts = args_with_ele_ref(opts)
|
@@ -123,39 +126,38 @@ module Appium
|
|
123
126
|
#
|
124
127
|
# Note that iOS 7 simulators have broken swipe.
|
125
128
|
#
|
129
|
+
# For iOS: Use `offset_x` and `offset_y` to define the end point.
|
130
|
+
#
|
131
|
+
# For Android: Use `end_x` and `end_y` to define the end point.
|
132
|
+
#
|
133
|
+
# If you'd like more details, please read tests and its log samples in
|
134
|
+
# `ios_tests/lib/ios/specs/device/touch_actions.rb` and `ios_tests/lib/ios/specs/device/touch_actions.rb`
|
135
|
+
#
|
126
136
|
# @option opts [int] :start_x Where to start swiping, on the x axis. Default 0.
|
127
137
|
# @option opts [int] :start_y Where to start swiping, on the y axis. Default 0.
|
128
|
-
# @option opts [int] :
|
129
|
-
# @option opts [int] :
|
138
|
+
# @option opts [int] :offset_x For iOS. Offset, on the x axis. Default 0.
|
139
|
+
# @option opts [int] :offset_y For iOS. Offset, on the y axis. Default 0.
|
140
|
+
# @option opts [int] :end_x For Android. Where to end swiping, on the x axis. Default 0.
|
141
|
+
# @option opts [int] :end_y For Android. Where to end swiping, on the y axis. Default 0.
|
130
142
|
# @option opts [int] :duration How long the actual swipe takes to complete in milliseconds. Default 200.
|
131
|
-
# @deprecated Please do not use end_x, end_y anymore
|
132
143
|
def swipe(opts, ele = nil)
|
133
144
|
start_x = opts.fetch :start_x, 0
|
134
145
|
start_y = opts.fetch :start_y, 0
|
135
|
-
|
136
|
-
|
146
|
+
offset_x = opts.fetch :offset_x, nil
|
147
|
+
offset_y = opts.fetch :offset_y, nil
|
137
148
|
end_x = opts.fetch :end_x, nil
|
138
149
|
end_y = opts.fetch :end_y, nil
|
139
|
-
|
140
|
-
if end_x || end_y
|
141
|
-
warn '[DEPRECATION] `end_x` and `end_y` are deprecated. Please use `delta_x` and `delta_y` instead.'
|
142
|
-
end
|
143
|
-
|
144
|
-
delta_x ||= end_x
|
145
|
-
delta_y ||= end_y
|
146
|
-
|
147
|
-
delta_x ||= 0
|
148
|
-
delta_y ||= 0
|
149
|
-
|
150
150
|
duration = opts.fetch :duration, 200
|
151
151
|
|
152
|
+
coordinates = swipe_coordinates(end_x: end_x, end_y: end_y, offset_x: offset_x, offset_y: offset_y)
|
153
|
+
|
152
154
|
if ele # pinch/zoom for XCUITest
|
153
155
|
press x: start_x, y: start_y, element: ele
|
154
|
-
move_to x:
|
156
|
+
move_to x: coordinates[:offset_x], y: coordinates[:offset_y], element: ele
|
155
157
|
else
|
156
158
|
press x: start_x, y: start_y
|
157
159
|
wait(duration) if duration
|
158
|
-
move_to x:
|
160
|
+
move_to x: coordinates[:offset_x], y: coordinates[:offset_y]
|
159
161
|
end
|
160
162
|
release
|
161
163
|
|
@@ -175,6 +177,22 @@ module Appium
|
|
175
177
|
self
|
176
178
|
end
|
177
179
|
|
180
|
+
def swipe_coordinates(end_x: nil, end_y: nil, offset_x: nil, offset_y: nil)
|
181
|
+
if $driver.device_is_android?
|
182
|
+
puts 'end_x and end_y are used for Android. Not offset_x and offset_y.' if end_x.nil? || end_y.nil?
|
183
|
+
end_x ||= 0
|
184
|
+
end_y ||= 0
|
185
|
+
return { offset_x: end_x, offset_y: end_y }
|
186
|
+
elsif offset_x.nil? || offset_y.nil?
|
187
|
+
puts 'offset_x and offset_y are used for iOS. Not end_x and end_y point.'
|
188
|
+
end
|
189
|
+
|
190
|
+
offset_x ||= 0
|
191
|
+
offset_y ||= 0
|
192
|
+
|
193
|
+
{ offset_x: offset_x, offset_y: offset_y }
|
194
|
+
end
|
195
|
+
|
178
196
|
private
|
179
197
|
|
180
198
|
def chain_method(method, args = nil)
|
data/lib/appium_lib/driver.rb
CHANGED
@@ -304,23 +304,52 @@ module Appium
|
|
304
304
|
# Return http client called in start_driver()
|
305
305
|
# @return [Selenium::WebDriver::Remote::Http::Default] the http client
|
306
306
|
attr_reader :http_client
|
307
|
+
# Return a time wait timeout
|
308
|
+
# Wait time for ::Appium::Common.wait or ::Appium::Common.wait_true.
|
309
|
+
# Provide Appium::Drive like { appium_lib: { wait_timeout: 20 } }
|
310
|
+
# @return [Integer]
|
311
|
+
attr_reader :appium_wait_timeout
|
312
|
+
# Return a time wait timeout
|
313
|
+
# Wait interval time for ::Appium::Common.wait or ::Appium::Common.wait_true.
|
314
|
+
# Provide Appium::Drive like { appium_lib: { wait_interval: 20 } }
|
315
|
+
# @return [Integer]
|
316
|
+
attr_reader :appium_wait_interval
|
307
317
|
|
308
318
|
# Creates a new driver
|
309
319
|
#
|
310
|
-
#
|
311
|
-
# require 'rubygems'
|
312
|
-
# require 'appium_lib'
|
320
|
+
# @example
|
313
321
|
#
|
314
|
-
#
|
322
|
+
# ```ruby
|
323
|
+
# require 'rubygems'
|
324
|
+
# require 'appium_lib'
|
315
325
|
#
|
316
|
-
#
|
317
|
-
# opts = { caps: { platformName: :ios, app: '/path/to/MyiOS.app' } }
|
318
|
-
# Appium::Driver.new(opts).start_driver
|
326
|
+
# # platformName takes a string or a symbol.
|
319
327
|
#
|
320
|
-
#
|
321
|
-
#
|
322
|
-
#
|
323
|
-
#
|
328
|
+
# # Start iOS driver
|
329
|
+
# opts = {
|
330
|
+
# caps: {
|
331
|
+
# platformName: :ios,
|
332
|
+
# app: '/path/to/MyiOS.app'
|
333
|
+
# },
|
334
|
+
# appium_lib: {
|
335
|
+
# wait_timeout: 30
|
336
|
+
# }
|
337
|
+
# }
|
338
|
+
# Appium::Driver.new(opts).start_driver
|
339
|
+
#
|
340
|
+
# # Start Android driver
|
341
|
+
# opts = {
|
342
|
+
# caps: {
|
343
|
+
# platformName: :android,
|
344
|
+
# app: '/path/to/my.apk'
|
345
|
+
# },
|
346
|
+
# appium_lib: {
|
347
|
+
# wait_timeout: 30,
|
348
|
+
# wait_interval: 1
|
349
|
+
# }
|
350
|
+
# }
|
351
|
+
# Appium::Driver.new(opts).start_driver
|
352
|
+
# ```
|
324
353
|
#
|
325
354
|
# @param opts [Object] A hash containing various options.
|
326
355
|
# @return [Driver]
|
@@ -344,6 +373,9 @@ module Appium
|
|
344
373
|
@sauce_access_key = appium_lib_opts.fetch :sauce_access_key, ENV['SAUCE_ACCESS_KEY']
|
345
374
|
@sauce_access_key = nil if !@sauce_access_key || (@sauce_access_key.is_a?(String) && @sauce_access_key.empty?)
|
346
375
|
@appium_port = appium_lib_opts.fetch :port, 4723
|
376
|
+
# timeout and interval used in ::Appium::Comm.wait/wait_true
|
377
|
+
@appium_wait_timeout = appium_lib_opts.fetch :wait_timeout, 30
|
378
|
+
@appium_wait_interval = appium_lib_opts.fetch :wait_interval, 0.5
|
347
379
|
|
348
380
|
# to pass it in Selenium.new.
|
349
381
|
# `listener = opts.delete(:listener)` is called in Selenium::Driver.new
|
@@ -408,7 +440,9 @@ module Appium
|
|
408
440
|
port: @appium_port,
|
409
441
|
device: @appium_device,
|
410
442
|
debug: @appium_debug,
|
411
|
-
listener: @listener
|
443
|
+
listener: @listener,
|
444
|
+
wait_timeout: @appium_wait_timeout,
|
445
|
+
wait_interval: @appium_wait_interval
|
412
446
|
}
|
413
447
|
|
414
448
|
# Return duplicates so attributes are immutable
|
@@ -432,8 +466,8 @@ module Appium
|
|
432
466
|
# If the Appium server is under REQUIRED_VERSION_XCUITEST, then error is raised.
|
433
467
|
# @return [Boolean]
|
434
468
|
def check_server_version_xcuitest
|
435
|
-
if automation_name_is_xcuitest? && (@appium_server_version['build']['version']
|
436
|
-
raise Appium::Error::NotSupportedAppiumServer, "XCUITest requires
|
469
|
+
if automation_name_is_xcuitest? && (@appium_server_version['build']['version'] < REQUIRED_VERSION_XCUITEST)
|
470
|
+
raise Appium::Error::NotSupportedAppiumServer, "XCUITest requires Appium version >= #{REQUIRED_VERSION_XCUITEST}"
|
437
471
|
end
|
438
472
|
true
|
439
473
|
end
|
@@ -610,11 +644,11 @@ module Appium
|
|
610
644
|
#
|
611
645
|
# exists { button('sign in') } ? puts('true') : puts('false')
|
612
646
|
#
|
613
|
-
# @param
|
614
|
-
# wait to before checking
|
615
|
-
# @param
|
616
|
-
# wait to after checking
|
617
|
-
# @
|
647
|
+
# @param [Integer] pre_check The amount in seconds to set the
|
648
|
+
# wait to before checking existence
|
649
|
+
# @param [Integer] post_check The amount in seconds to set the
|
650
|
+
# wait to after checking existence
|
651
|
+
# @yield The block to call
|
618
652
|
# @return [Boolean]
|
619
653
|
def exists(pre_check = 0, post_check = @default_wait)
|
620
654
|
# do not uset set_wait here.
|
@@ -637,8 +671,8 @@ module Appium
|
|
637
671
|
end
|
638
672
|
|
639
673
|
# The same as @driver.execute_script
|
640
|
-
# @param
|
641
|
-
# @param
|
674
|
+
# @param [String] script The script to execute
|
675
|
+
# @param [*args] args The args to pass to the script
|
642
676
|
# @return [Object]
|
643
677
|
def execute_script(script, *args)
|
644
678
|
@driver.execute_script script, *args
|
@@ -646,7 +680,7 @@ module Appium
|
|
646
680
|
|
647
681
|
# Calls @driver.find_elements
|
648
682
|
#
|
649
|
-
# @param
|
683
|
+
# @param [*args] args The args to use
|
650
684
|
# @return [Array<Element>] Array is empty when no elements are found.
|
651
685
|
def find_elements(*args)
|
652
686
|
@driver.find_elements_with_appium(*args)
|
@@ -654,7 +688,7 @@ module Appium
|
|
654
688
|
|
655
689
|
# Calls @driver.find_elements
|
656
690
|
#
|
657
|
-
# @param
|
691
|
+
# @param [*args] args The args to use
|
658
692
|
# @return [Element]
|
659
693
|
def find_element(*args)
|
660
694
|
@driver.find_element_with_appium(*args)
|
@@ -664,7 +698,7 @@ module Appium
|
|
664
698
|
#
|
665
699
|
# @note This method does not work on real devices.
|
666
700
|
#
|
667
|
-
# @param
|
701
|
+
# @param [Hash] opts consisting of:
|
668
702
|
# @option opts [Float] :latitude the latitude in degrees (required)
|
669
703
|
# @option opts [Float] :longitude the longitude in degees (required)
|
670
704
|
# @option opts [Float] :altitude the altitude, defaulting to 75
|
@@ -18,7 +18,7 @@ module Appium
|
|
18
18
|
return ele_index button_class, value if value.is_a? Numeric
|
19
19
|
|
20
20
|
if automation_name_is_xcuitest?
|
21
|
-
|
21
|
+
raise_error_if_no_element buttons(value).first
|
22
22
|
else
|
23
23
|
ele_by_json_visible_contains button_class, value
|
24
24
|
end
|
@@ -32,8 +32,8 @@ module Appium
|
|
32
32
|
return tags button_class unless value
|
33
33
|
|
34
34
|
if automation_name_is_xcuitest?
|
35
|
-
|
36
|
-
|
35
|
+
visible_elements = tags button_class
|
36
|
+
elements_include visible_elements, value
|
37
37
|
else
|
38
38
|
eles_by_json_visible_contains button_class, value
|
39
39
|
end
|
@@ -58,7 +58,7 @@ module Appium
|
|
58
58
|
# @return [UIAButton|XCUIElementTypeButton]
|
59
59
|
def button_exact(value)
|
60
60
|
if automation_name_is_xcuitest?
|
61
|
-
|
61
|
+
raise_error_if_no_element buttons_exact(value).first
|
62
62
|
else
|
63
63
|
ele_by_json_visible_exact button_class, value
|
64
64
|
end
|
@@ -69,8 +69,8 @@ module Appium
|
|
69
69
|
# @return [Array<UIAButton|XCUIElementTypeButton>]
|
70
70
|
def buttons_exact(value)
|
71
71
|
if automation_name_is_xcuitest?
|
72
|
-
|
73
|
-
|
72
|
+
visible_elements = tags button_class
|
73
|
+
elements_exact visible_elements, value
|
74
74
|
else
|
75
75
|
eles_by_json_visible_exact button_class, value
|
76
76
|
end
|
@@ -5,7 +5,7 @@ module Appium
|
|
5
5
|
# @return [Element]
|
6
6
|
def find(value)
|
7
7
|
if automation_name_is_xcuitest?
|
8
|
-
|
8
|
+
raise_error_if_no_element finds(value).first
|
9
9
|
else
|
10
10
|
ele_by_json_visible_contains '*', value
|
11
11
|
end
|
@@ -16,7 +16,8 @@ module Appium
|
|
16
16
|
# @return [Array<Element>]
|
17
17
|
def finds(value)
|
18
18
|
if automation_name_is_xcuitest?
|
19
|
-
find_eles_by_attr_include '*', '*', value
|
19
|
+
elements = find_eles_by_attr_include '*', '*', value
|
20
|
+
select_visible_elements elements
|
20
21
|
else
|
21
22
|
eles_by_json_visible_contains '*', value
|
22
23
|
end
|
@@ -27,7 +28,7 @@ module Appium
|
|
27
28
|
# @return [Element]
|
28
29
|
def find_exact(value)
|
29
30
|
if automation_name_is_xcuitest?
|
30
|
-
|
31
|
+
raise_error_if_no_element finds_exact(value).first
|
31
32
|
else
|
32
33
|
ele_by_json_visible_exact '*', value
|
33
34
|
end
|
@@ -38,7 +39,8 @@ module Appium
|
|
38
39
|
# @return [Array<Element>]
|
39
40
|
def finds_exact(value)
|
40
41
|
if automation_name_is_xcuitest?
|
41
|
-
find_eles_by_attr '*', '*', value
|
42
|
+
elements = find_eles_by_attr '*', '*', value
|
43
|
+
select_visible_elements elements
|
42
44
|
else
|
43
45
|
eles_by_json_visible_exact '*', value
|
44
46
|
end
|
@@ -46,25 +48,43 @@ module Appium
|
|
46
48
|
|
47
49
|
private
|
48
50
|
|
49
|
-
def
|
50
|
-
|
51
|
+
def raise_error_if_no_element(element)
|
52
|
+
error_message = 'An element could not be located on the page using the given search parameters.'
|
53
|
+
raise(::Selenium::WebDriver::Error::NoSuchElementError, error_message) if element.nil?
|
51
54
|
element
|
52
55
|
end
|
53
56
|
|
54
|
-
|
57
|
+
# Return all elements include not displayed elements.
|
58
|
+
def elements_include(elements, value)
|
55
59
|
return [] if elements.empty?
|
56
60
|
elements.select do |element|
|
61
|
+
# `text` is equal to `value` if value is not `nil`
|
62
|
+
# `text` is equal to `name` if value is `nil`
|
57
63
|
name = element.name
|
58
|
-
|
64
|
+
text = element.value
|
65
|
+
name_result = name.nil? ? false : name.downcase.include?(value.downcase)
|
66
|
+
text_result = text.nil? ? false : text.downcase.include?(value.downcase)
|
67
|
+
name_result || text_result
|
59
68
|
end
|
60
69
|
end
|
61
70
|
|
62
|
-
|
71
|
+
# Return all elements include not displayed elements.
|
72
|
+
def elements_exact(elements, value)
|
63
73
|
return [] if elements.empty?
|
64
74
|
elements.select do |element|
|
75
|
+
# `text` is equal to `value` if value is not `nil`
|
76
|
+
# `text` is equal to `name` if value is `nil`
|
65
77
|
name = element.name
|
66
|
-
|
78
|
+
text = element.value
|
79
|
+
name_result = name.nil? ? false : name.casecmp(value).zero?
|
80
|
+
text_result = text.nil? ? false : text.casecmp(value).zero?
|
81
|
+
name_result || text_result
|
67
82
|
end
|
68
83
|
end
|
84
|
+
|
85
|
+
# Return visible elements.
|
86
|
+
def select_visible_elements(elements)
|
87
|
+
elements.select(&:displayed?)
|
88
|
+
end
|
69
89
|
end # module Ios
|
70
90
|
end # module Appium
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# UIAStaticText|XCUIElementTypeStaticText methods
|
2
2
|
module Appium
|
3
3
|
module Ios
|
4
|
-
|
4
|
+
UIAStaticText = 'UIAStaticText'.freeze
|
5
5
|
XCUIElementTypeStaticText = 'XCUIElementTypeStaticText'.freeze
|
6
6
|
|
7
7
|
# @return [String] Class name for text
|
8
8
|
def static_text_class
|
9
|
-
automation_name_is_xcuitest? ? XCUIElementTypeStaticText :
|
9
|
+
automation_name_is_xcuitest? ? XCUIElementTypeStaticText : UIAStaticText
|
10
10
|
end
|
11
11
|
|
12
12
|
# Find the first UIAStaticText|XCUIElementTypeStaticText that contains value or by index.
|
@@ -17,7 +17,7 @@ module Appium
|
|
17
17
|
return ele_index static_text_class, value if value.is_a? Numeric
|
18
18
|
|
19
19
|
if automation_name_is_xcuitest?
|
20
|
-
|
20
|
+
raise_error_if_no_element texts(value).first
|
21
21
|
else
|
22
22
|
ele_by_json_visible_contains static_text_class, value
|
23
23
|
end
|
@@ -31,8 +31,8 @@ module Appium
|
|
31
31
|
return tags static_text_class unless value
|
32
32
|
|
33
33
|
if automation_name_is_xcuitest?
|
34
|
-
|
35
|
-
|
34
|
+
visible_elements = tags static_text_class
|
35
|
+
elements_include visible_elements, value
|
36
36
|
else
|
37
37
|
eles_by_json_visible_contains static_text_class, value
|
38
38
|
end
|
@@ -55,7 +55,7 @@ module Appium
|
|
55
55
|
# @return [UIAStaticText|XCUIElementTypeStaticText]
|
56
56
|
def text_exact(value)
|
57
57
|
if automation_name_is_xcuitest?
|
58
|
-
|
58
|
+
raise_error_if_no_element texts_exact(value).first
|
59
59
|
else
|
60
60
|
ele_by_json_visible_exact static_text_class, value
|
61
61
|
end
|
@@ -66,8 +66,8 @@ module Appium
|
|
66
66
|
# @return [Array<UIAStaticText|XCUIElementTypeStaticText>]
|
67
67
|
def texts_exact(value)
|
68
68
|
if automation_name_is_xcuitest?
|
69
|
-
|
70
|
-
|
69
|
+
visible_elements = tags static_text_class
|
70
|
+
elements_exact visible_elements, value
|
71
71
|
else
|
72
72
|
eles_by_json_visible_exact static_text_class, value
|
73
73
|
end
|
@@ -27,13 +27,14 @@ module Appium
|
|
27
27
|
# @private
|
28
28
|
# for XCUITest
|
29
29
|
def _textfield_with_xpath
|
30
|
-
|
30
|
+
raise_error_if_no_element _textfields_with_xpath.first
|
31
31
|
end
|
32
32
|
|
33
33
|
# @private
|
34
34
|
# for XCUITest
|
35
35
|
def _textfields_with_xpath
|
36
|
-
xpaths "//#{_textfields}"
|
36
|
+
elements = xpaths "//#{_textfields}"
|
37
|
+
select_visible_elements elements
|
37
38
|
end
|
38
39
|
|
39
40
|
# Appium
|
@@ -78,7 +79,7 @@ module Appium
|
|
78
79
|
end
|
79
80
|
|
80
81
|
if automation_name_is_xcuitest?
|
81
|
-
|
82
|
+
raise_error_if_no_element textfields(value).first
|
82
83
|
else
|
83
84
|
ele_by_json _textfield_contains_string value
|
84
85
|
end
|
@@ -91,7 +92,8 @@ module Appium
|
|
91
92
|
def textfields(value = false)
|
92
93
|
if automation_name_is_xcuitest?
|
93
94
|
return _textfields_with_xpath unless value
|
94
|
-
find_eles_by_attr_include _textfields, '*', value
|
95
|
+
elements = find_eles_by_attr_include _textfields, '*', value
|
96
|
+
select_visible_elements elements
|
95
97
|
else
|
96
98
|
return eles_by_json _textfield_visible unless value
|
97
99
|
eles_by_json _textfield_contains_string value
|
@@ -125,7 +127,7 @@ module Appium
|
|
125
127
|
# @return [TextField]
|
126
128
|
def textfield_exact(value)
|
127
129
|
if automation_name_is_xcuitest?
|
128
|
-
|
130
|
+
raise_error_if_no_element textfields_exact(value).first
|
129
131
|
else
|
130
132
|
ele_by_json _textfield_exact_string value
|
131
133
|
end
|
@@ -136,7 +138,8 @@ module Appium
|
|
136
138
|
# @return [Array<TextField>]
|
137
139
|
def textfields_exact(value)
|
138
140
|
if automation_name_is_xcuitest?
|
139
|
-
find_eles_by_attr _textfields, '*', value
|
141
|
+
elements = find_eles_by_attr _textfields, '*', value
|
142
|
+
select_visible_elements elements
|
140
143
|
else
|
141
144
|
eles_by_json _textfield_exact_string value
|
142
145
|
end
|