appium_lib 0.24.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +17 -8
  3. data/android_tests/Gemfile +1 -0
  4. data/android_tests/LICENSE-2.0.txt +202 -0
  5. data/android_tests/Rakefile +61 -0
  6. data/android_tests/api.apk +0 -0
  7. data/android_tests/appium.txt +3 -0
  8. data/android_tests/flaky.txt +1 -0
  9. data/android_tests/lib/android/specs/android/dynamic.rb +5 -0
  10. data/android_tests/lib/android/specs/android/element/alert.rb +41 -0
  11. data/android_tests/lib/android/specs/android/element/button.rb +55 -0
  12. data/android_tests/lib/android/specs/android/element/generic.rb +48 -0
  13. data/android_tests/lib/android/specs/android/element/text.rb +39 -0
  14. data/android_tests/lib/android/specs/android/element/textfield.rb +60 -0
  15. data/android_tests/lib/android/specs/android/helper.rb +80 -0
  16. data/android_tests/lib/android/specs/android/patch.rb +14 -0
  17. data/android_tests/lib/android/specs/common/device.rb +117 -0
  18. data/android_tests/lib/android/specs/common/element/window.rb +9 -0
  19. data/android_tests/lib/android/specs/common/helper.rb +112 -0
  20. data/android_tests/lib/android/specs/common/patch.rb +69 -0
  21. data/android_tests/lib/android/specs/common/version.rb +9 -0
  22. data/android_tests/lib/android/specs/driver.rb +174 -0
  23. data/android_tests/lib/format.rb +49 -0
  24. data/android_tests/lib/run.rb +72 -0
  25. data/android_tests/readme.md +27 -0
  26. data/appium_lib.gemspec +8 -5
  27. data/docs/android_docs.md +1052 -716
  28. data/docs/ios_docs.md +657 -834
  29. data/docs_gen/make_docs.rb +1 -3
  30. data/ios_tests/Gemfile +1 -0
  31. data/ios_tests/LICENSE-2.0.txt +202 -0
  32. data/ios_tests/Rakefile +47 -0
  33. data/ios_tests/UICatalog.app.zip +0 -0
  34. data/ios_tests/UICatalog.app/12-6AM.png +0 -0
  35. data/ios_tests/UICatalog.app/12-6PM.png +0 -0
  36. data/ios_tests/UICatalog.app/6-12AM.png +0 -0
  37. data/ios_tests/UICatalog.app/6-12PM.png +0 -0
  38. data/ios_tests/UICatalog.app/Default-568h@2x.png +0 -0
  39. data/ios_tests/UICatalog.app/Default@2x.png +0 -0
  40. data/ios_tests/UICatalog.app/Info.plist +0 -0
  41. data/ios_tests/UICatalog.app/PkgInfo +1 -0
  42. data/ios_tests/UICatalog.app/UIButton_custom.png +0 -0
  43. data/ios_tests/UICatalog.app/UICatalog +0 -0
  44. data/ios_tests/UICatalog.app/blueButton.png +0 -0
  45. data/ios_tests/UICatalog.app/bookmarkImage.png +0 -0
  46. data/ios_tests/UICatalog.app/bookmarkImageHighlighted.png +0 -0
  47. data/ios_tests/UICatalog.app/divider.png +0 -0
  48. data/ios_tests/UICatalog.app/en.lproj/AlertsViewController.nib +0 -0
  49. data/ios_tests/UICatalog.app/en.lproj/ButtonsViewController.nib +0 -0
  50. data/ios_tests/UICatalog.app/en.lproj/ControlsViewController.nib +0 -0
  51. data/ios_tests/UICatalog.app/en.lproj/ImagesViewController.nib +0 -0
  52. data/ios_tests/UICatalog.app/en.lproj/Localizable.strings +0 -0
  53. data/ios_tests/UICatalog.app/en.lproj/MainWindow.nib +0 -0
  54. data/ios_tests/UICatalog.app/en.lproj/PickerViewController.nib +0 -0
  55. data/ios_tests/UICatalog.app/en.lproj/SearchBarController.nib +0 -0
  56. data/ios_tests/UICatalog.app/en.lproj/SegmentViewController.nib +0 -0
  57. data/ios_tests/UICatalog.app/en.lproj/TextFieldController.nib +0 -0
  58. data/ios_tests/UICatalog.app/en.lproj/TextViewController.nib +0 -0
  59. data/ios_tests/UICatalog.app/en.lproj/ToolbarViewController.nib +0 -0
  60. data/ios_tests/UICatalog.app/en.lproj/TransitionViewController.nib +0 -0
  61. data/ios_tests/UICatalog.app/en.lproj/WebViewController.nib +0 -0
  62. data/ios_tests/UICatalog.app/orangeslide.png +0 -0
  63. data/ios_tests/UICatalog.app/scene1.jpg +0 -0
  64. data/ios_tests/UICatalog.app/scene2.jpg +0 -0
  65. data/ios_tests/UICatalog.app/scene3.jpg +0 -0
  66. data/ios_tests/UICatalog.app/scene4.jpg +0 -0
  67. data/ios_tests/UICatalog.app/scene5.jpg +0 -0
  68. data/ios_tests/UICatalog.app/searchBarBackground.png +0 -0
  69. data/ios_tests/UICatalog.app/segment_check.png +0 -0
  70. data/ios_tests/UICatalog.app/segment_search.png +0 -0
  71. data/ios_tests/UICatalog.app/segment_tools.png +0 -0
  72. data/ios_tests/UICatalog.app/segmentedBackground.png +0 -0
  73. data/ios_tests/UICatalog.app/slider_ball.png +0 -0
  74. data/ios_tests/UICatalog.app/toolbarBackground.png +0 -0
  75. data/ios_tests/UICatalog.app/whiteButton.png +0 -0
  76. data/ios_tests/UICatalog.app/yellowslide.png +0 -0
  77. data/ios_tests/appium.txt +3 -0
  78. data/ios_tests/flaky.txt +1 -0
  79. data/ios_tests/lib/format.rb +25 -0
  80. data/ios_tests/lib/ios/specs/common/element/window.rb +15 -0
  81. data/ios_tests/lib/ios/specs/common/helper.rb +204 -0
  82. data/ios_tests/lib/ios/specs/common/patch.rb +50 -0
  83. data/ios_tests/lib/ios/specs/common/version.rb +17 -0
  84. data/ios_tests/lib/ios/specs/device/device.rb +82 -0
  85. data/ios_tests/lib/ios/specs/device/multi_touch.rb +12 -0
  86. data/ios_tests/lib/ios/specs/device/touch_actions.rb +15 -0
  87. data/ios_tests/lib/ios/specs/driver.rb +203 -0
  88. data/ios_tests/lib/ios/specs/ios/element/alert.rb +48 -0
  89. data/ios_tests/lib/ios/specs/ios/element/button.rb +58 -0
  90. data/ios_tests/lib/ios/specs/ios/element/generic.rb +35 -0
  91. data/ios_tests/lib/ios/specs/ios/element/text.rb +54 -0
  92. data/ios_tests/lib/ios/specs/ios/element/textfield.rb +123 -0
  93. data/ios_tests/lib/ios/specs/ios/helper.rb +27 -0
  94. data/ios_tests/lib/ios/specs/ios/patch.rb +30 -0
  95. data/ios_tests/lib/run.rb +106 -0
  96. data/ios_tests/readme.md +30 -0
  97. data/ios_tests/upload/sauce_storage.rb +64 -0
  98. data/ios_tests/upload/upload.rb +6 -0
  99. data/lib/appium_lib.rb +4 -14
  100. data/lib/appium_lib/android/dynamic.rb +30 -32
  101. data/lib/appium_lib/android/element/alert.rb +34 -33
  102. data/lib/appium_lib/android/element/button.rb +91 -0
  103. data/lib/appium_lib/android/element/generic.rb +51 -146
  104. data/lib/appium_lib/android/element/text.rb +54 -0
  105. data/lib/appium_lib/android/element/textfield.rb +46 -41
  106. data/lib/appium_lib/android/helper.rb +248 -417
  107. data/lib/appium_lib/android/mobile_methods.rb +17 -0
  108. data/lib/appium_lib/android/patch.rb +9 -8
  109. data/lib/appium_lib/awesome_print/ostruct.rb +33 -0
  110. data/lib/appium_lib/common/element/window.rb +9 -8
  111. data/lib/appium_lib/common/helper.rb +182 -243
  112. data/lib/appium_lib/common/patch.rb +65 -79
  113. data/lib/appium_lib/common/version.rb +2 -3
  114. data/lib/appium_lib/device/device.rb +339 -0
  115. data/lib/appium_lib/device/multi_touch.rb +94 -0
  116. data/lib/appium_lib/device/touch_actions.rb +142 -0
  117. data/lib/appium_lib/driver.rb +217 -306
  118. data/lib/appium_lib/ios/element/alert.rb +16 -92
  119. data/lib/appium_lib/ios/element/button.rb +55 -0
  120. data/lib/appium_lib/ios/element/generic.rb +27 -160
  121. data/lib/appium_lib/ios/element/text.rb +54 -0
  122. data/lib/appium_lib/ios/element/textfield.rb +78 -65
  123. data/lib/appium_lib/ios/helper.rb +300 -190
  124. data/lib/appium_lib/ios/mobile_methods.rb +17 -0
  125. data/lib/appium_lib/ios/patch.rb +55 -41
  126. data/lib/appium_lib/logger.rb +13 -0
  127. data/lib/appium_lib/rails/duplicable.rb +116 -0
  128. data/readme.md +6 -1
  129. data/release_notes.md +118 -0
  130. metadata +170 -12
  131. data/lib/appium_lib/common/element/button.rb +0 -83
  132. data/lib/appium_lib/common/element/text.rb +0 -61
