appium-xcuitest-driver 10.3.0 → 10.4.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 (257) 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 -38
  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 +275 -197
  175. package/build/lib/commands/web.d.ts.map +1 -1
  176. package/build/lib/commands/web.js +866 -785
  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 +277 -1597
  187. package/build/lib/driver.d.ts.map +1 -1
  188. package/build/lib/driver.js +318 -235
  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/lib/commands/active-app-info.js +12 -0
  194. package/lib/commands/alert.js +68 -65
  195. package/lib/commands/app-management.js +308 -301
  196. package/lib/commands/app-strings.js +24 -26
  197. package/lib/commands/appearance.js +54 -56
  198. package/lib/commands/audit.js +18 -20
  199. package/lib/commands/battery.js +35 -37
  200. package/lib/commands/biometric.js +44 -46
  201. package/lib/commands/certificate.js +226 -215
  202. package/lib/commands/clipboard.js +30 -32
  203. package/lib/commands/condition.js +98 -100
  204. package/lib/commands/content-size.js +36 -38
  205. package/lib/commands/context.js +495 -490
  206. package/lib/commands/deviceInfo.js +19 -20
  207. package/lib/commands/element.js +367 -357
  208. package/lib/commands/execute.js +72 -72
  209. package/lib/commands/file-movement.js +132 -134
  210. package/lib/commands/find.js +160 -159
  211. package/lib/commands/general.js +238 -231
  212. package/lib/commands/geolocation.js +6 -14
  213. package/lib/commands/gesture.js +525 -515
  214. package/lib/commands/increase-contrast.js +30 -32
  215. package/lib/commands/iohid.js +32 -34
  216. package/lib/commands/keyboard.js +49 -51
  217. package/lib/commands/keychains.js +12 -14
  218. package/lib/commands/localization.js +24 -26
  219. package/lib/commands/location.js +102 -104
  220. package/lib/commands/lock.js +38 -38
  221. package/lib/commands/log.js +197 -198
  222. package/lib/commands/memory.js +40 -42
  223. package/lib/commands/navigation.js +96 -100
  224. package/lib/commands/notifications.js +57 -59
  225. package/lib/commands/pasteboard.js +37 -39
  226. package/lib/commands/pcap.js +84 -86
  227. package/lib/commands/performance.js +132 -133
  228. package/lib/commands/permissions.js +67 -69
  229. package/lib/commands/proxy-helper.js +60 -61
  230. package/lib/commands/record-audio.js +115 -120
  231. package/lib/commands/recordscreen.js +145 -149
  232. package/lib/commands/screenshots.js +116 -116
  233. package/lib/commands/simctl.js +25 -29
  234. package/lib/commands/source.js +42 -46
  235. package/lib/commands/timeouts.js +59 -63
  236. package/lib/commands/web.js +932 -859
  237. package/lib/commands/xctest-record-screen.js +103 -105
  238. package/lib/commands/xctest.js +134 -139
  239. package/lib/driver.js +286 -235
  240. package/lib/execute-method-map.ts +9 -0
  241. package/npm-shrinkwrap.json +8 -8
  242. package/package.json +1 -1
  243. package/build/lib/commands/activeAppInfo.d.ts +0 -12
  244. package/build/lib/commands/activeAppInfo.d.ts.map +0 -1
  245. package/build/lib/commands/activeAppInfo.js +0 -15
  246. package/build/lib/commands/activeAppInfo.js.map +0 -1
  247. package/build/lib/commands/index.d.ts +0 -96
  248. package/build/lib/commands/index.d.ts.map +0 -1
  249. package/build/lib/commands/index.js +0 -100
  250. package/build/lib/commands/index.js.map +0 -1
  251. package/build/lib/cookies.d.ts +0 -15
  252. package/build/lib/cookies.d.ts.map +0 -1
  253. package/build/lib/cookies.js +0 -84
  254. package/build/lib/cookies.js.map +0 -1
  255. package/lib/commands/activeAppInfo.js +0 -14
  256. package/lib/commands/index.js +0 -95
  257. package/lib/cookies.js +0 -92
