appium_lib 6.0.0 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +28 -0
  4. data/.travis.yml +10 -0
  5. data/Rakefile +9 -1
  6. data/android_tests/Gemfile +1 -1
  7. data/android_tests/Rakefile +20 -13
  8. data/android_tests/lib/android/specs/android/element/alert.rb +1 -1
  9. data/android_tests/lib/android/specs/android/element/button.rb +2 -2
  10. data/android_tests/lib/android/specs/android/element/generic.rb +1 -2
  11. data/android_tests/lib/android/specs/android/element/text.rb +2 -3
  12. data/android_tests/lib/android/specs/android/element/textfield.rb +2 -2
  13. data/android_tests/lib/android/specs/android/helper.rb +5 -3
  14. data/android_tests/lib/android/specs/android/patch.rb +2 -2
  15. data/android_tests/lib/android/specs/common/device.rb +16 -9
  16. data/android_tests/lib/android/specs/common/device_touchaction.rb +5 -2
  17. data/android_tests/lib/android/specs/common/element/window.rb +1 -1
  18. data/android_tests/lib/android/specs/common/helper.rb +14 -15
  19. data/android_tests/lib/android/specs/common/patch.rb +11 -9
  20. data/android_tests/lib/android/specs/common/version.rb +3 -3
  21. data/android_tests/lib/android/specs/common/web_context.rb +2 -3
  22. data/android_tests/lib/android/specs/driver.rb +38 -29
  23. data/android_tests/lib/android/specs/install.rb +3 -3
  24. data/android_tests/lib/format.rb +6 -8
  25. data/android_tests/lib/run.rb +25 -17
  26. data/android_tests/readme.md +4 -2
  27. data/appium_lib.gemspec +13 -11
  28. data/contributing.md +1 -1
  29. data/docs/android_docs.md +358 -274
  30. data/docs/ios_docs.md +333 -270
  31. data/docs/migration.md +10 -0
  32. data/docs_gen/make_docs.rb +3 -1
  33. data/ios_tests/Gemfile +1 -1
  34. data/ios_tests/Rakefile +17 -10
  35. data/ios_tests/appium.txt +1 -1
  36. data/ios_tests/lib/common.rb +8 -4
  37. data/ios_tests/lib/format.rb +5 -7
  38. data/ios_tests/lib/ios/specs/common/element/window.rb +1 -1
  39. data/ios_tests/lib/ios/specs/common/helper.rb +40 -39
  40. data/ios_tests/lib/ios/specs/common/patch.rb +15 -11
  41. data/ios_tests/lib/ios/specs/common/version.rb +3 -3
  42. data/ios_tests/lib/ios/specs/common/web_context.rb +1 -2
  43. data/ios_tests/lib/ios/specs/device/device.rb +7 -7
  44. data/ios_tests/lib/ios/specs/device/multi_touch.rb +6 -8
  45. data/ios_tests/lib/ios/specs/device/touch_actions.rb +12 -12
  46. data/ios_tests/lib/ios/specs/driver.rb +23 -22
  47. data/ios_tests/lib/ios/specs/ios/element/alert.rb +6 -2
  48. data/ios_tests/lib/ios/specs/ios/element/button.rb +2 -2
  49. data/ios_tests/lib/ios/specs/ios/element/generic.rb +1 -1
  50. data/ios_tests/lib/ios/specs/ios/element/text.rb +4 -1
  51. data/ios_tests/lib/ios/specs/ios/element/textfield.rb +6 -6
  52. data/ios_tests/lib/ios/specs/ios/helper.rb +5 -5
  53. data/ios_tests/lib/ios/specs/ios/patch.rb +2 -2
  54. data/ios_tests/lib/run.rb +1 -1
  55. data/ios_tests/readme.md +3 -3
  56. data/ios_tests/upload/sauce_storage.rb +8 -8
  57. data/ios_tests/upload/upload.rb +1 -1
  58. data/lib/appium_lib/android/client_xpath.rb +7 -7
  59. data/lib/appium_lib/android/element/alert.rb +2 -2
  60. data/lib/appium_lib/android/element/button.rb +16 -16
  61. data/lib/appium_lib/android/element/generic.rb +12 -13
  62. data/lib/appium_lib/android/element/text.rb +5 -5
  63. data/lib/appium_lib/android/element/textfield.rb +5 -5
  64. data/lib/appium_lib/android/helper.rb +82 -52
  65. data/lib/appium_lib/android/mobile_methods.rb +2 -2
  66. data/lib/appium_lib/android/patch.rb +3 -3
  67. data/lib/appium_lib/common/element/window.rb +1 -1
  68. data/lib/appium_lib/common/helper.rb +30 -35
  69. data/lib/appium_lib/common/patch.rb +22 -20
  70. data/lib/appium_lib/common/version.rb +3 -3
  71. data/lib/appium_lib/common/wait.rb +9 -10
  72. data/lib/appium_lib/device/device.rb +39 -33
  73. data/lib/appium_lib/device/multi_touch.rb +5 -7
  74. data/lib/appium_lib/device/touch_actions.rb +14 -15
  75. data/lib/appium_lib/driver.rb +97 -76
  76. data/lib/appium_lib/ios/element/alert.rb +1 -1
  77. data/lib/appium_lib/ios/element/button.rb +5 -5
  78. data/lib/appium_lib/ios/element/generic.rb +5 -6
  79. data/lib/appium_lib/ios/element/text.rb +5 -5
  80. data/lib/appium_lib/ios/element/textfield.rb +15 -15
  81. data/lib/appium_lib/ios/helper.rb +103 -90
  82. data/lib/appium_lib/ios/mobile_methods.rb +2 -2
  83. data/lib/appium_lib/ios/patch.rb +4 -4
  84. data/lib/appium_lib/logger.rb +7 -5
  85. data/lib/appium_lib/rails/duplicable.rb +3 -1
  86. data/readme.md +7 -1
  87. data/release_notes.md +152 -0
  88. metadata +28 -54