@@ -1,95 +1,19 @@
1
- # encoding: utf-8
2
- module Appium::Ios
3
- # iOS only
4
- # Tap the alert button identified by value.
5
- #
6
- # Click the ok button:
7
- # alert_click 'OK'
8
- #
9
- # Click the first button:
10
- # alert_click 0
11
- #
12
- # @param value [Integer, String] either an integer index of the button or the button's name
13
- # @return [void]
14
- def alert_click value
15
- value = "'#{value}'" if value.is_a?(String)
16
- @driver.execute_script "UIATarget.localTarget().frontMostApp().alert().buttons()[#{value}].tap();"
17
- end
18
-
19
- # Get the alert message text.
20
- # @return [String]
21
- def alert_text
22
- # this will call get text twice so call bridge directly
23
- # ".switch_to.alert" calls it once, then ".text" another time.
24
- # @driver.switch_to.alert.text
25
- driver.send(:bridge).getAlertText
26
- end
27
-
28
- # Accept the alert.
29
- # @return [void]
30
- def alert_accept
31
- # @driver.switch_to.alert.accept
32
- # ".switch_to.alert" calls getAlertText so use bridge directly
33
- driver.send(:bridge).acceptAlert
34
- end
35
-
36
- # Get the text of the alert's accept button.
37
- # The last button is considered "accept." on iOS 6
38
- # The first button is considered "accept." on iOS 7
39
- # @return [String]
40
- def alert_accept_text
41
- old_wait = default_wait
42
- set_wait 0
43
- target_text = ''
44
-
45
- a = ignore { @driver.find_element(:tag_name, :alert) }
46
-
47
- begin
48
- if a.nil? # either no alert or on iOS 7
49
- b = xpaths 'actionsheet/button'
50
- target_text = b.first.text if b && b.size >= 1
51
- else # iOS 6 alert found
52
- b = a.find_elements(:tag_name, :button)
53
- target_text = b.last.text if b && b.size >= 1
54
- end
55
- rescue
56
- ensure
57
- set_wait old_wait
58
- return target_text
1
+ module Appium
2
+ module Ios
3
+ # Accept the alert.
4
+ # @return [void]
5
+ def alert_accept
6
+ # @driver.switch_to.alert.accept
7
+ # ".switch_to.alert" calls getAlertText so use bridge directly
8
+ driver.send(:bridge).acceptAlert
59
9
  end
