@limrun/appium-xcuitest-driver 10.11.0-lim.3 → 10.14.6-lim.1

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 (285) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/build/lib/commands/active-app-info.d.ts +4 -3
  3. package/build/lib/commands/active-app-info.d.ts.map +1 -1
  4. package/build/lib/commands/active-app-info.js +2 -3
  5. package/build/lib/commands/active-app-info.js.map +1 -1
  6. package/build/lib/commands/alert.d.ts +26 -31
  7. package/build/lib/commands/alert.d.ts.map +1 -1
  8. package/build/lib/commands/alert.js +20 -29
  9. package/build/lib/commands/alert.js.map +1 -1
  10. package/build/lib/commands/app-management.d.ts +99 -76
  11. package/build/lib/commands/app-management.d.ts.map +1 -1
  12. package/build/lib/commands/app-management.js +83 -73
  13. package/build/lib/commands/app-management.js.map +1 -1
  14. package/build/lib/commands/app-strings.d.ts +6 -7
  15. package/build/lib/commands/app-strings.d.ts.map +1 -1
  16. package/build/lib/commands/app-strings.js +3 -8
  17. package/build/lib/commands/app-strings.js.map +1 -1
  18. package/build/lib/commands/appearance.d.ts +7 -9
  19. package/build/lib/commands/appearance.d.ts.map +1 -1
  20. package/build/lib/commands/appearance.js +13 -19
  21. package/build/lib/commands/appearance.js.map +1 -1
  22. package/build/lib/commands/audit.d.ts +5 -33
  23. package/build/lib/commands/audit.d.ts.map +1 -1
  24. package/build/lib/commands/audit.js +3 -16
  25. package/build/lib/commands/audit.js.map +1 -1
  26. package/build/lib/commands/battery.d.ts +4 -4
  27. package/build/lib/commands/battery.d.ts.map +1 -1
  28. package/build/lib/commands/battery.js +3 -7
  29. package/build/lib/commands/battery.js.map +1 -1
  30. package/build/lib/commands/biometric.d.ts +12 -14
  31. package/build/lib/commands/biometric.d.ts.map +1 -1
  32. package/build/lib/commands/biometric.js +10 -19
  33. package/build/lib/commands/biometric.js.map +1 -1
  34. package/build/lib/commands/certificate.d.ts +14 -19
  35. package/build/lib/commands/certificate.d.ts.map +1 -1
  36. package/build/lib/commands/certificate.js +24 -31
  37. package/build/lib/commands/certificate.js.map +1 -1
  38. package/build/lib/commands/clipboard.d.ts +9 -11
  39. package/build/lib/commands/clipboard.d.ts.map +1 -1
  40. package/build/lib/commands/clipboard.js +8 -13
  41. package/build/lib/commands/clipboard.js.map +1 -1
  42. package/build/lib/commands/condition.d.ts +9 -72
  43. package/build/lib/commands/condition.d.ts.map +1 -1
  44. package/build/lib/commands/condition.js +5 -66
  45. package/build/lib/commands/condition.js.map +1 -1
  46. package/build/lib/commands/content-size.d.ts +16 -19
  47. package/build/lib/commands/content-size.d.ts.map +1 -1
  48. package/build/lib/commands/content-size.js +14 -22
  49. package/build/lib/commands/content-size.js.map +1 -1
  50. package/build/lib/commands/context.d.ts +130 -161
  51. package/build/lib/commands/context.d.ts.map +1 -1
  52. package/build/lib/commands/context.js +123 -108
  53. package/build/lib/commands/context.js.map +1 -1
  54. package/build/lib/commands/device-info.d.ts +13 -0
  55. package/build/lib/commands/device-info.d.ts.map +1 -0
  56. package/build/lib/commands/device-info.js +20 -0
  57. package/build/lib/commands/device-info.js.map +1 -0
  58. package/build/lib/commands/element.d.ts +83 -67
  59. package/build/lib/commands/element.d.ts.map +1 -1
  60. package/build/lib/commands/element.js +111 -134
  61. package/build/lib/commands/element.js.map +1 -1
  62. package/build/lib/commands/execute.d.ts +10 -22
  63. package/build/lib/commands/execute.d.ts.map +1 -1
  64. package/build/lib/commands/execute.js +13 -29
  65. package/build/lib/commands/execute.js.map +1 -1
  66. package/build/lib/commands/file-movement.d.ts +31 -42
  67. package/build/lib/commands/file-movement.d.ts.map +1 -1
  68. package/build/lib/commands/file-movement.js +146 -205
  69. package/build/lib/commands/file-movement.js.map +1 -1
  70. package/build/lib/commands/find.d.ts +20 -12
  71. package/build/lib/commands/find.d.ts.map +1 -1
  72. package/build/lib/commands/find.js +27 -65
  73. package/build/lib/commands/find.js.map +1 -1
  74. package/build/lib/commands/general.d.ts +84 -80
  75. package/build/lib/commands/general.d.ts.map +1 -1
  76. package/build/lib/commands/general.js +67 -54
  77. package/build/lib/commands/general.js.map +1 -1
  78. package/build/lib/commands/geolocation.d.ts +16 -36
  79. package/build/lib/commands/geolocation.d.ts.map +1 -1
  80. package/build/lib/commands/geolocation.js +8 -25
  81. package/build/lib/commands/geolocation.js.map +1 -1
  82. package/build/lib/commands/gesture.d.ts +103 -119
  83. package/build/lib/commands/gesture.d.ts.map +1 -1
  84. package/build/lib/commands/gesture.js +98 -138
  85. package/build/lib/commands/gesture.js.map +1 -1
  86. package/build/lib/commands/increase-contrast.d.ts +10 -13
  87. package/build/lib/commands/increase-contrast.d.ts.map +1 -1
  88. package/build/lib/commands/increase-contrast.js +8 -16
  89. package/build/lib/commands/increase-contrast.js.map +1 -1
  90. package/build/lib/commands/iohid.d.ts +6 -1359
  91. package/build/lib/commands/iohid.d.ts.map +1 -1
  92. package/build/lib/commands/iohid.js +5 -10
  93. package/build/lib/commands/iohid.js.map +1 -1
  94. package/build/lib/commands/keyboard.d.ts +16 -13
  95. package/build/lib/commands/keyboard.d.ts.map +1 -1
  96. package/build/lib/commands/keyboard.js +14 -18
  97. package/build/lib/commands/keyboard.js.map +1 -1
  98. package/build/lib/commands/keychains.d.ts +2 -2
  99. package/build/lib/commands/keychains.d.ts.map +1 -1
  100. package/build/lib/commands/keychains.js +1 -4
  101. package/build/lib/commands/keychains.js.map +1 -1
  102. package/build/lib/commands/localization.d.ts +7 -6
  103. package/build/lib/commands/localization.d.ts.map +1 -1
  104. package/build/lib/commands/localization.js +7 -8
  105. package/build/lib/commands/localization.js.map +1 -1
  106. package/build/lib/commands/location.d.ts +8 -11
  107. package/build/lib/commands/location.d.ts.map +1 -1
  108. package/build/lib/commands/location.js +7 -15
  109. package/build/lib/commands/location.js.map +1 -1
  110. package/build/lib/commands/lock.d.ts +6 -10
  111. package/build/lib/commands/lock.d.ts.map +1 -1
  112. package/build/lib/commands/lock.js +3 -10
  113. package/build/lib/commands/lock.js.map +1 -1
  114. package/build/lib/commands/log.d.ts +42 -44
  115. package/build/lib/commands/log.d.ts.map +1 -1
  116. package/build/lib/commands/log.js +32 -53
  117. package/build/lib/commands/log.js.map +1 -1
  118. package/build/lib/commands/memory.d.ts +4 -5
  119. package/build/lib/commands/memory.d.ts.map +1 -1
  120. package/build/lib/commands/memory.js +3 -8
  121. package/build/lib/commands/memory.js.map +1 -1
  122. package/build/lib/commands/navigation.d.ts +14 -26
  123. package/build/lib/commands/navigation.d.ts.map +1 -1
  124. package/build/lib/commands/navigation.js +22 -32
  125. package/build/lib/commands/navigation.js.map +1 -1
  126. package/build/lib/commands/notifications.d.ts +10 -10
  127. package/build/lib/commands/notifications.d.ts.map +1 -1
  128. package/build/lib/commands/notifications.js +8 -12
  129. package/build/lib/commands/notifications.js.map +1 -1
  130. package/build/lib/commands/pasteboard.d.ts +9 -10
  131. package/build/lib/commands/pasteboard.d.ts.map +1 -1
  132. package/build/lib/commands/pasteboard.js +8 -13
  133. package/build/lib/commands/pasteboard.js.map +1 -1
  134. package/build/lib/commands/pcap.d.ts +18 -38
  135. package/build/lib/commands/pcap.d.ts.map +1 -1
  136. package/build/lib/commands/pcap.js +9 -14
  137. package/build/lib/commands/pcap.js.map +1 -1
  138. package/build/lib/commands/performance.d.ts +36 -55
  139. package/build/lib/commands/performance.d.ts.map +1 -1
  140. package/build/lib/commands/performance.js +93 -86
  141. package/build/lib/commands/performance.js.map +1 -1
  142. package/build/lib/commands/permissions.d.ts +15 -17
  143. package/build/lib/commands/permissions.d.ts.map +1 -1
  144. package/build/lib/commands/permissions.js +12 -18
  145. package/build/lib/commands/permissions.js.map +1 -1
  146. package/build/lib/commands/proxy-helper.d.ts +11 -11
  147. package/build/lib/commands/proxy-helper.d.ts.map +1 -1
  148. package/build/lib/commands/proxy-helper.js +15 -24
  149. package/build/lib/commands/proxy-helper.js.map +1 -1
  150. package/build/lib/commands/record-audio.d.ts +25 -52
  151. package/build/lib/commands/record-audio.d.ts.map +1 -1
  152. package/build/lib/commands/record-audio.js +17 -19
  153. package/build/lib/commands/record-audio.js.map +1 -1
  154. package/build/lib/commands/recordscreen.d.ts +31 -62
  155. package/build/lib/commands/recordscreen.d.ts.map +1 -1
  156. package/build/lib/commands/recordscreen.js +29 -28
  157. package/build/lib/commands/recordscreen.js.map +1 -1
  158. package/build/lib/commands/screenshots.d.ts +15 -9
  159. package/build/lib/commands/screenshots.d.ts.map +1 -1
  160. package/build/lib/commands/screenshots.js +16 -16
  161. package/build/lib/commands/screenshots.js.map +1 -1
  162. package/build/lib/commands/simctl.d.ts +16 -22
  163. package/build/lib/commands/simctl.d.ts.map +1 -1
  164. package/build/lib/commands/simctl.js +13 -17
  165. package/build/lib/commands/simctl.js.map +1 -1
  166. package/build/lib/commands/source.d.ts +10 -8
  167. package/build/lib/commands/source.d.ts.map +1 -1
  168. package/build/lib/commands/source.js +11 -14
  169. package/build/lib/commands/source.js.map +1 -1
  170. package/build/lib/commands/timeouts.d.ts +25 -32
  171. package/build/lib/commands/timeouts.d.ts.map +1 -1
  172. package/build/lib/commands/timeouts.js +19 -15
  173. package/build/lib/commands/timeouts.js.map +1 -1
  174. package/build/lib/commands/types.d.ts +80 -0
  175. package/build/lib/commands/types.d.ts.map +1 -1
  176. package/build/lib/commands/web.d.ts +199 -202
  177. package/build/lib/commands/web.d.ts.map +1 -1
  178. package/build/lib/commands/web.js +216 -175
  179. package/build/lib/commands/web.js.map +1 -1
  180. package/build/lib/commands/xctest-record-screen.d.ts +17 -47
  181. package/build/lib/commands/xctest-record-screen.d.ts.map +1 -1
  182. package/build/lib/commands/xctest-record-screen.js +28 -59
  183. package/build/lib/commands/xctest-record-screen.js.map +1 -1
  184. package/build/lib/commands/xctest.d.ts +37 -37
  185. package/build/lib/commands/xctest.d.ts.map +1 -1
  186. package/build/lib/commands/xctest.js +38 -50
  187. package/build/lib/commands/xctest.js.map +1 -1
  188. package/build/lib/desired-caps.js +1 -1
  189. package/build/lib/device/log/ios-simulator-log.d.ts.map +1 -1
  190. package/build/lib/device/log/ios-simulator-log.js +2 -0
  191. package/build/lib/device/log/ios-simulator-log.js.map +1 -1
  192. package/build/lib/device/simulator-management.d.ts.map +1 -1
  193. package/build/lib/device/simulator-management.js +4 -5
  194. package/build/lib/device/simulator-management.js.map +1 -1
  195. package/build/lib/device-log/ios-crash-log.d.ts +1 -1
  196. package/build/lib/device-log/ios-crash-log.d.ts.map +1 -1
  197. package/build/lib/device-log/ios-simulator-log.d.ts +1 -1
  198. package/build/lib/device-log/ios-simulator-log.d.ts.map +1 -1
  199. package/build/lib/doctor/optional-checks.d.ts +0 -9
  200. package/build/lib/doctor/optional-checks.d.ts.map +1 -1
  201. package/build/lib/doctor/optional-checks.js +1 -30
  202. package/build/lib/doctor/optional-checks.js.map +1 -1
  203. package/build/lib/driver.d.ts +11 -3
  204. package/build/lib/driver.d.ts.map +1 -1
  205. package/build/lib/driver.js +36 -12
  206. package/build/lib/driver.js.map +1 -1
  207. package/build/lib/execute-method-map.d.ts.map +1 -1
  208. package/build/lib/execute-method-map.js +0 -9
  209. package/build/lib/execute-method-map.js.map +1 -1
  210. package/build/lib/simulator-management.js +3 -3
  211. package/build/lib/simulator-management.js.map +1 -1
  212. package/lib/commands/active-app-info.ts +15 -0
  213. package/lib/commands/alert.ts +98 -0
  214. package/lib/commands/app-management.ts +414 -0
  215. package/lib/commands/{app-strings.js → app-strings.ts} +10 -9
  216. package/lib/commands/appearance.ts +70 -0
  217. package/lib/commands/audit.ts +25 -0
  218. package/lib/commands/{battery.js → battery.ts} +10 -12
  219. package/lib/commands/biometric.ts +52 -0
  220. package/lib/commands/{certificate.js → certificate.ts} +55 -50
  221. package/lib/commands/clipboard.ts +37 -0
  222. package/lib/commands/{condition.js → condition.ts} +21 -77
  223. package/lib/commands/content-size.ts +67 -0
  224. package/lib/commands/{context.js → context.ts} +174 -146
  225. package/lib/commands/device-info.ts +24 -0
  226. package/lib/commands/element.ts +419 -0
  227. package/lib/commands/{execute.js → execute.ts} +42 -38
  228. package/lib/commands/{file-movement.js → file-movement.ts} +212 -235
  229. package/lib/commands/find.ts +277 -0
  230. package/lib/commands/{general.js → general.ts} +102 -77
  231. package/lib/commands/geolocation.ts +55 -0
  232. package/lib/commands/{gesture.js → gesture.ts} +225 -183
  233. package/lib/commands/increase-contrast.ts +49 -0
  234. package/lib/commands/{iohid.js → iohid.ts} +15 -13
  235. package/lib/commands/keyboard.ts +70 -0
  236. package/lib/commands/keychains.ts +16 -0
  237. package/lib/commands/{localization.js → localization.ts} +22 -12
  238. package/lib/commands/{location.js → location.ts} +19 -22
  239. package/lib/commands/lock.ts +43 -0
  240. package/lib/commands/{log.js → log.ts} +68 -68
  241. package/lib/commands/{memory.js → memory.ts} +9 -9
  242. package/lib/commands/{navigation.js → navigation.ts} +42 -39
  243. package/lib/commands/{notifications.js → notifications.ts} +22 -14
  244. package/lib/commands/pasteboard.ts +44 -0
  245. package/lib/commands/{pcap.js → pcap.ts} +28 -28
  246. package/lib/commands/{performance.js → performance.ts} +133 -114
  247. package/lib/commands/permissions.ts +90 -0
  248. package/lib/commands/{proxy-helper.js → proxy-helper.ts} +26 -26
  249. package/lib/commands/{record-audio.js → record-audio.ts} +35 -33
  250. package/lib/commands/{recordscreen.js → recordscreen.ts} +78 -50
  251. package/lib/commands/{screenshots.js → screenshots.ts} +27 -21
  252. package/lib/commands/simctl.ts +82 -0
  253. package/lib/commands/{source.js → source.ts} +23 -20
  254. package/lib/commands/timeouts.ts +95 -0
  255. package/lib/commands/types.ts +86 -0
  256. package/lib/commands/{web.js → web.ts} +314 -264
  257. package/lib/commands/{xctest-record-screen.js → xctest-record-screen.ts} +54 -71
  258. package/lib/commands/{xctest.js → xctest.ts} +78 -71
  259. package/lib/desired-caps.ts +1 -1
  260. package/lib/device/log/ios-simulator-log.ts +2 -0
  261. package/lib/device/simulator-management.ts +3 -6
  262. package/lib/doctor/optional-checks.ts +0 -33
  263. package/lib/driver.ts +38 -13
  264. package/lib/execute-method-map.ts +0 -9
  265. package/package.json +6 -5
  266. package/lib/commands/active-app-info.js +0 -12
  267. package/lib/commands/alert.js +0 -88
  268. package/lib/commands/app-management.js +0 -346
  269. package/lib/commands/appearance.js +0 -71
  270. package/lib/commands/audit.js +0 -31
  271. package/lib/commands/biometric.js +0 -52
  272. package/lib/commands/clipboard.js +0 -35
  273. package/lib/commands/content-size.js +0 -68
  274. package/lib/commands/deviceInfo.js +0 -27
  275. package/lib/commands/element.js +0 -423
  276. package/lib/commands/find.js +0 -205
  277. package/lib/commands/geolocation.js +0 -56
  278. package/lib/commands/increase-contrast.js +0 -50
  279. package/lib/commands/keyboard.js +0 -62
  280. package/lib/commands/keychains.js +0 -17
  281. package/lib/commands/lock.js +0 -46
  282. package/lib/commands/pasteboard.js +0 -43
  283. package/lib/commands/permissions.js +0 -85
  284. package/lib/commands/simctl.js +0 -71
  285. package/lib/commands/timeouts.js +0 -68
