appium_lib 0.24.1 → 1.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.
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