@@ -3,134 +3,134 @@ import _ from 'lodash';
3
3
  import {errors} from 'appium/driver';
4
4
  import {util, imageUtil} from 'appium/support';
5
5
 
6
- export default {
7
- /**
8
- * @this {XCUITestDriver}
9
- * @returns {Promise<string>}
10
- */
11
- async getScreenshot() {
12
- if (this.isWebContext()) {
13
- const webScreenshotMode = (await this.settings.getSettings()).webScreenshotMode;
14
- switch (_.toLower(webScreenshotMode)) {
15
- case 'page':
16
- case 'viewport':
17
- return await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote)).captureScreenshot({
18
- coordinateSystem: /** @type {'Viewport'|'Page'} */ (_.capitalize(webScreenshotMode)),
19
- });
20
- case 'native':
21
- case undefined:
22
- case null:
23
- break;
24
- default:
25
- this.log.warn(
26
- `The webScreenshotMode setting value '${webScreenshotMode}' is not known. ` +
27
- `Supported values are: page, viewport and native. Falling back to the native mode.`
28
- );
29
- break;
30
- }
31
- }
32
-
33
- const getScreenshotFromWDA = async () => {
34
- this.log.debug(`Taking screenshot with WDA`);
35
- const data = await this.proxyCommand('/screenshot', 'GET');
36
- if (!_.isString(data)) {
37
- throw new Error(`Unable to take screenshot. WDA returned '${JSON.stringify(data)}'`);
38
- }
39
- return data;
40
- };
41
-
42
- // if we've specified an mjpeg server, use that
43
- if (this.mjpegStream) {
44
- this.log.info(`mjpeg video stream provided, returning latest frame as screenshot`);
45
- const data = await this.mjpegStream.lastChunkPNGBase64();
46
- if (data) {
47
- return data;
48
- }
49
- this.log.warn(
50
- 'Tried to get screenshot from active MJPEG stream, but there ' +
51
- 'was no data yet. Falling back to regular screenshot methods.',
52
- );
6
+ /**
7
+ * @this {XCUITestDriver}
8
+ * @returns {Promise<string>}
9
+ */
10
+ export async function getScreenshot() {
11
+ if (this.isWebContext()) {
12
+ const webScreenshotMode = (await this.settings.getSettings()).webScreenshotMode;
13
+ switch (_.toLower(webScreenshotMode)) {
14
+ case 'page':
15
+ case 'viewport':
16
+ return await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote)).captureScreenshot({
17
+ coordinateSystem: /** @type {'Viewport'|'Page'} */ (_.capitalize(webScreenshotMode)),
18
+ });
19
+ case 'native':
20
+ case undefined:
21
+ case null:
22
+ break;
23
+ default:
24
+ this.log.warn(
25
+ `The webScreenshotMode setting value '${webScreenshotMode}' is not known. ` +
26
+ `Supported values are: page, viewport and native. Falling back to the native mode.`
27
+ );
28
+ break;
53
29
  }
30
+ }
54
31
 