@@ -1,44 +1,43 @@
1
1
  module Appium
2
2
  module Android
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 value
6
+ def find(value)
8
7
  complex_find_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 value
13
+ def finds(value)
15
14
  complex_finds_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 value
20
+ def find_exact(value)
22
21
  complex_find_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 value
27
+ def finds_exact(value)
29
28
  complex_finds_exact '*', value
30
29
  end
31
30
 
32
31
  # @private
33
- def scroll_uiselector content
34
- "new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(#{content}.instance(0));"
35
- end
32
+ def scroll_uiselector(content)
33
+ "new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(#{content}.instance(0));"
34
+ end
36
35
 
37
36
  # Scroll to the first element containing target text or description.
38
37
  # @param text [String] the text to search for in the text value and content description
39
38
  # @return [Element] the element scrolled to
40
- def scroll_to text
41
- text = %Q("#{text}")
39
+ def scroll_to(text)
40
+ text = %("#{text}")
42
41
 
43
42
  args = scroll_uiselector("new UiSelector().textContains(#{text})") +
44
43
  scroll_uiselector("new UiSelector().descriptionContains(#{text})")
@@ -49,8 +48,8 @@ module Appium
49
48
  # Scroll to the first element with the exact target text or description.
50
49
  # @param text [String] the text to search for in the text value and content description
51
50
  # @return [Element] the element scrolled to
52
- def scroll_to_exact text
53
- text = %Q("#{text}")
51
+ def scroll_to_exact(text)
52
+ text = %("#{text}")
54
53
 
55
54
  args = scroll_uiselector("new UiSelector().text(#{text})") +
56
55
  scroll_uiselector("new UiSelector().description(#{text})")
@@ -58,4 +57,4 @@ module Appium
58
57
  find_element :uiautomator, args
59
58
  end
60
59
  end # module Android
61
- end # module Appium
60
+ 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 TextView at that index is returned.
9
9
  # @return [TextView]
10
- def text value
10
+ def text(value)
11
11
  return ele_index TextView, value if value.is_a? Numeric
12
12
  complex_find_contains TextView, value
13
13
  end
@@ -16,7 +16,7 @@ module Appium
16
16
  # If value is omitted, all texts are returned.
17
17
  # @param value [String] the value to search for
18
18
  # @return [Array<TextView>]
19
- def texts value=false
19
+ def texts(value = false)
20
20
  return tags TextView unless value
