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
@@ -4,25 +4,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.gesturesChainToString = gesturesChainToString;
7
+ exports.mobileShake = mobileShake;
8
+ exports.click = click;
9
+ exports.releaseActions = releaseActions;
10
+ exports.performActions = performActions;
11
+ exports.nativeClick = nativeClick;
12
+ exports.mobileScrollToElement = mobileScrollToElement;
13
+ exports.mobileScroll = mobileScroll;
14
+ exports.mobileSwipe = mobileSwipe;
15
+ exports.mobilePinch = mobilePinch;
16
+ exports.mobileDoubleTap = mobileDoubleTap;
17
+ exports.mobileTwoFingerTap = mobileTwoFingerTap;
18
+ exports.mobileTouchAndHold = mobileTouchAndHold;
19
+ exports.mobileTap = mobileTap;
20
+ exports.mobileDragFromToForDuration = mobileDragFromToForDuration;
21
+ exports.mobileDragFromToWithVelocity = mobileDragFromToWithVelocity;
22
+ exports.mobileTapWithNumberOfTaps = mobileTapWithNumberOfTaps;
23
+ exports.mobileForcePress = mobileForcePress;
24
+ exports.mobileSelectPickerWheelValue = mobileSelectPickerWheelValue;
25
+ exports.mobileRotateElement = mobileRotateElement;
7
26
  const driver_1 = require("appium/driver");
8
27
  const support_1 = require("appium/support");
9
28
  const lodash_1 = __importDefault(require("lodash"));
10
29
  const SUPPORTED_GESTURE_DIRECTIONS = ['up', 'down', 'left', 'right'];