60
- end
61
-
62
- # Dismiss the alert.
63
- # @return [void]
64
- def alert_dismiss
65
- # @driver.switch_to.alert.dismiss
66
- # ".switch_to.alert" calls getAlertText so use bridge directly
67
- driver.send(:bridge).dismissAlert
68
- end
69
-
70
- # Get the text of the alert's dismiss button.
71
- # The first button is considered "dismiss." on iOS 6
72
- # The last button is considered "dismiss." on iOS 7
73
- # @return [String]
74
- def alert_dismiss_text
75
- old_wait = default_wait
76
- set_wait 0
77
- target_text = ''
78
-
79
- a = ignore { @driver.find_element(:tag_name, :alert) }
80
10
 
81
- begin
82
- if a.nil? # either no alert or on iOS 7
83
- b = xpaths 'actionsheet/button'
84
- target_text = b.last.text if b && b.size >= 1
85
- else # iOS 6 alert found
86
- b = a.find_elements(:tag_name, :button)
87
- target_text = b.first.text if b && b.size >= 1
88
- end
89
- rescue
90
- ensure
91
- set_wait old_wait
92
- return target_text
11
+ # Dismiss the alert.
12
+ # @return [void]
13
+ def alert_dismiss
14
+ # @driver.switch_to.alert.dismiss
15
+ # ".switch_to.alert" calls getAlertText so use bridge directly
16
+ driver.send(:bridge).dismissAlert
93
17
  end
