@limrun/appium-xcuitest-driver 10.4.3-lim.1 → 10.10.1-lim.2

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 (205) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/build/lib/app-utils.d.ts +2 -2
  3. package/build/lib/app-utils.d.ts.map +1 -1
  4. package/build/lib/app-utils.js +4 -1
  5. package/build/lib/app-utils.js.map +1 -1
  6. package/build/lib/commands/app-management.js +2 -2
  7. package/build/lib/commands/app-management.js.map +1 -1
  8. package/build/lib/commands/appearance.js +2 -2
  9. package/build/lib/commands/appearance.js.map +1 -1
  10. package/build/lib/commands/bidi/models.d.ts.map +1 -1
  11. package/build/lib/commands/bidi/models.js +1 -0
  12. package/build/lib/commands/bidi/models.js.map +1 -1
  13. package/build/lib/commands/bidi/types.d.ts +1 -0
  14. package/build/lib/commands/bidi/types.d.ts.map +1 -1
  15. package/build/lib/commands/biometric.js +3 -3
  16. package/build/lib/commands/biometric.js.map +1 -1
  17. package/build/lib/commands/certificate.d.ts.map +1 -1
  18. package/build/lib/commands/certificate.js +9 -3
  19. package/build/lib/commands/certificate.js.map +1 -1
  20. package/build/lib/commands/condition.d.ts +2 -0
  21. package/build/lib/commands/condition.d.ts.map +1 -1
  22. package/build/lib/commands/condition.js +75 -2
  23. package/build/lib/commands/condition.js.map +1 -1
  24. package/build/lib/commands/context.d.ts +5 -5
  25. package/build/lib/commands/context.d.ts.map +1 -1
  26. package/build/lib/commands/context.js +6 -6
  27. package/build/lib/commands/context.js.map +1 -1
  28. package/build/lib/commands/file-movement.d.ts.map +1 -1
  29. package/build/lib/commands/file-movement.js +7 -7
  30. package/build/lib/commands/file-movement.js.map +1 -1
  31. package/build/lib/commands/general.js +1 -1
  32. package/build/lib/commands/general.js.map +1 -1
  33. package/build/lib/commands/gesture.js +1 -1
  34. package/build/lib/commands/gesture.js.map +1 -1
  35. package/build/lib/commands/keychains.js +1 -1
  36. package/build/lib/commands/keychains.js.map +1 -1
  37. package/build/lib/commands/localization.js +1 -1
  38. package/build/lib/commands/localization.js.map +1 -1
  39. package/build/lib/commands/location.d.ts +3 -2
  40. package/build/lib/commands/location.d.ts.map +1 -1
  41. package/build/lib/commands/location.js +10 -4
  42. package/build/lib/commands/location.js.map +1 -1
  43. package/build/lib/commands/log.js +9 -9
  44. package/build/lib/commands/log.js.map +1 -1
  45. package/build/lib/commands/memory.js +1 -1
  46. package/build/lib/commands/memory.js.map +1 -1
  47. package/build/lib/commands/notifications.js +1 -1
  48. package/build/lib/commands/notifications.js.map +1 -1
  49. package/build/lib/commands/pasteboard.js +2 -2
  50. package/build/lib/commands/pasteboard.js.map +1 -1
  51. package/build/lib/commands/pcap.js +1 -1
  52. package/build/lib/commands/pcap.js.map +1 -1
  53. package/build/lib/commands/performance.d.ts.map +1 -1
  54. package/build/lib/commands/performance.js +13 -4
  55. package/build/lib/commands/performance.js.map +1 -1
  56. package/build/lib/commands/permissions.js +2 -2
  57. package/build/lib/commands/permissions.js.map +1 -1
  58. package/build/lib/commands/proxy-helper.d.ts.map +1 -1
  59. package/build/lib/commands/proxy-helper.js +0 -3
  60. package/build/lib/commands/proxy-helper.js.map +1 -1
  61. package/build/lib/commands/screenshots.js +1 -1
  62. package/build/lib/commands/screenshots.js.map +1 -1
  63. package/build/lib/commands/simctl.d.ts +1 -1
  64. package/build/lib/commands/simctl.d.ts.map +1 -1
  65. package/build/lib/commands/simctl.js +1 -1
  66. package/build/lib/commands/simctl.js.map +1 -1
  67. package/build/lib/commands/web.js +1 -1
  68. package/build/lib/commands/web.js.map +1 -1
  69. package/build/lib/commands/xctest-record-screen.js +2 -2
  70. package/build/lib/commands/xctest-record-screen.js.map +1 -1
  71. package/build/lib/desired-caps.d.ts +392 -505
  72. package/build/lib/desired-caps.d.ts.map +1 -1
  73. package/build/lib/desired-caps.js +19 -10
  74. package/build/lib/desired-caps.js.map +1 -1
  75. package/build/lib/device/clients/base-device-client.d.ts +22 -0
  76. package/build/lib/device/clients/base-device-client.d.ts.map +1 -0
  77. package/build/lib/device/clients/base-device-client.js +14 -0
  78. package/build/lib/device/clients/base-device-client.js.map +1 -0
  79. package/build/lib/device/clients/py-ios-device-client.d.ts +21 -0
  80. package/build/lib/device/clients/py-ios-device-client.d.ts.map +1 -0
  81. package/build/lib/device/clients/py-ios-device-client.js +125 -0
  82. package/build/lib/device/clients/py-ios-device-client.js.map +1 -0
  83. package/build/lib/device/device-connections-factory.d.ts +18 -0
  84. package/build/lib/device/device-connections-factory.d.ts.map +1 -0
  85. package/build/lib/device/device-connections-factory.js +260 -0
  86. package/build/lib/device/device-connections-factory.js.map +1 -0
  87. package/build/lib/device/log/helpers.d.ts +10 -0
  88. package/build/lib/device/log/helpers.d.ts.map +1 -0
  89. package/build/lib/device/log/helpers.js +37 -0
  90. package/build/lib/device/log/helpers.js.map +1 -0
  91. package/build/lib/device/log/ios-crash-log.d.ts +34 -0
  92. package/build/lib/device/log/ios-crash-log.d.ts.map +1 -0
  93. package/build/lib/device/log/ios-crash-log.js +141 -0
  94. package/build/lib/device/log/ios-crash-log.js.map +1 -0
  95. package/build/lib/device/log/ios-device-log.d.ts +19 -0
  96. package/build/lib/device/log/ios-device-log.d.ts.map +1 -0
  97. package/build/lib/device/log/ios-device-log.js +42 -0
  98. package/build/lib/device/log/ios-device-log.js.map +1 -0
  99. package/build/lib/device/log/ios-log.d.ts +24 -0
  100. package/build/lib/device/log/ios-log.d.ts.map +1 -0
  101. package/build/lib/device/log/ios-log.js +50 -0
  102. package/build/lib/device/log/ios-log.js.map +1 -0
  103. package/build/lib/device/log/ios-performance-log.d.ts +18 -0
  104. package/build/lib/device/log/ios-performance-log.d.ts.map +1 -0
  105. package/build/lib/device/log/ios-performance-log.js +43 -0
  106. package/build/lib/device/log/ios-performance-log.js.map +1 -0
  107. package/build/lib/device/log/ios-simulator-log.d.ts +38 -0
  108. package/build/lib/device/log/ios-simulator-log.d.ts.map +1 -0
  109. package/build/lib/device/log/ios-simulator-log.js +184 -0
  110. package/build/lib/device/log/ios-simulator-log.js.map +1 -0
  111. package/build/lib/device/log/line-consuming-log.d.ts +9 -0
  112. package/build/lib/device/log/line-consuming-log.d.ts.map +1 -0
  113. package/build/lib/device/log/line-consuming-log.js +16 -0
  114. package/build/lib/device/log/line-consuming-log.js.map +1 -0
  115. package/build/lib/device/log/safari-console-log.d.ts +67 -0
  116. package/build/lib/device/log/safari-console-log.d.ts.map +1 -0
  117. package/build/lib/device/log/safari-console-log.js +81 -0
  118. package/build/lib/device/log/safari-console-log.js.map +1 -0
  119. package/build/lib/device/log/safari-network-log.d.ts +75 -0
  120. package/build/lib/device/log/safari-network-log.d.ts.map +1 -0
  121. package/build/lib/device/log/safari-network-log.js +47 -0
  122. package/build/lib/device/log/safari-network-log.js.map +1 -0
  123. package/build/lib/device/real-device-management.d.ts +146 -0
  124. package/build/lib/device/real-device-management.d.ts.map +1 -0
  125. package/build/lib/device/real-device-management.js +740 -0
  126. package/build/lib/device/real-device-management.js.map +1 -0
  127. package/build/lib/device/simulator-management.d.ts +65 -0
  128. package/build/lib/device/simulator-management.d.ts.map +1 -0
  129. package/build/lib/device/simulator-management.js +261 -0
  130. package/build/lib/device/simulator-management.js.map +1 -0
  131. package/build/lib/device-log/ios-crash-log.d.ts +1 -1
  132. package/build/lib/device-log/ios-crash-log.d.ts.map +1 -1
  133. package/build/lib/device-log/ios-simulator-log.d.ts +1 -1
  134. package/build/lib/device-log/ios-simulator-log.d.ts.map +1 -1
  135. package/build/lib/doctor/required-checks.js +1 -1
  136. package/build/lib/doctor/required-checks.js.map +1 -1
  137. package/build/lib/driver.d.ts +129 -1377
  138. package/build/lib/driver.d.ts.map +1 -1
  139. package/build/lib/driver.js +461 -573
  140. package/build/lib/driver.js.map +1 -1
  141. package/build/lib/method-map.d.ts +1 -1
  142. package/build/lib/method-map.d.ts.map +1 -1
  143. package/build/lib/method-map.js +2 -2
  144. package/build/lib/method-map.js.map +1 -1
  145. package/build/lib/simulator-management.d.ts +10 -0
  146. package/build/lib/simulator-management.d.ts.map +1 -1
  147. package/build/lib/simulator-management.js +9 -5
  148. package/build/lib/simulator-management.js.map +1 -1
  149. package/build/lib/utils.d.ts +2 -9
  150. package/build/lib/utils.d.ts.map +1 -1
  151. package/build/lib/utils.js +3 -47
  152. package/build/lib/utils.js.map +1 -1
  153. package/lib/app-utils.js +5 -1
  154. package/lib/commands/app-management.js +2 -2
  155. package/lib/commands/appearance.js +2 -2
  156. package/lib/commands/bidi/models.ts +1 -0
  157. package/lib/commands/bidi/types.ts +1 -0
  158. package/lib/commands/biometric.js +3 -3
  159. package/lib/commands/certificate.js +9 -3
  160. package/lib/commands/condition.js +85 -2
  161. package/lib/commands/context.js +6 -6
  162. package/lib/commands/file-movement.js +11 -7
  163. package/lib/commands/general.js +1 -1
  164. package/lib/commands/gesture.js +1 -1
  165. package/lib/commands/keychains.js +1 -1
  166. package/lib/commands/localization.js +1 -1
  167. package/lib/commands/location.js +11 -4
  168. package/lib/commands/log.js +9 -9
  169. package/lib/commands/memory.js +1 -1
  170. package/lib/commands/notifications.js +1 -1
  171. package/lib/commands/pasteboard.js +2 -2
  172. package/lib/commands/pcap.js +1 -1
  173. package/lib/commands/performance.js +12 -1
  174. package/lib/commands/permissions.js +2 -2
  175. package/lib/commands/proxy-helper.js +0 -3
  176. package/lib/commands/screenshots.js +1 -1
  177. package/lib/commands/simctl.js +1 -1
  178. package/lib/commands/web.js +1 -1
  179. package/lib/commands/xctest-record-screen.js +2 -2
  180. package/lib/{desired-caps.js → desired-caps.ts} +20 -6
  181. package/lib/{real-device-clients → device/clients}/py-ios-device-client.ts +1 -1
  182. package/lib/{device-connections-factory.js → device/device-connections-factory.ts} +96 -60
  183. package/lib/{device-log → device/log}/helpers.ts +1 -1
  184. package/lib/{device-log → device/log}/ios-crash-log.ts +4 -4
  185. package/lib/{device-log → device/log}/ios-log.ts +1 -1
  186. package/lib/{device-log → device/log}/ios-simulator-log.ts +1 -1
  187. package/lib/{device-log → device/log}/line-consuming-log.ts +1 -1
  188. package/lib/{device-log → device/log}/safari-console-log.ts +1 -1
  189. package/lib/device/real-device-management.ts +831 -0
  190. package/lib/{simulator-management.js → device/simulator-management.ts} +75 -64
  191. package/lib/doctor/required-checks.ts +1 -1
  192. package/lib/{driver.js → driver.ts} +623 -707
  193. package/lib/{method-map.js → method-map.ts} +5 -2
  194. package/lib/utils.js +3 -54
  195. package/package.json +17 -19
  196. package/scripts/build-wda.js +3 -3
  197. package/lib/ios-fs-helpers.js +0 -355
  198. package/lib/ios-generic-simulators.js +0 -11
  199. package/lib/real-device-management.js +0 -133
  200. package/lib/real-device.js +0 -347
  201. package/lib/xcrun.js +0 -16
  202. /package/lib/{real-device-clients → device/clients}/base-device-client.ts +0 -0
  203. /package/lib/{device-log → device/log}/ios-device-log.ts +0 -0
  204. /package/lib/{device-log → device/log}/ios-performance-log.ts +0 -0
  205. /package/lib/{device-log → device/log}/safari-network-log.ts +0 -0