55
- try {
56
- return await getScreenshotFromWDA();
57
- } catch (err) {
58
- this.log.warn(`Error getting screenshot: ${err.message}`);
32
+ const getScreenshotFromWDA = async () => {
33
+ this.log.debug(`Taking screenshot with WDA`);
34
+ const data = await this.proxyCommand('/screenshot', 'GET');
35
+ if (!_.isString(data)) {
36
+ throw new Error(`Unable to take screenshot. WDA returned '${JSON.stringify(data)}'`);
59
37
  }
38
+ return data;
39
+ };
60
40
 
61
- // simulator attempt
62
- if (this.isSimulator()) {
63
- this.log.info(`Falling back to 'simctl io screenshot' API`);
64
- const payload = await /** @type {import('../driver').Simulator} */ (this.device).simctl.getScreenshot();
65
- if (!payload) {
66
- throw new errors.UnableToCaptureScreen();
67
- }
68
- return payload;
41
+ // if we've specified an mjpeg server, use that
42
+ if (this.mjpegStream) {
43
+ this.log.info(`mjpeg video stream provided, returning latest frame as screenshot`);
44
+ const data = await this.mjpegStream.lastChunkPNGBase64();
45
+ if (data) {
46
+ return data;
69
47
  }
48
+ this.log.warn(
49
+ 'Tried to get screenshot from active MJPEG stream, but there ' +
50
+ 'was no data yet. Falling back to regular screenshot methods.',
51
+ );
52
+ }
70
53
 
71
- // Retry for real devices only. Fail fast on Simulator if simctl does not work as expected
72
- return /** @type {string} */ (await retryInterval(2, 1000, getScreenshotFromWDA));
73
- },
74
- /**
75
- * @this {XCUITestDriver}
76
- */
77
- async getElementScreenshot(el) {
78
- el = util.unwrapElement(el);
79
- if (this.isWebContext()) {
80
- const atomsElement = this.getAtomsElement(el);
81
- const {width, height} = await this.executeAtom('get_size', [atomsElement]);
82
- if (!width || !height) {
83
- throw new errors.UnableToCaptureScreen('Cannot take a screenshot of a zero-size element');
84
- }
85
- const {x, y} = await this.executeAtom('get_top_left_coordinates', [atomsElement]);
86
- return await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote))
87
- .captureScreenshot({rect: {x, y, width, height}});
88
- }
54
+ try {
55
+ return await getScreenshotFromWDA();
56
+ } catch (err) {
57
+ this.log.warn(`Error getting screenshot: ${err.message}`);
58
+ }
89
59
 
90
- const data = await this.proxyCommand(`/element/${el}/screenshot`, 'GET');
91
- if (!_.isString(data)) {
92
- throw new errors.UnableToCaptureScreen(
93
- `Unable to take an element screenshot. WDA returned: ${JSON.stringify(data)}`,
94
- );
95
- }
96
- return data;
97
- },
98
- /**
99
- * @this {XCUITestDriver}
100
- * @returns {Promise<string>}
101
- */
102
- async getViewportScreenshot() {
103
- if (this.isWebContext()) {
104
- return await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote))
105
- .captureScreenshot();
60
+ // simulator attempt
61
+ if (this.isSimulator()) {
62
+ this.log.info(`Falling back to 'simctl io screenshot' API`);
63
+ const payload = await /** @type {import('../driver').Simulator} */ (this.device).simctl.getScreenshot();
64
+ if (!payload) {
65
+ throw new errors.UnableToCaptureScreen();
106
66
  }
67
+ return payload;
68
+ }
107
69
 
108
- const screenshot = await this.getScreenshot();
109
- // if we don't have a status bar, there's nothing to crop, so we can avoid
110
- // extra calls and return straight away
111
- if ((await this.getStatusBarHeight()) === 0) {
112
- return screenshot;
113
- }
70
+ // Retry for real devices only. Fail fast on Simulator if simctl does not work as expected
71
+ return /** @type {string} */ (await retryInterval(2, 1000, getScreenshotFromWDA));
72
+ }
114
73
 