94
- end
95
- end # module Appium::Ios
18
+ end # module Ios
19
+ end # module Appium
@@ -0,0 +1,55 @@
1
+ # UIAButton methods
2
+ module Appium
3
+ module Ios
4
+ UIAButton = 'UIAButton'
5
+
6
+ # Find the first UIAButton that contains value or by index.
7
+ # @param value [String, Integer] the value to exactly match.
8
+ # If int then the UIAButton at that index is returned.
9
+ # @return [UIAButton]
10
+ def button value
11
+ # return button at index.
12
+ return ele_index UIAButton, value if value.is_a? Numeric
13
+ xpath_visible_contains UIAButton, value
14
+ end
15
+
16
+ # Find all UIAButtons containing value
17
+ # @param value [String] the value to search for
18
+ # @return [Array<UIAButton>]
19
+ def buttons value
20
+ xpaths_visible_contains UIAButton, value
21
+ end
22
+
23
+ # Find the first UIAButton.
24
+ # @return [UIAButton]
25
+ def first_button
26
+ first_ele UIAButton
27
+ end
28
+
29
+ # Find the last UIAButton.
30
+ # @return [UIAButton]
31
+ def last_button
32
+ last_ele UIAButton
33
+ end
34
+
35
+ # Find the first UIAButton that exactly matches value.
36
+ # @param value [String] the value to match exactly
37
+ # @return [UIAButton]
38
+ def button_exact value
39
+ xpath_visible_exact UIAButton, value
40
+ end
41
+
42
+ # Find all UIAButtons that exactly match value.
43
+ # @param value [String] the value to match exactly
44
+ # @return [Array<UIAButton>]
45
+ def buttons_exact value
46
+ xpaths_visible_exact UIAButton, value
47
+ end
48
+
49
+ # Find all UIAButtons.
50
+ # @return [Array<UIAButton>]
51
+ def e_buttons
52
+ tags UIAButton
53
+ end
54
+ end # module Ios
55
+ end # module Appium
@@ -1,165 +1,32 @@
1
- # encoding: utf-8
2
- module Appium::Ios
3
- =begin
4
- name, names, text, text should match substring and case insensitive.
5
-
6
- iOS .name() is the accessibility attribute. If not defined, then .label() is used instead.
7
- This differs from Android where name (the content description) is empty when not set.
8
-
9
- name defaults to label when undefined. value is never a default so that must be
10
- included in a new search.
11
-
12
- Find - search everything.
13
-
14
- The search order is:
15
- 1. name
16
- 2. label (implied by name)
17
- 3. value
18
-
19
- Android name = iOS name & label
20
- Android text = iOS value
21
- =end
22
-
23
- # @private
24
- # returnElems requires a wrapped $(element).
25
- # set to empty array when length is zero to prevent hang.
26
- #
27
- # UIAElementNil when not matched
28
- #
29
- # 1. secureTextFields
30
- # 2. textFields
31
- # 3. buttons
32
- # 4. elements
33
- #
34
- # search takes the window to search.
35
- # start searching webview first.
36
- # window 0 is the main window.
37
- # window 1 is the 1st webview (if it exists)
38
- # must break instead of return because it's not a function.
39
- #
40
- # single element length is undefined when found and 0 when not found.
41
- # @param predicate [String] the predicate
42
- # @return [String] the completed JavaScript program
43
- def first_ele_js predicate
44
- (<<-JS).strip # remove trailing newline
45
- au.mainApp().getFirstWithPredicateWeighted("#{predicate}");
46
- JS
47
- end
48
-
49
- # @private
50
- # @param predicate [String] the predicate
51
- # @return [String] the completed JavaScript program
52
- def all_ele_js predicate
53
- (<<-JS).strip # remove trailing newline
54
- au.mainApp().getAllWithPredicate("#{predicate}");
55
- JS
56
- end
57
-
58
- # Return the first element matching text.
59
- # @param text [String] the text to search for
60
- # @return [Element] the first matching element
61
- def find text
62
- text = escape_single_quote text
63
- ele = nil
64
- # prefer value search. this may error with:
65
- # Can't use in/contains operator with collection 1
66
- js = first_ele_js "value contains[c] '#{text}'"
67
- ele = ignore { execute_script js }
68
-
69
- # now search name and label if the value search didn't match.
70
- unless ele
71
- js = first_ele_js "name contains[c] '#{text}' || label contains[c] '#{text}'"
72
- ele = ignore { execute_script js }
1
+ module Appium
2
+ module Ios
3
+
4
+ # Find the first element containing value
5
+ # @param value [String] the value to search for
6
+ # @return [Element]
7
+ def find value
8
+ xpath_visible_contains '*', value
73
9
  end
