appium-xcuitest-driver 10.2.2 → 10.4.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 (262) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/lib/commands/active-app-info.d.ts +9 -0
  3. package/build/lib/commands/active-app-info.d.ts.map +1 -0
  4. package/build/lib/commands/active-app-info.js +14 -0
  5. package/build/lib/commands/active-app-info.js.map +1 -0
  6. package/build/lib/commands/alert.d.ts +42 -45
  7. package/build/lib/commands/alert.d.ts.map +1 -1
  8. package/build/lib/commands/alert.js +66 -62
  9. package/build/lib/commands/alert.js.map +1 -1
  10. package/build/lib/commands/app-management.d.ts +150 -153
  11. package/build/lib/commands/app-management.d.ts.map +1 -1
  12. package/build/lib/commands/app-management.js +300 -286
  13. package/build/lib/commands/app-management.js.map +1 -1
  14. package/build/lib/commands/app-strings.d.ts +14 -17
  15. package/build/lib/commands/app-strings.d.ts.map +1 -1
  16. package/build/lib/commands/app-strings.js +23 -24
  17. package/build/lib/commands/app-strings.js.map +1 -1
  18. package/build/lib/commands/appearance.d.ts +19 -22
  19. package/build/lib/commands/appearance.d.ts.map +1 -1
  20. package/build/lib/commands/appearance.js +56 -56
  21. package/build/lib/commands/appearance.js.map +1 -1
  22. package/build/lib/commands/audit.d.ts +22 -17
  23. package/build/lib/commands/audit.d.ts.map +1 -1
  24. package/build/lib/commands/audit.js +17 -18
  25. package/build/lib/commands/audit.js.map +1 -1
  26. package/build/lib/commands/battery.d.ts +11 -14
  27. package/build/lib/commands/battery.d.ts.map +1 -1
  28. package/build/lib/commands/battery.js +36 -37
  29. package/build/lib/commands/battery.js.map +1 -1
  30. package/build/lib/commands/biometric.d.ts +30 -33
  31. package/build/lib/commands/biometric.d.ts.map +1 -1
  32. package/build/lib/commands/biometric.js +42 -41
  33. package/build/lib/commands/biometric.js.map +1 -1
  34. package/build/lib/commands/certificate.d.ts +48 -45
  35. package/build/lib/commands/certificate.d.ts.map +1 -1
  36. package/build/lib/commands/certificate.js +218 -205
  37. package/build/lib/commands/certificate.js.map +1 -1
  38. package/build/lib/commands/clipboard.d.ts +19 -22
  39. package/build/lib/commands/clipboard.d.ts.map +1 -1
  40. package/build/lib/commands/clipboard.js +30 -30
  41. package/build/lib/commands/clipboard.js.map +1 -1
  42. package/build/lib/commands/condition.d.ts +49 -26
  43. package/build/lib/commands/condition.d.ts.map +1 -1
  44. package/build/lib/commands/condition.js +87 -86
  45. package/build/lib/commands/condition.js.map +1 -1
  46. package/build/lib/commands/content-size.d.ts +26 -29
  47. package/build/lib/commands/content-size.d.ts.map +1 -1
  48. package/build/lib/commands/content-size.js +36 -36
  49. package/build/lib/commands/content-size.js.map +1 -1
  50. package/build/lib/commands/context.d.ts +161 -108
  51. package/build/lib/commands/context.d.ts.map +1 -1
  52. package/build/lib/commands/context.js +530 -517
  53. package/build/lib/commands/context.js.map +1 -1
  54. package/build/lib/commands/deviceInfo.d.ts +9 -12
  55. package/build/lib/commands/deviceInfo.d.ts.map +1 -1
  56. package/build/lib/commands/deviceInfo.js +17 -18
  57. package/build/lib/commands/deviceInfo.js.map +1 -1
  58. package/build/lib/commands/element.d.ts +102 -105
  59. package/build/lib/commands/element.d.ts.map +1 -1
  60. package/build/lib/commands/element.js +337 -323
  61. package/build/lib/commands/element.js.map +1 -1
  62. package/build/lib/commands/execute.d.ts +24 -19
  63. package/build/lib/commands/execute.d.ts.map +1 -1
  64. package/build/lib/commands/execute.js +63 -62
  65. package/build/lib/commands/execute.js.map +1 -1
  66. package/build/lib/commands/file-movement.d.ts +77 -80
  67. package/build/lib/commands/file-movement.d.ts.map +1 -1
  68. package/build/lib/commands/file-movement.js +130 -124
  69. package/build/lib/commands/file-movement.js.map +1 -1
  70. package/build/lib/commands/find.d.ts +18 -21
  71. package/build/lib/commands/find.d.ts.map +1 -1
  72. package/build/lib/commands/find.js +158 -156
  73. package/build/lib/commands/find.js.map +1 -1
  74. package/build/lib/commands/general.d.ts +124 -116
  75. package/build/lib/commands/general.d.ts.map +1 -1
  76. package/build/lib/commands/general.js +248 -232
  77. package/build/lib/commands/general.js.map +1 -1
  78. package/build/lib/commands/geolocation.d.ts +43 -46
  79. package/build/lib/commands/geolocation.d.ts.map +1 -1
  80. package/build/lib/commands/geolocation.js +10 -11
  81. package/build/lib/commands/geolocation.js.map +1 -1
  82. package/build/lib/commands/gesture.d.ts +273 -276
  83. package/build/lib/commands/gesture.d.ts.map +1 -1
  84. package/build/lib/commands/gesture.js +506 -492
  85. package/build/lib/commands/gesture.js.map +1 -1
  86. package/build/lib/commands/increase-contrast.d.ts +20 -23
  87. package/build/lib/commands/increase-contrast.d.ts.map +1 -1
  88. package/build/lib/commands/increase-contrast.js +30 -30
  89. package/build/lib/commands/increase-contrast.js.map +1 -1
  90. package/build/lib/commands/iohid.d.ts +1370 -1373
  91. package/build/lib/commands/iohid.d.ts.map +1 -1
  92. package/build/lib/commands/iohid.js +30 -31
  93. package/build/lib/commands/iohid.js.map +1 -1
  94. package/build/lib/commands/keyboard.d.ts +29 -32
  95. package/build/lib/commands/keyboard.d.ts.map +1 -1
  96. package/build/lib/commands/keyboard.js +53 -51
  97. package/build/lib/commands/keyboard.js.map +1 -1
  98. package/build/lib/commands/keychains.d.ts +9 -12
  99. package/build/lib/commands/keychains.d.ts.map +1 -1
  100. package/build/lib/commands/keychains.js +13 -14
  101. package/build/lib/commands/keychains.js.map +1 -1
  102. package/build/lib/commands/localization.d.ts +16 -19
  103. package/build/lib/commands/localization.d.ts.map +1 -1
  104. package/build/lib/commands/localization.js +25 -26
  105. package/build/lib/commands/localization.js.map +1 -1
  106. package/build/lib/commands/location.d.ts +36 -39
  107. package/build/lib/commands/location.d.ts.map +1 -1
  108. package/build/lib/commands/location.js +99 -98
  109. package/build/lib/commands/location.js.map +1 -1
  110. package/build/lib/commands/lock.d.ts +21 -24
  111. package/build/lib/commands/lock.d.ts.map +1 -1
  112. package/build/lib/commands/lock.js +39 -38
  113. package/build/lib/commands/lock.js.map +1 -1
  114. package/build/lib/commands/log.d.ts +43 -37
  115. package/build/lib/commands/log.d.ts.map +1 -1
  116. package/build/lib/commands/log.js +174 -171
  117. package/build/lib/commands/log.js.map +1 -1
  118. package/build/lib/commands/memory.d.ts +9 -12
  119. package/build/lib/commands/memory.d.ts.map +1 -1
  120. package/build/lib/commands/memory.js +37 -39
  121. package/build/lib/commands/memory.js.map +1 -1
  122. package/build/lib/commands/navigation.d.ts +30 -33
  123. package/build/lib/commands/navigation.d.ts.map +1 -1
  124. package/build/lib/commands/navigation.js +92 -92
  125. package/build/lib/commands/navigation.js.map +1 -1
  126. package/build/lib/commands/notifications.d.ts +26 -29
  127. package/build/lib/commands/notifications.d.ts.map +1 -1
  128. package/build/lib/commands/notifications.js +53 -53
  129. package/build/lib/commands/notifications.js.map +1 -1
  130. package/build/lib/commands/pasteboard.d.ts +21 -24
  131. package/build/lib/commands/pasteboard.d.ts.map +1 -1
  132. package/build/lib/commands/pasteboard.js +37 -37
  133. package/build/lib/commands/pasteboard.js.map +1 -1
  134. package/build/lib/commands/pcap.d.ts +39 -26
  135. package/build/lib/commands/pcap.d.ts.map +1 -1
  136. package/build/lib/commands/pcap.js +81 -81
  137. package/build/lib/commands/pcap.js.map +1 -1
  138. package/build/lib/commands/performance.d.ts +63 -44
  139. package/build/lib/commands/performance.d.ts.map +1 -1
  140. package/build/lib/commands/performance.js +105 -105
  141. package/build/lib/commands/performance.js.map +1 -1
  142. package/build/lib/commands/permissions.d.ts +33 -36
  143. package/build/lib/commands/permissions.d.ts.map +1 -1
  144. package/build/lib/commands/permissions.js +66 -65
  145. package/build/lib/commands/permissions.js.map +1 -1
  146. package/build/lib/commands/proxy-helper.d.ts +12 -15
  147. package/build/lib/commands/proxy-helper.d.ts.map +1 -1
  148. package/build/lib/commands/proxy-helper.js +53 -54
  149. package/build/lib/commands/proxy-helper.js.map +1 -1
  150. package/build/lib/commands/record-audio.d.ts +49 -29
  151. package/build/lib/commands/record-audio.d.ts.map +1 -1
  152. package/build/lib/commands/record-audio.js +100 -104
  153. package/build/lib/commands/record-audio.js.map +1 -1
  154. package/build/lib/commands/recordscreen.d.ts +54 -18
  155. package/build/lib/commands/recordscreen.d.ts.map +1 -1
  156. package/build/lib/commands/recordscreen.js +127 -129
  157. package/build/lib/commands/recordscreen.js.map +1 -1
  158. package/build/lib/commands/screenshots.d.ts +14 -17
  159. package/build/lib/commands/screenshots.d.ts.map +1 -1
  160. package/build/lib/commands/screenshots.js +108 -107
  161. package/build/lib/commands/screenshots.js.map +1 -1
  162. package/build/lib/commands/simctl.d.ts +11 -14
  163. package/build/lib/commands/simctl.d.ts.map +1 -1
  164. package/build/lib/commands/simctl.js +23 -26
  165. package/build/lib/commands/simctl.js.map +1 -1
  166. package/build/lib/commands/source.d.ts +14 -17
  167. package/build/lib/commands/source.d.ts.map +1 -1
  168. package/build/lib/commands/source.js +40 -43
  169. package/build/lib/commands/source.js.map +1 -1
  170. package/build/lib/commands/timeouts.d.ts +44 -33
  171. package/build/lib/commands/timeouts.d.ts.map +1 -1
  172. package/build/lib/commands/timeouts.js +65 -63
  173. package/build/lib/commands/timeouts.js.map +1 -1
  174. package/build/lib/commands/web.d.ts +247 -197
  175. package/build/lib/commands/web.d.ts.map +1 -1
  176. package/build/lib/commands/web.js +815 -786
  177. package/build/lib/commands/web.js.map +1 -1
  178. package/build/lib/commands/xctest-record-screen.d.ts +63 -66
  179. package/build/lib/commands/xctest-record-screen.d.ts.map +1 -1
  180. package/build/lib/commands/xctest-record-screen.js +103 -102
  181. package/build/lib/commands/xctest-record-screen.js.map +1 -1
  182. package/build/lib/commands/xctest.d.ts +55 -51
  183. package/build/lib/commands/xctest.d.ts.map +1 -1
  184. package/build/lib/commands/xctest.js +116 -117
  185. package/build/lib/commands/xctest.js.map +1 -1
  186. package/build/lib/driver.d.ts +278 -1597
  187. package/build/lib/driver.d.ts.map +1 -1
  188. package/build/lib/driver.js +320 -236
  189. package/build/lib/driver.js.map +1 -1
  190. package/build/lib/execute-method-map.d.ts.map +1 -1
  191. package/build/lib/execute-method-map.js +9 -0
  192. package/build/lib/execute-method-map.js.map +1 -1
  193. package/build/lib/real-device.d.ts +1 -1
  194. package/build/lib/real-device.d.ts.map +1 -1
  195. package/build/lib/real-device.js +2 -2
  196. package/build/lib/real-device.js.map +1 -1
  197. package/lib/commands/active-app-info.js +12 -0
  198. package/lib/commands/alert.js +68 -65
  199. package/lib/commands/app-management.js +308 -301
  200. package/lib/commands/app-strings.js +24 -26
  201. package/lib/commands/appearance.js +54 -56
  202. package/lib/commands/audit.js +18 -20
  203. package/lib/commands/battery.js +35 -37
  204. package/lib/commands/biometric.js +44 -46
  205. package/lib/commands/certificate.js +226 -215
  206. package/lib/commands/clipboard.js +30 -32
  207. package/lib/commands/condition.js +98 -100
  208. package/lib/commands/content-size.js +36 -38
  209. package/lib/commands/context.js +495 -490
  210. package/lib/commands/deviceInfo.js +19 -20
  211. package/lib/commands/element.js +367 -357
  212. package/lib/commands/execute.js +72 -72
  213. package/lib/commands/file-movement.js +132 -134
  214. package/lib/commands/find.js +160 -159
  215. package/lib/commands/general.js +238 -231
  216. package/lib/commands/geolocation.js +6 -14
  217. package/lib/commands/gesture.js +525 -515
  218. package/lib/commands/increase-contrast.js +30 -32
  219. package/lib/commands/iohid.js +32 -34
  220. package/lib/commands/keyboard.js +49 -51
  221. package/lib/commands/keychains.js +12 -14
  222. package/lib/commands/localization.js +24 -26
  223. package/lib/commands/location.js +102 -104
  224. package/lib/commands/lock.js +38 -38
  225. package/lib/commands/log.js +197 -198
  226. package/lib/commands/memory.js +40 -43
  227. package/lib/commands/navigation.js +96 -100
  228. package/lib/commands/notifications.js +57 -59
  229. package/lib/commands/pasteboard.js +37 -39
  230. package/lib/commands/pcap.js +84 -86
  231. package/lib/commands/performance.js +132 -133
  232. package/lib/commands/permissions.js +67 -69
  233. package/lib/commands/proxy-helper.js +60 -61
  234. package/lib/commands/record-audio.js +115 -120
  235. package/lib/commands/recordscreen.js +145 -149
  236. package/lib/commands/screenshots.js +116 -116
  237. package/lib/commands/simctl.js +25 -29
  238. package/lib/commands/source.js +42 -46
  239. package/lib/commands/timeouts.js +59 -63
  240. package/lib/commands/web.js +878 -858
  241. package/lib/commands/xctest-record-screen.js +103 -105
  242. package/lib/commands/xctest.js +134 -139
  243. package/lib/driver.js +288 -236
  244. package/lib/execute-method-map.ts +9 -0
  245. package/lib/real-device.js +2 -2
  246. package/npm-shrinkwrap.json +440 -76
  247. package/package.json +2 -1
  248. package/build/lib/commands/activeAppInfo.d.ts +0 -12
  249. package/build/lib/commands/activeAppInfo.d.ts.map +0 -1
  250. package/build/lib/commands/activeAppInfo.js +0 -15
  251. package/build/lib/commands/activeAppInfo.js.map +0 -1
  252. package/build/lib/commands/index.d.ts +0 -96
  253. package/build/lib/commands/index.d.ts.map +0 -1
  254. package/build/lib/commands/index.js +0 -100
  255. package/build/lib/commands/index.js.map +0 -1
  256. package/build/lib/real-device-clients/devicectl.d.ts +0 -204
  257. package/build/lib/real-device-clients/devicectl.d.ts.map +0 -1
  258. package/build/lib/real-device-clients/devicectl.js +0 -264
  259. package/build/lib/real-device-clients/devicectl.js.map +0 -1
  260. package/lib/commands/activeAppInfo.js +0 -14
  261. package/lib/commands/index.js +0 -95
  262. package/lib/real-device-clients/devicectl.js +0 -291