115
- const sharp = imageUtil.requireSharp();
116
- const {width, height} = await sharp(Buffer.from(screenshot, 'base64')).metadata();
74
+ /**
75
+ * @this {XCUITestDriver}
76
+ */
77
+ export async function getElementScreenshot(el) {
78
+ el = util.unwrapElement(el);
79
+ if (this.isWebContext()) {
80
+ const atomsElement = this.getAtomsElement(el);
81
+ const {width, height} = await this.executeAtom('get_size', [atomsElement]);
117
82
  if (!width || !height) {
118
- throw new errors.UnableToCaptureScreen('The device screenshot is empty');
119
- }
120
- this.log.debug(`Screenshot dimensions: ${width}x${height}`);
121
- const region = await this.getViewportRect();
122
- if (region.width + region.left > width) {
123
- this.log.info('Viewport region exceeds screenshot width, adjusting region to fit');
124
- region.width = width - region.left;
125
- }
126
- if (region.height + region.top > height) {
127
- this.log.info('Viewport region exceeds screenshot height, adjusting region to fit');
128
- region.height = height - region.top;
83
+ throw new errors.UnableToCaptureScreen('Cannot take a screenshot of a zero-size element');
129
84
  }
130
- this.log.debug(`Calculated viewport rect: ${JSON.stringify(region)}`);
131
- return await imageUtil.cropBase64Image(screenshot, region);
132
- },
133
- };
85
+ const {x, y} = await this.executeAtom('get_top_left_coordinates', [atomsElement]);
86
+ return await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote))
87
+ .captureScreenshot({rect: {x, y, width, height}});
88
+ }
89
+
90
+ const data = await this.proxyCommand(`/element/${el}/screenshot`, 'GET');
91
+ if (!_.isString(data)) {
92
+ throw new errors.UnableToCaptureScreen(
93
+ `Unable to take an element screenshot. WDA returned: ${JSON.stringify(data)}`,
94
+ );
95
+ }
96
+ return data;
97
+ }
98
+
99
+ /**
100
+ * @this {XCUITestDriver}
101
+ * @returns {Promise<string>}
102
+ */
103
+ export async function getViewportScreenshot() {
104
+ if (this.isWebContext()) {
105
+ return await (/** @type {import('appium-remote-debugger').RemoteDebugger} */ (this.remote))
106
+ .captureScreenshot();
107
+ }
108
+
109
+ const screenshot = await this.getScreenshot();
110
+ // if we don't have a status bar, there's nothing to crop, so we can avoid
111
+ // extra calls and return straight away
112
+ if ((await this.getStatusBarHeight()) === 0) {
113
+ return screenshot;
114
+ }
115
+
116
+ const sharp = imageUtil.requireSharp();
117
+ const {width, height} = await sharp(Buffer.from(screenshot, 'base64')).metadata();
118
+ if (!width || !height) {
119
+ throw new errors.UnableToCaptureScreen('The device screenshot is empty');
120
+ }
121
+ this.log.debug(`Screenshot dimensions: ${width}x${height}`);
122
+ const region = await this.getViewportRect();
123
+ if (region.width + region.left > width) {
124
+ this.log.info('Viewport region exceeds screenshot width, adjusting region to fit');
125
+ region.width = width - region.left;
126
+ }
127
+ if (region.height + region.top > height) {
128
+ this.log.info('Viewport region exceeds screenshot height, adjusting region to fit');
129
+ region.height = height - region.top;
130
+ }
131
+ this.log.debug(`Calculated viewport rect: ${JSON.stringify(region)}`);
132
+ return await imageUtil.cropBase64Image(screenshot, region);
133
+ }
134
134
 