74
10
 
75
- # manually raise error if no element was found
76
- raise Selenium::WebDriver::Error::NoSuchElementError, 'An element could not be located on the page using the given search parameters.' unless ele
77
-
78
- ele
79
- end
80
-
81
- # Return all elements matching text.
82
- # @param text [String] the text to search for
83
- # @return [Array<Element>] all matching elements
84
- def finds text
85
- text = escape_single_quote text
86
- eles = []
87
- # value contains may error
88
- js = all_ele_js "value contains[c] '#{text}'"
89
- eles = ignore { execute_script js }
90
-
91
- js = all_ele_js "name contains[c] '#{text}' || label contains[c] '#{text}'"
92
- eles += ignore { execute_script js }
93
- eles
94
- end
95
-
96
- # Return the first element matching text.
97
- # @param text [String] the text to search for
98
- # @return [Element] the first matching element
99
- def text text
100
- text = escape_single_quote text
101
- js = first_ele_js "value contains[c] '#{text}'"
102
- execute_script js
103
- end
104
-
105
- # Return all elements matching text.
106
- # @param text [String] the text to search for
107
- # @return [Array<Element>] all matching elements
108
- def texts text
109
- text = escape_single_quote text
110
- # XPath //* is not implemented on iOS
111
- # https://github.com/appium/appium/issues/430
112
- js = all_ele_js "value contains[c] '#{text}'"
113
- execute_script js
114
- end
115
-
116
- # Return the first element matching name.
117
- # on Android name is content description
118
- # on iOS name is the accessibility label or the text.
119
- #
120
- # ```ruby
121
- # # find element with name or label containing example and access the name attribute.
122
- # name('example').name
123
- #
124
- # # find element with name or label containing example and access the label attribute.
125
- # name('example').label
126
- # ```
127
- #
128
- # @param name [String] the name to search for
129
- # @return [Element] the first matching element
130
- def name name
131
- name = escape_single_quote name
132
- mobile :findElementNameContains, name: name
133
- end
134
-
135
- def name_exact name
136
- name = escape_single_quote name
137
- js = all_ele_js "name == '#{name}'"
138
- result = execute_script js
139
-
140
- return result if result.kind_of? Selenium::WebDriver::Element
141
-
142
- if result.length > 0
143
- result.first
144
- else
145
- Appium::Common.raise_no_element_error
11
+ # Find all elements containing value
12
+ # @param value [String] the value to search for
13
+ # @return [Array<Element>]
14
+ def finds value
15
+ xpaths_visible_contains '*', value
146
16
  end
147
- end
148
17
 
