appium_lib 6.0.0 → 7.0.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/.gitignore +2 -0
- data/.rubocop.yml +28 -0
- data/.travis.yml +10 -0
- data/Rakefile +9 -1
- data/android_tests/Gemfile +1 -1
- data/android_tests/Rakefile +20 -13
- data/android_tests/lib/android/specs/android/element/alert.rb +1 -1
- data/android_tests/lib/android/specs/android/element/button.rb +2 -2
- data/android_tests/lib/android/specs/android/element/generic.rb +1 -2
- data/android_tests/lib/android/specs/android/element/text.rb +2 -3
- data/android_tests/lib/android/specs/android/element/textfield.rb +2 -2
- data/android_tests/lib/android/specs/android/helper.rb +5 -3
- data/android_tests/lib/android/specs/android/patch.rb +2 -2
- data/android_tests/lib/android/specs/common/device.rb +16 -9
- data/android_tests/lib/android/specs/common/device_touchaction.rb +5 -2
- data/android_tests/lib/android/specs/common/element/window.rb +1 -1
- data/android_tests/lib/android/specs/common/helper.rb +14 -15
- data/android_tests/lib/android/specs/common/patch.rb +11 -9
- data/android_tests/lib/android/specs/common/version.rb +3 -3
- data/android_tests/lib/android/specs/common/web_context.rb +2 -3
- data/android_tests/lib/android/specs/driver.rb +38 -29
- data/android_tests/lib/android/specs/install.rb +3 -3
- data/android_tests/lib/format.rb +6 -8
- data/android_tests/lib/run.rb +25 -17
- data/android_tests/readme.md +4 -2
- data/appium_lib.gemspec +13 -11
- data/contributing.md +1 -1
- data/docs/android_docs.md +358 -274
- data/docs/ios_docs.md +333 -270
- data/docs/migration.md +10 -0
- data/docs_gen/make_docs.rb +3 -1
- data/ios_tests/Gemfile +1 -1
- data/ios_tests/Rakefile +17 -10
- data/ios_tests/appium.txt +1 -1
- data/ios_tests/lib/common.rb +8 -4
- data/ios_tests/lib/format.rb +5 -7
- data/ios_tests/lib/ios/specs/common/element/window.rb +1 -1
- data/ios_tests/lib/ios/specs/common/helper.rb +40 -39
- data/ios_tests/lib/ios/specs/common/patch.rb +15 -11
- data/ios_tests/lib/ios/specs/common/version.rb +3 -3
- data/ios_tests/lib/ios/specs/common/web_context.rb +1 -2
- data/ios_tests/lib/ios/specs/device/device.rb +7 -7
- data/ios_tests/lib/ios/specs/device/multi_touch.rb +6 -8
- data/ios_tests/lib/ios/specs/device/touch_actions.rb +12 -12
- data/ios_tests/lib/ios/specs/driver.rb +23 -22
- data/ios_tests/lib/ios/specs/ios/element/alert.rb +6 -2
- data/ios_tests/lib/ios/specs/ios/element/button.rb +2 -2
- data/ios_tests/lib/ios/specs/ios/element/generic.rb +1 -1
- data/ios_tests/lib/ios/specs/ios/element/text.rb +4 -1
- data/ios_tests/lib/ios/specs/ios/element/textfield.rb +6 -6
- data/ios_tests/lib/ios/specs/ios/helper.rb +5 -5
- data/ios_tests/lib/ios/specs/ios/patch.rb +2 -2
- data/ios_tests/lib/run.rb +1 -1
- data/ios_tests/readme.md +3 -3
- data/ios_tests/upload/sauce_storage.rb +8 -8
- data/ios_tests/upload/upload.rb +1 -1
- data/lib/appium_lib/android/client_xpath.rb +7 -7
- data/lib/appium_lib/android/element/alert.rb +2 -2
- data/lib/appium_lib/android/element/button.rb +16 -16
- data/lib/appium_lib/android/element/generic.rb +12 -13
- data/lib/appium_lib/android/element/text.rb +5 -5
- data/lib/appium_lib/android/element/textfield.rb +5 -5
- data/lib/appium_lib/android/helper.rb +82 -52
- data/lib/appium_lib/android/mobile_methods.rb +2 -2
- data/lib/appium_lib/android/patch.rb +3 -3
- data/lib/appium_lib/common/element/window.rb +1 -1
- data/lib/appium_lib/common/helper.rb +30 -35
- data/lib/appium_lib/common/patch.rb +22 -20
- data/lib/appium_lib/common/version.rb +3 -3
- data/lib/appium_lib/common/wait.rb +9 -10
- data/lib/appium_lib/device/device.rb +39 -33
- data/lib/appium_lib/device/multi_touch.rb +5 -7
- data/lib/appium_lib/device/touch_actions.rb +14 -15
- data/lib/appium_lib/driver.rb +97 -76
- data/lib/appium_lib/ios/element/alert.rb +1 -1
- data/lib/appium_lib/ios/element/button.rb +5 -5
- data/lib/appium_lib/ios/element/generic.rb +5 -6
- data/lib/appium_lib/ios/element/text.rb +5 -5
- data/lib/appium_lib/ios/element/textfield.rb +15 -15
- data/lib/appium_lib/ios/helper.rb +103 -90
- data/lib/appium_lib/ios/mobile_methods.rb +2 -2
- data/lib/appium_lib/ios/patch.rb +4 -4
- data/lib/appium_lib/logger.rb +7 -5
- data/lib/appium_lib/rails/duplicable.rb +3 -1
- data/readme.md +7 -1
- data/release_notes.md +152 -0
- metadata +28 -54
@@ -7,7 +7,7 @@ module Appium
|
|
7
7
|
# @param value [String, Integer] the value to exactly match.
|
8
8
|
# If int then the UIAButton at that index is returned.
|
9
9
|
# @return [UIAButton]
|
10
|
-
def button
|
10
|
+
def button(value)
|
11
11
|
# return button at index.
|
12
12
|
return ele_index UIAButton, value if value.is_a? Numeric
|
13
13
|
ele_by_json_visible_contains UIAButton, value
|
@@ -17,7 +17,7 @@ module Appium
|
|
17
17
|
# If value is omitted, all UIAButtons are returned.
|
18
18
|
# @param value [String] the value to search for
|
19
19
|
# @return [Array<UIAButton>]
|
20
|
-
def buttons
|
20
|
+
def buttons(value = false)
|
21
21
|
return tags UIAButton unless value
|
22
22
|
eles_by_json_visible_contains UIAButton, value
|
23
23
|
end
|
@@ -37,15 +37,15 @@ module Appium
|
|
37
37
|
# Find the first UIAButton that exactly matches value.
|
38
38
|
# @param value [String] the value to match exactly
|
39
39
|
# @return [UIAButton]
|
40
|
-
def button_exact
|
40
|
+
def button_exact(value)
|
41
41
|
ele_by_json_visible_exact UIAButton, value
|
42
42
|
end
|
43
43
|
|
44
44
|
# Find all UIAButtons that exactly match value.
|
45
45
|
# @param value [String] the value to match exactly
|
46
46
|
# @return [Array<UIAButton>]
|
47
|
-
def buttons_exact
|
47
|
+
def buttons_exact(value)
|
48
48
|
eles_by_json_visible_exact UIAButton, value
|
49
49
|
end
|
50
50
|
end # module Ios
|
51
|
-
end # module Appium
|
51
|
+
end # module Appium
|
@@ -1,32 +1,31 @@
|
|
1
1
|
module Appium
|
2
2
|
module Ios
|
3
|
-
|
4
3
|
# Find the first element containing value
|
5
4
|
# @param value [String] the value to search for
|
6
5
|
# @return [Element]
|
7
|
-
def find
|
6
|
+
def find(value)
|
8
7
|
ele_by_json_visible_contains '*', value
|
9
8
|
end
|
10
9
|
|
11
10
|
# Find all elements containing value
|
12
11
|
# @param value [String] the value to search for
|
13
12
|
# @return [Array<Element>]
|
14
|
-
def finds
|
13
|
+
def finds(value)
|
15
14
|
eles_by_json_visible_contains '*', value
|
16
15
|
end
|
17
16
|
|
18
17
|
# Find the first element exactly matching value
|
19
18
|
# @param value [String] the value to search for
|
20
19
|
# @return [Element]
|
21
|
-
def find_exact
|
20
|
+
def find_exact(value)
|
22
21
|
ele_by_json_visible_exact '*', value
|
23
22
|
end
|
24
23
|
|
25
24
|
# Find all elements exactly matching value
|
26
25
|
# @param value [String] the value to search for
|
27
26
|
# @return [Array<Element>]
|
28
|
-
def finds_exact
|
27
|
+
def finds_exact(value)
|
29
28
|
eles_by_json_visible_exact '*', value
|
30
29
|
end
|
31
30
|
end # module Ios
|
32
|
-
end # module Appium
|
31
|
+
end # module Appium
|
@@ -7,7 +7,7 @@ module Appium
|
|
7
7
|
# @param value [String, Integer] the value to find.
|
8
8
|
# If int then the UIAStaticText at that index is returned.
|
9
9
|
# @return [UIAStaticText]
|
10
|
-
def text
|
10
|
+
def text(value)
|
11
11
|
return ele_index UIAStaticText, value if value.is_a? Numeric
|
12
12
|
ele_by_json_visible_contains UIAStaticText, value
|
13
13
|
end
|
@@ -16,7 +16,7 @@ module Appium
|
|
16
16
|
# If value is omitted, all UIAStaticTexts are returned
|
17
17
|
# @param value [String] the value to search for
|
18
18
|
# @return [Array<UIAStaticText>]
|
19
|
-
def texts
|
19
|
+
def texts(value = false)
|
20
20
|
return tags UIAStaticText unless value
|
21
21
|
eles_by_json_visible_contains UIAStaticText, value
|
22
22
|
end
|
@@ -36,15 +36,15 @@ module Appium
|
|
36
36
|
# Find the first UIAStaticText that exactly matches value.
|
37
37
|
# @param value [String] the value to match exactly
|
38
38
|
# @return [UIAStaticText]
|
39
|
-
def text_exact
|
39
|
+
def text_exact(value)
|
40
40
|
ele_by_json_visible_exact UIAStaticText, value
|
41
41
|
end
|
42
42
|
|
43
43
|
# Find all UIAStaticTexts that exactly match value.
|
44
44
|
# @param value [String] the value to match exactly
|
45
45
|
# @return [Array<UIAStaticText>]
|
46
|
-
def texts_exact
|
46
|
+
def texts_exact(value)
|
47
47
|
eles_by_json_visible_exact UIAStaticText, value
|
48
48
|
end
|
49
49
|
end # module Ios
|
50
|
-
end # module Appium
|
50
|
+
end # module Appium
|
@@ -9,36 +9,36 @@ module Appium
|
|
9
9
|
def _textfield_visible
|
10
10
|
{
|
11
11
|
typeArray: [UIATextField, UIASecureTextField],
|
12
|
-
onlyVisible: true
|
12
|
+
onlyVisible: true
|
13
13
|
}
|
14
14
|
end
|
15
15
|
|
16
16
|
# @private
|
17
|
-
def _textfield_exact_string
|
17
|
+
def _textfield_exact_string(value)
|
18
18
|
exact = {
|
19
19
|
target: value,
|
20
20
|
substring: false,
|
21
|
-
insensitive: false
|
21
|
+
insensitive: false
|
22
22
|
}
|
23
23
|
exact_obj = {
|
24
24
|
name: exact,
|
25
25
|
label: exact,
|
26
|
-
value: exact
|
26
|
+
value: exact
|
27
27
|
}
|
28
28
|
_textfield_visible.merge(exact_obj)
|
29
29
|
end
|
30
30
|
|
31
31
|
# @private
|
32
|
-
def _textfield_contains_string
|
32
|
+
def _textfield_contains_string(value)
|
33
33
|
contains = {
|
34
34
|
target: value,
|
35
35
|
substring: true,
|
36
|
-
insensitive: true
|
36
|
+
insensitive: true
|
37
37
|
}
|
38
38
|
contains_obj = {
|
39
39
|
name: contains,
|
40
40
|
label: contains,
|
41
|
-
value: contains
|
41
|
+
value: contains
|
42
42
|
}
|
43
43
|
_textfield_visible.merge(contains_obj)
|
44
44
|
end
|
@@ -49,16 +49,16 @@ module Appium
|
|
49
49
|
# @param value [String, Integer] the text to match exactly.
|
50
50
|
# If int then the TextField at that index is returned.
|
51
51
|
# @return [TextField]
|
52
|
-
def textfield
|
52
|
+
def textfield(value)
|
53
53
|
# Don't use ele_index because that only works on one element type.
|
54
54
|
# iOS needs to combine textfield and secure to match Android.
|
55
55
|
if value.is_a? Numeric
|
56
56
|
index = value
|
57
|
-
|
57
|
+
fail "#{index} is not a valid index. Must be >= 1" if index <= 0
|
58
58
|
index -= 1 # eles_by_json is 0 indexed.
|
59
59
|
|
60
60
|
result = eles_by_json(_textfield_visible)[index]
|
61
|
-
|
61
|
+
fail _no_such_element if result.nil?
|
62
62
|
return result
|
63
63
|
end
|
64
64
|
|
@@ -69,7 +69,7 @@ module Appium
|
|
69
69
|
# If value is omitted, all TextFields are returned.
|
70
70
|
# @param value [String] the value to search for
|
71
71
|
# @return [Array<TextField>]
|
72
|
-
def textfields
|
72
|
+
def textfields(value = false)
|
73
73
|
return eles_by_json _textfield_visible unless value
|
74
74
|
eles_by_json _textfield_contains_string value
|
75
75
|
end
|
@@ -84,22 +84,22 @@ module Appium
|
|
84
84
|
# @return [TextField]
|
85
85
|
def last_textfield
|
86
86
|
result = eles_by_json(_textfield_visible).last
|
87
|
-
|
87
|
+
fail _no_such_element if result.nil?
|
88
88
|
result
|
89
89
|
end
|
90
90
|
|
91
91
|
# Find the first TextField that exactly matches value.
|
92
92
|
# @param value [String] the value to match exactly
|
93
93
|
# @return [TextField]
|
94
|
-
def textfield_exact
|
94
|
+
def textfield_exact(value)
|
95
95
|
ele_by_json _textfield_exact_string value
|
96
96
|
end
|
97
97
|
|
98
98
|
# Find all TextFields that exactly match value.
|
99
99
|
# @param value [String] the value to match exactly
|
100
100
|
# @return [Array<TextField>]
|
101
|
-
def textfields_exact
|
101
|
+
def textfields_exact(value)
|
102
102
|
eles_by_json _textfield_exact_string value
|
103
103
|
end
|
104
104
|
end # module Ios
|
105
|
-
end # module Appium
|
105
|
+
end # module Appium
|
@@ -5,7 +5,7 @@ module Appium
|
|
5
5
|
# Password character returned from value of UIASecureTextField
|
6
6
|
# @param length [Integer] the length of the password to generate
|
7
7
|
# @return [String] the returned string is of size length
|
8
|
-
def ios_password
|
8
|
+
def ios_password(length = 1)
|
9
9
|
8226.chr('UTF-8') * length
|
10
10
|
end
|
11
11
|
|
@@ -17,17 +17,17 @@ module Appium
|
|
17
17
|
# @option element [Object] the element to search. omit to search everything
|
18
18
|
# @option class_name [String,Symbol] the class name to filter on. case insensitive include match.
|
19
19
|
# @return [String]
|
20
|
-
def get_page
|
20
|
+
def get_page(element = source_window(0), class_name = nil)
|
21
21
|
lazy_load_strings # populate @strings_xml
|
22
22
|
class_name = class_name.to_s.downcase
|
23
23
|
|
24
24
|
# @private
|
25
|
-
def empty
|
26
|
-
(ele['name'] || ele['label'] || ele['value'])
|
25
|
+
def empty(ele)
|
26
|
+
(ele['name'] || ele['label'] || ele['value']).nil?
|
27
27
|
end
|
28
28
|
|
29
29
|
# @private
|
30
|
-
def fix_space
|
30
|
+
def fix_space(s)
|
31
31
|
# if s is an int, we can't call .empty
|
32
32
|
return nil if s.nil? || (s.respond_to?(:empty) && s.empty?)
|
33
33
|
# ints don't respond to force encoding
|
@@ -51,6 +51,9 @@ module Appium
|
|
51
51
|
visible = fix_space element['visible']
|
52
52
|
type = fix_space element['type']
|
53
53
|
|
54
|
+
# TODO: Rubocop warning cleanup
|
55
|
+
# rubocop:disable Metrics/BlockNesting
|
56
|
+
|
54
57
|
# if class_name is set, mark non-matches as invisible
|
55
58
|
visible = (type.downcase.include?(class_name)).to_s if class_name
|
56
59
|
if visible && visible == 'true'
|
@@ -75,6 +78,7 @@ module Appium
|
|
75
78
|
puts " value: #{value}" if value
|
76
79
|
puts " hint: #{hint}" if hint
|
77
80
|
end
|
81
|
+
# rubocop:enable Metrics/BlockNesting
|
78
82
|
|
79
83
|
# there may be many ids with the same value.
|
80
84
|
# output all exact matches.
|
@@ -93,10 +97,10 @@ module Appium
|
|
93
97
|
match_str = ''
|
94
98
|
max_len = id_matches.keys.max_by(&:length).length
|
95
99
|
|
96
|
-
# [0] = key, [1] =
|
97
|
-
id_matches.each do |key,
|
100
|
+
# [0] = key, [1] = val
|
101
|
+
id_matches.each do |key, val|
|
98
102
|
arrow_space = ' ' * (max_len - key.length).to_i
|
99
|
-
match_str
|
103
|
+
match_str += ' ' * 7 + "#{key} #{arrow_space}=> #{val}\n"
|
100
104
|
end
|
101
105
|
puts " id: #{match_str.strip}\n"
|
102
106
|
end
|
@@ -122,7 +126,7 @@ module Appium
|
|
122
126
|
# @option class [Symbol] class name to filter on
|
123
127
|
#
|
124
128
|
# @return [void]
|
125
|
-
def page
|
129
|
+
def page(opts = {})
|
126
130
|
if opts.is_a?(Hash)
|
127
131
|
window_number = opts.fetch :window, -1
|
128
132
|
class_name = opts.fetch :class, nil
|
@@ -154,7 +158,7 @@ module Appium
|
|
154
158
|
# Gets the JSON source of window number
|
155
159
|
# @param window_number [Integer] the int index of the target window
|
156
160
|
# @return [JSON]
|
157
|
-
def source_window
|
161
|
+
def source_window(window_number = 0)
|
158
162
|
# appium 1.0 still returns JSON when getTree() is invoked so this
|
159
163
|
# doesn't need to change to XML. If getTree() is removed then
|
160
164
|
# source_window will need to parse the elements of getTreeForXML()\
|
@@ -168,7 +172,7 @@ module Appium
|
|
168
172
|
#
|
169
173
|
# @param window_number [Integer] the int index of the target window
|
170
174
|
# @return [void]
|
171
|
-
def page_window
|
175
|
+
def page_window(window_number = 0)
|
172
176
|
get_page source_window window_number
|
173
177
|
nil
|
174
178
|
end
|
@@ -176,7 +180,7 @@ module Appium
|
|
176
180
|
# Find by id
|
177
181
|
# @param id [String] the id to search for
|
178
182
|
# @return [Element]
|
179
|
-
def id
|
183
|
+
def id(id)
|
180
184
|
find_element :id, id
|
181
185
|
end
|
182
186
|
|
@@ -184,32 +188,32 @@ module Appium
|
|
184
188
|
# @return [Array<Integer>]
|
185
189
|
def ios_version
|
186
190
|
ios_version = execute_script 'UIATarget.localTarget().systemVersion()'
|
187
|
-
ios_version.split('.').map
|
191
|
+
ios_version.split('.').map(&:to_i)
|
188
192
|
end
|
189
193
|
|
190
194
|
# Get the element of type class_name at matching index.
|
191
195
|
# @param class_name [String] the class name to find
|
192
196
|
# @param index [Integer] the index
|
193
197
|
# @return [Element]
|
194
|
-
def ele_index
|
195
|
-
|
198
|
+
def ele_index(class_name, index)
|
199
|
+
fail 'Index must be >= 1' unless index == 'last()' || (index.is_a?(Integer) && index >= 1)
|
196
200
|
elements = tags(class_name)
|
197
201
|
|
198
202
|
if index == 'last()'
|
199
203
|
result = elements.last
|
200
204
|
else
|
201
205
|
# elements array is 0 indexed
|
202
|
-
index
|
206
|
+
index -= 1
|
203
207
|
result = elements[index]
|
204
208
|
end
|
205
209
|
|
206
|
-
|
210
|
+
fail _no_such_element if result.nil?
|
207
211
|
result
|
208
212
|
end
|
209
213
|
|
210
214
|
# @private
|
211
|
-
def string_attr_exact
|
212
|
-
%
|
215
|
+
def string_attr_exact(class_name, attr, value)
|
216
|
+
%(//#{class_name}[@visible="true" and @#{attr}='#{value}'])
|
213
217
|
end
|
214
218
|
|
215
219
|
# Find the first element exactly matching class and attribute value.
|
@@ -218,7 +222,7 @@ module Appium
|
|
218
222
|
# @param attr [String] the attribute to inspect
|
219
223
|
# @param value [String] the expected value of the attribute
|
220
224
|
# @return [Element]
|
221
|
-
def find_ele_by_attr
|
225
|
+
def find_ele_by_attr(class_name, attr, value)
|
222
226
|
@driver.find_element :xpath, string_attr_exact(class_name, attr, value)
|
223
227
|
end
|
224
228
|
|
@@ -228,13 +232,13 @@ module Appium
|
|
228
232
|
# @param attr [String] the attribute to compare
|
229
233
|
# @param value [String] the value of the attribute that the element must have
|
230
234
|
# @return [Array<Element>]
|
231
|
-
def find_eles_by_attr
|
235
|
+
def find_eles_by_attr(class_name, attr, value)
|
232
236
|
@driver.find_elements :xpath, string_attr_exact(class_name, attr, value)
|
233
237
|
end
|
234
238
|
|
235
239
|
# @private
|
236
|
-
def string_attr_include
|
237
|
-
%
|
240
|
+
def string_attr_include(class_name, attr, value)
|
241
|
+
%(//#{class_name}[@visible="true" and contains(translate(@#{attr},'#{value.upcase}', '#{value}'), '#{value}')])
|
238
242
|
end
|
239
243
|
|
240
244
|
# Get the first tag by attribute that exactly matches value.
|
@@ -243,7 +247,7 @@ module Appium
|
|
243
247
|
# @param attr [String] the attribute to compare
|
244
248
|
# @param value [String] the value of the attribute that the element must include
|
245
249
|
# @return [Element] the element of type tag who's attribute includes value
|
246
|
-
def find_ele_by_attr_include
|
250
|
+
def find_ele_by_attr_include(class_name, attr, value)
|
247
251
|
@driver.find_element :xpath, string_attr_include(class_name, attr, value)
|
248
252
|
end
|
249
253
|
|
@@ -253,14 +257,14 @@ module Appium
|
|
253
257
|
# @param attr [String] the attribute to compare
|
254
258
|
# @param value [String] the value of the attribute that the element must include
|
255
259
|
# @return [Array<Element>] the elements of type tag who's attribute includes value
|
256
|
-
def find_eles_by_attr_include
|
260
|
+
def find_eles_by_attr_include(class_name, attr, value)
|
257
261
|
@driver.find_elements :xpath, string_attr_include(class_name, attr, value)
|
258
262
|
end
|
259
263
|
|
260
264
|
# Get the first tag that matches class_name
|
261
265
|
# @param class_name [String] the tag to match
|
262
266
|
# @return [Element]
|
263
|
-
def first_ele
|
267
|
+
def first_ele(class_name)
|
264
268
|
# XPath index starts at 1
|
265
269
|
ele_index class_name, 1
|
266
270
|
end
|
@@ -268,7 +272,7 @@ module Appium
|
|
268
272
|
# Get the last tag that matches class_name
|
269
273
|
# @param class_name [String] the tag to match
|
270
274
|
# @return [Element]
|
271
|
-
def last_ele
|
275
|
+
def last_ele(class_name)
|
272
276
|
ele_index class_name, 'last()'
|
273
277
|
end
|
274
278
|
|
@@ -276,22 +280,22 @@ module Appium
|
|
276
280
|
#
|
277
281
|
# @param class_name [String] the class_name to search for
|
278
282
|
# @return [Element]
|
279
|
-
def tag
|
280
|
-
ele_by_json(
|
281
|
-
|
282
|
-
|
283
|
-
|
283
|
+
def tag(class_name)
|
284
|
+
ele_by_json(
|
285
|
+
typeArray: [class_name],
|
286
|
+
onlyVisible: true
|
287
|
+
)
|
284
288
|
end
|
285
289
|
|
286
290
|
# Returns all visible elements matching class_name
|
287
291
|
#
|
288
292
|
# @param class_name [String] the class_name to search for
|
289
293
|
# @return [Element]
|
290
|
-
def tags
|
291
|
-
eles_by_json(
|
292
|
-
|
293
|
-
|
294
|
-
|
294
|
+
def tags(class_name)
|
295
|
+
eles_by_json(
|
296
|
+
typeArray: [class_name],
|
297
|
+
onlyVisible: true
|
298
|
+
)
|
295
299
|
end
|
296
300
|
|
297
301
|
# @private
|
@@ -302,11 +306,11 @@ module Appium
|
|
302
306
|
# @param element [String] the class name for the element
|
303
307
|
# @param value [String] the value to search for
|
304
308
|
# @return [String]
|
305
|
-
def string_visible_contains
|
309
|
+
def string_visible_contains(element, value)
|
306
310
|
contains = {
|
307
311
|
target: value,
|
308
312
|
substring: true,
|
309
|
-
insensitive: true
|
313
|
+
insensitive: true
|
310
314
|
}
|
311
315
|
|
312
316
|
{
|
@@ -314,7 +318,7 @@ module Appium
|
|
314
318
|
onlyVisible: true,
|
315
319
|
name: contains,
|
316
320
|
label: contains,
|
317
|
-
value: contains
|
321
|
+
value: contains
|
318
322
|
}
|
319
323
|
end
|
320
324
|
|
@@ -322,7 +326,7 @@ module Appium
|
|
322
326
|
# @param element [String] the class name for the element
|
323
327
|
# @param value [String] the value to search for
|
324
328
|
# @return [Element]
|
325
|
-
def ele_by_json_visible_contains
|
329
|
+
def ele_by_json_visible_contains(element, value)
|
326
330
|
ele_by_json string_visible_contains element, value
|
327
331
|
end
|
328
332
|
|
@@ -330,7 +334,7 @@ module Appium
|
|
330
334
|
# @param element [String] the class name for the element
|
331
335
|
# @param value [String] the value to search for
|
332
336
|
# @return [Array<Element>]
|
333
|
-
def eles_by_json_visible_contains
|
337
|
+
def eles_by_json_visible_contains(element, value)
|
334
338
|
eles_by_json string_visible_contains element, value
|
335
339
|
end
|
336
340
|
|
@@ -339,11 +343,11 @@ module Appium
|
|
339
343
|
# @param element [String] the class name for the element
|
340
344
|
# @param value [String] the value to search for
|
341
345
|
# @return [String]
|
342
|
-
def string_visible_exact
|
346
|
+
def string_visible_exact(element, value)
|
343
347
|
exact = {
|
344
348
|
target: value,
|
345
349
|
substring: false,
|
346
|
-
insensitive: false
|
350
|
+
insensitive: false
|
347
351
|
}
|
348
352
|
|
349
353
|
{
|
@@ -351,7 +355,7 @@ module Appium
|
|
351
355
|
onlyVisible: true,
|
352
356
|
name: exact,
|
353
357
|
label: exact,
|
354
|
-
value: exact
|
358
|
+
value: exact
|
355
359
|
}
|
356
360
|
end
|
357
361
|
|
@@ -359,7 +363,7 @@ module Appium
|
|
359
363
|
# @param element [String] the class name for the element
|
360
364
|
# @param value [String] the value to search for
|
361
365
|
# @return [Element]
|
362
|
-
def ele_by_json_visible_exact
|
366
|
+
def ele_by_json_visible_exact(element, value)
|
363
367
|
ele_by_json string_visible_exact element, value
|
364
368
|
end
|
365
369
|
|
@@ -367,7 +371,7 @@ module Appium
|
|
367
371
|
# @param element [String] the class name for the element
|
368
372
|
# @param value [String] the value to search for
|
369
373
|
# @return [Element]
|
370
|
-
def eles_by_json_visible_exact
|
374
|
+
def eles_by_json_visible_exact(element, value)
|
371
375
|
eles_by_json string_visible_exact element, value
|
372
376
|
end
|
373
377
|
|
@@ -377,22 +381,22 @@ module Appium
|
|
377
381
|
# If close key is present then tap it.
|
378
382
|
# @param close_key [String] close key to tap. Default value is 'Done'
|
379
383
|
# @return [void]
|
380
|
-
def hide_ios_keyboard
|
381
|
-
|
382
|
-
|
383
|
-
app specific circumstances. webview keyboard will require a window.tap for example.
|
384
|
-
|
385
|
-
Find the top left corner of the keyboard and move up 10 pixels (origin.y - 10)
|
386
|
-
now swipe down until the end of the window - 10 pixels.
|
387
|
-
-10 to ensure we're not going outside the window bounds.
|
388
|
-
|
389
|
-
Swiping inside the keyboard will not dismiss it.
|
390
|
-
|
391
|
-
If the 'Done' key exists then that should be pressed to dismiss the keyboard
|
392
|
-
because swiping to dismiss works only if such key doesn't exist.
|
393
|
-
|
394
|
-
Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
|
395
|
-
|
384
|
+
def hide_ios_keyboard(close_key = 'Done')
|
385
|
+
#
|
386
|
+
# TODO: there are many various ways to hide the keyboard that work in different
|
387
|
+
# app specific circumstances. webview keyboard will require a window.tap for example.
|
388
|
+
#
|
389
|
+
# Find the top left corner of the keyboard and move up 10 pixels (origin.y - 10)
|
390
|
+
# now swipe down until the end of the window - 10 pixels.
|
391
|
+
# -10 to ensure we're not going outside the window bounds.
|
392
|
+
#
|
393
|
+
# Swiping inside the keyboard will not dismiss it.
|
394
|
+
#
|
395
|
+
# If the 'Done' key exists then that should be pressed to dismiss the keyboard
|
396
|
+
# because swiping to dismiss works only if such key doesn't exist.
|
397
|
+
#
|
398
|
+
# Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
|
399
|
+
#
|
396
400
|
dismiss_keyboard = (<<-JS).strip
|
397
401
|
if (!au.mainApp().keyboard().isNil()) {
|
398
402
|
var key = au.mainApp().keyboard().buttons()['#{close_key}']
|
@@ -431,11 +435,11 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
|
|
431
435
|
#
|
432
436
|
# visible - if true, only visible elements are returned. default true
|
433
437
|
#
|
434
|
-
def _all_pred
|
438
|
+
def _all_pred(opts)
|
435
439
|
predicate = opts[:predicate]
|
436
|
-
|
440
|
+
fail 'predicate must be provided' unless predicate
|
437
441
|
visible = opts.fetch :visible, true
|
438
|
-
%
|
442
|
+
%($.mainApp().getAllWithPredicate("#{predicate}", #{visible});)
|
439
443
|
end
|
440
444
|
|
441
445
|
# returns element matching predicate contained in the main app
|
@@ -444,7 +448,7 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
|
|
444
448
|
#
|
445
449
|
# visible - if true, only visible elements are returned. default true
|
446
450
|
# @return [Element]
|
447
|
-
def ele_with_pred
|
451
|
+
def ele_with_pred(opts)
|
448
452
|
# true = return only visible
|
449
453
|
find_element(:uiautomation, _all_pred(opts))
|
450
454
|
end
|
@@ -455,7 +459,7 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
|
|
455
459
|
#
|
456
460
|
# visible - if true, only visible elements are returned. default true
|
457
461
|
# @return [Array<Element>]
|
458
|
-
def eles_with_pred
|
462
|
+
def eles_with_pred(opts)
|
459
463
|
find_elements(:uiautomation, _all_pred(opts))
|
460
464
|
end
|
461
465
|
|
@@ -465,23 +469,23 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
|
|
465
469
|
_print_source get_source
|
466
470
|
end
|
467
471
|
|
468
|
-
def _validate_object
|
469
|
-
|
472
|
+
def _validate_object(*objects)
|
473
|
+
fail 'objects must be an array' unless objects.is_a? Array
|
470
474
|
objects.each do |obj|
|
471
475
|
next unless obj # obj may be nil. if so, ignore.
|
472
476
|
|
473
477
|
valid_keys = [:target, :substring, :insensitive]
|
474
478
|
unknown_keys = obj.keys - valid_keys
|
475
|
-
|
479
|
+
fail "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
|
476
480
|
|
477
481
|
target = obj[:target]
|
478
|
-
|
482
|
+
fail 'target must be a string' unless target.is_a? String
|
479
483
|
|
480
484
|
substring = obj[:substring]
|
481
|
-
|
485
|
+
fail 'substring must be a boolean' unless [true, false].include? substring
|
482
486
|
|
483
487
|
insensitive = obj[:insensitive]
|
484
|
-
|
488
|
+
fail 'insensitive must be a boolean' unless [true, false].include? insensitive
|
485
489
|
end
|
486
490
|
end
|
487
491
|
|
@@ -513,33 +517,42 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
|
|
513
517
|
# }
|
514
518
|
# }
|
515
519
|
#
|
516
|
-
def _by_json
|
520
|
+
def _by_json(opts)
|
517
521
|
valid_keys = [:typeArray, :onlyFirst, :onlyVisible, :name, :label, :value]
|
518
522
|
unknown_keys = opts.keys - valid_keys
|
519
|
-
|
523
|
+
fail "Unknown keys: #{unknown_keys}" unless unknown_keys.empty?
|
520
524
|
|
521
|
-
|
522
|
-
|
525
|
+
type_array = opts[:typeArray]
|
526
|
+
fail 'typeArray must be an array' unless type_array.is_a? Array
|
523
527
|
|
524
|
-
|
525
|
-
|
528
|
+
only_first = opts[:onlyFirst]
|
529
|
+
fail 'onlyFirst must be a boolean' unless [true, false].include? only_first
|
526
530
|
|
527
|
-
|
528
|
-
|
531
|
+
only_visible = opts[:onlyVisible]
|
532
|
+
fail 'onlyVisible must be a boolean' unless [true, false].include? only_visible
|
529
533
|
|
530
534
|
# name/label/value are optional. when searching for class only, then none
|
531
535
|
# will be present.
|
532
536
|
_validate_object opts[:name], opts[:label], opts[:value]
|
533
537
|
|
538
|
+
# note that mainWindow is sometimes nil so it's passed as a param
|
539
|
+
# $._elementOrElementsByType will validate that the window isn't nil
|
534
540
|
element_or_elements_by_type = <<-JS
|
535
541
|
(function() {
|
536
|
-
var opts = #{opts.to_json}
|
542
|
+
var opts = #{opts.to_json};
|
543
|
+
var result = false;
|
544
|
+
|
545
|
+
try {
|
546
|
+
result = $._elementOrElementsByType($.mainWindow(), opts);
|
547
|
+
} catch (e) {
|
548
|
+
}
|
537
549
|
|
538
|
-
return
|
550
|
+
return result;
|
539
551
|
})();
|
540
552
|
JS
|
541
553
|
|
542
|
-
execute_script element_or_elements_by_type
|
554
|
+
res = execute_script element_or_elements_by_type
|
555
|
+
res ? res : fail(Selenium::Client::CommandError, 'mainWindow is nil')
|
543
556
|
end
|
544
557
|
|
545
558
|
# example usage:
|
@@ -553,16 +566,16 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
|
|
553
566
|
# insensitive: false,
|
554
567
|
# },
|
555
568
|
# })
|
556
|
-
def eles_by_json
|
569
|
+
def eles_by_json(opts)
|
557
570
|
opts[:onlyFirst] = false
|
558
|
-
|
571
|
+
_by_json opts
|
559
572
|
end
|
560
573
|
|
561
574
|
# see eles_by_json
|
562
|
-
def ele_by_json
|
575
|
+
def ele_by_json(opts)
|
563
576
|
opts[:onlyFirst] = true
|
564
577
|
result = _by_json(opts).first
|
565
|
-
|
578
|
+
fail _no_such_element if result.nil?
|
566
579
|
result
|
567
580
|
end
|
568
581
|
|
@@ -573,4 +586,4 @@ Don't use window.tap. See https://github.com/appium/appium-uiauto/issues/28
|
|
573
586
|
@driver.page_source
|
574
587
|
end
|
575
588
|
end # module Ios
|
576
|
-
end # module Appium
|
589
|
+
end # module Appium
|