135
135
  /**
136
136
  * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
@@ -29,39 +29,35 @@ const SUBCOMMANDS_HAS_DEVICE = [
29
29
  'uninstall'
30
30
  ];
31
31
 
32
- const commands = {
33
- /**
34
- * Run the given command with arguments as `xcrun simctl` subcommand.
35
- * This method works behind the 'simctl' security flag.
36
- * @this {XCUITestDriver}
37
- * @param {string} command Subcommand to run with `xcrun simctl`
38
- * @param {string[]} [args=[]] arguments for the subcommand. The arguments should be after <device> in the help.
39
- * @param {number|undefined} timeout - The maximum number of milliseconds
40
- * @returns {Promise<SimctlExecResponse>}
41
- * @throws {Error} If the simctl subcommand command returns non-zero return code, or the given subcommand was invalid.
42
- */
43
- async mobileSimctl(command, args = [], timeout = undefined) {
44
- if (!this.isSimulator()) {
45
- throw new errors.UnsupportedOperationError(`Only simulator is supported.`);
46
- };
47
-
48
- if (!this.opts.udid) {
49
- throw new errors.InvalidArgumentError(`Unknown device or simulator UDID: '${this.opts.udid}'`);
50
- }
32
+ /**
33
+ * Run the given command with arguments as `xcrun simctl` subcommand.
34
+ * This method works behind the 'simctl' security flag.
35
+ * @this {XCUITestDriver}
36
+ * @param {string} command Subcommand to run with `xcrun simctl`
37
+ * @param {string[]} [args=[]] arguments for the subcommand. The arguments should be after <device> in the help.
38
+ * @param {number|undefined} timeout - The maximum number of milliseconds
39
+ * @returns {Promise<SimctlExecResponse>}
40
+ * @throws {Error} If the simctl subcommand command returns non-zero return code, or the given subcommand was invalid.
41
+ */
42
+ export async function mobileSimctl(command, args = [], timeout = undefined) {
43
+ if (!this.isSimulator()) {
44
+ throw new errors.UnsupportedOperationError(`Only simulator is supported.`);
45
+ }
51
46
 
52
- if (!SUBCOMMANDS_HAS_DEVICE.includes(command)) {
53
- throw new errors.InvalidArgumentError(`The given command '${command}' is not supported. ` +
54
- `Available subcommands are ${SUBCOMMANDS_HAS_DEVICE.join(',')}`);
55
- }
47
+ if (!this.opts.udid) {
48
+ throw new errors.InvalidArgumentError(`Unknown device or simulator UDID: '${this.opts.udid}'`);
49
+ }
56
50
 
57
- return await /** @type {import('./../driver').Simulator} */ (this.device).simctl.exec(
58
- command,
59
- {args: [this.opts.udid, ...args], timeout}
60
- );
51
+ if (!SUBCOMMANDS_HAS_DEVICE.includes(command)) {
52
+ throw new errors.InvalidArgumentError(`The given command '${command}' is not supported. ` +
53
+ `Available subcommands are ${SUBCOMMANDS_HAS_DEVICE.join(',')}`);
61
54
  }
62
- };
63
55
 
64
- export default {...commands};
56
+ return await /** @type {import('./../driver').Simulator} */ (this.device).simctl.exec(
57
+ command,
58
+ {args: [this.opts.udid, ...args], timeout}
59
+ );
60
+ }
65
61
 
66
62
  /**
67
63
  * @typedef {Object} SimctlExecResponse
@@ -3,54 +3,51 @@ import js2xml from 'js2xmlparser2';
3
3
 
4
4
  const APPIUM_AUT_TAG = 'AppiumAUT';
5
5
 
6
- const commands = {
7
- /**
8
- * @this {XCUITestDriver}
9
- */
10
- async getPageSource() {
11
- if (this.isWebContext()) {
12
- const script = 'return document.documentElement.outerHTML';
13
- return await this.executeAtom('execute_script', [script, []]);
14
- }
6
+ /**
7
+ * @this {XCUITestDriver}
8
+ */
9
+ export async function getPageSource() {
10
+ if (this.isWebContext()) {
11
+ const script = 'return document.documentElement.outerHTML';
12
+ return await this.executeAtom('execute_script', [script, []]);
13
+ }
15
14
 
16
- const {
17
- pageSourceExcludedAttributes: excludedAttributes,
18
- useJSONSource
19
- } = await this.settings.getSettings();
20
- const hasExcludedAttributes = _.isString(excludedAttributes) && !_.isEmpty(excludedAttributes);
21
- if (useJSONSource) {
22
- const srcTree = await this.mobileGetSource('json', hasExcludedAttributes ? excludedAttributes : undefined);
23
- return getSourceXml(getTreeForXML(srcTree));
24
- }
15
+ const {
16
+ pageSourceExcludedAttributes: excludedAttributes,
17
+ useJSONSource
18
+ } = await this.settings.getSettings();
19
+ const hasExcludedAttributes = _.isString(excludedAttributes) && !_.isEmpty(excludedAttributes);
20
+ if (useJSONSource) {
21
+ const srcTree = await this.mobileGetSource('json', hasExcludedAttributes ? excludedAttributes : undefined);
22
+ return getSourceXml(getTreeForXML(srcTree));
23
+ }
25
24
 
26
- return await this.mobileGetSource('xml', hasExcludedAttributes ? excludedAttributes : undefined);
27
- },
28
- };
25
+ return await this.mobileGetSource('xml', hasExcludedAttributes ? excludedAttributes : undefined);
26
+ }
27
+
28
+ /**
29
+ * Retrieve the source tree of the current page in XML or JSON format.
30
+ *
31
+ * @param {import('./types').SourceFormat} format - Page tree source representation format.
32
+ * @param {string} [excludedAttributes] A comma-separated string of attribute names to exclude from the output. Only works if `format` is `xml`.
33
+ * @privateRemarks Why isn't `excludedAttributes` an array?
34
+ * @returns {Promise<string>} The source tree of the current page in the given format.
35
+ * @this {XCUITestDriver}
36
+ */
37
+ export async function mobileGetSource(format = 'xml', excludedAttributes) {
38
+ const paramsMap = {
39
+ format,
40
+ scope: APPIUM_AUT_TAG,
41
+ };
42
+ if (excludedAttributes) {
43
+ paramsMap.excluded_attributes = excludedAttributes;
44
+ }
45
+ const query = Object.entries(paramsMap)
46
+ .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
47
+ .join('&');
48
+ return /** @type {string} */ (await this.proxyCommand(`/source?${query}`, 'GET'));
49
+ }
29
50
 