21
21
  complex_finds_contains TextView, value
22
22
  end
@@ -36,15 +36,15 @@ module Appium
36
36
  # Find the first TextView that exactly matches value.
37
37
  # @param value [String] the value to match exactly
38
38
  # @return [TextView]
39
- def text_exact value
39
+ def text_exact(value)
40
40
  complex_find_exact TextView, value
41
41
  end
42
42
 
43
43
  # Find all TextViews that exactly match value.
44
44
  # @param value [String] the value to match exactly
45
45
  # @return [Array<TextView>]
46
- def texts_exact value
46
+ def texts_exact(value)
47
47
  complex_finds_exact TextView, value
48
48
  end
49
49
  end # module Android
50
- end # module Appium
50
+ end # module Appium
@@ -6,7 +6,7 @@ module Appium
6
6
  # @param value [String, Integer] the text to match exactly.
7
7
  # If int then the EditText at that index is returned.
8
8
  # @return [EditText]
9
- def textfield value
9
+ def textfield(value)
10
10
  return ele_index EditText, value if value.is_a? Numeric
11
11
  complex_find_contains EditText, value
12
12
  end
@@ -15,7 +15,7 @@ module Appium
15
15
  # If value is omitted, all EditTexts are returned.
16
16
  # @param value [String] the value to search for
17
17
  # @return [Array<EditText>]
18
- def textfields value=false
18
+ def textfields(value = false)
19
19
  return tags EditText unless value
20
20
  complex_finds_contains EditText, value
21
21
  end
@@ -35,15 +35,15 @@ module Appium
35
35
  # Find the first EditText that exactly matches value.
36
36
  # @param value [String] the value to match exactly
37
37
  # @return [EditText]
38
- def textfield_exact value
38
+ def textfield_exact(value)
39
39
  complex_find_exact EditText, value
40
40
  end
41
41
 
42
42
  # Find all EditTexts that exactly match value.
43
43
  # @param value [String] the value to match exactly
44
44
  # @return [Array<EditText>]
45
- def textfields_exact value
45
+ def textfields_exact(value)
46
46
  complex_finds_exact EditText, value
47
47
  end
48
48
  end # module Android
49
- end # module Appium
49
+ end # module Appium
@@ -3,14 +3,10 @@ module Appium
3
3
  # @private
4
4
  # http://nokogiri.org/Nokogiri/XML/SAX.html
5
5
  class AndroidElements < Nokogiri::XML::SAX::Document
6
- attr_reader :result, :keys, :instance
7
-
8
- def filter
9
- @filter
10
- end
6
+ attr_reader :result, :keys, :instance, :filter
11
7
 
12
8
  # convert to string to support symbols
13
- def filter= value
9
+ def filter=(value)
14
10
  # nil and false disable the filter
15
11
  return @filter = false unless value
16
12
  @filter = value.to_s.downcase
@@ -19,17 +15,17 @@ module Appium
19
15
  def initialize
20
16
  reset
21
17
  @filter = false
22
- @instance = Hash.new -1
18
+ @instance = Hash.new(-1)
23
19
  end
24
20
 
25
21
  def reset
26
22
  @result = ''
27
- @keys = %w[text resource-id content-desc]
28
- @instance = Hash.new -1
23
+ @keys = %w(text resource-id content-desc)
24
+ @instance = Hash.new(-1)
29
25
  end
30
26
 
31
27
  # http://nokogiri.org/Nokogiri/XML/SAX/Document.html
32
- def start_element name, attrs = []
28
+ def start_element(name, attrs = [])
33
29
  return if filter && !name.downcase.include?(filter)
34
30
 
35
31
  # instance numbers start at 0.
@@ -38,15 +34,18 @@ module Appium
38
34
  attributes = {}
39
35
 
40
36
  attrs.each do |key, value|
41
- if keys.include?(key) && !value.empty?
42
- attributes[key] = value
43
- end
37
+ attributes[key] = value if keys.include?(key) && !value.empty?
44
38
  end
45
39
 
46
40
  # scoped to: text resource-id content-desc
47
41
  attributes_values = attributes.values