11
- /**
12
- * Converts the given value to a float number.
13
- *
14
- * @throws If `value` is `NaN`
15
- * @param {any} value
16
- * @param {string} paramName
17
- * @returns {number}
18
- */
19
- function requireFloat(value, paramName) {
20
- const num = parseFloat(String(value));
21
- if (Number.isNaN(num)) {
22
- throw new driver_1.errors.InvalidArgumentError(`"${paramName}" parameter should be a valid number. "${value}" is given instead`);
23
- }
24
- return num;
25
- }
26
30
  /**
27
31
  *
28
32
  * @param {any[]} gestures
@@ -42,493 +46,488 @@ function gesturesChainToString(gestures, keysToInclude = ['options']) {
42
46
  })
43
47
  .join('-');
44
48
  }
45
- const commands = {
46
- /**
47
- * Shake the device
48
- * @this {XCUITestDriver}
49
- * @group Simulator Only
50
- */
51
- async mobileShake() {
52
- if (!this.isSimulator()) {
53
- throw new driver_1.errors.UnknownError('Shake is not supported on real devices');
54
- }
55
- await /** @type {import('../driver').Simulator} */ (this.device).shake();
56
- },
57
- /**
58
- * @this {XCUITestDriver}
59
- */
60
- async click(el) {
61
- if (!this.isWebContext()) {
62
- // there are multiple commands that map here, so manually proxy
63
- return await this.nativeClick(el);
64
- }
65
- el = support_1.util.unwrapElement(el);
66
- const { nativeWebTap, nativeWebTapStrict } = this.settings.getSettings();
67
- if (nativeWebTap || nativeWebTapStrict) {
68
- // atoms-based clicks don't always work in safari 7
69
- this.log.debug('Using native web tap');
70
- await this.nativeWebTap(el);
49
+ /**
50
+ * Shake the device
51
+ * @this {XCUITestDriver}
52
+ * @group Simulator Only
53
+ */
54
+ async function mobileShake() {
55
+ if (!this.isSimulator()) {
56
+ throw new driver_1.errors.UnknownError('Shake is not supported on real devices');
57
+ }
58
+ await /** @type {import('../driver').Simulator} */ (this.device).shake();
59
+ }
60
+ /**
61
+ * @this {XCUITestDriver}
62
+ */
63
+ async function click(el) {
64
+ if (!this.isWebContext()) {
65
+ // there are multiple commands that map here, so manually proxy
66
+ return await this.nativeClick(el);
67
+ }
68
+ el = support_1.util.unwrapElement(el);
69
+ const { nativeWebTap, nativeWebTapStrict } = this.settings.getSettings();
70
+ if (nativeWebTap || nativeWebTapStrict) {
71
+ // atoms-based clicks don't always work in safari 7
72
+ this.log.debug('Using native web tap');
73
+ await this.nativeWebTap(el);
74
+ }
75
+ else {
76
+ const atomsElement = this.getAtomsElement(el);
77
+ // clicking can cause an alert to pop up and freeze the event loop, meaning the click atom
78
+ // itself never returns. we have alert handling in `waitForAtom` but with click, we create
79
+ // a special case where if a click results in an unexpected alert error, we just return
80
+ // control to the client. they will encounter the error on their next command, which mirrors
81
+ // the behaviour of selenium.
82
+ try {
83
+ return await this.executeAtom('click', [atomsElement]);
71
84
  }
72
- else {
73
- const atomsElement = this.getAtomsElement(el);
74
- // clicking can cause an alert to pop up and freeze the event loop, meaning the click atom
75
- // itself never returns. we have alert handling in `waitForAtom` but with click, we create
76
- // a special case where if a click results in an unexpected alert error, we just return
77
- // control to the client. they will encounter the error on their next command, which mirrors
78
- // the behaviour of selenium.
79
- try {
80
- return await this.executeAtom('click', [atomsElement]);
81
- }
82
- catch (err) {
83
- if (err.error === driver_1.errors.UnexpectedAlertOpenError.error()) {
84
- return;
85
- }
86
- throw err;
85
+ catch (err) {
86
+ if (err.error === driver_1.errors.UnexpectedAlertOpenError.error()) {
87
+ return;
87
88
  }
89
+ throw err;
88
90
  }
89
- },
90
- /**
91
- * @this {XCUITestDriver}
92
- */
93
- async releaseActions() {
94
- this.log.warn('On this platform, releaseActions is a no-op');
95
- },
96
- /**
97
- * @param {import('@appium/types').ActionSequence[]} actions
98
- * @returns {Promise<void>}
99
- * @this {XCUITestDriver}
100
- */
101
- async performActions(actions) {
102
- this.log.debug(`Received the following W3C actions: ${JSON.stringify(actions, null, ' ')}`);
103
- assertNoWebElements(actions);
104
- // This is mandatory, since WDA only supports TOUCH pointer type
105
- // and Selenium API uses MOUSE as the default one
106
- const preprocessedActions = actions
107
- .map((action) => ({
108
- ...action,
109
- ...(action.type === 'pointer'
110
- ? {
111
- parameters: {
112
- pointerType: 'touch',
113
- },
114
- }
115
- : {}),
116
- }))
117
- .map((action) => {
118
- const modifiedAction = lodash_1.default.clone(action) || {};
119
- // Selenium API unexpectedly inserts zero pauses, which are not supported by WDA
120
- modifiedAction.actions = (action.actions || []).filter((innerAction) => !(innerAction.type === 'pause' && innerAction.duration === 0));
121
- return modifiedAction;
122
- });
123
- this.log.debug(`Preprocessed actions: ${JSON.stringify(preprocessedActions, null, ' ')}`);
124
- await this.proxyCommand('/actions', 'POST', { actions: preprocessedActions });
125
- },
126
- /**
127
- * @param {import('@appium/types').Element|string} el
128
- * @this {XCUITestDriver}
129
- * @group Native Only
130
- */
131
- async nativeClick(el) {
132
- el = support_1.util.unwrapElement(el);
133
- let endpoint = `/element/${el}/click`;
134
- return await this.proxyCommand(endpoint, 'POST', {});
135
- },
136
- /**
137
- * Scrolls the current viewport to the given element.
138
- *
139
- * This command expects the destination element to be inside a scrollable container and is hittable. The scroll direction is detected automatically.
140
- *
141
- * This API uses native XCTest calls, so it is performant. The same native call is implicitly performed by a `click` command if the destination element is outside the current viewport.
142
- *
143
- * @since 4.7.0
144
- * @throws If the scrolling action cannot be performed
145
- * @privateRemarks See https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Commands/FBElementCommands.m for details on WDA gestures API
146
- * @param {Element|string} elementId - The internal element identifier (as hexadecimal hash string) to scroll to. The destination element must be located in a scrollable container and must be hittable. If the element is already present in the current viewport then no action is performed.
147
- * @returns {Promise<void>}
148
- * @this {XCUITestDriver}
149
- */
150
- async mobileScrollToElement(elementId) {
151
- if (!elementId) {
152
- throw new driver_1.errors.InvalidArgumentError('Element id must be provided');
153
- }
154
- return await this.proxyCommand(`/wda/element/${elementId}/scrollTo`, 'POST', {});
155
- },
156
- };
157
- const helpers = {
158
- /**
159
- * Scrolls an element or the entire screen.
160
- *
161
- * Use this command to emulate precise scrolling in tables or collection views where it is already known to which element the scrolling should be performed.
162
- *
163
- * The arguments define the chosen strategy: one of `name`, `direction`, `predicateString` or `toVisible`.
164
- *
165
- * **All strategies are exclusive**; only one strategy can be used at one time.
166
- *
167
- * **Known Limitations:**
168
- *
169
- * - If it is necessary to perform many scroll gestures on parent container to reach the necessary child element (tens of them), then the method call may fail. *
170
- * - The implementation of this extension relies on several undocumented XCTest features, which might not always be reliable.
171
- *
172
- * @param {string} [name] - The internal element identifier (as hexadecimal hash string) to scroll on (e.g. the container). The Application element will be used if this argument is not provided.
173
- * @param {import('./types').Direction} [direction] - The main difference between this command and a `mobile: swipe` command using the same direction is that `mobile: scroll` will attempt to move the current viewport exactly to the next or previous page (the term "page" means the content, which fits into a single device screen).
174
- * @param {string} [predicateString] - The `NSPredicate` locator of the child element, to which the scrolling should be performed. Has no effect if `elementId` is not a container.
175
- * @param {boolean} [toVisible] - If `true`, scrolls to the first visible `elementId` in the parent container. Has no effect if `elementId` is unset.
176
- * @param {number} [distance] - A ratio of the screen height; `1.0` means a full-screen-worth of scrolling.
177
- * @param {Element|string} [elementId] - Element ID or Element used in various strategies.
178
- * @returns {Promise<void>}
179
- * @this {XCUITestDriver}
180
- * @example
181
- * ```python
182
- * driver.execute_script('mobile: scroll', {'direction': 'down'})
183
- * ```
184
- */
185
- async mobileScroll(name, direction, predicateString, toVisible, distance, elementId) {
186
- /**
187
- * @todo This should be defined in WDA instead.
188
- * @typedef WdaScrollParams
189
- * @property {string} [name]
190
- * @property {import('./types').Direction} [direction]
191
- * @property {string} [predicateString]
192
- * @property {boolean} [toVisible]
193
- * @property {number} [distance]
194
- */
195
- /** @type {WdaScrollParams} */
196
- const params = {};
197
- if (name) {
198
- params.name = name;
199
- }
200
- else if (direction) {
201
- if (!SUPPORTED_GESTURE_DIRECTIONS.includes(lodash_1.default.toLower(direction))) {
202
- throw new driver_1.errors.InvalidArgumentError(`'direction' must be one of: ${SUPPORTED_GESTURE_DIRECTIONS}`);
91
+ }
92
+ }
93
+ /**
94
+ * @this {XCUITestDriver}
95
+ */
96
+ async function releaseActions() {
97
+ this.log.warn('On this platform, releaseActions is a no-op');
98
+ }
99
+ /**
100
+ * @param {import('@appium/types').ActionSequence[]} actions
101
+ * @returns {Promise<void>}
102
+ * @this {XCUITestDriver}
103
+ */
104
+ async function performActions(actions) {
105
+ this.log.debug(`Received the following W3C actions: ${JSON.stringify(actions, null, ' ')}`);
106
+ assertNoWebElements(actions);
107
+ // This is mandatory, since WDA only supports TOUCH pointer type
108
+ // and Selenium API uses MOUSE as the default one
109
+ const preprocessedActions = actions
110
+ .map((action) => ({
111
+ ...action,
112
+ ...(action.type === 'pointer'
113
+ ? {
114
+ parameters: {
115
+ pointerType: 'touch',
116
+ },
203
117
  }
204
- params.direction = direction;
205
- }
206
- else if (predicateString) {
207
- params.predicateString = predicateString;
208
- }
209
- else if (toVisible) {
210
- params.toVisible = toVisible;
211
- }
212
- else {
213
- throw new driver_1.errors.InvalidArgumentError('Mobile scroll supports the following strategies: name, direction, predicateString, and toVisible. ' +
214
- 'Specify one of these');
215
- }
216
- // we can also optionally pass a distance which appears to be a ratio of
217
- // screen height, so 1.0 means a full screen's worth of scrolling
218
- if (!lodash_1.default.isNil(distance)) {
219
- params.distance = distance;
220
- }
221
- const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/scroll` : '/wda/scroll';
222
- return await this.proxyCommand(endpoint, 'POST', params);
223
- },
118
+ : {}),
119
+ }))
120
+ .map((action) => {
121
+ const modifiedAction = lodash_1.default.clone(action) || {};
122
+ // Selenium API unexpectedly inserts zero pauses, which are not supported by WDA
123
+ modifiedAction.actions = (action.actions || []).filter((innerAction) => !(innerAction.type === 'pause' && innerAction.duration === 0));
124
+ return modifiedAction;
125
+ });
126
+ this.log.debug(`Preprocessed actions: ${JSON.stringify(preprocessedActions, null, ' ')}`);
127
+ await this.proxyCommand('/actions', 'POST', { actions: preprocessedActions });
128
+ }
129
+ /**
130
+ * @param {import('@appium/types').Element|string} el
131
+ * @this {XCUITestDriver}
132
+ * @group Native Only
133
+ */
134
+ async function nativeClick(el) {
135
+ el = support_1.util.unwrapElement(el);
136
+ let endpoint = `/element/${el}/click`;
137
+ return await this.proxyCommand(endpoint, 'POST', {});
138
+ }
139
+ /**
140
+ * Scrolls the current viewport to the given element.
141
+ *
142
+ * This command expects the destination element to be inside a scrollable container and is hittable. The scroll direction is detected automatically.
143
+ *
144
+ * This API uses native XCTest calls, so it is performant. The same native call is implicitly performed by a `click` command if the destination element is outside the current viewport.
145
+ *
146
+ * @since 4.7.0
147
+ * @throws If the scrolling action cannot be performed
148
+ * @privateRemarks See https://github.com/facebook/WebDriverAgent/blob/master/WebDriverAgentLib/Commands/FBElementCommands.m for details on WDA gestures API
149
+ * @param {Element|string} elementId - The internal element identifier (as hexadecimal hash string) to scroll to. The destination element must be located in a scrollable container and must be hittable. If the element is already present in the current viewport then no action is performed.
150
+ * @returns {Promise<void>}
151
+ * @this {XCUITestDriver}
152
+ */
153
+ async function mobileScrollToElement(elementId) {
154
+ if (!elementId) {
155
+ throw new driver_1.errors.InvalidArgumentError('Element id must be provided');
156
+ }
157
+ return await this.proxyCommand(`/wda/element/${elementId}/scrollTo`, 'POST', {});
158
+ }
159
+ /**
160
+ * Scrolls an element or the entire screen.
161
+ *
162
+ * Use this command to emulate precise scrolling in tables or collection views where it is already known to which element the scrolling should be performed.
163
+ *
164
+ * The arguments define the chosen strategy: one of `name`, `direction`, `predicateString` or `toVisible`.
165
+ *
166
+ * **All strategies are exclusive**; only one strategy can be used at one time.
167
+ *
168
+ * **Known Limitations:**
169
+ *
170
+ * - If it is necessary to perform many scroll gestures on parent container to reach the necessary child element (tens of them), then the method call may fail. *
171
+ * - The implementation of this extension relies on several undocumented XCTest features, which might not always be reliable.
172
+ *
173
+ * @param {string} [name] - The internal element identifier (as hexadecimal hash string) to scroll on (e.g. the container). The Application element will be used if this argument is not provided.
174
+ * @param {import('./types').Direction} [direction] - The main difference between this command and a `mobile: swipe` command using the same direction is that `mobile: scroll` will attempt to move the current viewport exactly to the next or previous page (the term "page" means the content, which fits into a single device screen).
175
+ * @param {string} [predicateString] - The `NSPredicate` locator of the child element, to which the scrolling should be performed. Has no effect if `elementId` is not a container.
176
+ * @param {boolean} [toVisible] - If `true`, scrolls to the first visible `elementId` in the parent container. Has no effect if `elementId` is unset.
177
+ * @param {number} [distance] - A ratio of the screen height; `1.0` means a full-screen-worth of scrolling.
178
+ * @param {Element|string} [elementId] - Element ID or Element used in various strategies.
179
+ * @returns {Promise<void>}
180
+ * @this {XCUITestDriver}
181
+ * @example
182
+ * ```python
183
+ * driver.execute_script('mobile: scroll', {'direction': 'down'})
184
+ * ```
185
+ */
186
+ async function mobileScroll(name, direction, predicateString, toVisible, distance, elementId) {
224
187
  /**
225
- * @param {import('./types').Direction} direction
226
- * @param {number} [velocity]
227
- * @param {Element|string} [elementId]
228
- * @this {XCUITestDriver}
188
+ * @todo This should be defined in WDA instead.
189
+ * @typedef WdaScrollParams
190
+ * @property {string} [name]
191
+ * @property {import('./types').Direction} [direction]
192
+ * @property {string} [predicateString]
193
+ * @property {boolean} [toVisible]
194
+ * @property {number} [distance]
229
195
  */
230
- async mobileSwipe(direction, velocity, elementId) {
196
+ /** @type {WdaScrollParams} */
197
+ const params = {};
198
+ if (name) {
199
+ params.name = name;
200
+ }
201
+ else if (direction) {
231
202
  if (!SUPPORTED_GESTURE_DIRECTIONS.includes(lodash_1.default.toLower(direction))) {
232
203
  throw new driver_1.errors.InvalidArgumentError(`'direction' must be one of: ${SUPPORTED_GESTURE_DIRECTIONS}`);
233
204
  }
234
- const params = { direction };
235
- if (!lodash_1.default.isNil(velocity)) {
236
- params.velocity = velocity;
237
- }
238
- const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/swipe` : '/wda/swipe';
239
- await this.proxyCommand(endpoint, 'POST', params);
240
- },
241
- /**
242
- * Performs a pinch gesture on the given element or on the Application element.
243
- *
244
- * @param {number} scale - Pinch scale (float value). A value between `0` and `1` performs a "pinch close" (or "zoom out"); a value greater than `1` performs a "pinch open" ("zoom in").
245
- * @param {number} velocity - The velocity of the pinch in scale factor per second (float value).
246
- * @param {Element|string} [elementId] The internal element identifier (as hexadecimal hash string) to pinch on. The Application element will be used if this parameter is not provided.
247
- * @returns {Promise<void>}
248
- * @this {XCUITestDriver}
249
- * @see https://developer.apple.com/documentation/xctest/xcuielement/1618669-pinchwithscale?language=objc
250
- * @example
251
- *
252
- * ```ruby
253
- * execute_script 'mobile: pinch', scale: 0.5, velocity: 1.1, element: element.ref
254
- * ```
255
- */
256
- async mobilePinch(scale, velocity, elementId) {
257
- const params = {
258
- scale: requireFloat(scale, 'scale'),
259
- velocity: requireFloat(velocity, 'velocity'),
260
- };
261
- const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/pinch` : '/wda/pinch';
262
- await this.proxyCommand(endpoint, 'POST', params);
263
- },
264
- /**
265
- * Performs double tap gesture on the given element or on the screen.
266
- *
267
- * @param {Element|string} [elementId] - The internal element identifier (as hexadecimal hash string) to double tap on. The Application element will be used if this parameter is not provided.
268
- * @param {number} [x] - The _x_ coordinate (float value) to double tap on.
269
- * @param {number} [y] - The _y_ coordinate (float value) to double tap on.
270
- * @returns {Promise<void>}
271
- * @this {XCUITestDriver}
272
- * @example
273
- * ```javascript
274
- * // using WebdriverIO
275
- * await driver.execute('mobile: doubleTap', {element: element.value.ELEMENT});
276
- * ```
277
- */
278
- async mobileDoubleTap(elementId, x, y) {
279
- const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/doubleTap` : '/wda/doubleTap';
280
- await this.proxyCommand(endpoint, 'POST', { x, y });
281
- },
282
- /**
283
- * Performs two finger tap gesture on the given element or on the application element.
284
- *
285
- * @param {Element|string} [elementId] - The internal element identifier (as hexadecimal hash string) to double tap on. The Application element will be used if this parameter is not provided.
286
- * @returns {Promise<void>}
287
- * @this {XCUITestDriver}
288
- * @see https://developer.apple.com/documentation/xctest/xcuielement/1618675-twofingertap?language=objc
289
- * @example
290
- * ```csharp
291
- * Dictionary<string, object> tfTap = new Dictionary<string, object>();
292
- * tfTap.Add("element", element.Id);
293
- * ((IJavaScriptExecutor)driver).ExecuteScript("mobile: twoFingerTap", tfTap);
294
- * ```
295
- */
296
- async mobileTwoFingerTap(elementId) {
297
- const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/twoFingerTap` : '/wda/twoFingerTap';
298
- await this.proxyCommand(endpoint, 'POST');
299
- },
300
- /**
301
- * Performs a "long press" gesture on the given element or on the screen.
302
- *
303
- * @param {number} duration - The duration (in seconds) of the gesture.
304
- * @param {number} [y] - The _y_ coordinate (float value) to hold on.
305
- * @param {number} [x] - The _x_ coordinate (float value) to hold on.
306
- * @param {Element|string} [elementId] - The internal element identifier (as hexadecimal hash string) to double tap on. The Application element will be used if this parameter is not provided.
307
- * @this {XCUITestDriver}
308
- * @see https://developer.apple.com/documentation/xctest/xcuielement/1618663-pressforduration?language=objc
309
- * @example
310
- * ```csharp
311
- * Dictionary<string, object> tfLongTap = new Dictionary<string, object>();
312
- * tfLongTap.Add("element", element.Id);
313
- * tfLongTap.Add("duration", 2.0);
314
- * ((IJavaScriptExecutor)driver).ExecuteScript("mobile: touchAndHold", tfLongTap);
315
- * ```
316
- */
317
- async mobileTouchAndHold(duration, x, y, elementId) {
318
- const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/touchAndHold` : '/wda/touchAndHold';
319
- await this.proxyCommand(endpoint, 'POST', {
320
- duration: requireFloat(duration, 'duration'),
321
- x, y,
322
- });
323
- },
324
- /**
325
- * Performs tap gesture by coordinates on the given element or on the screen.
326
- *
327
- * @param {number} x - The _x_ coordinate (float value) to tap on. If `elementId` is provided, this is computed relative to the element; otherwise it is computed relative to the active Application element.
328
- * @param {number} y - The _y_ coordinate (float value) to tap on. If `elementId` is provided, this is computed relative to the element; otherwise it is computed relative to the active Application element.
329
- * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to tap on. The Application element will be used if this parameter is not provided.
330
- * @this {XCUITestDriver}
331
- * @returns {Promise<void>}
332
- */
333
- async mobileTap(x, y, elementId) {
334
- const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/tap` : '/wda/tap';
335
- await this.proxyCommand(endpoint, 'POST', { x, y });
336
- },
337
- /**
338
- * Performs drag and drop gesture by coordinates on the given element or on the screen.
339
- *
340
- * @param {number} duration - The duration (in seconds) of the gesture. Must be between `0.5` and `60.0`, inclusive.
341
- * @param {number} fromX - The _x_ coordinate (float value) of the starting drag point.
342
- * @param {number} fromY - The _y_ coordinate (float value) of the starting drag point.
343
- * @param {number} toX - The _x_ coordinate (float value) of the ending drag point.
344
- * @param {number} toY - The _y_ coordinate (float value) of the ending drag point.
345
- * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to drag. If provided, all coordinates will be calculated relative to this element; otherwise they will be calculated relative to the active Application element.
346
- * @returns {Promise<void>}
347
- * @see https://developer.apple.com/documentation/xctest/xcuielement/1500989-clickforduration?language=objc
348
- * @this {XCUITestDriver}
349
- * @example
350
- * ```java
351
- * JavascriptExecutor js = (JavascriptExecutor) driver;
352
- * Map<String, Object> params = new HashMap<>();
353
- * params.put("duration", 1.0);
354
- * params.put("fromX", 100);
355
- * params.put("fromY", 100);
356
- * params.put("toX", 200);
357
- * params.put("toY", 200);
358
- * params.put("element", ((RemoteWebElement) element).getId());
359
- * js.executeScript("mobile: dragFromToForDuration", params);
360
- * ```
361
- */
362
- async mobileDragFromToForDuration(duration, fromX, fromY, toX, toY, elementId) {
363
- const params = {
364
- duration: requireFloat(duration, 'duration'),
365
- fromX: requireFloat(fromX, 'fromX'),
366
- fromY: requireFloat(fromY, 'fromY'),
367
- toX: requireFloat(toX, 'toX'),
368
- toY: requireFloat(toY, 'toY'),
369
- };
370
- return elementId
371
- ? // Drag element
372
- await this.proxyCommand(`/wda/element/${support_1.util.unwrapElement(elementId)}/dragfromtoforduration`, 'POST', params)
373
- : // Drag coordinates
374
- await this.proxyCommand('/wda/dragfromtoforduration', 'POST', params);
375
- },
376
- /**
377
- * Initiates a press-and-hold gesture, drags to another coordinate or an element with a given velocity, and holds for a given duration.
378
- *
379
- * @param {number} pressDuration - The duration (in seconds) of the press-and-hold gesture at the starting point. Must be between `0.5` and `60.0`, inclusive.
380
- * @param {number} holdDuration - The duration (in seconds) of the hold gesture at the ending point (after dragging). Must be between `0.5` and `60.0`, inclusive.
381
- * @param {number} velocity - The speed (in pixels-per-second) which to move from the initial position to the end position.
382
- * @param {string|Element} [fromElementId] - The internal element identifier (as hexadecimal hash string) to drag from. Absolute screen coordinates are expected if this argument is not provided.
383
- * @param {string|Element} [toElementId] - The internal element identifier (as hexadecimal hash string) to drag to. Absolute screen coordinates are expected if this argument is not provided.
384
- * @param {number} [fromX] - The _x_ coordinate (float value) of the starting drag point.
385
- * @param {number} [fromY] - The _y_ coordinate (float value) of the starting drag point.
386
- * @param {number} [toX] - The _x_ coordinate (float value) of the ending drag point.
387
- * @param {number} [toY] - The _y_ coordinate (float value) of the ending drag point.
388
- * @returns {Promise<void>}
389
- * @see https://developer.apple.com/documentation/xctest/xcuielement/3551693-pressforduration?language=objc
390
- * @see https://developer.apple.com/documentation/xctest/xcuicoordinate/3551692-pressforduration?language=objc
391
- * @this {XCUITestDriver}
392
- */
393
- async mobileDragFromToWithVelocity(pressDuration, holdDuration, velocity, fromElementId, toElementId, fromX, fromY, toX, toY) {
394
- const params = {
395
- pressDuration: requireFloat(pressDuration, 'pressDuration'),
396
- holdDuration: requireFloat(holdDuration, 'holdDuration'),
397
- velocity: requireFloat(velocity, 'velocity'),
398
- };
399
- fromElementId = fromElementId ? support_1.util.unwrapElement(fromElementId) : undefined;
400
- if (fromElementId) {
401
- toElementId = toElementId ? support_1.util.unwrapElement(toElementId) : undefined;
402
- if (!toElementId) {
403
- throw new driver_1.errors.InvalidArgumentError(`"toElementId" parameter is mandatory for "dragFromToWithVelocity" call`);
404
- }
405
- params.toElement = toElementId;
406
- return await this.proxyCommand(`/wda/element/${fromElementId}/pressAndDragWithVelocity`, 'POST', params);
407
- }
408
- params.fromX = requireFloat(fromX, 'fromX');
409
- params.fromY = requireFloat(fromY, 'fromY');
410
- params.toX = requireFloat(toX, 'toX');
411
- params.toY = requireFloat(toY, 'toY');
412
- return await this.proxyCommand('/wda/pressAndDragWithVelocity', 'POST', params);
413
- },
414
- /**
415
- * Sends one or more taps with one or more touch points.
416
- *
417
- * @since 1.17.1
418
- * @param {number} [numberOfTaps=1] - Number of taps to perform.
419
- * @param {number} [numberOfTouches=1] - Number of touch points to use.
420
- * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to perform one or more taps.
421
- * The Application element will be used if this parameter is not provided.
422
- * @returns {Promise<void>}
423
- * @this {XCUITestDriver}
424
- * @see https://developer.apple.com/documentation/xctest/xcuielement/1618671-tapwithnumberoftaps?language=objc
425
- * @example
426
- * ```ruby
427
- * e = @driver.find_element :id, 'target element'
428
- * # Taps the element with a single touch point twice
429
- * @driver.execute_script 'mobile: tapWithNumberOfTaps', {element: e.ref, numberOfTaps: 2, numberOfTouches: 1}
430
- * ```
431
- */
432
- async mobileTapWithNumberOfTaps(numberOfTouches = 1, numberOfTaps = 1, elementId = undefined) {
433
- const endpoint = elementId
434
- ? `/wda/element/${support_1.util.unwrapElement(elementId)}/tapWithNumberOfTaps`
435
- : '/wda/tapWithNumberOfTaps';
436
- return await this.proxyCommand(endpoint, 'POST', {
437
- numberOfTaps,
438
- numberOfTouches,
439
- });
440
- },
441
- /**
442
- * Performs a "force press" on the given element or coordinates.
443
- *
444
- * @throws If the target device does not support the "force press" gesture.
445
- * @param {number} [x] - The _x_ coordinate of the gesture. If `elementId` is set, this is calculated relative to its position; otherwise it's calculated relative to the active Application.
446
- * @param {number} [y] - The _y_ coordinate of the gesture. If `elementId` is set, this is calculated relative to its position; otherwise it's calculated relative to the active Application.
447
- * @param {number} [duration] - The duration (in seconds) of the force press. If this is provided, `pressure` must also be provided.
448
- * @param {number} [pressure] - A float value defining the pressure of the force press. If this is provided, `duration` must also be provided.
449
- * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to perform one or more taps.
450
- * The Application element will be used if this parameter is not provided.
451
- * @returns {Promise<void>}
452
- * @this {XCUITestDriver}
453
- */
454
- async mobileForcePress(x, y, duration, pressure, elementId) {
455
- const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/forceTouch` : `/wda/forceTouch`;
456
- return await this.proxyCommand(endpoint, 'POST', { x, y, duration, pressure });
457
- },
458
- /**
459
- * Performs selection of the next or previous picker wheel value.
460
- *
461
- * This might be useful if these values are populated dynamically; you don't know which one to select, or the value selection using the `sendKeys` API does not work (for whatever reason).
462
- *
463
- * @throws Upon failure to change the current picker value.
464
- * @param {string|Element} elementId - `PickerWheel`'s internal element ID as hexadecimal hash string. Value selection will be performed on this element. This element must be of type `XCUIElementTypePickerWheel`.
465
- * @param {'next'|'previous'} order - Either `next` to select the value _next_ to the current from the target picker wheel, or `previous` to select the _previous_ value.
466
- * @param {number} [offset=0.2] - The value in range `[0.01, 0.5]`. It defines how far from picker wheel's center the click should happen. The actual distance is calculated by multiplying this value to the actual picker wheel height. Too small an offset value may not change the picker wheel value at all, and too high a value may cause the wheel to switch two or more values at once. Usually the optimal value is located in range `[0.15, 0.3]`.
467
- * @param {string?} [value=undefined] - If provided WDA will try to automatically scroll in the given direction until the actual picker value reaches the expected one or the amount of scrolling attempts is exceeded.
468
- * @param {number} [maxAttempts=25] - The maximum number of scrolling attempts to reach `value` before an error will be thrown. Only makes sense in combination with `value`.
469
- * @this {XCUITestDriver}
470
- * @example
471
- * ```java
472
- * JavascriptExecutor js = (JavascriptExecutor) driver;
473
- * Map<String, Object> params = new HashMap<>();
474
- * params.put("order", "next");
475
- * params.put("offset", 0.15);
476
- * params.put("element", ((RemoteWebElement) element).getId());
477
- * js.executeScript("mobile: selectPickerWheelValue", params);
478
- * ```
479
- */
480
- async mobileSelectPickerWheelValue(elementId, order, offset, value, maxAttempts) {
481
- if (!elementId) {
482
- throw new driver_1.errors.InvalidArgumentError('elementId is expected to be set for selectPickerWheelValue method');
483
- }
484
- if (!lodash_1.default.isString(order) || !['next', 'previous'].includes(order.toLowerCase())) {
485
- throw new driver_1.errors.InvalidArgumentError(`The mandatory 'order' parameter is expected to be equal either to 'next' or 'previous'. ` +
486
- `'${order}' is given instead`);
487
- }
488
- const params = { order };
489
- if (offset) {
490
- params.offset = requireFloat(offset, 'offset');
491
- }
492
- if (!lodash_1.default.isNil(value)) {
493
- params.value = value;
494
- }
495
- if (!lodash_1.default.isNil(maxAttempts)) {
496
- params.maxAttempts = maxAttempts;
205
+ params.direction = direction;
206
+ }
207
+ else if (predicateString) {
208
+ params.predicateString = predicateString;
209
+ }
210
+ else if (toVisible) {
211
+ params.toVisible = toVisible;
212
+ }
213
+ else {
214
+ throw new driver_1.errors.InvalidArgumentError('Mobile scroll supports the following strategies: name, direction, predicateString, and toVisible. ' +
215
+ 'Specify one of these');
216
+ }
217
+ // we can also optionally pass a distance which appears to be a ratio of
218
+ // screen height, so 1.0 means a full screen's worth of scrolling
219
+ if (!lodash_1.default.isNil(distance)) {
220
+ params.distance = distance;
221
+ }
222
+ const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/scroll` : '/wda/scroll';
223
+ return await this.proxyCommand(endpoint, 'POST', params);
224
+ }
225
+ /**
226
+ * @param {import('./types').Direction} direction
227
+ * @param {number} [velocity]
228
+ * @param {Element|string} [elementId]
229
+ * @this {XCUITestDriver}
230
+ */
231
+ async function mobileSwipe(direction, velocity, elementId) {
232
+ if (!SUPPORTED_GESTURE_DIRECTIONS.includes(lodash_1.default.toLower(direction))) {
233
+ throw new driver_1.errors.InvalidArgumentError(`'direction' must be one of: ${SUPPORTED_GESTURE_DIRECTIONS}`);
234
+ }
235
+ const params = { direction };
236
+ if (!lodash_1.default.isNil(velocity)) {
237
+ params.velocity = velocity;
238
+ }
239
+ const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/swipe` : '/wda/swipe';
240
+ await this.proxyCommand(endpoint, 'POST', params);
241
+ }
242
+ /**
243
+ * Performs a pinch gesture on the given element or on the Application element.
244
+ *
245
+ * @param {number} scale - Pinch scale (float value). A value between `0` and `1` performs a "pinch close" (or "zoom out"); a value greater than `1` performs a "pinch open" ("zoom in").
246
+ * @param {number} velocity - The velocity of the pinch in scale factor per second (float value).
247
+ * @param {Element|string} [elementId] The internal element identifier (as hexadecimal hash string) to pinch on. The Application element will be used if this parameter is not provided.
248
+ * @returns {Promise<void>}
249
+ * @this {XCUITestDriver}
250
+ * @see https://developer.apple.com/documentation/xctest/xcuielement/1618669-pinchwithscale?language=objc
251
+ * @example
252
+ *
253
+ * ```ruby
254
+ * execute_script 'mobile: pinch', scale: 0.5, velocity: 1.1, element: element.ref
255
+ * ```
256
+ */
257
+ async function mobilePinch(scale, velocity, elementId) {
258
+ const params = {
259
+ scale: requireFloat(scale, 'scale'),
260
+ velocity: requireFloat(velocity, 'velocity'),
261
+ };
262
+ const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/pinch` : '/wda/pinch';
263
+ await this.proxyCommand(endpoint, 'POST', params);
264
+ }
265
+ /**
266
+ * Performs double tap gesture on the given element or on the screen.
267
+ *
268
+ * @param {Element|string} [elementId] - The internal element identifier (as hexadecimal hash string) to double tap on. The Application element will be used if this parameter is not provided.
269
+ * @param {number} [x] - The _x_ coordinate (float value) to double tap on.
270
+ * @param {number} [y] - The _y_ coordinate (float value) to double tap on.
271
+ * @returns {Promise<void>}
272
+ * @this {XCUITestDriver}
273
+ * @example
274
+ * ```javascript
275
+ * // using WebdriverIO
276
+ * await driver.execute('mobile: doubleTap', {element: element.value.ELEMENT});
277
+ * ```
278
+ */
279
+ async function mobileDoubleTap(elementId, x, y) {
280
+ const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/doubleTap` : '/wda/doubleTap';
281
+ await this.proxyCommand(endpoint, 'POST', { x, y });
282
+ }
283
+ /**
284
+ * Performs two finger tap gesture on the given element or on the application element.
285
+ *
286
+ * @param {Element|string} [elementId] - The internal element identifier (as hexadecimal hash string) to double tap on. The Application element will be used if this parameter is not provided.
287
+ * @returns {Promise<void>}
288
+ * @this {XCUITestDriver}
289
+ * @see https://developer.apple.com/documentation/xctest/xcuielement/1618675-twofingertap?language=objc
290
+ * @example
291
+ * ```csharp
292
+ * Dictionary<string, object> tfTap = new Dictionary<string, object>();
293
+ * tfTap.Add("element", element.Id);
294
+ * ((IJavaScriptExecutor)driver).ExecuteScript("mobile: twoFingerTap", tfTap);
295
+ * ```
296
+ */
297
+ async function mobileTwoFingerTap(elementId) {
298
+ const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/twoFingerTap` : '/wda/twoFingerTap';
299
+ await this.proxyCommand(endpoint, 'POST');
300
+ }
301
+ /**
302
+ * Performs a "long press" gesture on the given element or on the screen.
303
+ *
304
+ * @param {number} duration - The duration (in seconds) of the gesture.
305
+ * @param {number} [y] - The _y_ coordinate (float value) to hold on.
306
+ * @param {number} [x] - The _x_ coordinate (float value) to hold on.
307
+ * @param {Element|string} [elementId] - The internal element identifier (as hexadecimal hash string) to double tap on. The Application element will be used if this parameter is not provided.
308
+ * @this {XCUITestDriver}
309
+ * @see https://developer.apple.com/documentation/xctest/xcuielement/1618663-pressforduration?language=objc
310
+ * @example
311
+ * ```csharp
312
+ * Dictionary<string, object> tfLongTap = new Dictionary<string, object>();
313
+ * tfLongTap.Add("element", element.Id);
314
+ * tfLongTap.Add("duration", 2.0);
315
+ * ((IJavaScriptExecutor)driver).ExecuteScript("mobile: touchAndHold", tfLongTap);
316
+ * ```
317
+ */
318
+ async function mobileTouchAndHold(duration, x, y, elementId) {
319
+ const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/touchAndHold` : '/wda/touchAndHold';
320
+ await this.proxyCommand(endpoint, 'POST', {
321
+ duration: requireFloat(duration, 'duration'),
322
+ x, y,
323
+ });
324
+ }
325
+ /**
326
+ * Performs tap gesture by coordinates on the given element or on the screen.
327
+ *
328
+ * @param {number} x - The _x_ coordinate (float value) to tap on. If `elementId` is provided, this is computed relative to the element; otherwise it is computed relative to the active Application element.
329
+ * @param {number} y - The _y_ coordinate (float value) to tap on. If `elementId` is provided, this is computed relative to the element; otherwise it is computed relative to the active Application element.
330
+ * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to tap on. The Application element will be used if this parameter is not provided.
331
+ * @this {XCUITestDriver}
332
+ * @returns {Promise<void>}
333
+ */
334
+ async function mobileTap(x, y, elementId) {
335
+ const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/tap` : '/wda/tap';
336
+ await this.proxyCommand(endpoint, 'POST', { x, y });
337
+ }
338
+ /**
339
+ * Performs drag and drop gesture by coordinates on the given element or on the screen.
340
+ *
341
+ * @param {number} duration - The duration (in seconds) of the gesture. Must be between `0.5` and `60.0`, inclusive.
342
+ * @param {number} fromX - The _x_ coordinate (float value) of the starting drag point.
343
+ * @param {number} fromY - The _y_ coordinate (float value) of the starting drag point.
344
+ * @param {number} toX - The _x_ coordinate (float value) of the ending drag point.
345
+ * @param {number} toY - The _y_ coordinate (float value) of the ending drag point.
346
+ * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to drag. If provided, all coordinates will be calculated relative to this element; otherwise they will be calculated relative to the active Application element.
347
+ * @returns {Promise<void>}
348
+ * @see https://developer.apple.com/documentation/xctest/xcuielement/1500989-clickforduration?language=objc
349
+ * @this {XCUITestDriver}
350
+ * @example
351
+ * ```java
352
+ * JavascriptExecutor js = (JavascriptExecutor) driver;
353
+ * Map<String, Object> params = new HashMap<>();
354
+ * params.put("duration", 1.0);
355
+ * params.put("fromX", 100);
356
+ * params.put("fromY", 100);
357
+ * params.put("toX", 200);
358
+ * params.put("toY", 200);
359
+ * params.put("element", ((RemoteWebElement) element).getId());
360
+ * js.executeScript("mobile: dragFromToForDuration", params);
361
+ * ```
362
+ */
363
+ async function mobileDragFromToForDuration(duration, fromX, fromY, toX, toY, elementId) {
364
+ const params = {
365
+ duration: requireFloat(duration, 'duration'),
366
+ fromX: requireFloat(fromX, 'fromX'),
367
+ fromY: requireFloat(fromY, 'fromY'),
368
+ toX: requireFloat(toX, 'toX'),
369
+ toY: requireFloat(toY, 'toY'),
370
+ };
371
+ return elementId
372
+ ? // Drag element
373
+ await this.proxyCommand(`/wda/element/${support_1.util.unwrapElement(elementId)}/dragfromtoforduration`, 'POST', params)
374
+ : // Drag coordinates
375
+ await this.proxyCommand('/wda/dragfromtoforduration', 'POST', params);
376
+ }
377
+ /**
378
+ * Initiates a press-and-hold gesture, drags to another coordinate or an element with a given velocity, and holds for a given duration.
379
+ *
380
+ * @param {number} pressDuration - The duration (in seconds) of the press-and-hold gesture at the starting point. Must be between `0.5` and `60.0`, inclusive.
381
+ * @param {number} holdDuration - The duration (in seconds) of the hold gesture at the ending point (after dragging). Must be between `0.5` and `60.0`, inclusive.
382
+ * @param {number} velocity - The speed (in pixels-per-second) which to move from the initial position to the end position.
383
+ * @param {string|Element} [fromElementId] - The internal element identifier (as hexadecimal hash string) to drag from. Absolute screen coordinates are expected if this argument is not provided.
384
+ * @param {string|Element} [toElementId] - The internal element identifier (as hexadecimal hash string) to drag to. Absolute screen coordinates are expected if this argument is not provided.
385
+ * @param {number} [fromX] - The _x_ coordinate (float value) of the starting drag point.
386
+ * @param {number} [fromY] - The _y_ coordinate (float value) of the starting drag point.
387
+ * @param {number} [toX] - The _x_ coordinate (float value) of the ending drag point.
388
+ * @param {number} [toY] - The _y_ coordinate (float value) of the ending drag point.
389
+ * @returns {Promise<void>}
390
+ * @see https://developer.apple.com/documentation/xctest/xcuielement/3551693-pressforduration?language=objc
391
+ * @see https://developer.apple.com/documentation/xctest/xcuicoordinate/3551692-pressforduration?language=objc
392
+ * @this {XCUITestDriver}
393
+ */
394
+ async function mobileDragFromToWithVelocity(pressDuration, holdDuration, velocity, fromElementId, toElementId, fromX, fromY, toX, toY) {
395
+ const params = {
396
+ pressDuration: requireFloat(pressDuration, 'pressDuration'),
397
+ holdDuration: requireFloat(holdDuration, 'holdDuration'),
398
+ velocity: requireFloat(velocity, 'velocity'),
399
+ };
400
+ fromElementId = fromElementId ? support_1.util.unwrapElement(fromElementId) : undefined;
401
+ if (fromElementId) {
402
+ toElementId = toElementId ? support_1.util.unwrapElement(toElementId) : undefined;
403
+ if (!toElementId) {
404
+ throw new driver_1.errors.InvalidArgumentError(`"toElementId" parameter is mandatory for "dragFromToWithVelocity" call`);
497
405
  }
498
- return await this.proxyCommand(`/wda/pickerwheel/${support_1.util.unwrapElement(elementId)}/select`, 'POST', params);
499
- },
500
- /**
501
- * Performs a rotate gesture on the given element.
502
- *
503
- * @see https://developer.apple.com/documentation/xctest/xcuielement/1618665-rotate?language=objc
504
- * @param {number} rotation - The rotation gesture (in radians)
505
- * @param {number} velocity - The velocity (in radians-per-second) of the gesture.
506
- * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to perform the gesture on.
507
- * The Application element will be used if this parameter is not provided.
508
- * @returns {Promise<void>}
509
- * @this {XCUITestDriver}
510
- * @example
511
- * ```java
512
- * JavascriptExecutor js = (JavascriptExecutor) driver;
513
- * js.executeScript("mobile: rotateElement", ImmutableMap.of(
514
- * // rotate clockwise, 90 degrees
515
- * "rotation", -Math.PI / 2,
516
- * // in approximately two seconds
517
- * "velocity", Math.PI / 4,
518
- * "element", ((RemoteWebElement) element).getId()
519
- * ));
520
- * ```
521
- */
522
- async mobileRotateElement(rotation, velocity, elementId) {
523
- const params = {
524
- rotation: requireFloat(rotation, 'rotation'),
525
- velocity: requireFloat(velocity, 'velocity'),
526
- };
527
- const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/rotate` : '/wda/rotate';
528
- return await this.proxyCommand(endpoint, 'POST', params);
529
- },
530
- };
531
- exports.default = { ...helpers, ...commands };
406
+ params.toElement = toElementId;
407
+ return await this.proxyCommand(`/wda/element/${fromElementId}/pressAndDragWithVelocity`, 'POST', params);
408
+ }
409
+ params.fromX = requireFloat(fromX, 'fromX');
410
+ params.fromY = requireFloat(fromY, 'fromY');
411
+ params.toX = requireFloat(toX, 'toX');
412
+ params.toY = requireFloat(toY, 'toY');
413
+ return await this.proxyCommand('/wda/pressAndDragWithVelocity', 'POST', params);
414
+ }
415
+ /**
416
+ * Sends one or more taps with one or more touch points.
417
+ *
418
+ * @since 1.17.1
419
+ * @param {number} [numberOfTaps=1] - Number of taps to perform.
420
+ * @param {number} [numberOfTouches=1] - Number of touch points to use.
421
+ * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to perform one or more taps.
422
+ * The Application element will be used if this parameter is not provided.
423
+ * @returns {Promise<void>}
424
+ * @this {XCUITestDriver}
425
+ * @see https://developer.apple.com/documentation/xctest/xcuielement/1618671-tapwithnumberoftaps?language=objc
426
+ * @example
427
+ * ```ruby
428
+ * e = @driver.find_element :id, 'target element'
429
+ * # Taps the element with a single touch point twice
430
+ * @driver.execute_script 'mobile: tapWithNumberOfTaps', {element: e.ref, numberOfTaps: 2, numberOfTouches: 1}
431
+ * ```
432
+ */
433
+ async function mobileTapWithNumberOfTaps(numberOfTouches = 1, numberOfTaps = 1, elementId = undefined) {
434
+ const endpoint = elementId
435
+ ? `/wda/element/${support_1.util.unwrapElement(elementId)}/tapWithNumberOfTaps`
436
+ : '/wda/tapWithNumberOfTaps';
437
+ return await this.proxyCommand(endpoint, 'POST', {
438
+ numberOfTaps,
439
+ numberOfTouches,
440
+ });
441
+ }
442
+ /**
443
+ * Performs a "force press" on the given element or coordinates.
444
+ *
445
+ * @throws If the target device does not support the "force press" gesture.
446
+ * @param {number} [x] - The _x_ coordinate of the gesture. If `elementId` is set, this is calculated relative to its position; otherwise it's calculated relative to the active Application.
447
+ * @param {number} [y] - The _y_ coordinate of the gesture. If `elementId` is set, this is calculated relative to its position; otherwise it's calculated relative to the active Application.
448
+ * @param {number} [duration] - The duration (in seconds) of the force press. If this is provided, `pressure` must also be provided.
449
+ * @param {number} [pressure] - A float value defining the pressure of the force press. If this is provided, `duration` must also be provided.
450
+ * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to perform one or more taps.
451
+ * The Application element will be used if this parameter is not provided.
452
+ * @returns {Promise<void>}
453
+ * @this {XCUITestDriver}
454
+ */
455
+ async function mobileForcePress(x, y, duration, pressure, elementId) {
456
+ const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/forceTouch` : `/wda/forceTouch`;
457
+ return await this.proxyCommand(endpoint, 'POST', { x, y, duration, pressure });
458
+ }
459
+ /**
460
+ * Performs selection of the next or previous picker wheel value.
461
+ *
462
+ * This might be useful if these values are populated dynamically; you don't know which one to select, or the value selection using the `sendKeys` API does not work (for whatever reason).
463
+ *
464
+ * @throws Upon failure to change the current picker value.
465
+ * @param {string|Element} elementId - `PickerWheel`'s internal element ID as hexadecimal hash string. Value selection will be performed on this element. This element must be of type `XCUIElementTypePickerWheel`.
466
+ * @param {'next'|'previous'} order - Either `next` to select the value _next_ to the current from the target picker wheel, or `previous` to select the _previous_ value.
467
+ * @param {number} [offset=0.2] - The value in range `[0.01, 0.5]`. It defines how far from picker wheel's center the click should happen. The actual distance is calculated by multiplying this value to the actual picker wheel height. Too small an offset value may not change the picker wheel value at all, and too high a value may cause the wheel to switch two or more values at once. Usually the optimal value is located in range `[0.15, 0.3]`.
468
+ * @param {string?} [value=undefined] - If provided WDA will try to automatically scroll in the given direction until the actual picker value reaches the expected one or the amount of scrolling attempts is exceeded.
469
+ * @param {number} [maxAttempts=25] - The maximum number of scrolling attempts to reach `value` before an error will be thrown. Only makes sense in combination with `value`.
470
+ * @this {XCUITestDriver}
471
+ * @example
472
+ * ```java
473
+ * JavascriptExecutor js = (JavascriptExecutor) driver;
474
+ * Map<String, Object> params = new HashMap<>();
475
+ * params.put("order", "next");
476
+ * params.put("offset", 0.15);
477
+ * params.put("element", ((RemoteWebElement) element).getId());
478
+ * js.executeScript("mobile: selectPickerWheelValue", params);
479
+ * ```
480
+ */
481
+ async function mobileSelectPickerWheelValue(elementId, order, offset, value, maxAttempts) {
482
+ if (!elementId) {
483
+ throw new driver_1.errors.InvalidArgumentError('elementId is expected to be set for selectPickerWheelValue method');
484
+ }
485
+ if (!lodash_1.default.isString(order) || !['next', 'previous'].includes(order.toLowerCase())) {
486
+ throw new driver_1.errors.InvalidArgumentError(`The mandatory 'order' parameter is expected to be equal either to 'next' or 'previous'. ` +
487
+ `'${order}' is given instead`);
488
+ }
489
+ const params = { order };
490
+ if (offset) {
491
+ params.offset = requireFloat(offset, 'offset');
492
+ }
493
+ if (!lodash_1.default.isNil(value)) {
494
+ params.value = value;
495
+ }
496
+ if (!lodash_1.default.isNil(maxAttempts)) {
497
+ params.maxAttempts = maxAttempts;
498
+ }
499
+ return await this.proxyCommand(`/wda/pickerwheel/${support_1.util.unwrapElement(elementId)}/select`, 'POST', params);
500
+ }
501
+ /**
502
+ * Performs a rotate gesture on the given element.
503
+ *
504
+ * @see https://developer.apple.com/documentation/xctest/xcuielement/1618665-rotate?language=objc
505
+ * @param {number} rotation - The rotation gesture (in radians)
506
+ * @param {number} velocity - The velocity (in radians-per-second) of the gesture.
507
+ * @param {string|Element} [elementId] - The internal element identifier (as hexadecimal hash string) to perform the gesture on.
508
+ * The Application element will be used if this parameter is not provided.
509
+ * @returns {Promise<void>}
510
+ * @this {XCUITestDriver}
511
+ * @example
512
+ * ```java
513
+ * JavascriptExecutor js = (JavascriptExecutor) driver;
514
+ * js.executeScript("mobile: rotateElement", ImmutableMap.of(
515
+ * // rotate clockwise, 90 degrees
516
+ * "rotation", -Math.PI / 2,
517
+ * // in approximately two seconds
518
+ * "velocity", Math.PI / 4,
519
+ * "element", ((RemoteWebElement) element).getId()
520
+ * ));
521
+ * ```
522
+ */
523
+ async function mobileRotateElement(rotation, velocity, elementId) {
524
+ const params = {
525
+ rotation: requireFloat(rotation, 'rotation'),
526
+ velocity: requireFloat(velocity, 'velocity'),
527
+ };
528
+ const endpoint = elementId ? `/wda/element/${support_1.util.unwrapElement(elementId)}/rotate` : '/wda/rotate';
529
+ return await this.proxyCommand(endpoint, 'POST', params);
530
+ }
532
531
  /**
533
532
  * @param {import('@appium/types').ActionSequence[]} actionSeq
534
533
  */
@@ -544,6 +543,21 @@ function assertNoWebElements(actionSeq) {
544
543
  `and passing them to your gesture instead.`);
545
544
  }
546
545
  }
546
+ /**
547
+ * Converts the given value to a float number.
548
+ *
549
+ * @throws If `value` is `NaN`
550
+ * @param {any} value
551
+ * @param {string} paramName
552
+ * @returns {number}
553
+ */
554
+ function requireFloat(value, paramName) {
555
+ const num = parseFloat(String(value));
556
+ if (Number.isNaN(num)) {
557
+ throw new driver_1.errors.InvalidArgumentError(`"${paramName}" parameter should be a valid number. "${value}" is given instead`);
558
+ }
559
+ return num;
560
+ }
547
561
  /**
548
562
  * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
549
563
  * @typedef {import('@appium/types').Element} Element