30
- const helpers = {
31
- /**
32
- * Retrieve the source tree of the current page in XML or JSON format.
33
- *
34
- * @param {import('./types').SourceFormat} format - Page tree source representation format.
35
- * @param {string} [excludedAttributes] A comma-separated string of attribute names to exclude from the output. Only works if `format` is `xml`.
36
- * @privateRemarks Why isn't `excludedAttributes` an array?
37
- * @returns {Promise<string>} The source tree of the current page in the given format.
38
- * @this {XCUITestDriver}
39
- */
40
- async mobileGetSource(format = 'xml', excludedAttributes) {
41
- const paramsMap = {
42
- format,
43
- scope: APPIUM_AUT_TAG,
44
- };
45
- if (excludedAttributes) {
46
- paramsMap.excluded_attributes = excludedAttributes;
47
- }
48
- const query = Object.entries(paramsMap)
49
- .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
50
- .join('&');
51
- return /** @type {string} */ (await this.proxyCommand(`/source?${query}`, 'GET'));
52
- },
53
- };
54
51
  /**
55
52
  * Will get JSON of the form:
56
53
  *
@@ -129,7 +126,6 @@ function getSourceXml(jsonSource) {
129
126
  });
130
127
  }
131
128
 
132
- export default {...helpers, ...commands};
133
129
  /**
134
130
  * @typedef {import('../driver').XCUITestDriver} XCUITestDriver
135
131
  */