48
- id_matches = $driver.lazy_load_strings.select do |key, value|
49
- attributes_values.include? value
42
+ strings = $driver.lazy_load_strings
43
+ id_matches = []
44
+
45
+ unless strings.empty?
46
+ id_matches = strings.select do |_key, value|
47
+ attributes_values.include? value
48
+ end
50
49
  end
51
50
 
52
51
  string_ids = nil
@@ -56,7 +55,7 @@ module Appium
56
55
  string_ids = ''
57
56
 
58
57
  # add first
59
- string_ids += "#{id_matches.shift[0]}\n"
58
+ string_ids += "#{id_matches.shift[0]}\n"
60
59
 
61
60
  # use padding for remaining values
62
61
  # [0] = key, [1] = value
@@ -76,8 +75,8 @@ module Appium
76
75
  string += " text: #{text}\n" unless text.nil?
77
76
  string += " desc: #{desc}\n" unless desc.nil?
78
77
  end
79
- string += " id: #{id}\n" unless id.nil?
80
- string += " strings.xml: #{string_ids}" unless string_ids.nil?
78
+ string += " id: #{id}\n" unless id.nil?
79
+ string += " strings.xml: #{string_ids}" unless string_ids.nil?
81
80
 
82
81
  @result += "\n#{name} (#{number})\n#{string}" unless attributes.empty?
83
82
  end
@@ -86,7 +85,7 @@ module Appium
86
85
  # Fix uiautomator's xml dump.
87
86
  # https://github.com/appium/appium/issues/2822
88
87
  # https://code.google.com/p/android/issues/detail?id=74143
89
- def _fix_android_native_source source
88
+ def _fix_android_native_source(source)
90
89
  # <android.app.ActionBar$Tab
91
90
  # <android.app.ActionBar $ Tab
92
91
 
@@ -105,8 +104,8 @@ module Appium
105
104
 
106
105
  # <android.app.ActionBar$Tab => <android.app.ActionBar.Tab
107
106
  # </android.app.ActionBar$Tab> => </android.app.ActionBar.Tab>