149
- # Return all elements matching name.
150
- # on Android name is content description
151
- # on iOS name is the accessibility label or the text.
152
- # @param name [String] the name to search for
153
- # @return [Array<Element>] all matching elements
154
- def names name
155
- name = escape_single_quote name
156
- # :name is not consistent across iOS and Android so use custom JavaScript
157
- # https://github.com/appium/appium/issues/379
158
- js = all_ele_js "name contains[c] '#{name}' || label contains[c] '#{name}'"
159
- execute_script js
160
- end
18
+ # Find the first element exactly matching value
19
+ # @param value [String] the value to search for
20
+ # @return [Element]
21
+ def find_exact value
22
+ xpath_visible_exact '*', value
23
+ end
161
24
 
162
- def escape_single_quote text_to_escape
163
- text_to_escape.gsub("'", '\\' * 4 + "'")
164
- end
165
- end # module Appium::Ios
25
+ # Find all elements exactly matching value
26
+ # @param value [String] the value to search for
27
+ # @return [Array<Element>]
28
+ def finds_exact value
29
+ xpaths_visible_exact '*', value
30
+ end
31
+ end # module Ios
32
+ end # module Appium
@@ -0,0 +1,54 @@
1
+ # UIAStaticText methods
2
+ module Appium
3
+ module Ios
4
+ UIAStaticText = 'UIAStaticText'
5
+
6
+ # Find the first UIAStaticText that contains value or by index.
7
+ # @param value [String, Integer] the value to find.
8
+ # If int then the UIAStaticText at that index is returned.
9
+ # @return [UIAStaticText]
10
+ def s_text value
11
+ return ele_index UIAStaticText, value if value.is_a? Numeric
12
+ xpath_visible_contains UIAStaticText, value
13
+ end
14
+
15
+ # Find all UIAStaticText containing value.
16
+ # @param value [String] the value to search for
17
+ # @return [Array<UIAStaticText>]
18
+ def s_texts value
19
+ xpaths_visible_contains UIAStaticText, value
20
+ end
21
+
22
+ # Find the first UIAStaticText.
23
+ # @return [UIAStaticText]
24
+ def first_s_text
25
+ first_ele UIAStaticText
26
+ end
27
+
28
+ # Find the last UIAStaticText.
29
+ # @return [UIAStaticText]
30
+ def last_s_text
31
+ last_ele UIAStaticText
32
+ end
33
+
34
+ # Find the first UIAStaticText that exactly matches value.
35
+ # @param value [String] the value to match exactly
36
+ # @return [UIAStaticText]
37
+ def s_text_exact value
38
+ xpath_visible_exact UIAStaticText, value
39
+ end
40
+
41
+ # Find all UIAStaticTexts that exactly match value.
42
+ # @param value [String] the value to match exactly
43
+ # @return [Array<UIAStaticText>]
44
+ def s_texts_exact value
45
+ xpaths_visible_exact UIAStaticText, value
46
+ end
47
+
48
+ # Find all UIAStaticTexts.
49
+ # @return [Array<UIAStaticText>]
50
+ def e_s_texts
51
+ tags UIAStaticText
52
+ end
53
+ end # module Ios
54
+ end # module Appium
@@ -1,77 +1,90 @@
1
- # encoding: utf-8
2
- module Appium::Ios
3
- # UIATextField & UIASecureTextField methods
4
- #
5
- # Find textfield and then secure elements in one server call
6
- # to match Android.
1
+ module Appium
2
+ module Ios
3
+ UIATextField = 'UIATextField'
4
+ UIASecureTextField = 'UIASecureTextField'
7
5
 
8
- def locate_single_textfield js
9
- ele = execute_script(js)
10
- ele = ele.first if ele.kind_of? Array
11
- raise_no_element_error unless ele.kind_of? Selenium::WebDriver::Element
12
- ele
13
- end
6
+ private
14
7
 