@@ -1,71 +1,67 @@
1
- const commands = {
2
- /**
3
- * @this {XCUITestDriver}
4
- */
5
- async pageLoadTimeoutW3C(ms) {
6
- await this.setPageLoadTimeout(this.parseTimeoutArgument(ms));
7
- },
8
- /**
9
- * @this {XCUITestDriver}
10
- */
11
- async pageLoadTimeoutMJSONWP(ms) {
12
- await this.setPageLoadTimeout(this.parseTimeoutArgument(ms));
13
- },
1
+ /**
2
+ * @this {XCUITestDriver}
3
+ */
4
+ export async function pageLoadTimeoutW3C(ms) {
5
+ await this.setPageLoadTimeout(this.parseTimeoutArgument(ms));
6
+ }
14
7
 
15
- /**
16
- * @this {XCUITestDriver}
17
- */
18
- async scriptTimeoutW3C(ms) {
19
- // XXX: this is synchronous
20
- await this.setAsyncScriptTimeout(this.parseTimeoutArgument(ms));
21
- },
8
+ /**
9
+ * @this {XCUITestDriver}
10
+ */
11
+ export async function pageLoadTimeoutMJSONWP(ms) {
12
+ await this.setPageLoadTimeout(this.parseTimeoutArgument(ms));
13
+ }
22
14
 
23
- /**
24
- * Alias for {@linkcode XCUITestDriver.scriptTimeoutW3C}.
25
- *
26
- * @param {number} ms - the timeout
27
- * @this {XCUITestDriver}
28
- * @deprecated Use {@linkcode XCUITestDriver.scriptTimeoutW3C} instead
29
- */
30
- async scriptTimeoutMJSONWP(ms) {
31
- await this.asyncScriptTimeout(ms);
32
- },
15
+ /**
16
+ * @this {XCUITestDriver}
17
+ */
18
+ export async function scriptTimeoutW3C(ms) {
19
+ // XXX: this is synchronous
20
+ await this.setAsyncScriptTimeout(this.parseTimeoutArgument(ms));
21
+ }
33
22
 
34
- /**
35
- * Alias for {@linkcode XCUITestDriver.scriptTimeoutW3C}.
36
- *
37
- * @param {number} ms - the timeout
38
- *
39
- * @deprecated Use {@linkcode XCUITestDriver.scriptTimeoutW3C} instead
40
- * @this {XCUITestDriver}
41
- */
42
- async asyncScriptTimeout(ms) {
43
- await this.scriptTimeoutW3C(ms);
44
- },
45
- };
23
+ /**
24
+ * Alias for {@linkcode XCUITestDriver.scriptTimeoutW3C}.
25
+ *
26
+ * @param {number} ms - the timeout
27
+ * @this {XCUITestDriver}
28
+ * @deprecated Use {@linkcode XCUITestDriver.scriptTimeoutW3C} instead
29
+ */
30
+ export async function scriptTimeoutMJSONWP(ms) {
31
+ await this.asyncScriptTimeout(ms);
32
+ }
46
33
 
47
- const helpers = {
48
- /**
49
- * @this {XCUITestDriver}
50
- */
51
- setPageLoadTimeout(ms) {
52
- ms = parseInt(ms, 10);
53
- this.pageLoadMs = ms;
54
- if (this.remote) {
55
- this.remote.pageLoadMs = ms;
56
- }
57
- this.log.debug(`Set page load timeout to ${ms}ms`);
58
- },
59
- /**
60
- * @this {XCUITestDriver}
61
- */
62
- setAsyncScriptTimeout(ms) {
63
- this.asyncWaitMs = ms;
64
- this.log.debug(`Set async script timeout to ${ms}ms`);
65
- },
66
- };
34
+ /**
35
+ * Alias for {@linkcode XCUITestDriver.scriptTimeoutW3C}.
36
+ *
37
+ * @param {number} ms - the timeout
38
+ *
39
+ * @deprecated Use {@linkcode XCUITestDriver.scriptTimeoutW3C} instead
40
+ * @this {XCUITestDriver}
41
+ */
42
+ export async function asyncScriptTimeout(ms) {
43
+ await this.scriptTimeoutW3C(ms);
44
+ }
67
45
 
68
- export default {...helpers, ...commands};
46
+ /**
47
+ * @this {XCUITestDriver}
48
+ */
49
+ export function setPageLoadTimeout(ms) {
50
+ ms = parseInt(ms, 10);
51
+ this.pageLoadMs = ms;
52
+ if (this.remote) {
53
+ this.remote.pageLoadMs = ms;
54
+ }
55
+ this.log.debug(`Set page load timeout to ${ms}ms`);
56
+ }
57
+
58
+ /**
59
+ * @this {XCUITestDriver}
60
+ */
61
+ export function setAsyncScriptTimeout(ms) {
62
+ this.asyncWaitMs = ms;
63
+ this.log.debug(`Set async script timeout to ${ms}ms`);
64
+ }
69
65
 
70
66
  /**
71
67
  * @typedef {import('../driver').XCUITestDriver} XCUITestDriver