108
- source = source.gsub(/<#{before}\s*\$\s*#{after}/, "<#{fixed}").
109
- gsub(/<\/#{before}\s*\$\s*#{after}>/, "</#{fixed}>")
107
+ source = source.gsub(/<#{before}\s*\$\s*#{after}/,
108
+ "<#{fixed}").gsub(/<\/#{before}\s*\$\s*#{after}>/, "</#{fixed}>")
110
109
  end
111
110
 
112
111
  source
@@ -124,7 +123,7 @@ module Appium
124
123
  # @param class_name [String] the class name to filter on.
125
124
  # if false (default) then all classes will be inspected
126
125
  # @return [String]
127
- def get_android_inspect class_name=false
126
+ def get_android_inspect(class_name = false)
128
127
  source = get_source
129
128
 
130
129
  doctype_string = '<!doctyp'
@@ -150,7 +149,7 @@ module Appium
150
149
  # @option class [Symbol] the class name to filter on. case insensitive include match.
151
150
  # if nil (default) then all classes will be inspected
152
151
  # @return [void]
153
- def page opts={}
152
+ def page(opts = {})
154
153
  class_name = opts.is_a?(Hash) ? opts.fetch(:class, nil) : opts
155
154
  puts get_android_inspect class_name
156
155
  nil
@@ -160,7 +159,8 @@ module Appium
160
159
  # Works on local host only (not remote).
161
160
 
162
161
  # example line:
163
- # "mFocusedApp=AppWindowToken{b1420058 token=Token{b128add0 ActivityRecord{b1264d10 u0 com.example.android.apis/.ApiDemos t23}}}"
162
+ # "mFocusedApp=AppWindowToken{b1420058 token=Token{b128add0
163
+ # ActivityRecord{b1264d10 u0 com.example.android.apis/.ApiDemos t23}}}"
164
164
  def current_app
165
165
  line = `adb shell dumpsys window windows`.each_line.grep(/mFocusedApp/).first.strip
166
166
 
@@ -169,7 +169,7 @@ module Appium
169
169
 
170
170
  # @private
171
171
  # noinspection RubyArgCount
172
- def _parse_current_app_line line
172
+ def _parse_current_app_line(line)
173
173
  match = line.match(/ ([^\/ ]+\/[^ }]+)[ }]/)
174
174
  return nil unless match && match[1]
175
175
 
@@ -185,7 +185,7 @@ module Appium
185
185
  # Find the first matching element by id
186
186
  # @param id [String] the id to search for
187
187
  # @return [Element]
188
- def id id
188
+ def id(id)
189
189
  # Android auto resolves strings.xml ids
190
190
  find_element :id, id
191
191
  end
@@ -193,7 +193,7 @@ module Appium
193
193
  # Find all matching elements by id
194
194
  # @param id [String] the id to search for
195
195
  # @return [Element]
196
- def ids id
196
+ def ids(id)
197
197
  # Android auto resolves strings.xml ids
198
198
  find_elements :id, id
199
199
  end
@@ -202,13 +202,13 @@ module Appium
202
202
  # @param class_name [String] the class name to find
203
203
  # @param index [Integer] the index
204
204
  # @return [Element] the found element of type class_name
205
- def ele_index class_name, index
205
+ def ele_index(class_name, index)
206
206
  results = tags(class_name)
207
207
  if index == 'last()'
208
208
  index = results.length
209
209
  index -= 1 if index >= 0
210
210
  else
211
- raise 'Index must be >= 1' unless index >= 1
211
+ fail 'Index must be >= 1' unless index >= 1
212
212
  index -= 1 if index >= 1
213
213
  end
214
214
 
@@ -220,14 +220,14 @@ module Appium
220
220
  # Find the first element that matches class_name
221
221
  # @param class_name [String] the tag to match
222
222
  # @return [Element]
223
- def first_ele class_name
223
+ def first_ele(class_name)
224
224
  tag(class_name)
225
225
  end
226
226
 
227
227
  # Find the last element that matches class_name
228
228
  # @param class_name [String] the tag to match
229
229
  # @return [Element]
230
- def last_ele class_name
230
+ def last_ele(class_name)
231
231
  ele_index class_name, 'last()'
232
232
  end
233
233
 
@@ -235,7 +235,7 @@ module Appium
235
235
  #
236
236
  # @param class_name [String] the class_name to search for
237
237
  # @return [Element]
238
- def tag class_name
238
+ def tag(class_name)
239
239
  find_element :class, class_name
240
240
  end
241
241
 
@@ -243,11 +243,41 @@ module Appium
243
243
  #
244
244
  # @param class_name [String] the class_name to search for
245
245
  # @return [Element]
246
- def tags class_name
246
+ def tags(class_name)
247
247
  find_elements :class, class_name
248
248
  end
249
249
 
250
250
  # @private
251
+ # Detects if the string represents a resourceId
252
+ # resourceId is only supported on API >= 18 devices
253
+ #
254
+ # @param string [String] the string check for a resourceId
255
+ # value will be auto unquoted
256
+ # @param on_match [String] the string to return on resourceId match
257
+ #
258
+ # @return [String] empty string on failure, on_match on successful match
259
+ def _resource_id(string, on_match)
260
+ return '' unless string
261
+
262
+ # unquote the string
263
+ # "com.example.Test:id/enter" -> com.example.Test:id/enter
264
+ unquote = string.match(/"(.+)"/)
265
+ string = unquote[1] if unquote
266
+
267
+ # java_package : type / name
268
+ #
269
+ # com.example.Test:id/enter
270
+ #
271
+ # ^[a-zA-Z_] - Java package must start with letter or underscore
272
+ # [a-zA-Z0-9\._]* - Java package may contain letters, numbers, periods and underscores
273
+ # : - : ends the package and starts the type
274
+ # [^\/]+ - type is made up of at least one non-/ characters
275
+ # \\/ - / ends the type and starts the name
276
+ # [\S]+$ - the name contains at least one non-space character and then the line is ended
277
+ resource_id = /^[a-zA-Z_][a-zA-Z0-9\._]*:[^\/]+\/[\S]+$/
278
+ string.match(resource_id) ? on_match : ''
279
+ end
280
+
251
281
  # Returns a string that matches the first element that contains value
252
282
  #
253
283
  # example: complex_find_contains 'UIATextField', 'sign in'
@@ -255,19 +285,19 @@ module Appium
255
285
  # @param class_name [String] the class name for the element
256
286
  # @param value [String] the value to search for
257
287
  # @return [String]
258
- def string_visible_contains class_name, value
259
- value = %Q("#{value}")
288
+ def string_visible_contains(class_name, value)
289
+ value = %("#{value}")
260
290
 
261
291
  if class_name == '*'
262
- return "new UiSelector().resourceId(#{value});" +
263
- "new UiSelector().descriptionContains(#{value});" +
292
+ return _resource_id(value, "new UiSelector().resourceId(#{value});") +
293
+ "new UiSelector().descriptionContains(#{value});" \
264
294
  "new UiSelector().textContains(#{value});"
265
295
  end
266
296
 
267
- class_name = %Q("#{class_name}")
297
+ class_name = %("#{class_name}")
268
298
 
269
- "new UiSelector().className(#{class_name}).resourceId(#{value});" +
270
- "new UiSelector().className(#{class_name}).descriptionContains(#{value});" +
299
+ _resource_id(value, "new UiSelector().className(#{class_name}).resourceId(#{value});") +
300
+ "new UiSelector().className(#{class_name}).descriptionContains(#{value});" \
271
301
  "new UiSelector().className(#{class_name}).textContains(#{value});"
272
302
  end
273
303
 
@@ -275,7 +305,7 @@ module Appium
275
305
  # @param element [String] the class name for the element
276
306
  # @param value [String] the value to search for
277
307
  # @return [Element]
278
- def complex_find_contains element, value
308
+ def complex_find_contains(element, value)
279
309
  find_element :uiautomator, string_visible_contains(element, value)
280
310
  end
281
311
 
@@ -283,7 +313,7 @@ module Appium
283
313
  # @param element [String] the class name for the element
284
314
  # @param value [String] the value to search for
285
315
  # @return [Array<Element>]
286
- def complex_finds_contains element, value
316
+ def complex_finds_contains(element, value)
287
317
  find_elements :uiautomator, string_visible_contains(element, value)
288
318
  end
289
319
 
@@ -292,19 +322,19 @@ module Appium
292
322
  # @param class_name [String] the class name for the element
293
323
  # @param value [String] the value to search for
294
324
  # @return [String]
295
- def string_visible_exact class_name, value
296
- value = %Q("#{value}")
325
+ def string_visible_exact(class_name, value)
326
+ value = %("#{value}")
297
327
 
298
328
  if class_name == '*'
299
- return "new UiSelector().resourceId(#{value});" +
300
- "new UiSelector().description(#{value});" +
329
+ return _resource_id(value, "new UiSelector().resourceId(#{value});") +
330
+ "new UiSelector().description(#{value});" \
301
331
  "new UiSelector().text(#{value});"
302
332
  end
303
333
 
304
- class_name = %Q("#{class_name}")
334
+ class_name = %("#{class_name}")
305
335
 
306
- "new UiSelector().className(#{class_name}).resourceId(#{value});" +
307
- "new UiSelector().className(#{class_name}).description(#{value});" +
336
+ _resource_id(value, "new UiSelector().className(#{class_name}).resourceId(#{value});") +
337
+ "new UiSelector().className(#{class_name}).description(#{value});" \
308
338
  "new UiSelector().className(#{class_name}).text(#{value});"
309
339
  end
310
340
 
@@ -312,7 +342,7 @@ module Appium
312
342
  # @param class_name [String] the class name for the element
313
343
  # @param value [String] the value to search for
314
344
  # @return [Element]
315
- def complex_find_exact class_name, value
345
+ def complex_find_exact(class_name, value)
316
346
  find_element :uiautomator, string_visible_exact(class_name, value)
317
347
  end
318
348
 
@@ -320,7 +350,7 @@ module Appium
320
350
  # @param class_name [String] the class name for the element
321
351
  # @param value [String] the value to search for
322
352
  # @return [Element]
323
- def complex_finds_exact class_name, value
353
+ def complex_finds_exact(class_name, value)
324
354
  find_elements :uiautomator, string_visible_exact(class_name, value)
325
355
  end
326
356
 
@@ -334,4 +364,4 @@ module Appium
334
364
  src
335
365
  end
336
366
  end # module Android
337
- end # module Appium
367
+ end # module Appium