@@ -1,4 +1,7 @@
1
- export const newMethodMap = /** @type {const} */ ({
1
+ import type { MethodMap } from '@appium/types';
2
+ import type { XCUITestDriver } from './driver';
3
+
4
+ export const newMethodMap = {
2
5
  '/session/:sessionId/timeouts/async_script': {
3
6
  POST: {
4
7
  command: 'asyncScriptTimeout',
@@ -193,4 +196,4 @@ export const newMethodMap = /** @type {const} */ ({
193
196
  deprecated: true,
194
197
  },
195
198
  },
196
- });
199
+ } as const satisfies MethodMap<XCUITestDriver>;
package/lib/utils.js CHANGED
@@ -1,4 +1,4 @@
1
- import * as xcode from '@limrun/appium-xcode';
1
+ import * as xcode from 'appium-xcode';
2
2
  import {errors} from 'appium/driver';
3
3
  import {fs, net, util} from 'appium/support';
4
4
  import B from 'bluebird';
@@ -8,7 +8,6 @@ import path from 'node:path';
8
8
  import url from 'node:url';
9
9
  import * as semver from 'semver';
10
10
  import {exec} from 'teen_process';
11
- import iosGenericSimulators from './ios-generic-simulators';
12
11
  import log from './logger';
13
12
  import {PLATFORM_NAME_TVOS, PLATFORM_NAME_IOS} from './desired-caps';
14
13
 
@@ -50,61 +49,12 @@ async function getAndCheckXcodeVersion() {
50
49
  */
51
50
  async function getAndCheckIosSdkVersion() {
52
51
  try {
53
- return '26';
54
52
  return await xcode.getMaxIOSSDK();
55
53
  } catch (err) {
56
54
  throw log.errorWithException(`Could not determine iOS SDK version: ${err.message}`);
57
55
  }
58
56
  }
59
57
 
60
- /**
61
- * Get the generic simulator for a given IOS version and device type (iPhone, iPad)
62
- *
63
- * @param {string|number} platformVersion IOS version. e.g.) 13.0
64
- * @param {string} deviceName Type of IOS device. Can be iPhone, iPad (possibly more in the future)
65
- *
66
- * @returns {string?} Generic iPhone or iPad simulator (if applicable)
67
- */
68
- function getGenericSimulatorForIosVersion(platformVersion, deviceName) {
69
- const genericSimulators = iosGenericSimulators[deviceName];
70
- if (!genericSimulators) {
71
- return null;
72
- }
73
-
74
- // Find the highest iOS version in the list that is below the provided version
75
- let result = null;
76
- const compareVersions = ([simOne], [simTwo]) =>
77
- util.compareVersions(simOne, '<', simTwo) ? -1 : 1;
78
- for (const [platformVersionFromList, iosSimulator] of genericSimulators.sort(compareVersions)) {
79
- if (util.compareVersions(platformVersionFromList, '>', String(platformVersion))) {
80
- break;
81
- }
82
- result = iosSimulator;
83
- }
84
- return result;
85
- }
86
-
87
- /**
88
- *
89
- * @param {string} platformVersion
90
- * @param {string} deviceName
91
- * @returns {string}
92
- */
93
- function translateDeviceName(platformVersion, deviceName) {
94
- if (!deviceName) {
95
- return deviceName;
96
- }
97
- const deviceNameTranslated = getGenericSimulatorForIosVersion(
98
- platformVersion,
99
- `${deviceName}`.toLowerCase().trim(),
100
- );
101
- if (!deviceNameTranslated) {
102
- return deviceName;
103
- }
104
-
105
- log.debug(`Changing deviceName from '${deviceName}' to '${deviceNameTranslated}'`);
106
- return deviceNameTranslated;
107
- }
108
58
 
109
59
  /**
110
60
  * @param {string[]} locations
@@ -531,7 +481,6 @@ export {
531
481
  checkAppPresent,
532
482
  getDriverInfo,
533
483
  clearSystemFiles,
534
- translateDeviceName,
535
484
  normalizeCommandTimeouts,
536
485
  DEFAULT_TIMEOUT_KEY,
537
486
  markSystemFilesForCleanup,
@@ -545,7 +494,7 @@ export {
545
494
  };
546
495
 
547
496
  /**
548
- * @typedef {import('@limrun/appium-xcode').XcodeVersion} XcodeVersion
549
- * @typedef {import('@limrun/appium-ios-simulator').Simulator} Simulator
497
+ * @typedef {import('appium-xcode').XcodeVersion} XcodeVersion
498
+ * @typedef {import('appium-ios-simulator').Simulator} Simulator
550
499
  * @typedef {import('./driver').XCUITestDriver} XCUITestDriver
551
500
  */
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "xcuitest",
9
9
  "xctest"
10
10
  ],
11
- "version": "10.4.3-lim.1",
11
+ "version": "10.10.1-lim.2",
12
12
  "author": "Appium Contributors",
13
13
  "license": "Apache-2.0",
14
14
  "repository": {
@@ -84,10 +84,10 @@
84
84
  "@colors/colors": "^1.6.0",
85
85
  "appium-idb": "^2.0.0",
86
86
  "appium-ios-device": "^3.0.0",
87
- "@limrun/appium-ios-simulator": "7.0.2-lim.1",
88
- "appium-remote-debugger": "^15.0.3",
89
- "appium-webdriveragent": "^10.2.1",
90
- "@limrun/appium-xcode": "6.1.2-lim.1",
87
+ "appium-ios-simulator": "npm:@limrun/appium-ios-simulator@8.0.5-lim.4",
88
+ "appium-remote-debugger": "^15.2.0",
89
+ "appium-webdriveragent": "npm:@limrun/appium-webdriveragent@10.4.0-lim.1",
90
+ "appium-xcode": "npm:@limrun/appium-xcode@6.1.3-lim.1",
91
91
  "async-lock": "^1.4.0",
92
92
  "asyncbox": "^3.0.0",
93
93
  "bluebird": "^3.7.2",
@@ -99,10 +99,9 @@
99
99
  "moment": "^2.29.4",
100
100
  "moment-timezone": "^0.x",
101
101
  "node-devicectl": "^1.1.0",
102
- "@limrun/node-simctl": "^8.0.5-lim.1",
102
+ "node-simctl": "npm:@limrun/node-simctl@8.0.5-lim.3",
103
103
  "portscanner": "^2.2.0",
104
104
  "semver": "^7.5.4",
105
- "source-map-support": "^0.x",
106
105
  "teen_process": "^3.0.0",
107
106
  "winston": "^3.17.0",
108
107
  "ws": "^8.13.0"
@@ -124,15 +123,15 @@
124
123
  "install-docs-deps": "appium-docs init --no-mkdocs",
125
124
  "prepare": "npm run rebuild",
126
125
  "rebuild": "npm run clean; npm run build",
127
- "test": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.js\"",
128
- "e2e-test": "mocha --exit --timeout 10m \"./test/functional/**/*-specs.js\"",
129
- "e2e-test:basic": "mocha \"./test/functional/basic\" --exit --timeout 10m",
130
- "e2e-test:device": "mocha \"./test/functional/device\" --exit --timeout 10m",
131
- "e2e-test:driver": "mocha \"./test/functional/driver\" --exit --timeout 10m",
132
- "e2e-test:long": "mocha \"./test/functional/long\" --exit --timeout 10m",
133
- "e2e-test:parallel": "mocha \"./test/functional/parallel\" --exit --timeout 10m",
134
- "e2e-test:web": "mocha \"./test/functional/web\" --exit --timeout 10m",
135
- "e2e-test:native-web-tap": "mocha \"./test/functional/web/safari-nativewebtap-e2e-specs.js\" --exit --timeout 10m",
126
+ "test": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.ts\"",
127
+ "e2e-test": "mocha --exit --timeout 10m \"./test/functional/**/*-specs.ts\"",
128
+ "e2e-test:basic": "mocha \"./test/functional/basic/**/*-specs.ts\" --exit --timeout 10m",
129
+ "e2e-test:device": "mocha \"./test/functional/device/**/*-specs.ts\" --exit --timeout 10m",
130
+ "e2e-test:driver": "mocha \"./test/functional/driver/**/*-specs.ts\" --exit --timeout 10m",
131
+ "e2e-test:long": "mocha \"./test/functional/long/**/*-specs.ts\" --exit --timeout 10m",
132
+ "e2e-test:parallel": "mocha \"./test/functional/parallel/**/*-specs.ts\" --exit --timeout 10m",
133
+ "e2e-test:web": "mocha \"./test/functional/web/**/*-specs.ts\" --exit --timeout 10m",
134
+ "e2e-test:native-web-tap": "mocha \"./test/functional/web/safari-nativewebtap-e2e-specs.ts\" --exit --timeout 10m",
136
135
  "start": "appium --relaxed-security --port 4567 --keep-alive-timeout 1200"
137
136
  },
138
137
  "prettier": {
@@ -146,7 +145,6 @@
146
145
  "devDependencies": {
147
146
  "@appium/docutils": "^2.0.0-rc.1",
148
147
  "@appium/eslint-config-appium-ts": "^2.0.0-rc.1",
149
- "@appium/test-support": "^4.0.0-rc.1",
150
148
  "@appium/tsconfig": "^1.0.0-rc.1",
151
149
  "@appium/types": "^1.0.0-rc.1",
152
150
  "@semantic-release/changelog": "^6.0.3",
@@ -154,7 +152,7 @@
154
152
  "@types/bluebird": "^3.5.38",
155
153
  "@types/lodash": "^4.14.196",
156
154
  "@types/mocha": "^10.0.1",
157
- "@types/node": "^24.0.1",
155
+ "@types/node": "^25.0.0",
158
156
  "@types/portscanner": "^2.1.1",
159
157
  "axios": "^1.4.0",
160
158
  "chai": "^6.0.0",
@@ -165,7 +163,7 @@
165
163
  "mocha-multi-reporters": "^1.5.1",
166
164
  "pem": "^1.14.8",
167
165
  "prettier": "^3.0.0",
168
- "semantic-release": "^25.0.0",
166
+ "semantic-release": "^25.0.2",
169
167
  "sharp": "^0.x",
170
168
  "sinon": "^21.0.0",
171
169
  "ts-node": "^10.9.1",
@@ -1,7 +1,7 @@
1
1
  const {WebDriverAgent} = require('appium-webdriveragent');
2
- const xcode = require('@limrun/appium-xcode');
3
- const {Simctl} = require('@limrun/node-simctl');
4
- const {getSimulator} = require('@limrun/appium-ios-simulator');
2
+ const xcode = require('appium-xcode');
3
+ const {Simctl} = require('node-simctl');
4
+ const {getSimulator} = require('appium-ios-simulator');
5
5
  const {logger} = require('appium/support');
6
6
  const {parseArgValue} = require('./utils');
7
7
 
@@ -1,355 +0,0 @@
1
- import _ from 'lodash';
2
- import B, {TimeoutError} from 'bluebird';
3
- import {fs, tempDir, mkdirp, zip, util, timing} from 'appium/support';
4
- import path from 'path';
5
- import log from './logger';
6
-
7
- export const IO_TIMEOUT_MS = 4 * 60 * 1000;
8
- // Mobile devices use NAND memory modules for the storage,
9
- // and the parallelism there is not as performant as on regular SSDs
10
- const MAX_IO_CHUNK_SIZE = 8;
11
-
12
- /**
13
- * Retrieve a file from a real device
14
- *
15
- * @param {any} afcService Apple File Client service instance from
16
- * 'appium-ios-device' module
17
- * @param {string} remotePath Relative path to the file on the device
18
- * @returns {Promise<Buffer>} The file content as a buffer
19
- */
20
- export async function pullFile(afcService, remotePath) {
21
- const stream = await afcService.createReadStream(remotePath, {autoDestroy: true});
22
- const pullPromise = new B((resolve, reject) => {
23
- stream.on('close', resolve);
24
- stream.on('error', reject);
25
- }).timeout(IO_TIMEOUT_MS);
26
- const buffers = [];
27
- stream.on('data', (data) => buffers.push(data));
28
- await pullPromise;
29
- return Buffer.concat(buffers);
30
- }
31
-
32
- /**
33
- * Checks a presence of a local folder.
34
- *
35
- * @param {string} folderPath Full path to the local folder
36
- * @returns {Promise<boolean>} True if the folder exists and is actually a folder
37
- */
38
- async function folderExists(folderPath) {
39
- try {
40
- return (await fs.stat(folderPath)).isDirectory();
41
- } catch {
42
- return false;
43
- }
44
- }
45
-
46
- /**
47
- * Retrieve a folder from a real device
48
- *
49
- * @param {any} afcService Apple File Client service instance from
50
- * 'appium-ios-device' module
51
- * @param {string} remoteRootPath Relative path to the folder on the device
52
- * @returns {Promise<Buffer>} The folder content as a zipped base64-encoded buffer
53
- */
54
- export async function pullFolder(afcService, remoteRootPath) {
55
- const tmpFolder = await tempDir.openDir();
56
- try {
57
- let localTopItem = null;
58
- let countFilesSuccess = 0;
59
- let countFilesFail = 0;
60
- let countFolders = 0;
61
- const pullPromises = [];
62
- await afcService.walkDir(remoteRootPath, true, async (remotePath, isDir) => {
63
- const localPath = path.join(tmpFolder, remotePath);
64
- const dirname = isDir ? localPath : path.dirname(localPath);
65
- if (!(await folderExists(dirname))) {
66
- await mkdirp(dirname);
67
- }
68
- if (!localTopItem || localPath.split(path.sep).length < localTopItem.split(path.sep).length) {
69
- localTopItem = localPath;
70
- }
71
- if (isDir) {
72
- ++countFolders;
73
- return;
74
- }
75
-
76
- const readStream = await afcService.createReadStream(remotePath, {autoDestroy: true});
77
- const writeStream = fs.createWriteStream(localPath, {autoClose: true});
78
- pullPromises.push(
79
- new B((resolve) => {
80
- writeStream.on('close', () => {
81
- ++countFilesSuccess;
82
- resolve();
83
- });
84
- const onStreamingError = (e) => {
85
- readStream.unpipe(writeStream);
86
- log.warn(
87
- `Cannot pull '${remotePath}' to '${localPath}'. ` +
88
- `The file will be skipped. Original error: ${e.message}`,
89
- );
90
- ++countFilesFail;
91
- resolve();
92
- };
93
- writeStream.on('error', onStreamingError);
94
- readStream.on('error', onStreamingError);
95
- }).timeout(IO_TIMEOUT_MS),
96
- );
97
- readStream.pipe(writeStream);
98
- if (pullPromises.length >= MAX_IO_CHUNK_SIZE) {
99
- await B.any(pullPromises);
100
- for (let i = pullPromises.length - 1; i >= 0; i--) {
101
- if (pullPromises[i].isFulfilled()) {
102
- pullPromises.splice(i, 1);
103
- }
104
- }
105
- }
106
- });
107
- // Wait for the rest of files to be pulled
108
- if (!_.isEmpty(pullPromises)) {
109
- await B.all(pullPromises);
110
- }
111
- log.info(
112
- `Pulled ${util.pluralize('file', countFilesSuccess, true)} out of ` +
113
- `${countFilesSuccess + countFilesFail} and ${util.pluralize(
114
- 'folder',
115
- countFolders,
116
- true,
117
- )} ` +
118
- `from '${remoteRootPath}'`,
119
- );
120
- return await zip.toInMemoryZip(localTopItem ? path.dirname(localTopItem) : tmpFolder, {
121
- encodeToBase64: true,
122
- });
123
- } finally {
124
- await fs.rimraf(tmpFolder);
125
- }
126
- }
127
-
128
- /**
129
- * Creates remote folder path recursively. Noop if the given path
130
- * already exists
131
- *
132
- * @param {any} afcService Apple File Client service instance from
133
- * 'appium-ios-device' module
134
- * @param {string} remoteRoot The relative path to the remote folder structure
135
- * to be created
136
- */
137
- async function remoteMkdirp(afcService, remoteRoot) {
138
- if (remoteRoot === '.' || remoteRoot === '/') {
139
- return;
140
- }
141
- try {
142
- await afcService.listDirectory(remoteRoot);
143
- return;
144
- } catch {
145
- // This means that the directory is missing and we got an object not found error.
146
- // Therefore, we are going to the parent
147
- await remoteMkdirp(afcService, path.dirname(remoteRoot));
148
- }
149
- await afcService.createDirectory(remoteRoot);
150
- }
151
-
152
- /**
153
- * @typedef {Object} PushFileOptions
154
- * @property {number} [timeoutMs=240000] The maximum count of milliceconds to wait until
155
- * file push is completed. Cannot be lower than 60000ms
156
- */
157
-
158
- /**
159
- * Pushes a file to a real device
160
- *
161
- * @param {any} afcService afcService Apple File Client service instance from
162
- * 'appium-ios-device' module
163
- * @param {string|Buffer} localPathOrPayload Either full path to the source file
164
- * or a buffer payload to be written into the remote destination
165
- * @param {string} remotePath Relative path to the file on the device. The remote
166
- * folder structure is created automatically if necessary.
167
- * @param {PushFileOptions} [opts={}]
168
- */
169
- export async function pushFile(afcService, localPathOrPayload, remotePath, opts = {}) {
170
- const {timeoutMs = IO_TIMEOUT_MS} = opts;
171
- const timer = new timing.Timer().start();
172
- await remoteMkdirp(afcService, path.dirname(remotePath));
173
- const source = Buffer.isBuffer(localPathOrPayload)
174
- ? localPathOrPayload
175
- : fs.createReadStream(localPathOrPayload, {autoClose: true});
176
- const writeStream = await afcService.createWriteStream(remotePath, {
177
- autoDestroy: true,
178
- });
179
- writeStream.on('finish', writeStream.destroy);
180
- let pushError = null;
181
- const filePushPromise = new B((resolve, reject) => {
182
- writeStream.on('close', () => {
183
- if (pushError) {
184
- reject(pushError);
185
- } else {
186
- resolve();
187
- }
188
- });
189
- const onStreamError = (e) => {
190
- if (!Buffer.isBuffer(source)) {
191
- source.unpipe(writeStream);
192
- }
193
- log.debug(e);
194
- pushError = e;
195
- };
196
- writeStream.on('error', onStreamError);
197
- if (!Buffer.isBuffer(source)) {
198
- source.on('error', onStreamError);
199
- }
200
- });
201
- if (Buffer.isBuffer(source)) {
202
- writeStream.write(source);
203
- writeStream.end();
204
- } else {
205
- source.pipe(writeStream);
206
- }
207
- await filePushPromise.timeout(Math.max(timeoutMs, 60000));
208
- const fileSize = Buffer.isBuffer(localPathOrPayload)
209
- ? localPathOrPayload.length
210
- : (await fs.stat(localPathOrPayload)).size;
211
- log.debug(
212
- `Successfully pushed the file payload (${util.toReadableSizeString(fileSize)}) ` +
213
- `to the remote location '${remotePath}' in ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`,
214
- );
215
- }
216
-
217
- /**
218
- * @typedef {Object} PushFolderOptions
219
- *
220
- * @property {number} [timeoutMs=240000] The maximum timeout to wait until a
221
- * single file is copied
222
- * @property {boolean} [enableParallelPush=false] Whether to push files in parallel.
223
- * This usually gives better performance, but might sometimes be less stable.
224
- */
225
-
226
- /**
227
- * Pushes a folder to a real device
228
- *
229
- * @param {any} afcService Apple File Client service instance from
230
- * 'appium-ios-device' module
231
- * @param {string} srcRootPath The full path to the source folder
232
- * @param {string} dstRootPath The relative path to the destination folder. The folder
233
- * will be deleted if already exists.
234
- * @param {PushFolderOptions} opts
235
- */
236
- export async function pushFolder(afcService, srcRootPath, dstRootPath, opts = {}) {
237
- const {timeoutMs = IO_TIMEOUT_MS, enableParallelPush = false} = opts;
238
-
239
- const timer = new timing.Timer().start();
240
- const allItems = /** @type {import('path-scurry').Path[]} */ (
241
- /** @type {unknown} */ (
242
- await fs.glob('**', {
243
- cwd: srcRootPath,
244
- withFileTypes: true,
245
- })
246
- )
247
- );
248
- log.debug(`Successfully scanned the tree structure of '${srcRootPath}'`);
249
- // top-level folders go first
250
- /** @type {string[]} */
251
- const foldersToPush = allItems
252
- .filter((x) => x.isDirectory())
253
- .map((x) => x.relative())
254
- .sort((a, b) => a.split(path.sep).length - b.split(path.sep).length);
255
- // larger files go first
256
- /** @type {string[]} */
257
- const filesToPush = allItems
258
- .filter((x) => !x.isDirectory())
259
- .sort((a, b) => (b.size ?? 0) - (a.size ?? 0))
260
- .map((x) => x.relative());
261
- log.debug(
262
- `Got ${util.pluralize('folder', foldersToPush.length, true)} and ` +
263
- `${util.pluralize('file', filesToPush.length, true)} to push`,
264
- );
265
- // create the folder structure first
266
- try {
267
- await afcService.deleteDirectory(dstRootPath);
268
- } catch {}
269
- await afcService.createDirectory(dstRootPath);
270
- for (const relativeFolderPath of foldersToPush) {
271
- // createDirectory does not accept folder names ending with a path separator
272
- const absoluteFolderPath = _.trimEnd(path.join(dstRootPath, relativeFolderPath), path.sep);
273
- if (absoluteFolderPath) {
274
- await afcService.createDirectory(absoluteFolderPath);
275
- }
276
- }
277
- // do not forget about the root folder
278
- log.debug(
279
- `Successfully created the remote folder structure ` +
280
- `(${util.pluralize('item', foldersToPush.length + 1, true)})`,
281
- );
282
-
283
- const _pushFile = async (/** @type {string} */ relativePath) => {
284
- const absoluteSourcePath = path.join(srcRootPath, relativePath);
285
- const readStream = fs.createReadStream(absoluteSourcePath, {autoClose: true});
286
- const absoluteDestinationPath = path.join(dstRootPath, relativePath);
287
- const writeStream = await afcService.createWriteStream(absoluteDestinationPath, {
288
- autoDestroy: true,
289
- });
290
- writeStream.on('finish', writeStream.destroy);
291
- let pushError = null;
292
- const filePushPromise = new B((resolve, reject) => {
293
- writeStream.on('close', () => {
294
- if (pushError) {
295
- reject(pushError);
296
- } else {
297
- resolve();
298
- }
299
- });
300
- const onStreamError = (e) => {
301
- readStream.unpipe(writeStream);
302
- log.debug(e);
303
- pushError = e;
304
- };
305
- writeStream.on('error', onStreamError);
306
- readStream.on('error', onStreamError);
307
- });
308
- readStream.pipe(writeStream);
309
- await filePushPromise.timeout(Math.max(timeoutMs - timer.getDuration().asMilliSeconds, 60000));
310
- };
311
-
312
- if (enableParallelPush) {
313
- log.debug(`Proceeding to parallel files push (max ${MAX_IO_CHUNK_SIZE} writers)`);
314
- const pushPromises = [];
315
- for (const relativeFilePath of filesToPush) {
316
- pushPromises.push(B.resolve(_pushFile(relativeFilePath)));
317
- // keep the push queue filled
318
- if (pushPromises.length >= MAX_IO_CHUNK_SIZE) {
319
- await B.any(pushPromises);
320
- const elapsedMs = timer.getDuration().asMilliSeconds;
321
- if (elapsedMs > timeoutMs) {
322
- throw new TimeoutError(`Timed out after ${elapsedMs} ms`);
323
- }
324
- }
325
- for (let i = pushPromises.length - 1; i >= 0; i--) {
326
- if (pushPromises[i].isFulfilled()) {
327
- pushPromises.splice(i, 1);
328
- }
329
- }
330
- }
331
- if (!_.isEmpty(pushPromises)) {
332
- const remainingPromises = pushPromises.filter((p) => !p.isFulfilled());
333
- if (remainingPromises.length > 0) {
334
- await B.all(remainingPromises).timeout(
335
- Math.max(timeoutMs - timer.getDuration().asMilliSeconds, 60000),
336
- );
337
- }
338
- }
339
- } else {
340
- log.debug(`Proceeding to serial files push`);
341
- for (const relativeFilePath of filesToPush) {
342
- await _pushFile(relativeFilePath);
343
- const elapsedMs = timer.getDuration().asMilliSeconds;
344
- if (elapsedMs > timeoutMs) {
345
- throw new TimeoutError(`Timed out after ${elapsedMs} ms`);
346
- }
347
- }
348
- }
349
-
350
- log.debug(
351
- `Successfully pushed ${util.pluralize('folder', foldersToPush.length, true)} ` +
352
- `and ${util.pluralize('file', filesToPush.length, true)} ` +
353
- `within ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`,
354
- );
355
- }
@@ -1,11 +0,0 @@
1
- export default {
2
- 'ipad simulator': [
3
- ['0.0', 'iPad Retina'],
4
- ['10.3', 'iPad Air'],
5
- ['13.0', 'iPad (5th generation)'],
6
- ],
7
- 'iphone simulator': [
8
- ['0.0', 'iPhone 6'],
9
- ['13.0', 'iPhone X'],
10
- ],
11
- };