@@ -3,178 +3,179 @@ import CssConverter from '../css-converter';
3
3
  import {errors} from 'appium/driver';
4
4
  import {util} from 'appium/support';
5
5
 
6
- // we override the xpath search for this first-visible-child selector, which
7
- // looks like /*[@firstVisible="true"]
8
- const MAGIC_FIRST_VIS_CHILD_SEL = /\/\*\[@firstVisible\s*=\s*('|")true\1\]/;
9
-
10
- // we likewise override xpath search to provide a shortcut for finding all
11
- // scrollable elements
12
- const MAGIC_SCROLLABLE_SEL = /\/\/\*\[@scrollable\s*=\s*('|")true\1\]/;
6
+ /**
7
+ * @this {XCUITestDriver}
8
+ */
9
+ export async function findElOrEls(strategy, selector, mult, context) {
10
+ if (this.isWebview()) {
11
+ return await this.findWebElementOrElements(strategy, selector, mult, context);
12
+ } else {
13
+ return await this.findNativeElementOrElements(strategy, selector, mult, context);
14
+ }
15
+ }
13
16
 
14
- const WDA_CLASS_CHAIN_STRATEGY = 'class chain';
17
+ /**
18
+ * @this {XCUITestDriver}
19
+ * @privateRemarks I'm not sure what these objects are; they aren't `Element`.
20
+ * @returns {Promise<any|any[]|undefined>}
21
+ */
22
+ export async function findNativeElementOrElements(strategy, selector, mult, context) {
23
+ const initSelector = selector;
24
+ let rewroteSelector = false;
25
+ if (strategy === '-ios predicate string') {
26
+ // WebDriverAgent uses 'predicate string'
27
+ strategy = 'predicate string';
28
+ } else if (strategy === '-ios class chain') {
29
+ // WebDriverAgent uses 'class chain'
30
+ strategy = WDA_CLASS_CHAIN_STRATEGY;
31
+ } else if (strategy === 'css selector') {
32
+ strategy = WDA_CLASS_CHAIN_STRATEGY;
33
+ selector = CssConverter.toIosClassChainSelector(selector);
34
+ }
15
35
 
16
- export default {
17
- /**
18
- * @this {XCUITestDriver}
19
- */
20
- async findElOrEls(strategy, selector, mult, context) {
21
- if (this.isWebview()) {
22
- return await this.findWebElementOrElements(strategy, selector, mult, context);
23
- } else {
24
- return await this.findNativeElementOrElements(strategy, selector, mult, context);
25
- }
26
- },
27
- /**
28
- * @this {XCUITestDriver}
29
- * @privateRemarks I'm not sure what these objects are; they aren't `Element`.
30
- * @returns {Promise<any|any[]|undefined>}
31
- */
32
- async findNativeElementOrElements(strategy, selector, mult, context) {
33
- const initSelector = selector;
34
- let rewroteSelector = false;
35
- if (strategy === '-ios predicate string') {
36
- // WebDriverAgent uses 'predicate string'
37
- strategy = 'predicate string';
38
- } else if (strategy === '-ios class chain') {
39
- // WebDriverAgent uses 'class chain'
40
- strategy = WDA_CLASS_CHAIN_STRATEGY;
41
- } else if (strategy === 'css selector') {
42
- strategy = WDA_CLASS_CHAIN_STRATEGY;
43
- selector = CssConverter.toIosClassChainSelector(selector);
36
+ if (strategy === 'class name') {
37
+ // XCUITest classes have `XCUIElementType` prepended
38
+ // first check if there is the old `UIA` prefix
39
+ if (selector.startsWith('UIA')) {
40
+ selector = selector.substring(3);
44
41
  }
45
-
46
- // Check if the word 'View' is appended to selector and if it is, strip it out
47
- function stripViewFromSelector(selector) {
48
- // Don't strip it out if it's one of these 4 element types
49
- // (see https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Utilities/FBElementTypeTransformer.m for reference)
50
- const keepView = [
51
- 'XCUIElementTypeScrollView',
52
- 'XCUIElementTypeCollectionView',
53
- 'XCUIElementTypeTextView',
54
- 'XCUIElementTypeWebView',
55
- ].includes(selector);
56
-
57
- if (!keepView && selector.indexOf('View') === selector.length - 4) {
58
- return selector.substr(0, selector.length - 4);
59
- } else {
60
- return selector;
61
- }
42
+ // now check if we need to add `XCUIElementType`
43
+ if (!selector.startsWith('XCUIElementType')) {
44
+ selector = stripViewFromSelector(`XCUIElementType${selector}`);
45
+ rewroteSelector = true;
62
46
  }
47
+ }
63
48
 
64
- if (strategy === 'class name') {
65
- // XCUITest classes have `XCUIElementType` prepended
66
- // first check if there is the old `UIA` prefix
67
- if (selector.startsWith('UIA')) {
68
- selector = selector.substring(3);
69
- }
70
- // now check if we need to add `XCUIElementType`
71
- if (!selector.startsWith('XCUIElementType')) {
72
- selector = stripViewFromSelector(`XCUIElementType${selector}`);
73
- rewroteSelector = true;
74
- }
75
- }
49
+ if (strategy === 'xpath' && MAGIC_FIRST_VIS_CHILD_SEL.test(selector)) {
50
+ return await this.getFirstVisibleChild(mult, context);
51
+ } else if (strategy === 'xpath' && MAGIC_SCROLLABLE_SEL.test(selector)) {
52
+ [strategy, selector] = rewriteMagicScrollable(mult, this.log);
53
+ } else if (strategy === 'xpath') {
54
+ // Replace UIA if it comes after a forward slash or is at the beginning of the string
55
+ selector = selector.replace(/(^|\/)(UIA)([^[/]+)/g, (str, g1, g2, g3) => {
56
+ rewroteSelector = true;
57
+ return g1 + stripViewFromSelector(`XCUIElementType${g3}`);
58
+ });
59
+ }
76
60
 
77
- if (strategy === 'xpath' && MAGIC_FIRST_VIS_CHILD_SEL.test(selector)) {
78
- return await this.getFirstVisibleChild(mult, context);
79
- } else if (strategy === 'xpath' && MAGIC_SCROLLABLE_SEL.test(selector)) {
80
- [strategy, selector] = rewriteMagicScrollable(mult, this.log);
81
- } else if (strategy === 'xpath') {
82
- // Replace UIA if it comes after a forward slash or is at the beginning of the string
83
- selector = selector.replace(/(^|\/)(UIA)([^[/]+)/g, (str, g1, g2, g3) => {
84
- rewroteSelector = true;
85
- return g1 + stripViewFromSelector(`XCUIElementType${g3}`);
86
- });
87
- }
61
+ if (rewroteSelector) {
62
+ this.log.info(
63
+ `Rewrote incoming selector from '${initSelector}' to ` +
64
+ `'${selector}' to match XCUI type. You should consider ` +
65
+ `updating your tests to use the new selectors directly`,
66
+ );
67
+ }
88
68
 
89
- if (rewroteSelector) {
90
- this.log.info(
91
- `Rewrote incoming selector from '${initSelector}' to ` +
92
- `'${selector}' to match XCUI type. You should consider ` +
93
- `updating your tests to use the new selectors directly`,
94
- );
95
- }
69
+ return await this.doNativeFind(strategy, selector, mult, context);
70
+ }
96
71
 
97
- return await this.doNativeFind(strategy, selector, mult, context);
98
- },
99
- /**
100
- * @this {XCUITestDriver}
101
- */
102
- async doNativeFind(strategy, selector, mult, context) {
103
- context = util.unwrapElement(context);
104
-
105
- let endpoint = `/element${context ? `/${context}/element` : ''}${mult ? 's' : ''}`;
106
-
107
- let body = {
108
- using: strategy,
109
- value: selector,
110
- };
111
-
112
- /** @type {import('./proxy-helper').AllowedHttpMethod} */
113
- const method = 'POST';
114
-
115
- // This is either an array is mult === true
116
- // or an object if mult === false
117
- /** @type {Element[]|undefined} */
118
- let els;
119
- try {
120
- await this.implicitWaitForCondition(async () => {
121
- try {
122
- els = /** @type {Element[]|undefined} */ (
123
- await this.proxyCommand(endpoint, method, body)
124
- );
125
- } catch {
126
- els = [];
127
- }
128
- // we succeed if we get some elements
129
- return !_.isEmpty(els);
130
- });
131
- } catch (err) {
132
- if (err.message?.match(/Condition unmet/)) {
133
- // condition was not met setting res to empty array
72
+ /**
73
+ * @this {XCUITestDriver}
74
+ */
75
+ export async function doNativeFind(strategy, selector, mult, context) {
76
+ context = util.unwrapElement(context);
77
+
78
+ let endpoint = `/element${context ? `/${context}/element` : ''}${mult ? 's' : ''}`;
79
+
80
+ let body = {
81
+ using: strategy,
82
+ value: selector,
83
+ };
84
+
85
+ /** @type {import('./proxy-helper').AllowedHttpMethod} */
86
+ const method = 'POST';
87
+
88
+ // This is either an array is mult === true
89
+ // or an object if mult === false
90
+ /** @type {Element[]|undefined} */
91
+ let els;
92
+ try {
93
+ await this.implicitWaitForCondition(async () => {
94
+ try {
95
+ els = /** @type {Element[]|undefined} */ (
96
+ await this.proxyCommand(endpoint, method, body)
97
+ );
98
+ } catch {
134
99
  els = [];
135
- } else {
136
- throw err;
137
100
  }
101
+ // we succeed if we get some elements
102
+ return !_.isEmpty(els);
103
+ });
104
+ } catch (err) {
105
+ if (err.message?.match(/Condition unmet/)) {
106
+ // condition was not met setting res to empty array
107
+ els = [];
108
+ } else {
109
+ throw err;
138
110
  }
139
- if (mult) {
140
- return els;
141
- }
142
- if (_.isEmpty(els)) {
143
- throw new errors.NoSuchElementError();
144
- }
111
+ }
112
+ if (mult) {
145
113
  return els;
146
- },
147
- /**
148
- * @this {XCUITestDriver}
149
- */
150
- async getFirstVisibleChild(mult, context) {
151
- this.log.info(`Getting first visible child`);
152
- if (mult) {
153
- throw new Error('Cannot get multiple first visible children!');
154
- }
155
- if (!context) {
156
- throw new Error('Cannot get first visible child without a context element');
157
- }
158
- let index = 1;
159
- // loop through children via class-chain finds, until we run out of children
160
- // or we find a visible one. This loop looks infinite but its not, because at
161
- // some point the call to doNativeFind will throw with an Element Not Found
162
- // error, when the index gets higher than the number of child elements. This
163
- // is what we want because that error will halt the loop and make it all the
164
- // way to the client.
165
- while (true) {
166
- const strategy = WDA_CLASS_CHAIN_STRATEGY;
167
- const selector = `*[${index}]`;
168
- const nthChild = await this.doNativeFind(strategy, selector, false, context);
169
- const visible = await this.getAttribute('visible', nthChild);
170
- if (visible === 'true') {
171
- this.log.info(`Found first visible child at position ${index}`);
172
- return nthChild;
173
- }
174
- index++;
114
+ }
115
+ if (_.isEmpty(els)) {
116
+ throw new errors.NoSuchElementError();
117
+ }
118
+ return els;
119
+ }
120
+
121
+ /**
122
+ * @this {XCUITestDriver}
123
+ */
124
+ export async function getFirstVisibleChild(mult, context) {
125
+ this.log.info(`Getting first visible child`);
126
+ if (mult) {
127
+ throw new Error('Cannot get multiple first visible children!');
128
+ }
129
+ if (!context) {
130
+ throw new Error('Cannot get first visible child without a context element');
131
+ }
132
+ let index = 1;
133
+ // loop through children via class-chain finds, until we run out of children
134
+ // or we find a visible one. This loop looks infinite but its not, because at
135
+ // some point the call to doNativeFind will throw with an Element Not Found
136
+ // error, when the index gets higher than the number of child elements. This
137
+ // is what we want because that error will halt the loop and make it all the
138
+ // way to the client.
139
+ while (true) {
140
+ const strategy = WDA_CLASS_CHAIN_STRATEGY;
141
+ const selector = `*[${index}]`;
142
+ const nthChild = await this.doNativeFind(strategy, selector, false, context);
143
+ const visible = await this.getAttribute('visible', nthChild);
144
+ if (visible === 'true') {
145
+ this.log.info(`Found first visible child at position ${index}`);
146
+ return nthChild;
175
147
  }
176
- },
177
- };
148
+ index++;
149
+ }
150
+ }
151
+
152
+ // we override the xpath search for this first-visible-child selector, which
153
+ // looks like /*[@firstVisible="true"]
154
+ const MAGIC_FIRST_VIS_CHILD_SEL = /\/\*\[@firstVisible\s*=\s*('|")true\1\]/;
155
+
156
+ // we likewise override xpath search to provide a shortcut for finding all
157
+ // scrollable elements
158
+ const MAGIC_SCROLLABLE_SEL = /\/\/\*\[@scrollable\s*=\s*('|")true\1\]/;
159
+
160
+ const WDA_CLASS_CHAIN_STRATEGY = 'class chain';
161
+
162
+ // Check if the word 'View' is appended to selector and if it is, strip it out
163
+ function stripViewFromSelector(selector) {
164
+ // Don't strip it out if it's one of these 4 element types
165
+ // (see https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Utilities/FBElementTypeTransformer.m for reference)
166
+ const keepView = [
167
+ 'XCUIElementTypeScrollView',
168
+ 'XCUIElementTypeCollectionView',
169
+ 'XCUIElementTypeTextView',
170
+ 'XCUIElementTypeWebView',
171
+ ].includes(selector);
172
+
173
+ if (!keepView && selector.indexOf('View') === selector.length - 4) {
174
+ return selector.substr(0, selector.length - 4);
175
+ } else {
176
+ return selector;
177
+ }
178
+ }
178
179
 
179
180
  /**
180
181
  *