@@ -0,0 +1,277 @@
1
+ import _ from 'lodash';
2
+ import {CssConverter} from '../css-converter';
3
+ import {errors} from 'appium/driver';
4
+ import {util} from 'appium/support';
5
+ import type {Element, AppiumLogger} from '@appium/types';
6
+ import type {XCUITestDriver} from '../driver';
7
+ import type {AllowedHttpMethod} from './proxy-helper';
8
+
9
+ /**
10
+ * Finds elements, delegating to web or native based on context.
11
+ */
12
+ export async function findElOrEls(
13
+ this: XCUITestDriver,
14
+ strategy: string,
15
+ selector: string,
16
+ mult: true,
17
+ context?: any,
18
+ ): Promise<Element[]>;
19
+ export async function findElOrEls(
20
+ this: XCUITestDriver,
21
+ strategy: string,
22
+ selector: string,
23
+ mult: false,
24
+ context?: any,
25
+ ): Promise<Element>;
26
+ export async function findElOrEls(
27
+ this: XCUITestDriver,
28
+ strategy: string,
29
+ selector: string,
30
+ mult: boolean,
31
+ context?: any,
32
+ ): Promise<Element | Element[]>;
33
+ export async function findElOrEls(
34
+ this: XCUITestDriver,
35
+ strategy: string,
36
+ selector: string,
37
+ mult: boolean,
38
+ context?: any,
39
+ ): Promise<Element | Element[]>;
40
+ export async function findElOrEls(
41
+ this: XCUITestDriver,
42
+ strategy: string,
43
+ selector: string,
44
+ mult: boolean,
45
+ context?: any,
46
+ ): Promise<Element | Element[]> {
47
+ if (this.isWebview()) {
48
+ return mult
49
+ ? await this.findWebElementOrElements(strategy, selector, true, context)
50
+ : await this.findWebElementOrElements(strategy, selector, false, context);
51
+ }
52
+ return mult
53
+ ? await this.findNativeElementOrElements(strategy, selector, true, context)
54
+ : await this.findNativeElementOrElements(strategy, selector, false, context);
55
+ }
56
+
57
+ /**
58
+ * Finds elements natively with strategy/selector rewriting for WDA.
59
+ */
60
+ export async function findNativeElementOrElements(
61
+ this: XCUITestDriver,
62
+ strategy: string,
63
+ selector: string,
64
+ mult: true,
65
+ context?: any,
66
+ ): Promise<Element[]>;
67
+ export async function findNativeElementOrElements(
68
+ this: XCUITestDriver,
69
+ strategy: string,
70
+ selector: string,
71
+ mult: false,
72
+ context?: any,
73
+ ): Promise<Element>;
74
+ export async function findNativeElementOrElements(
75
+ this: XCUITestDriver,
76
+ strategy: string,
77
+ selector: string,
78
+ mult: boolean,
79
+ context?: any,
80
+ ): Promise<Element | Element[]>;
81
+ export async function findNativeElementOrElements(
82
+ this: XCUITestDriver,
83
+ strategy: string,
84
+ selector: string,
85
+ mult: boolean,
86
+ context?: any,
87
+ ): Promise<Element | Element[]> {
88
+ const initSelector = selector;
89
+ let rewroteSelector = false;
90
+ if (strategy === '-ios predicate string') {
91
+ strategy = 'predicate string';
92
+ } else if (strategy === '-ios class chain') {
93
+ strategy = WDA_CLASS_CHAIN_STRATEGY;
94
+ } else if (strategy === 'css selector') {
95
+ strategy = WDA_CLASS_CHAIN_STRATEGY;
96
+ selector = CssConverter.toIosClassChainSelector(selector);
97
+ }
98
+
99
+ if (strategy === 'class name') {
100
+ if (selector.startsWith('UIA')) {
101
+ selector = selector.substring(3);
102
+ }
103
+ if (!selector.startsWith('XCUIElementType')) {
104
+ selector = stripViewFromSelector(`XCUIElementType${selector}`);
105
+ rewroteSelector = true;
106
+ }
107
+ }
108
+
109
+ if (strategy === 'xpath' && MAGIC_FIRST_VIS_CHILD_SEL.test(selector)) {
110
+ return await this.getFirstVisibleChild(mult, context);
111
+ } else if (strategy === 'xpath' && MAGIC_SCROLLABLE_SEL.test(selector)) {
112
+ [strategy, selector] = rewriteMagicScrollable(mult, this.log);
113
+ } else if (strategy === 'xpath') {
114
+ selector = selector.replace(/(^|\/)(UIA)([^[/]+)/g, (str, g1, _g2, g3) => {
115
+ rewroteSelector = true;
116
+ return g1 + stripViewFromSelector(`XCUIElementType${g3}`);
117
+ });
118
+ }
119
+
120
+ if (rewroteSelector) {
121
+ this.log.info(
122
+ `Rewrote incoming selector from '${initSelector}' to ` +
123
+ `'${selector}' to match XCUI type. You should consider ` +
124
+ `updating your tests to use the new selectors directly`,
125
+ );
126
+ }
127
+
128
+ return mult
129
+ ? await this.doNativeFind(strategy, selector, true, context)
130
+ : await this.doNativeFind(strategy, selector, false, context);
131
+ }
132
+
133
+ /**
134
+ * Finds elements natively and returns either a single element or an array depending on `mult`.
135
+ *
136
+ * Returns an array when `mult` is true; otherwise returns a single element.
137
+ */
138
+ export async function doNativeFind(
139
+ this: XCUITestDriver,
140
+ strategy: string,
141
+ selector: string,
142
+ mult: true,
143
+ context?: any,
144
+ ): Promise<Element[]>;
145
+ export async function doNativeFind(
146
+ this: XCUITestDriver,
147
+ strategy: string,
148
+ selector: string,
149
+ mult: false,
150
+ context?: any,
151
+ ): Promise<Element>;
152
+ export async function doNativeFind(
153
+ this: XCUITestDriver,
154
+ strategy: string,
155
+ selector: string,
156
+ mult: boolean,
157
+ context?: any,
158
+ ): Promise<Element | Element[]>;
159
+ export async function doNativeFind(
160
+ this: XCUITestDriver,
161
+ strategy: string,
162
+ selector: string,
163
+ mult: boolean,
164
+ context?: any,
165
+ ): Promise<Element | Element[]>;
166
+ export async function doNativeFind(
167
+ this: XCUITestDriver,
168
+ strategy: string,
169
+ selector: string,
170
+ mult: boolean,
171
+ context?: any,
172
+ ): Promise<Element | Element[]> {
173
+ const ctx = util.unwrapElement(context ?? null);
174
+ const endpoint = `/element${ctx ? `/${ctx}/element` : ''}${mult ? 's' : ''}`;
175
+
176
+ const body = {
177
+ using: strategy,
178
+ value: selector,
179
+ };
180
+
181
+ const method: AllowedHttpMethod = 'POST';
182
+
183
+ let els: Element[] | Element = [];
184
+ try {
185
+ await this.implicitWaitForCondition(async () => {
186
+ try {
187
+ els = (await this.proxyCommand(endpoint, method, body)) as Element[] | Element;
188
+ } catch {
189
+ els = [] as Element[];
190
+ }
191
+ return !_.isEmpty(els as any[]);
192
+ });
193
+ } catch (err: any) {
194
+ if (err.message?.match(/Condition unmet/)) {
195
+ els = [] as Element[];
196
+ } else {
197
+ throw err;
198
+ }
199
+ }
200
+ if (mult) {
201
+ return Array.isArray(els) ? els : [els];
202
+ }
203
+ if (Array.isArray(els)) {
204
+ if (_.isEmpty(els)) {
205
+ throw new errors.NoSuchElementError();
206
+ }
207
+ return els[0];
208
+ }
209
+ if (!els) {
210
+ throw new errors.NoSuchElementError();
211
+ }
212
+ return els;
213
+ }
214
+
215
+ /**
216
+ * Finds the first visible child element inside a context.
217
+ */
218
+ export async function getFirstVisibleChild(
219
+ this: XCUITestDriver,
220
+ mult: boolean,
221
+ context: Element | string | null,
222
+ ): Promise<Element> {
223
+ this.log.info(`Getting first visible child`);
224
+ if (mult) {
225
+ throw new Error('Cannot get multiple first visible children!');
226
+ }
227
+ if (!context) {
228
+ throw new Error('Cannot get first visible child without a context element');
229
+ }
230
+ let index = 1;
231
+ while (true) {
232
+ const strategy = WDA_CLASS_CHAIN_STRATEGY;
233
+ const selector = `*[${index}]`;
234
+ const nthChild = (await this.doNativeFind(strategy, selector, false, context)) as Element;
235
+ const visible = await this.getAttribute('visible', nthChild);
236
+ if (visible === 'true') {
237
+ this.log.info(`Found first visible child at position ${index}`);
238
+ return nthChild;
239
+ }
240
+ index++;
241
+ }
242
+ }
243
+
244
+ const MAGIC_FIRST_VIS_CHILD_SEL = /\/\*\[@firstVisible\s*=\s*('|")true\1\]/;
245
+ const MAGIC_SCROLLABLE_SEL = /\/\/\*\[@scrollable\s*=\s*('|")true\1\]/;
246
+ const WDA_CLASS_CHAIN_STRATEGY = 'class chain';
247
+
248
+ function stripViewFromSelector(selector: string): string {
249
+ const keepView = [
250
+ 'XCUIElementTypeScrollView',
251
+ 'XCUIElementTypeCollectionView',
252
+ 'XCUIElementTypeTextView',
253
+ 'XCUIElementTypeWebView',
254
+ ].includes(selector);
255
+
256
+ if (!keepView && selector.indexOf('View') === selector.length - 4) {
257
+ return selector.substring(0, selector.length - 4);
258
+ }
259
+ return selector;
260
+ }
261
+
262
+ function rewriteMagicScrollable(mult: boolean, log: AppiumLogger | null = null): [string, string] {
263
+ const pred = ['ScrollView', 'Table', 'CollectionView', 'WebView']
264
+ .map((t) => `type == "XCUIElementType${t}"`)
265
+ .join(' OR ');
266
+ const strategy = WDA_CLASS_CHAIN_STRATEGY;
267
+ let selector = '**/*[`' + pred + '`]';
268
+ if (!mult) {
269
+ selector += '[1]';
270
+ }
271
+ log?.info(
272
+ 'Rewrote request for scrollable descendants to class chain ' +
273
+ `format with selector '${selector}'`,
274
+ );
275
+ return [strategy, selector];
276
+ }
277
+
@@ -3,13 +3,22 @@ import {errors} from 'appium/driver';
3
3
  import moment from 'moment-timezone';
4
4
  import {utilities} from 'appium-ios-device';
5
5
  import {exec} from 'teen_process';
6
+ import type {XCUITestDriver} from '../driver';
7
+ import type {Viewport, ScreenInfo, ButtonName} from './types';
8
+ import type {Size, Rect} from '@appium/types';
9
+ import type {Simulator} from 'appium-ios-simulator';
6
10
 
7
11
  const MOMENT_FORMAT_ISO8601 = 'YYYY-MM-DDTHH:mm:ssZ';
8
12
 
9
13
  /**
10
- * @this {XCUITestDriver}
14
+ * Gets the currently active element.
15
+ *
16
+ * In web context, returns the active element from the DOM.
17
+ * In native context, returns the active element from the current view.
18
+ *
19
+ * @returns The active element
11
20
  */
12
- export async function active() {
21
+ export async function active(this: XCUITestDriver): Promise<any> {
13
22
  if (this.isWebContext()) {
14
23
  return this.cacheWebElements(await this.executeAtom('active_element', []));
15
24
  }
@@ -17,31 +26,29 @@ export async function active() {
17
26
  }
18
27
 
19
28
  /**
20
- * Trigger a touch/fingerprint match or match failure
29
+ * Trigger a touch/fingerprint match or match failure.
21
30
  *
22
- * @param {boolean} match - whether the match should be a success or failure
23
- * @this {XCUITestDriver}
31
+ * @param match - Whether the match should be a success or failure
24
32
  */
25
- export async function touchId(match = true) {
33
+ export async function touchId(this: XCUITestDriver, match = true): Promise<void> {
26
34
  await this.mobileSendBiometricMatch('touchId', match);
27
35
  }
28
- /**
29
- * Toggle whether the device is enrolled in the touch ID program
30
- *
31
- * @param {boolean} isEnabled - whether to enable or disable the touch ID program
32
- *
33
- * @this {XCUITestDriver}
34
- */
35
- export async function toggleEnrollTouchId(isEnabled = true) {
36
+
37
+ /**
38
+ * Toggle whether the device is enrolled in the touch ID program.
39
+ *
40
+ * @param isEnabled - Whether to enable or disable the touch ID program
41
+ */
42
+ export async function toggleEnrollTouchId(this: XCUITestDriver, isEnabled = true): Promise<void> {
36
43
  await this.mobileEnrollBiometric(isEnabled);
37
44
  }
38
45
 
39
46
  /**
40
- * Get the window size
41
- * @this {XCUITestDriver}
42
- * @returns {Promise<import('@appium/types').Size>}
47
+ * Get the window size.
48
+ *
49
+ * @returns The window size (width and height)
43
50
  */
44
- export async function getWindowSize() {
51
+ export async function getWindowSize(this: XCUITestDriver): Promise<Size> {
45
52
  const {width, height} = await this.getWindowRect();
46
53
  return {width, height};
47
54
  }
@@ -49,11 +56,13 @@ export async function getWindowSize() {
49
56
  /**
50
57
  * Retrieves the actual device time.
51
58
  *
52
- * @param {string} format - The format specifier string. Read the [MomentJS documentation](https://momentjs.com/docs/) to get the full list of supported datetime format specifiers. The default format is `YYYY-MM-DDTHH:mm:ssZ`, which complies to ISO-8601.
53
- * @returns {Promise<string>} Formatted datetime string or the raw command output (if formatting fails)
54
- * @this {XCUITestDriver}
59
+ * @param format - The format specifier string. Read the [MomentJS documentation](https://momentjs.com/docs/) to get the full list of supported datetime format specifiers. The default format is `YYYY-MM-DDTHH:mm:ssZ`, which complies to ISO-8601.
60
+ * @returns Formatted datetime string or the raw command output (if formatting fails)
55
61
  */
56
- export async function getDeviceTime(format = MOMENT_FORMAT_ISO8601) {
62
+ export async function getDeviceTime(
63
+ this: XCUITestDriver,
64
+ format = MOMENT_FORMAT_ISO8601,
65
+ ): Promise<string> {
57
66
  this.log.info('Attempting to capture iOS device date and time');
58
67
  if (!this.isRealDevice()) {
59
68
  this.log.info('On simulator. Assuming device time is the same as host time');
@@ -94,22 +103,29 @@ export async function getDeviceTime(format = MOMENT_FORMAT_ISO8601) {
94
103
  }
95
104
 
96
105
  /**
97
- * Retrieves the current device time
106
+ * Retrieves the current device time.
98
107
  *
99
- * @param {string} format - See {@linkcode getDeviceTime.format}
100
- * @returns {Promise<string>} Formatted datetime string or the raw command output if formatting fails
101
- * @this {XCUITestDriver}
108
+ * This is a wrapper around {@linkcode getDeviceTime}.
109
+ *
110
+ * @param format - See {@linkcode getDeviceTime.format}
111
+ * @returns Formatted datetime string or the raw command output if formatting fails
102
112
  */
103
- export async function mobileGetDeviceTime(format = MOMENT_FORMAT_ISO8601) {
113
+ export async function mobileGetDeviceTime(
114
+ this: XCUITestDriver,
115
+ format = MOMENT_FORMAT_ISO8601,
116
+ ): Promise<string> {
104
117
  return await this.getDeviceTime(format);
105
118
  }
106
119
 
107
120
  /**
108
- * For W3C
109
- * @this {XCUITestDriver}
110
- * @return {Promise<import('@appium/types').Rect>}
121
+ * Gets the window rectangle (position and size).
122
+ *
123
+ * For W3C compatibility. In web context, returns the browser window dimensions.
124
+ * In native context, returns the device window dimensions.
125
+ *
126
+ * @returns The window rectangle
111
127
  */
112
- export async function getWindowRect() {
128
+ export async function getWindowRect(this: XCUITestDriver): Promise<Rect> {
113
129
  if (this.isWebContext()) {
114
130
  const script = 'return {' +
115
131
  'x: window.screenX || 0,' +
@@ -120,22 +136,29 @@ export async function getWindowRect() {
120
136
  return await this.executeAtom('execute_script', [script]);
121
137
  }
122
138
 
123
- return /** @type {import('@appium/types').Rect} */ (
124
- await this.proxyCommand('/window/rect', 'GET')
125
- );
139
+ return (await this.proxyCommand('/window/rect', 'GET')) as Rect;
126
140
  }
127
141
 
128
142
  /**
129
- * @this {XCUITestDriver}
143
+ * Removes/uninstalls the given application from the device under test.
144
+ *
145
+ * This is a wrapper around {@linkcode mobileRemoveApp mobile: removeApp}.
146
+ *
147
+ * @param bundleId - The bundle identifier of the application to be removed
148
+ * @returns `true` if the application has been removed successfully; `false` otherwise
130
149
  */
131
- export async function removeApp(bundleId) {
150
+ export async function removeApp(this: XCUITestDriver, bundleId: string): Promise<boolean> {
132
151
  return await this.mobileRemoveApp(bundleId);
133
152
  }
134
153
 
135
154
  /**
136
- * @this {XCUITestDriver}
155
+ * Launches the app.
156
+ *
157
+ * @deprecated This API has been deprecated and is not supported anymore.
158
+ * Consider using corresponding 'mobile:' extensions to manage the state of the app under test.
159
+ * @throws {Error} Always throws an error indicating the API is deprecated
137
160
  */
138
- export async function launchApp() {
161
+ export async function launchApp(this: XCUITestDriver): Promise<void> {
139
162
  throw new Error(
140
163
  `The launchApp API has been deprecated and is not supported anymore. ` +
141
164
  `Consider using corresponding 'mobile:' extensions to manage the state of the app under test.`,
@@ -143,9 +166,13 @@ export async function launchApp() {
143
166
  }
144
167
 
145
168
  /**
146
- * @this {XCUITestDriver}
169
+ * Closes the app.
170
+ *
171
+ * @deprecated This API has been deprecated and is not supported anymore.
172
+ * Consider using corresponding 'mobile:' extensions to manage the state of the app under test.
173
+ * @throws {Error} Always throws an error indicating the API is deprecated
147
174
  */
148
- export async function closeApp() {
175
+ export async function closeApp(this: XCUITestDriver): Promise<void> {
149
176
  throw new Error(
150
177
  `The closeApp API has been deprecated and is not supported anymore. ` +
151
178
  `Consider using corresponding 'mobile:' extensions to manage the state of the app under test.`,
@@ -153,25 +180,29 @@ export async function closeApp() {
153
180
  }
154
181
 
155
182
  /**
156
- * @this {XCUITestDriver}
157
- * @param {string} url
158
- * @returns {Promise<void>}
183
+ * Sets the URL for the current session.
184
+ *
185
+ * In web context, navigates to the URL using the remote debugger.
186
+ * In native context on real devices, uses the proxy command.
187
+ * In native context on simulators, uses simctl to open the URL.
188
+ *
189
+ * @param url - The URL to navigate to
159
190
  */
160
- export async function setUrl(url) {
191
+ export async function setUrl(this: XCUITestDriver, url: string): Promise<void> {
161
192
  this.log.debug(`Attempting to set url '${url}'`);
162
193
 
163
194
  if (this.isWebContext()) {
164
195
  this.setCurrentUrl(url);
165
196
  // make sure to clear out any leftover web frames
166
197
  this.curWebFrames = [];
167
- await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote)).navToUrl(url);
198
+ await this.remote.navToUrl(url);
168
199
  return;
169
200
  }
170
201
 
171
202
  if (this.isRealDevice()) {
172
203
  await this.proxyCommand('/url', 'POST', {url});
173
204
  } else {
174
- await /** @type {import('appium-ios-simulator').Simulator} */ (this.device).simctl.openUrl(url);
205
+ await (this.device as Simulator).simctl.openUrl(url);
175
206
  }
176
207
  }
177
208
 
@@ -179,10 +210,10 @@ export async function setUrl(url) {
179
210
  * Retrieves the viewport dimensions.
180
211
  *
181
212
  * The viewport is the device's screen size with status bar size subtracted if the latter is present/visible.
182
- * @returns {Promise<import('./types').Viewport>}
183
- * @this {XCUITestDriver}
213
+ *
214
+ * @returns The viewport rectangle
184
215
  */
185
- export async function getViewportRect() {
216
+ export async function getViewportRect(this: XCUITestDriver): Promise<Viewport> {
186
217
  const scale = await this.getDevicePixelRatio();
187
218
  // status bar height comes in unscaled, so scale it
188
219
  const statusBarHeight = Math.trunc((await this.getStatusBarHeight()) * scale);
@@ -202,26 +233,29 @@ export async function getViewportRect() {
202
233
  * Get information about the screen.
203
234
  *
204
235
  * @privateRemarks memoized in constructor
205
- * @this {XCUITestDriver}
206
- * @returns {Promise<ScreenInfo>}
236
+ * @returns Screen information including dimensions, scale, and status bar size
207
237
  */
208
- export async function getScreenInfo() {
209
- return /** @type {ScreenInfo} */ (await this.proxyCommand('/wda/screen', 'GET'));
238
+ export async function getScreenInfo(this: XCUITestDriver): Promise<ScreenInfo> {
239
+ return (await this.proxyCommand('/wda/screen', 'GET')) as ScreenInfo;
210
240
  }
211
241
 
212
242
  /**
213
- * @this {XCUITestDriver}
243
+ * Gets the status bar height.
244
+ *
245
+ * @returns The height of the status bar in logical pixels
214
246
  */
215
- export async function getStatusBarHeight() {
247
+ export async function getStatusBarHeight(this: XCUITestDriver): Promise<number> {
216
248
  const {statusBarSize} = await this.getScreenInfo();
217
249
  return statusBarSize.height;
218
250
  }
219
251
 
220
252
  /**
221
- * memoized in constructor
222
- * @this {XCUITestDriver}
253
+ * Gets the device pixel ratio.
254
+ *
255
+ * @privateRemarks memoized in constructor
256
+ * @returns The device pixel ratio (scale factor)
223
257
  */
224
- export async function getDevicePixelRatio() {
258
+ export async function getDevicePixelRatio(this: XCUITestDriver): Promise<number> {
225
259
  const {scale} = await this.getScreenInfo();
226
260
  return scale;
227
261
  }
@@ -236,11 +270,14 @@ export async function getDevicePixelRatio() {
236
270
  *
237
271
  * Use {@linkcode mobilePerformIoHidEvent} to call a more universal API to perform a button press with duration on any supported device.
238
272
  *
239
- * @param {import('./types').ButtonName} name - The name of the button to be pressed.
240
- * @param {number} [durationSeconds] - The duration of the button press in seconds (float).
241
- * @this {XCUITestDriver}
273
+ * @param name - The name of the button to be pressed
274
+ * @param durationSeconds - The duration of the button press in seconds (float)
242
275
  */
243
- export async function mobilePressButton(name, durationSeconds) {
276
+ export async function mobilePressButton(
277
+ this: XCUITestDriver,
278
+ name: ButtonName,
279
+ durationSeconds?: number,
280
+ ): Promise<void> {
244
281
  if (!name) {
245
282
  throw new errors.InvalidArgumentError('Button name is mandatory');
246
283
  }
@@ -254,25 +291,13 @@ export async function mobilePressButton(name, durationSeconds) {
254
291
  * Process a string as speech and send it to Siri.
255
292
  *
256
293
  * Presents the Siri UI, if it is not currently active, and accepts a string which is then processed as if it were recognized speech. See [the documentation of `activateWithVoiceRecognitionText`](https://developer.apple.com/documentation/xctest/xcuisiriservice/2852140-activatewithvoicerecognitiontext?language=objc) for more details.
257
-
258
- * @param {string} text - Text to be sent to Siri
259
- * @returns {Promise<void>}
260
- * @this {XCUITestDriver}
294
+ *
295
+ * @param text - Text to be sent to Siri
261
296
  */
262
- export async function mobileSiriCommand(text) {
297
+ export async function mobileSiriCommand(this: XCUITestDriver, text: string): Promise<void> {
263
298
  if (!text) {
264
299
  throw new errors.InvalidArgumentError('"text" argument is mandatory');
265
300
  }
266
301
  await this.proxyCommand('/wda/siri/activate', 'POST', {text});
267
302
  }
268
303
 
269
- /**
270
- * @typedef {Object} PressButtonOptions
271
- * @property {string} name - The name of the button to be pressed.
272
- * @property {number} [durationSeconds] - Duration in float seconds.
273
- */
274
-
275
- /**
276
- * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
277
- * @typedef {import('./types').ScreenInfo} ScreenInfo
278
- */
@@ -0,0 +1,55 @@
1
+ import type {XCUITestDriver} from '../driver';
2
+
3
+ export interface GeolocationInfo {
4
+ /** Measurement of distance north or south of the Equator, or `null` if {@linkcode XCUITestDriver.mobileSetSimulatedLocation} has not been called or {@linkcode mobileResetSimulatedLocation} has been called. */
5
+ latitude: number | null;
6
+ /** Measurement of distance east or west of the prime meridian, or `null` if {@linkcode XCUITestDriver.mobileSetSimulatedLocation} has not been called or {@linkcode mobileResetSimulatedLocation} has been called. */
7
+ longitude: number | null;
8
+ }
9
+
10
+ /**
11
+ * Retrieves the simulated geolocation value.
12
+ * Only works since Xcode 14.3/iOS 16.4
13
+ *
14
+ * @returns The current simulated geolocation
15
+ * @throws If the device under test does not support geolocation simulation.
16
+ * @since 4.18
17
+ */
18
+ export async function mobileGetSimulatedLocation(
19
+ this: XCUITestDriver,
20
+ ): Promise<GeolocationInfo> {
21
+ return await this.proxyCommand<any, GeolocationInfo>('/wda/simulatedLocation', 'GET');
22
+ }
23
+
24
+ /**
25
+ * Sets simulated geolocation value.
26
+ * Only works since Xcode 14.3/iOS 16.4
27
+ *
28
+ * @param latitude - Latitude value
29
+ * @param longitude - Longitude value
30
+ * @throws If the device under test does not support geolocation simulation.
31
+ * @since 4.18
32
+ */
33
+ export async function mobileSetSimulatedLocation(
34
+ this: XCUITestDriver,
35
+ latitude: number,
36
+ longitude: number,
37
+ ): Promise<void> {
38
+ await this.proxyCommand('/wda/simulatedLocation', 'POST', {latitude, longitude});
39
+ }
40
+
41
+ /**
42
+ * Resets simulated geolocation value.
43
+ * Only works since Xcode 14.3/iOS 16.4.
44
+ * ! Do not forget to reset the simulated geolocation value after your automated test is finished.
45
+ * ! If the value is not reset explicitly then the simulated one will remain until the next device restart.
46
+ *
47
+ * @throws If the device under test does not support geolocation simulation.
48
+ * @since 4.18
49
+ */
50
+ export async function mobileResetSimulatedLocation(
51
+ this: XCUITestDriver,
52
+ ): Promise<void> {
53
+ await this.proxyCommand('/wda/simulatedLocation', 'DELETE');
54
+ }
55
+