15
- # Get an array of textfield texts.
16
- # Does not respect implicit wait because we're using execute_script.
17
- # @return [Array<String>]
18
- def textfields
19
- find_2_eles_attr :textfield, :secure, :text
20
- end
8
+ # @private
9
+ def _textfield_visible_string opts={}
10
+ index = opts.fetch :index, false
11
+ if index
12
+ %Q(//#{UIATextField}[@visible="true"][#{index}] | //#{UIASecureTextField}[@visible="true"][#{index}])
13
+ else
14
+ %Q(//#{UIATextField}[@visible="true"] | //#{UIASecureTextField}[@visible="true"])
15
+ end
16
+ end
17
+
18
+ # @private
19
+ def _textfield_exact_string value
20
+ textfield = string_visible_exact UIATextField, value
21
+ secure = string_visible_exact UIASecureTextField, value
22
+ "#{textfield} | #{secure}"
23
+ end
24
+
25
+ # @private
26
+ def _textfield_contains_string value
27
+ textfield = string_visible_contains UIATextField, value
28
+ secure = string_visible_contains UIASecureTextField, value
29
+ "#{textfield} | #{secure}"
30
+ end
31
+
32
+ public
21
33
 
22
- # Get an array of textfield elements.
23
- # @return [Array<Textfield>]
24
- def e_textfields
25
- xpaths 'textfield'
26
- end
34
+ # Find the first TextField that contains value or by index.
35
+ # @param value [String, Integer] the text to match exactly.
36
+ # If int then the TextField at that index is returned.
37
+ # @return [TextField]
38
+ def textfield value
39
+ # Don't use ele_index because that only works on one element type.
40
+ # iOS needs to combine textfield and secure to match Android.
41
+ if value.is_a? Numeric
42
+ index = value
43
+ raise "#{index} is not a valid xpath index. Must be >= 1" if index <= 0
27
44
 
28
- # Get the first textfield element.
29
- # @return [Textfield]
30
- def first_textfield
31
- xpath 'textfield'
32
- end
45
+ return xpath _textfield_visible_string index: index
46
+ end
33
47
 
34
- # Get the last textfield element.
35
- # @return [Textfield]
36
- def last_textfield
37
- xpath 'textfield[last()]'
38
- end
48
+ xpath _textfield_contains_string value
49
+ end
50
+
51
+ # Find all TextFields containing value.
52
+ # @param value [String] the value to search for
53
+ # @return [Array<TextField>]
54
+ def textfields value
55
+ xpaths _textfield_contains_string value
56
+ end
39
57
 
40
- # Get the first textfield that matches text.
41
- # @param text [String, Integer] the text to match exactly. If int then the textfield at that index is returned.
42
- # @return [Textfield]
43
- def textfield text
44
- # Don't use ele_index because that only works on one element type.
45
- # iOS needs to combine textfield and secure to match Android.
46
- if text.is_a? Numeric
47
- raise "#{text} is not a valid xpath index. Must be >= 1" if text <= 0
48
- return xpath("textfield[#{text}]")
58
+ # Find the first TextField.
59
+ # @return [TextField]
60
+ def first_textfield
61
+ xpath _textfield_visible_string
49
62
  end
50
63
 
51
- textfield_include text
52
- end
64
+ # Find the last TextField.
65
+ # @return [TextField]
66
+ def last_textfield
67
+ xpath _textfield_visible_string index: 'last()'
68
+ end
53
69
 
54
- # Get the first textfield that includes text.
55
- # @param text [String] the text the textfield must include
56
- # @return [Textfield]
57
- def textfield_include text
58
- xpath "textfield[contains(@text,'#{text}')]"
59
- end
70
+ # Find the first TextField that exactly matches value.
71
+ # @param value [String] the value to match exactly
72
+ # @return [TextField]
73
+ def textfield_exact value
74
+ xpath _textfield_exact_string value
75
+ end
60
76
 
61
- # Get the first textfield that exactly matches text.
62
- # @param text [String] the text the textfield must exactly match
63
- # @return [Textfield]
64
- def textfield_exact text
65
- xpath "textfield[@text='#{text}']"
66
- end
77
+ # Find all TextFields that exactly match value.
78
+ # @param value [String] the value to match exactly
79
+ # @return [Array<TextField>]
80
+ def textfields_exact value
81
+ xpaths _textfield_exact_string value
82
+ end
67
83
 
68
- # Get the first textfield that exactly matches name
69
- # @return [Element]
70
- def textfield_named target_name
71
- wait do
72
- target = e_textfields.detect { |e| e.name == target_name }
73
- raise "Textfield named #{target_name} not found" unless target
74
- target
84
+ # Find all TextFields.
85
+ # @return [Array<TextField>]
86
+ def e_textfields
87
+ xpaths _textfield_visible_string
75
88
  end
76
- end
77
- end # module Appium::Ios
89
+ end # module Ios
90
+ end # module Appium