appium-xcuitest-driver 10.8.3 → 10.9.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 (218) hide show
  1. package/CHANGELOG.md +12 -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/biometric.js +3 -3
  11. package/build/lib/commands/biometric.js.map +1 -1
  12. package/build/lib/commands/certificate.d.ts.map +1 -1
  13. package/build/lib/commands/certificate.js +9 -3
  14. package/build/lib/commands/certificate.js.map +1 -1
  15. package/build/lib/commands/context.d.ts +5 -5
  16. package/build/lib/commands/context.d.ts.map +1 -1
  17. package/build/lib/commands/context.js +6 -6
  18. package/build/lib/commands/context.js.map +1 -1
  19. package/build/lib/commands/file-movement.d.ts.map +1 -1
  20. package/build/lib/commands/file-movement.js +7 -7
  21. package/build/lib/commands/file-movement.js.map +1 -1
  22. package/build/lib/commands/general.js +1 -1
  23. package/build/lib/commands/general.js.map +1 -1
  24. package/build/lib/commands/gesture.js +1 -1
  25. package/build/lib/commands/gesture.js.map +1 -1
  26. package/build/lib/commands/keychains.js +1 -1
  27. package/build/lib/commands/keychains.js.map +1 -1
  28. package/build/lib/commands/localization.js +1 -1
  29. package/build/lib/commands/localization.js.map +1 -1
  30. package/build/lib/commands/location.js +1 -1
  31. package/build/lib/commands/location.js.map +1 -1
  32. package/build/lib/commands/log.js +7 -7
  33. package/build/lib/commands/log.js.map +1 -1
  34. package/build/lib/commands/memory.js +1 -1
  35. package/build/lib/commands/memory.js.map +1 -1
  36. package/build/lib/commands/notifications.js +1 -1
  37. package/build/lib/commands/notifications.js.map +1 -1
  38. package/build/lib/commands/pasteboard.js +2 -2
  39. package/build/lib/commands/pasteboard.js.map +1 -1
  40. package/build/lib/commands/pcap.js +1 -1
  41. package/build/lib/commands/pcap.js.map +1 -1
  42. package/build/lib/commands/performance.d.ts.map +1 -1
  43. package/build/lib/commands/performance.js +13 -4
  44. package/build/lib/commands/performance.js.map +1 -1
  45. package/build/lib/commands/permissions.js +2 -2
  46. package/build/lib/commands/permissions.js.map +1 -1
  47. package/build/lib/commands/proxy-helper.d.ts.map +1 -1
  48. package/build/lib/commands/proxy-helper.js +0 -3
  49. package/build/lib/commands/proxy-helper.js.map +1 -1
  50. package/build/lib/commands/screenshots.js +1 -1
  51. package/build/lib/commands/screenshots.js.map +1 -1
  52. package/build/lib/commands/simctl.d.ts +1 -1
  53. package/build/lib/commands/simctl.d.ts.map +1 -1
  54. package/build/lib/commands/simctl.js +1 -1
  55. package/build/lib/commands/simctl.js.map +1 -1
  56. package/build/lib/commands/web.js +1 -1
  57. package/build/lib/commands/web.js.map +1 -1
  58. package/build/lib/commands/xctest-record-screen.js +2 -2
  59. package/build/lib/commands/xctest-record-screen.js.map +1 -1
  60. package/build/lib/desired-caps.d.ts +383 -507
  61. package/build/lib/desired-caps.d.ts.map +1 -1
  62. package/build/lib/desired-caps.js +6 -10
  63. package/build/lib/desired-caps.js.map +1 -1
  64. package/build/lib/device/clients/base-device-client.d.ts.map +1 -0
  65. package/build/lib/device/clients/base-device-client.js.map +1 -0
  66. package/build/lib/{real-device-clients → device/clients}/py-ios-device-client.d.ts +1 -1
  67. package/build/lib/device/clients/py-ios-device-client.d.ts.map +1 -0
  68. package/build/lib/device/clients/py-ios-device-client.js.map +1 -0
  69. package/build/lib/device/device-connections-factory.d.ts +18 -0
  70. package/build/lib/device/device-connections-factory.d.ts.map +1 -0
  71. package/build/lib/{device-connections-factory.js → device/device-connections-factory.js} +57 -41
  72. package/build/lib/device/device-connections-factory.js.map +1 -0
  73. package/build/lib/{device-log → device/log}/helpers.d.ts +1 -1
  74. package/build/lib/device/log/helpers.d.ts.map +1 -0
  75. package/build/lib/device/log/helpers.js.map +1 -0
  76. package/build/lib/{device-log → device/log}/ios-crash-log.d.ts +1 -1
  77. package/build/lib/device/log/ios-crash-log.d.ts.map +1 -0
  78. package/build/lib/{device-log → device/log}/ios-crash-log.js +1 -1
  79. package/build/lib/device/log/ios-crash-log.js.map +1 -0
  80. package/build/lib/device/log/ios-device-log.d.ts.map +1 -0
  81. package/build/lib/device/log/ios-device-log.js.map +1 -0
  82. package/build/lib/{device-log → device/log}/ios-log.d.ts +1 -1
  83. package/build/lib/device/log/ios-log.d.ts.map +1 -0
  84. package/build/lib/device/log/ios-log.js.map +1 -0
  85. package/build/lib/device/log/ios-performance-log.d.ts.map +1 -0
  86. package/build/lib/device/log/ios-performance-log.js.map +1 -0
  87. package/build/lib/device/log/ios-simulator-log.d.ts.map +1 -0
  88. package/build/lib/device/log/ios-simulator-log.js.map +1 -0
  89. package/build/lib/{device-log → device/log}/line-consuming-log.d.ts +1 -1
  90. package/build/lib/device/log/line-consuming-log.d.ts.map +1 -0
  91. package/build/lib/device/log/line-consuming-log.js.map +1 -0
  92. package/build/lib/{device-log → device/log}/safari-console-log.d.ts +1 -1
  93. package/build/lib/device/log/safari-console-log.d.ts.map +1 -0
  94. package/build/lib/device/log/safari-console-log.js.map +1 -0
  95. package/build/lib/device/log/safari-network-log.d.ts.map +1 -0
  96. package/build/lib/device/log/safari-network-log.js.map +1 -0
  97. package/build/lib/device/real-device-management.d.ts +146 -0
  98. package/build/lib/device/real-device-management.d.ts.map +1 -0
  99. package/build/lib/device/real-device-management.js +728 -0
  100. package/build/lib/device/real-device-management.js.map +1 -0
  101. package/build/lib/device/simulator-management.d.ts +65 -0
  102. package/build/lib/device/simulator-management.d.ts.map +1 -0
  103. package/build/lib/{simulator-management.js → device/simulator-management.js} +24 -43
  104. package/build/lib/device/simulator-management.js.map +1 -0
  105. package/build/lib/driver.d.ts +129 -1385
  106. package/build/lib/driver.d.ts.map +1 -1
  107. package/build/lib/driver.js +476 -600
  108. package/build/lib/driver.js.map +1 -1
  109. package/build/lib/method-map.d.ts +1 -1
  110. package/build/lib/method-map.d.ts.map +1 -1
  111. package/build/lib/method-map.js +2 -2
  112. package/build/lib/method-map.js.map +1 -1
  113. package/lib/app-utils.js +5 -1
  114. package/lib/commands/app-management.js +2 -2
  115. package/lib/commands/appearance.js +2 -2
  116. package/lib/commands/biometric.js +3 -3
  117. package/lib/commands/certificate.js +9 -3
  118. package/lib/commands/context.js +6 -6
  119. package/lib/commands/file-movement.js +11 -7
  120. package/lib/commands/general.js +1 -1
  121. package/lib/commands/gesture.js +1 -1
  122. package/lib/commands/keychains.js +1 -1
  123. package/lib/commands/localization.js +1 -1
  124. package/lib/commands/location.js +1 -1
  125. package/lib/commands/log.js +7 -7
  126. package/lib/commands/memory.js +1 -1
  127. package/lib/commands/notifications.js +1 -1
  128. package/lib/commands/pasteboard.js +2 -2
  129. package/lib/commands/pcap.js +1 -1
  130. package/lib/commands/performance.js +12 -1
  131. package/lib/commands/permissions.js +2 -2
  132. package/lib/commands/proxy-helper.js +0 -3
  133. package/lib/commands/screenshots.js +1 -1
  134. package/lib/commands/simctl.js +1 -1
  135. package/lib/commands/web.js +1 -1
  136. package/lib/commands/xctest-record-screen.js +2 -2
  137. package/lib/{desired-caps.js → desired-caps.ts} +7 -6
  138. package/lib/{real-device-clients → device/clients}/py-ios-device-client.ts +1 -1
  139. package/lib/{device-connections-factory.js → device/device-connections-factory.ts} +96 -60
  140. package/lib/{device-log → device/log}/helpers.ts +1 -1
  141. package/lib/{device-log → device/log}/ios-crash-log.ts +3 -3
  142. package/lib/{device-log → device/log}/ios-log.ts +1 -1
  143. package/lib/{device-log → device/log}/line-consuming-log.ts +1 -1
  144. package/lib/{device-log → device/log}/safari-console-log.ts +1 -1
  145. package/lib/device/real-device-management.ts +819 -0
  146. package/lib/{simulator-management.js → device/simulator-management.ts} +69 -62
  147. package/lib/{driver.js → driver.ts} +619 -713
  148. package/lib/{method-map.js → method-map.ts} +5 -2
  149. package/npm-shrinkwrap.json +5 -5
  150. package/package.json +1 -1
  151. package/build/lib/device-connections-factory.d.ts +0 -13
  152. package/build/lib/device-connections-factory.d.ts.map +0 -1
  153. package/build/lib/device-connections-factory.js.map +0 -1
  154. package/build/lib/device-log/helpers.d.ts.map +0 -1
  155. package/build/lib/device-log/helpers.js.map +0 -1
  156. package/build/lib/device-log/ios-crash-log.d.ts.map +0 -1
  157. package/build/lib/device-log/ios-crash-log.js.map +0 -1
  158. package/build/lib/device-log/ios-device-log.d.ts.map +0 -1
  159. package/build/lib/device-log/ios-device-log.js.map +0 -1
  160. package/build/lib/device-log/ios-log.d.ts.map +0 -1
  161. package/build/lib/device-log/ios-log.js.map +0 -1
  162. package/build/lib/device-log/ios-performance-log.d.ts.map +0 -1
  163. package/build/lib/device-log/ios-performance-log.js.map +0 -1
  164. package/build/lib/device-log/ios-simulator-log.d.ts.map +0 -1
  165. package/build/lib/device-log/ios-simulator-log.js.map +0 -1
  166. package/build/lib/device-log/line-consuming-log.d.ts.map +0 -1
  167. package/build/lib/device-log/line-consuming-log.js.map +0 -1
  168. package/build/lib/device-log/safari-console-log.d.ts.map +0 -1
  169. package/build/lib/device-log/safari-console-log.js.map +0 -1
  170. package/build/lib/device-log/safari-network-log.d.ts.map +0 -1
  171. package/build/lib/device-log/safari-network-log.js.map +0 -1
  172. package/build/lib/ios-fs-helpers.d.ts +0 -75
  173. package/build/lib/ios-fs-helpers.d.ts.map +0 -1
  174. package/build/lib/ios-fs-helpers.js +0 -370
  175. package/build/lib/ios-fs-helpers.js.map +0 -1
  176. package/build/lib/real-device-clients/base-device-client.d.ts.map +0 -1
  177. package/build/lib/real-device-clients/base-device-client.js.map +0 -1
  178. package/build/lib/real-device-clients/py-ios-device-client.d.ts.map +0 -1
  179. package/build/lib/real-device-clients/py-ios-device-client.js.map +0 -1
  180. package/build/lib/real-device-management.d.ts +0 -53
  181. package/build/lib/real-device-management.d.ts.map +0 -1
  182. package/build/lib/real-device-management.js +0 -128
  183. package/build/lib/real-device-management.js.map +0 -1
  184. package/build/lib/real-device.d.ts +0 -112
  185. package/build/lib/real-device.d.ts.map +0 -1
  186. package/build/lib/real-device.js +0 -352
  187. package/build/lib/real-device.js.map +0 -1
  188. package/build/lib/simulator-management.d.ts +0 -96
  189. package/build/lib/simulator-management.d.ts.map +0 -1
  190. package/build/lib/simulator-management.js.map +0 -1
  191. package/build/lib/xcrun.d.ts +0 -3
  192. package/build/lib/xcrun.d.ts.map +0 -1
  193. package/build/lib/xcrun.js +0 -17
  194. package/build/lib/xcrun.js.map +0 -1
  195. package/lib/ios-fs-helpers.js +0 -355
  196. package/lib/real-device-management.js +0 -133
  197. package/lib/real-device.js +0 -347
  198. package/lib/xcrun.js +0 -16
  199. /package/build/lib/{real-device-clients → device/clients}/base-device-client.d.ts +0 -0
  200. /package/build/lib/{real-device-clients → device/clients}/base-device-client.js +0 -0
  201. /package/build/lib/{real-device-clients → device/clients}/py-ios-device-client.js +0 -0
  202. /package/build/lib/{device-log → device/log}/helpers.js +0 -0
  203. /package/build/lib/{device-log → device/log}/ios-device-log.d.ts +0 -0
  204. /package/build/lib/{device-log → device/log}/ios-device-log.js +0 -0
  205. /package/build/lib/{device-log → device/log}/ios-log.js +0 -0
  206. /package/build/lib/{device-log → device/log}/ios-performance-log.d.ts +0 -0
  207. /package/build/lib/{device-log → device/log}/ios-performance-log.js +0 -0
  208. /package/build/lib/{device-log → device/log}/ios-simulator-log.d.ts +0 -0
  209. /package/build/lib/{device-log → device/log}/ios-simulator-log.js +0 -0
  210. /package/build/lib/{device-log → device/log}/line-consuming-log.js +0 -0
  211. /package/build/lib/{device-log → device/log}/safari-console-log.js +0 -0
  212. /package/build/lib/{device-log → device/log}/safari-network-log.d.ts +0 -0
  213. /package/build/lib/{device-log → device/log}/safari-network-log.js +0 -0
  214. /package/lib/{real-device-clients → device/clients}/base-device-client.ts +0 -0
  215. /package/lib/{device-log → device/log}/ios-device-log.ts +0 -0
  216. /package/lib/{device-log → device/log}/ios-performance-log.ts +0 -0
  217. /package/lib/{device-log → device/log}/ios-simulator-log.ts +0 -0
  218. /package/lib/{device-log → device/log}/safari-network-log.ts +0 -0
@@ -98,13 +98,12 @@ const xctestCommands = __importStar(require("./commands/xctest"));
98
98
  const xctestRecordScreenCommands = __importStar(require("./commands/xctest-record-screen"));
99
99
  const increaseContrastCommands = __importStar(require("./commands/increase-contrast"));
100
100
  const desired_caps_1 = require("./desired-caps");
101
- const device_connections_factory_1 = require("./device-connections-factory");
101
+ const device_connections_factory_1 = require("./device/device-connections-factory");
102
102
  const execute_method_map_1 = require("./execute-method-map");
103
103
  const method_map_1 = require("./method-map");
104
- const py_ios_device_client_1 = require("./real-device-clients/py-ios-device-client");
105
- const real_device_management_1 = require("./real-device-management");
106
- const real_device_1 = require("./real-device");
107
- const simulator_management_1 = require("./simulator-management");
104
+ const py_ios_device_client_1 = require("./device/clients/py-ios-device-client");
105
+ const real_device_management_1 = require("./device/real-device-management");
106
+ const simulator_management_1 = require("./device/simulator-management");
108
107
  const utils_1 = require("./utils");
109
108
  const app_infos_cache_1 = require("./app-infos-cache");
110
109
  const context_1 = require("./commands/context");
@@ -147,7 +146,6 @@ const WEB_ELEMENTS_CACHE_SIZE = 500;
147
146
  const SUPPORTED_ORIENATIONS = ['LANDSCAPE', 'PORTRAIT'];
148
147
  const DEFAULT_MJPEG_SERVER_PORT = 9100;
149
148
  /* eslint-disable no-useless-escape */
150
- /** @type {import('@appium/types').RouteMatcher[]} */
151
149
  const NO_PROXY_NATIVE_LIST = [
152
150
  ['DELETE', /window/],
153
151
  ['GET', /^\/session\/[^\/]+$/],
@@ -194,7 +192,7 @@ const NO_PROXY_NATIVE_LIST = [
194
192
  ['GET', /cookie/],
195
193
  ['POST', /cookie/],
196
194
  ];
197
- const NO_PROXY_WEB_LIST = /** @type {import('@appium/types').RouteMatcher[]} */ ([
195
+ const NO_PROXY_WEB_LIST = [
198
196
  ['GET', /attribute/],
199
197
  ['GET', /element/],
200
198
  ['GET', /text/],
@@ -206,89 +204,55 @@ const NO_PROXY_WEB_LIST = /** @type {import('@appium/types').RouteMatcher[]} */
206
204
  ['POST', /frame/],
207
205
  ['POST', /keys/],
208
206
  ['POST', /refresh/],
209
- ]).concat(NO_PROXY_NATIVE_LIST);
207
+ ...NO_PROXY_NATIVE_LIST,
208
+ ];
210
209
  /* eslint-enable no-useless-escape */
211
210
  const MEMOIZED_FUNCTIONS = ['getStatusBarHeight', 'getDevicePixelRatio', 'getScreenInfo'];
212
211
  // Capabilities that do not have xcodebuild process
213
212
  const CAP_NAMES_NO_XCODEBUILD_REQUIRED = ['webDriverAgentUrl', 'usePreinstalledWDA'];
214
213
  const BUNDLE_VERSION_PATTERN = /CFBundleVersion\s+=\s+"?([^(;|")]+)/;
215
- /**
216
- * @implements {ExternalDriver<XCUITestDriverConstraints, FullContext|string>}
217
- * @extends {BaseDriver<XCUITestDriverConstraints>}
218
- * @privateRemarks **This class should be considered "final"**. It cannot be extended
219
- * due to use of public class field assignments. If extending this class becomes a hard requirement, refer to the implementation of `BaseDriver` on how to do so.
220
- */
221
214
  class XCUITestDriver extends driver_1.BaseDriver {
222
215
  static newMethodMap = method_map_1.newMethodMap;
223
216
  static executeMethodMap = execute_method_map_1.executeMethodMap;
224
- /** @type {string|null|undefined} */
225
217
  curWindowHandle;
226
- /**
227
- * @type {boolean|undefined}
228
- */
229
218
  selectingNewPage;
230
- /** @type {string[]} */
231
219
  contexts;
232
- /** @type {string|null} */
233
220
  curContext;
234
- /** @type {string[]} */
235
221
  curWebFrames;
236
- /** @type {import('./types').CalibrationData|null} */
237
222
  webviewCalibrationResult;
238
- /** @type {import('./types').AsyncPromise|undefined} */
239
223
  asyncPromise;
240
- /** @type {number|undefined} */
241
224
  asyncWaitMs;
242
- /** @type {((logRecord: {message: string}) => void)|null} */
243
225
  _syslogWebsocketListener;
244
- /** @type {import('./commands/performance').PerfRecorder[]} */
245
226
  _perfRecorders;
246
- /** @type {LRUCache} */
247
227
  webElementsCache;
248
- /**
249
- * @type {any|null}
250
- * @privateRemarks needs types
251
- **/
252
- _conditionInducerService;
253
- /**
254
- * @type {import('./commands/condition.js').DVTServiceWithConnection|null}
255
- * @privateRemarks RemoteXPC DVT connection for iOS>=18 condition inducer
256
- **/
257
- _remoteXPCConditionInducerConnection;
258
- /** @type {boolean|undefined} */
228
+ _conditionInducerService; // needs types
229
+ _remoteXPCConditionInducerConnection; // RemoteXPC DVT connection for iOS>=18 condition inducer
259
230
  _isSafariIphone;
260
- /** @type {boolean|undefined} */
261
231
  _isSafariNotched;
262
- /** @type {import('./commands/types').WaitingAtoms} */
263
232
  _waitingAtoms;
264
- /** @type {import('./types').LifecycleData} */
265
233
  lifecycleData;
266
- /** @type {import('./commands/record-audio').AudioRecorder|null} */
267
234
  _audioRecorder;
268
- /** @type {XcodeVersion|undefined} */
269
235
  xcodeVersion;
270
- /** @type {import('./commands/pcap').TrafficCapture|null} */
271
236
  _trafficCapture;
272
- /** @type {import('./commands/recordscreen').ScreenRecorder|null} */
273
237
  _recentScreenRecorder;
274
- /** @type {Simulator|RealDevice} */
275
238
  _device;
276
- /** @type {string|null} */
277
239
  _iosSdkVersion;
278
- /** @type {WebDriverAgent} */
279
- wda;
280
- /** @type {import('appium-remote-debugger').RemoteDebugger|null} */
240
+ _wda;
281
241
  remote;
282
- /** @type {DriverLogs} */
283
242
  logs;
284
- /** @type {import('./commands/types').LogListener|undefined} */
285
243
  _bidiServerLogListener;
286
- /**
287
- *
288
- * @param {XCUITestDriverOpts} opts
289
- * @param {boolean} shouldValidateCaps
290
- */
291
- constructor(opts = /** @type {XCUITestDriverOpts} */ ({}), shouldValidateCaps = true) {
244
+ // Additional properties that were missing
245
+ appInfosCache;
246
+ doesSupportBidi;
247
+ jwpProxyActive;
248
+ proxyReqRes;
249
+ safari;
250
+ cachedWdaStatus;
251
+ _currentUrl;
252
+ pageLoadMs;
253
+ landscapeWebCoordsOffset;
254
+ mjpegStream;
255
+ constructor(opts, shouldValidateCaps = true) {
292
256
  super(opts, shouldValidateCaps);
293
257
  this.locatorStrategies = [
294
258
  'xpath',
@@ -332,7 +296,295 @@ class XCUITestDriver extends driver_1.BaseDriver {
332
296
  this.appInfosCache = new app_infos_cache_1.AppInfosCache(this.log);
333
297
  this.remote = null;
334
298
  this.doesSupportBidi = true;
299
+ this._wda = null;
300
+ }
301
+ // Override methods from BaseDriver
302
+ async createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData) {
303
+ try {
304
+ const [sessionId, initialCaps] = await super.createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData);
305
+ let caps = initialCaps;
306
+ // merge cli args to opts, and if we did merge any, revalidate opts to ensure the final set
307
+ // is also consistent
308
+ if (this.mergeCliArgsToOpts()) {
309
+ this.validateDesiredCaps({ ...caps, ...this.cliArgs });
310
+ }
311
+ await this.start();
312
+ // merge server capabilities + desired capabilities
313
+ caps = { ...defaultServerCaps, ...caps };
314
+ // update the udid with what is actually used
315
+ caps.udid = this.opts.udid;
316
+ // ensure we track nativeWebTap capability as a setting as well
317
+ if (lodash_1.default.has(this.opts, 'nativeWebTap')) {
318
+ await this.updateSettings({ nativeWebTap: this.opts.nativeWebTap });
319
+ }
320
+ // ensure we track nativeWebTapStrict capability as a setting as well
321
+ if (lodash_1.default.has(this.opts, 'nativeWebTapStrict')) {
322
+ await this.updateSettings({ nativeWebTapStrict: this.opts.nativeWebTapStrict });
323
+ }
324
+ // ensure we track useJSONSource capability as a setting as well
325
+ if (lodash_1.default.has(this.opts, 'useJSONSource')) {
326
+ await this.updateSettings({ useJSONSource: this.opts.useJSONSource });
327
+ }
328
+ const wdaSettings = {
329
+ elementResponseAttributes: DEFAULT_SETTINGS.elementResponseAttributes,
330
+ shouldUseCompactResponses: DEFAULT_SETTINGS.shouldUseCompactResponses,
331
+ };
332
+ if ('elementResponseAttributes' in this.opts && lodash_1.default.isString(this.opts.elementResponseAttributes)) {
333
+ wdaSettings.elementResponseAttributes = this.opts.elementResponseAttributes;
334
+ }
335
+ if ('shouldUseCompactResponses' in this.opts && lodash_1.default.isBoolean(this.opts.shouldUseCompactResponses)) {
336
+ wdaSettings.shouldUseCompactResponses = this.opts.shouldUseCompactResponses;
337
+ }
338
+ if ('mjpegServerScreenshotQuality' in this.opts && lodash_1.default.isNumber(this.opts.mjpegServerScreenshotQuality)) {
339
+ wdaSettings.mjpegServerScreenshotQuality = this.opts.mjpegServerScreenshotQuality;
340
+ }
341
+ if ('mjpegServerFramerate' in this.opts && lodash_1.default.isNumber(this.opts.mjpegServerFramerate)) {
342
+ wdaSettings.mjpegServerFramerate = this.opts.mjpegServerFramerate;
343
+ }
344
+ if (lodash_1.default.has(this.opts, 'screenshotQuality')) {
345
+ this.log.info(`Setting the quality of phone screenshot: '${this.opts.screenshotQuality}'`);
346
+ wdaSettings.screenshotQuality = this.opts.screenshotQuality;
347
+ }
348
+ // ensure WDA gets our defaults instead of whatever its own might be
349
+ await this.updateSettings(wdaSettings);
350
+ await this.handleMjpegOptions();
351
+ return [
352
+ sessionId,
353
+ caps,
354
+ ];
355
+ }
356
+ catch (e) {
357
+ this.log.error(JSON.stringify(e));
358
+ await this.deleteSession();
359
+ throw e;
360
+ }
361
+ }
362
+ async deleteSession(sessionId) {
363
+ await utils_1.removeAllSessionWebSocketHandlers.bind(this)();
364
+ for (const recorder of lodash_1.default.compact([
365
+ this._recentScreenRecorder,
366
+ this._audioRecorder,
367
+ this._trafficCapture,
368
+ ])) {
369
+ await recorder.interrupt(true);
370
+ await recorder.cleanup();
371
+ }
372
+ if (!lodash_1.default.isEmpty(this._perfRecorders)) {
373
+ await bluebird_1.default.all(this._perfRecorders.map((x) => x.stop(true)));
374
+ this._perfRecorders = [];
375
+ }
376
+ if (this._conditionInducerService || this._remoteXPCConditionInducerConnection) {
377
+ try {
378
+ await this.disableConditionInducer();
379
+ }
380
+ catch (err) {
381
+ this.log.warn(`Cannot disable condition inducer: ${err.message}`);
382
+ }
383
+ }
384
+ await this.stop();
385
+ if (this._wda && this.isXcodebuildNeeded()) {
386
+ if (this.opts.clearSystemFiles) {
387
+ let synchronizationKey = XCUITestDriver.name;
388
+ const derivedDataPath = await this.wda.retrieveDerivedDataPath();
389
+ if (derivedDataPath) {
390
+ synchronizationKey = node_path_1.default.normalize(derivedDataPath);
391
+ }
392
+ await SHARED_RESOURCES_GUARD.acquire(synchronizationKey, async () => {
393
+ await (0, utils_1.clearSystemFiles)(this.wda);
394
+ });
395
+ }
396
+ else {
397
+ this.log.debug('Not clearing log files. Use `clearSystemFiles` capability to turn on.');
398
+ }
399
+ }
400
+ if (this.remote) {
401
+ this.log.debug('Found a remote debugger session. Removing...');
402
+ await this.stopRemote();
403
+ }
404
+ if (this.opts.resetOnSessionStartOnly === false) {
405
+ await this.runReset(true);
406
+ }
407
+ const simulatorDevice = this.isSimulator() ? this.device : null;
408
+ if (simulatorDevice && this.lifecycleData.createSim) {
409
+ this.log.debug(`Deleting simulator created for this run (udid: '${simulatorDevice.udid}')`);
410
+ await simulator_management_1.shutdownSimulator.bind(this)();
411
+ await simulatorDevice.delete();
412
+ }
413
+ const shouldResetLocationService = this.isRealDevice() && !!this.opts.resetLocationService;
414
+ if (shouldResetLocationService) {
415
+ try {
416
+ await this.mobileResetLocationService();
417
+ }
418
+ catch {
419
+ /* Ignore this error since mobileResetLocationService already logged the error */
420
+ }
421
+ }
422
+ await this.logs.syslog?.stopCapture();
423
+ lodash_1.default.values(this.logs).forEach((x) => x?.removeAllListeners?.());
424
+ if (this._bidiServerLogListener) {
425
+ this.log.unwrap().off('log', this._bidiServerLogListener);
426
+ }
427
+ this.logs = {};
428
+ if (this.mjpegStream) {
429
+ this.log.info('Closing MJPEG stream');
430
+ this.mjpegStream.stop();
431
+ }
432
+ this.resetIos();
433
+ await super.deleteSession(sessionId);
434
+ }
435
+ async executeCommand(cmd, ...args) {
436
+ this.log.debug(`Executing command '${cmd}'`);
437
+ if (cmd === 'receiveAsyncResponse') {
438
+ return await this.receiveAsyncResponse(...args);
439
+ }
440
+ // TODO: once this fix gets into base driver remove from here
441
+ if (cmd === 'getStatus') {
442
+ return await this.getStatus();
443
+ }
444
+ return await super.executeCommand(cmd, ...args);
445
+ }
446
+ proxyActive() {
447
+ return Boolean(this.jwpProxyActive);
448
+ }
449
+ getProxyAvoidList() {
450
+ if (this.isWebview()) {
451
+ return NO_PROXY_WEB_LIST;
452
+ }
453
+ return NO_PROXY_NATIVE_LIST;
454
+ }
455
+ canProxy() {
456
+ return true;
457
+ }
458
+ validateLocatorStrategy(strategy) {
459
+ super.validateLocatorStrategy(strategy, this.isWebContext());
335
460
  }
461
+ validateDesiredCaps(caps) {
462
+ if (!super.validateDesiredCaps(caps)) {
463
+ return false;
464
+ }
465
+ // make sure that the capabilities have one of `app` or `bundleId`
466
+ if (lodash_1.default.toLower(caps.browserName) !== 'safari' && !caps.app && !caps.bundleId) {
467
+ this.log.info('The desired capabilities include neither an app nor a bundleId. ' +
468
+ 'WebDriverAgent will be started without the default app');
469
+ }
470
+ if (!support_1.util.coerceVersion(String(caps.platformVersion), false)) {
471
+ this.log.warn(`'platformVersion' capability ('${caps.platformVersion}') is not a valid version number. ` +
472
+ `Consider fixing it or be ready to experience an inconsistent driver behavior.`);
473
+ }
474
+ const verifyProcessArgument = (processArguments) => {
475
+ const { args, env } = processArguments;
476
+ if (!lodash_1.default.isNil(args) && !lodash_1.default.isArray(args)) {
477
+ throw this.log.errorWithException('processArguments.args must be an array of strings');
478
+ }
479
+ if (!lodash_1.default.isNil(env) && !lodash_1.default.isPlainObject(env)) {
480
+ throw this.log.errorWithException('processArguments.env must be an object <key,value> pair {a:b, c:d}');
481
+ }
482
+ };
483
+ // `processArguments` should be JSON string or an object with arguments and/ environment details
484
+ if (caps.processArguments) {
485
+ if (lodash_1.default.isString(caps.processArguments)) {
486
+ try {
487
+ // try to parse the string as JSON
488
+ caps.processArguments = JSON.parse(caps.processArguments);
489
+ verifyProcessArgument(caps.processArguments);
490
+ }
491
+ catch (err) {
492
+ throw this.log.errorWithException(`processArguments must be a JSON format or an object with format {args : [], env : {a:b, c:d}}. ` +
493
+ `Both environment and argument can be null. Error: ${err}`);
494
+ }
495
+ }
496
+ else if (lodash_1.default.isPlainObject(caps.processArguments)) {
497
+ verifyProcessArgument(caps.processArguments);
498
+ }
499
+ else {
500
+ throw this.log.errorWithException(`'processArguments must be an object, or a string JSON object with format {args : [], env : {a:b, c:d}}. ` +
501
+ `Both environment and argument can be null.`);
502
+ }
503
+ }
504
+ // there is no point in having `keychainPath` without `keychainPassword`
505
+ if ((caps.keychainPath && !caps.keychainPassword) ||
506
+ (!caps.keychainPath && caps.keychainPassword)) {
507
+ throw this.log.errorWithException(`If 'keychainPath' is set, 'keychainPassword' must also be set (and vice versa).`);
508
+ }
509
+ // `resetOnSessionStartOnly` should be set to true by default
510
+ this.opts.resetOnSessionStartOnly =
511
+ !support_1.util.hasValue(this.opts.resetOnSessionStartOnly) || this.opts.resetOnSessionStartOnly;
512
+ this.opts.useNewWDA = support_1.util.hasValue(this.opts.useNewWDA) ? this.opts.useNewWDA : false;
513
+ if (caps.commandTimeouts) {
514
+ caps.commandTimeouts = (0, utils_1.normalizeCommandTimeouts)(caps.commandTimeouts);
515
+ }
516
+ if (lodash_1.default.isString(caps.webDriverAgentUrl)) {
517
+ const { protocol, host } = node_url_1.default.parse(caps.webDriverAgentUrl);
518
+ if (lodash_1.default.isEmpty(protocol) || lodash_1.default.isEmpty(host)) {
519
+ throw this.log.errorWithException(`'webDriverAgentUrl' capability is expected to contain a valid WebDriverAgent server URL. ` +
520
+ `'${caps.webDriverAgentUrl}' is given instead`);
521
+ }
522
+ }
523
+ if (caps.browserName) {
524
+ if (caps.bundleId) {
525
+ throw this.log.errorWithException(`'browserName' cannot be set together with 'bundleId' capability`);
526
+ }
527
+ // warn if the capabilities have both `app` and `browser, although this
528
+ // is common with selenium grid
529
+ if (caps.app) {
530
+ this.log.warn(`The capabilities should generally not include both an 'app' and a 'browserName'`);
531
+ }
532
+ }
533
+ if (caps.permissions) {
534
+ try {
535
+ for (const [bundleId, perms] of lodash_1.default.toPairs(JSON.parse(caps.permissions))) {
536
+ if (!lodash_1.default.isString(bundleId)) {
537
+ throw new Error(`'${JSON.stringify(bundleId)}' must be a string`);
538
+ }
539
+ if (!lodash_1.default.isPlainObject(perms)) {
540
+ throw new Error(`'${JSON.stringify(perms)}' must be a JSON object`);
541
+ }
542
+ }
543
+ }
544
+ catch (e) {
545
+ throw this.log.errorWithException(`'${caps.permissions}' is expected to be a valid object with format ` +
546
+ `{"<bundleId1>": {"<serviceName1>": "<serviceStatus1>", ...}, ...}. Original error: ${e.message}`);
547
+ }
548
+ }
549
+ if (caps.platformVersion && !support_1.util.coerceVersion(caps.platformVersion, false)) {
550
+ throw this.log.errorWithException(`'platformVersion' must be a valid version number. ` +
551
+ `'${caps.platformVersion}' is given instead.`);
552
+ }
553
+ // additionalWebviewBundleIds is an array, JSON array, or string
554
+ if (caps.additionalWebviewBundleIds) {
555
+ caps.additionalWebviewBundleIds = this.helpers.parseCapsArray(caps.additionalWebviewBundleIds);
556
+ }
557
+ // finally, return true since the superclass check passed, as did this
558
+ return true;
559
+ }
560
+ // Getter methods
561
+ get wda() {
562
+ if (!this._wda) {
563
+ throw new Error('WebDriverAgent is not initialized');
564
+ }
565
+ return this._wda;
566
+ }
567
+ get driverData() {
568
+ // TODO fill out resource info here
569
+ return {};
570
+ }
571
+ get device() {
572
+ return this._device;
573
+ }
574
+ // Utility methods
575
+ isSafari() {
576
+ return !!this.safari;
577
+ }
578
+ isRealDevice() {
579
+ return 'devicectl' in (this.device ?? {});
580
+ }
581
+ isSimulator() {
582
+ return 'simctl' in (this.device ?? {});
583
+ }
584
+ isXcodebuildNeeded() {
585
+ return !(CAP_NAMES_NO_XCODEBUILD_REQUIRED.some((x) => Boolean(this.opts[x])));
586
+ }
587
+ // Core driver methods
336
588
  async onSettingsUpdate(key, value) {
337
589
  // skip sending the update request to the WDA nor saving it in opts
338
590
  // to not spend unnecessary time.
@@ -344,39 +596,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
344
596
  settings: { [key]: value },
345
597
  });
346
598
  }
347
- this.opts[key] = !!value;
348
- }
349
- resetIos() {
350
- this.opts = this.opts || {};
351
- // @ts-ignore this is ok
352
- this.wda = null;
353
- this.jwpProxyActive = false;
354
- this.proxyReqRes = null;
355
- this.safari = false;
356
- this.cachedWdaStatus = null;
357
- this.curWebFrames = [];
358
- this._currentUrl = null;
359
- this.curContext = null;
360
- this.xcodeVersion = undefined;
361
- this.contexts = [];
362
- this.implicitWaitMs = 0;
363
- this.pageLoadMs = 6000;
364
- this.landscapeWebCoordsOffset = 0;
365
- this.remote = null;
366
- this._conditionInducerService = null;
367
- this._remoteXPCConditionInducerConnection = null;
368
- this.webElementsCache = new lru_cache_1.LRUCache({
369
- max: WEB_ELEMENTS_CACHE_SIZE,
370
- });
371
- this._waitingAtoms = {
372
- count: 0,
373
- alertNotifier: new node_events_1.default(),
374
- alertMonitor: bluebird_1.default.resolve(),
375
- };
376
- }
377
- get driverData() {
378
- // TODO fill out resource info here
379
- return {};
599
+ this.opts[key] = !!value;
380
600
  }
381
601
  async getStatus() {
382
602
  const status = {
@@ -401,79 +621,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
401
621
  }
402
622
  return didMerge;
403
623
  }
404
- /**
405
- * @returns {Simulator|RealDevice}
406
- */
407
- get device() {
408
- return this._device;
409
- }
410
- isXcodebuildNeeded() {
411
- return !(CAP_NAMES_NO_XCODEBUILD_REQUIRED.some((x) => Boolean(this.opts[x])));
412
- }
413
- async createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData) {
414
- try {
415
- let [sessionId, caps] = await super.createSession(w3cCaps1, w3cCaps2, w3cCaps3, driverData);
416
- // merge cli args to opts, and if we did merge any, revalidate opts to ensure the final set
417
- // is also consistent
418
- if (this.mergeCliArgsToOpts()) {
419
- this.validateDesiredCaps({ ...caps, ...this.cliArgs });
420
- }
421
- await this.start();
422
- // merge server capabilities + desired capabilities
423
- caps = { ...defaultServerCaps, ...caps };
424
- // update the udid with what is actually used
425
- caps.udid = this.opts.udid;
426
- // ensure we track nativeWebTap capability as a setting as well
427
- if (lodash_1.default.has(this.opts, 'nativeWebTap')) {
428
- await this.updateSettings({ nativeWebTap: this.opts.nativeWebTap });
429
- }
430
- // ensure we track nativeWebTapStrict capability as a setting as well
431
- if (lodash_1.default.has(this.opts, 'nativeWebTapStrict')) {
432
- await this.updateSettings({ nativeWebTapStrict: this.opts.nativeWebTapStrict });
433
- }
434
- // ensure we track useJSONSource capability as a setting as well
435
- if (lodash_1.default.has(this.opts, 'useJSONSource')) {
436
- await this.updateSettings({ useJSONSource: this.opts.useJSONSource });
437
- }
438
- /** @type {import('appium-webdriveragent').WDASettings} */
439
- let wdaSettings = {
440
- elementResponseAttributes: DEFAULT_SETTINGS.elementResponseAttributes,
441
- shouldUseCompactResponses: DEFAULT_SETTINGS.shouldUseCompactResponses,
442
- };
443
- if ('elementResponseAttributes' in this.opts && lodash_1.default.isString(this.opts.elementResponseAttributes)) {
444
- wdaSettings.elementResponseAttributes = this.opts.elementResponseAttributes;
445
- }
446
- if ('shouldUseCompactResponses' in this.opts && lodash_1.default.isBoolean(this.opts.shouldUseCompactResponses)) {
447
- wdaSettings.shouldUseCompactResponses = this.opts.shouldUseCompactResponses;
448
- }
449
- if ('mjpegServerScreenshotQuality' in this.opts && lodash_1.default.isNumber(this.opts.mjpegServerScreenshotQuality)) {
450
- wdaSettings.mjpegServerScreenshotQuality = this.opts.mjpegServerScreenshotQuality;
451
- }
452
- if ('mjpegServerFramerate' in this.opts && lodash_1.default.isNumber(this.opts.mjpegServerFramerate)) {
453
- wdaSettings.mjpegServerFramerate = this.opts.mjpegServerFramerate;
454
- }
455
- if (lodash_1.default.has(this.opts, 'screenshotQuality')) {
456
- this.log.info(`Setting the quality of phone screenshot: '${this.opts.screenshotQuality}'`);
457
- wdaSettings.screenshotQuality = this.opts.screenshotQuality;
458
- }
459
- // ensure WDA gets our defaults instead of whatever its own might be
460
- await this.updateSettings(wdaSettings);
461
- await this.handleMjpegOptions();
462
- return /** @type {[string, import('@appium/types').DriverCaps<XCUITestDriverConstraints>]} */ ([
463
- sessionId,
464
- caps,
465
- ]);
466
- }
467
- catch (e) {
468
- this.log.error(JSON.stringify(e));
469
- await this.deleteSession();
470
- throw e;
471
- }
472
- }
473
- /**
474
- * Handles MJPEG server-related capabilities
475
- * @returns {Promise<void>}
476
- */
477
624
  async handleMjpegOptions() {
478
625
  await this.allocateMjpegServerPort();
479
626
  // turn on mjpeg stream reading if requested
@@ -483,11 +630,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
483
630
  await this.mjpegStream.start();
484
631
  }
485
632
  }
486
- /**
487
- * Allocates and configures port forwarding for the MJPEG server
488
- * @returns {Promise<void>}
489
- * @throws {Error} If port forwarding fails and mjpegServerPort capability value is provided explicitly
490
- */
491
633
  async allocateMjpegServerPort() {
492
634
  const mjpegServerPort = this.opts.mjpegServerPort || DEFAULT_MJPEG_SERVER_PORT;
493
635
  this.log.debug(`Forwarding MJPEG server port ${mjpegServerPort} to local port ${mjpegServerPort}`);
@@ -511,10 +653,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
511
653
  }
512
654
  }
513
655
  }
514
- /**
515
- * Returns the default URL for Safari browser
516
- * @returns {string} The default URL
517
- */
518
656
  getDefaultUrl() {
519
657
  // Setting this to some external URL slows down the session init
520
658
  return `${this.getWdaLocalhostRoot()}/health`;
@@ -534,7 +672,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
534
672
  }
535
673
  else {
536
674
  this.log.info(`Setting simulator devices set path to '${this.opts.simulatorDevicesSetPath}'`);
537
- ( /** @type {Simulator} */(this.device)).devicesSetPath = this.opts.simulatorDevicesSetPath;
675
+ this.device.devicesSetPath = this.opts.simulatorDevicesSetPath;
538
676
  }
539
677
  }
540
678
  // at this point if there is no platformVersion, get it from the device
@@ -575,21 +713,26 @@ class XCUITestDriver extends driver_1.BaseDriver {
575
713
  }
576
714
  }
577
715
  await this.runReset();
578
- this.wda = new appium_webdriveragent_1.WebDriverAgent(
579
- /** @type {import('appium-xcode').XcodeVersion} */ (this.xcodeVersion), {
716
+ this._wda = new appium_webdriveragent_1.WebDriverAgent(
717
+ // @ts-ignore This property is not used by WDA, and will be removed in the future
718
+ this.xcodeVersion, {
580
719
  ...this.opts,
581
720
  device: this.device,
582
721
  realDevice: this.isRealDevice(),
583
722
  iosSdkVersion: this._iosSdkVersion ?? undefined,
584
723
  reqBasePath: this.basePath,
585
- },
586
- // @ts-ignore this is ok
587
- this.log);
724
+ }, this.log);
588
725
  // Derived data path retrieval is an expensive operation
589
726
  // We could start that now in background and get the cached result
590
727
  // whenever it is needed
591
- // eslint-disable-next-line promise/prefer-await-to-then
592
- this.wda.retrieveDerivedDataPath().catch((e) => this.log.debug(e));
728
+ (async () => {
729
+ try {
730
+ await this.wda.retrieveDerivedDataPath();
731
+ }
732
+ catch (e) {
733
+ this.log.debug(e);
734
+ }
735
+ })();
593
736
  const memoizedLogInfo = lodash_1.default.memoize(() => {
594
737
  this.log.info("'skipLogCapture' is set. Skipping starting logs such as crash, system, safari console and safari network.");
595
738
  });
@@ -632,7 +775,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
632
775
  if (this.opts.permissions) {
633
776
  this.log.debug('Setting the requested permissions before WDA is started');
634
777
  for (const [bundleId, permissionsMapping] of lodash_1.default.toPairs(JSON.parse(this.opts.permissions))) {
635
- await /** @type {Simulator} */ (this.device).setPermissions(bundleId, permissionsMapping);
778
+ await this.device.setPermissions(bundleId, permissionsMapping);
636
779
  }
637
780
  }
638
781
  // TODO: Deprecate and remove this block together with calendarAccessAuthorized capability
@@ -671,11 +814,40 @@ class XCUITestDriver extends driver_1.BaseDriver {
671
814
  }
672
815
  }
673
816
  }
674
- /**
675
- * Start the simulator and initialize based on capabilities
676
- */
817
+ async runReset(enforceSimulatorShutdown = false) {
818
+ this.logEvent('resetStarted');
819
+ if (this.isRealDevice()) {
820
+ await real_device_management_1.runRealDeviceReset.bind(this)();
821
+ }
822
+ else {
823
+ await simulator_management_1.runSimulatorReset.bind(this)(enforceSimulatorShutdown);
824
+ }
825
+ this.logEvent('resetComplete');
826
+ }
827
+ async stop() {
828
+ this.jwpProxyActive = false;
829
+ this.proxyReqRes = null;
830
+ if (this._wda?.fullyStarted) {
831
+ if (this.wda.jwproxy) {
832
+ try {
833
+ await this.proxyCommand(`/session/${this.sessionId}`, 'DELETE');
834
+ }
835
+ catch (err) {
836
+ // an error here should not short-circuit the rest of clean up
837
+ this.log.debug(`Unable to DELETE session on WDA: '${err.message}'. Continuing shutdown.`);
838
+ }
839
+ }
840
+ // The former could cache the xcodebuild, so should not quit the process.
841
+ // If the session skipped the xcodebuild (this.wda.canSkipXcodebuild), the this.wda instance
842
+ // should quit properly.
843
+ if ((!this.wda.webDriverAgentUrl && this.opts.useNewWDA) || this.wda.canSkipXcodebuild) {
844
+ await this.wda.quit();
845
+ }
846
+ }
847
+ device_connections_factory_1.DEVICE_CONNECTIONS_FACTORY.releaseConnection(this.opts.udid);
848
+ }
677
849
  async initSimulator() {
678
- const device = /** @type {Simulator} */ (this.device);
850
+ const device = this.device;
679
851
  if (this.opts.shutdownOtherSimulators) {
680
852
  this.assertFeatureEnabled(SHUTDOWN_OTHER_FEAT_NAME);
681
853
  await simulator_management_1.shutdownOtherSimulators.bind(this)();
@@ -692,7 +864,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
692
864
  if (await simulator_management_1.setLocalizationPrefs.bind(this)()) {
693
865
  this.log.debug('Localization preferences have been updated');
694
866
  }
695
- /** @type {Promise[]} */
696
867
  const promises = ['reduceMotion', 'reduceTransparency', 'autoFillPasswords']
697
868
  .filter((optName) => lodash_1.default.isBoolean(this.opts[optName]))
698
869
  .map((optName) => {
@@ -714,9 +885,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
714
885
  }
715
886
  this.logEvent('simStarted');
716
887
  }
717
- /**
718
- * Start WebDriverAgentRunner
719
- */
720
888
  async startWda() {
721
889
  // Don't cleanup the processes if webDriverAgentUrl is set
722
890
  if (!support_1.util.hasValue(this.wda.webDriverAgentUrl)) {
@@ -787,7 +955,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
787
955
  this.log.debug(`Trying to start WebDriverAgent once since at least one of ${CAP_NAMES_NO_XCODEBUILD_REQUIRED} capabilities is provided`);
788
956
  startupRetries = 1;
789
957
  }
790
- /** @type {Error|null} */
791
958
  let shortCircuitError = null;
792
959
  let retryCount = 0;
793
960
  await (0, asyncbox_1.retryInterval)(startupRetries, startupRetryInterval, async () => {
@@ -799,207 +966,84 @@ class XCUITestDriver extends driver_1.BaseDriver {
799
966
  if (this.opts.usePreinstalledWDA) {
800
967
  await this.preparePreinstalledWda();
801
968
  }
802
- this.cachedWdaStatus = await this.wda.launch(/** @type {string} */ (this.sessionId));
803
- }
804
- catch (err) {
805
- this.logEvent('wdaStartFailed');
806
- this.log.debug(err.stack);
807
- retryCount++;
808
- let errorMsg = `Unable to launch WebDriverAgent. Original error: ${err.message}`;
809
- if (this.isRealDevice()) {
810
- errorMsg += `. Make sure you follow the tutorial at ${WDA_REAL_DEV_TUTORIAL_URL}`;
811
- }
812
- if (this.opts.usePreinstalledWDA) {
813
- try {
814
- // In case the bundle id process start got failed because of
815
- // auth popup in the device. Then, the bundle id process itself started. It is safe to stop it here.
816
- await this.mobileKillApp(this.wda.bundleIdForXctest);
817
- }
818
- catch { }
819
- ;
820
- // Mostly it failed to start the WDA process as no the bundle id
821
- // e.g. '<bundle id of WDA> not found on device <udid>'
822
- errorMsg = `Unable to launch WebDriverAgent. Original error: ${err.message}. ` +
823
- `Make sure the application ${this.wda.bundleIdForXctest} exists and it is launchable.`;
824
- if (this.isRealDevice()) {
825
- errorMsg += ` ${WDA_REAL_DEV_TUTORIAL_URL} may help to complete the preparation.`;
826
- }
827
- ;
828
- throw new Error(errorMsg);
829
- }
830
- else {
831
- await quitAndUninstall(errorMsg);
832
- }
833
- }
834
- this.proxyReqRes = this.wda.proxyReqRes.bind(this.wda);
835
- this.jwpProxyActive = true;
836
- try {
837
- this.logEvent('wdaSessionAttempted');
838
- this.log.debug('Sending createSession command to WDA');
839
- this.cachedWdaStatus = this.cachedWdaStatus || (await this.proxyCommand('/status', 'GET'));
840
- await this.startWdaSession(this.opts.bundleId, this.opts.processArguments);
841
- this.logEvent('wdaSessionStarted');
842
- }
843
- catch (err) {
844
- this.logEvent('wdaSessionFailed');
845
- this.log.debug(err.stack);
846
- if (err instanceof driver_1.errors.TimeoutError) {
847
- // Session startup timed out. There is no point to retry
848
- shortCircuitError = err;
849
- return;
850
- }
851
- let errorMsg = `Unable to start WebDriverAgent session. Original error: ${err.message}`;
852
- if (this.isRealDevice() && lodash_1.default.includes(err.message, 'xcodebuild')) {
853
- errorMsg += ` Make sure you follow the tutorial at ${WDA_REAL_DEV_TUTORIAL_URL}.`;
854
- }
855
- throw new Error(errorMsg);
856
- }
857
- if (this.opts.clearSystemFiles && this.isXcodebuildNeeded()) {
858
- await (0, utils_1.markSystemFilesForCleanup)(this.wda);
859
- }
860
- // We don't restrict the version, but show what version of WDA is running on the device for debugging purposes.
861
- if (this.cachedWdaStatus?.build) {
862
- this.log.info(`WebDriverAgent version: '${this.cachedWdaStatus.build.version}'`);
863
- }
864
- else {
865
- this.log.warn(`WebDriverAgent does not provide any version information. ` +
866
- `This might indicate either a custom or an outdated build.`);
867
- }
868
- // we expect certain socket errors until this point, but now
869
- // mark things as fully working
870
- this.wda.fullyStarted = true;
871
- this.logEvent('wdaStarted');
872
- });
873
- if (shortCircuitError) {
874
- throw shortCircuitError;
875
- }
876
- });
877
- }
878
- /**
879
- *
880
- * @param {boolean} [enforceSimulatorShutdown=false]
881
- */
882
- async runReset(enforceSimulatorShutdown = false) {
883
- this.logEvent('resetStarted');
884
- if (this.isRealDevice()) {
885
- await real_device_management_1.runRealDeviceReset.bind(this)();
886
- }
887
- else {
888
- await simulator_management_1.runSimulatorReset.bind(this)(enforceSimulatorShutdown);
889
- }
890
- this.logEvent('resetComplete');
891
- }
892
- async deleteSession(sessionId) {
893
- await utils_1.removeAllSessionWebSocketHandlers.bind(this)();
894
- for (const recorder of lodash_1.default.compact([
895
- this._recentScreenRecorder,
896
- this._audioRecorder,
897
- this._trafficCapture,
898
- ])) {
899
- await recorder.interrupt(true);
900
- await recorder.cleanup();
901
- }
902
- if (!lodash_1.default.isEmpty(this._perfRecorders)) {
903
- await bluebird_1.default.all(this._perfRecorders.map((x) => x.stop(true)));
904
- this._perfRecorders = [];
905
- }
906
- if (this._conditionInducerService || this._remoteXPCConditionInducerConnection) {
907
- try {
908
- await this.disableConditionInducer();
909
- }
910
- catch (err) {
911
- this.log.warn(`Cannot disable condition inducer: ${err.message}`);
912
- }
913
- }
914
- await this.stop();
915
- if (this.wda && this.isXcodebuildNeeded()) {
916
- if (this.opts.clearSystemFiles) {
917
- let synchronizationKey = XCUITestDriver.name;
918
- const derivedDataPath = await this.wda.retrieveDerivedDataPath();
919
- if (derivedDataPath) {
920
- synchronizationKey = node_path_1.default.normalize(derivedDataPath);
921
- }
922
- await SHARED_RESOURCES_GUARD.acquire(synchronizationKey, async () => {
923
- await (0, utils_1.clearSystemFiles)(this.wda);
924
- });
925
- }
926
- else {
927
- this.log.debug('Not clearing log files. Use `clearSystemFiles` capability to turn on.');
928
- }
929
- }
930
- if (this.remote) {
931
- this.log.debug('Found a remote debugger session. Removing...');
932
- await this.stopRemote();
933
- }
934
- if (this.opts.resetOnSessionStartOnly === false) {
935
- await this.runReset(true);
936
- }
937
- const simulatorDevice = this.isSimulator() ? /** @type {Simulator} */ (this.device) : null;
938
- if (simulatorDevice && this.lifecycleData.createSim) {
939
- this.log.debug(`Deleting simulator created for this run (udid: '${simulatorDevice.udid}')`);
940
- await simulator_management_1.shutdownSimulator.bind(this)();
941
- await simulatorDevice.delete();
942
- }
943
- const shouldResetLocationService = this.isRealDevice() && !!this.opts.resetLocationService;
944
- if (shouldResetLocationService) {
945
- try {
946
- await this.mobileResetLocationService();
947
- }
948
- catch {
949
- /* Ignore this error since mobileResetLocationService already logged the error */
950
- }
951
- }
952
- await this.logs.syslog?.stopCapture();
953
- lodash_1.default.values(this.logs).forEach((x) => x.removeAllListeners());
954
- if (this._bidiServerLogListener) {
955
- this.log.unwrap().off('log', this._bidiServerLogListener);
956
- }
957
- this.logs = {};
958
- if (this.mjpegStream) {
959
- this.log.info('Closing MJPEG stream');
960
- this.mjpegStream.stop();
961
- }
962
- this.resetIos();
963
- await super.deleteSession(sessionId);
964
- }
965
- async stop() {
966
- this.jwpProxyActive = false;
967
- this.proxyReqRes = null;
968
- if (this.wda?.fullyStarted) {
969
- if (this.wda.jwproxy) {
969
+ if (!this.sessionId) {
970
+ throw new Error('Session ID is required but was not set');
971
+ }
972
+ this.cachedWdaStatus = await this.wda.launch(this.sessionId);
973
+ }
974
+ catch (err) {
975
+ this.logEvent('wdaStartFailed');
976
+ this.log.debug(err.stack);
977
+ retryCount++;
978
+ let errorMsg = `Unable to launch WebDriverAgent. Original error: ${err.message}`;
979
+ if (this.isRealDevice()) {
980
+ errorMsg += `. Make sure you follow the tutorial at ${WDA_REAL_DEV_TUTORIAL_URL}`;
981
+ }
982
+ if (this.opts.usePreinstalledWDA) {
983
+ try {
984
+ // In case the bundle id process start got failed because of
985
+ // auth popup in the device. Then, the bundle id process itself started. It is safe to stop it here.
986
+ await this.mobileKillApp(this.wda.bundleIdForXctest);
987
+ }
988
+ catch { }
989
+ ;
990
+ // Mostly it failed to start the WDA process as no the bundle id
991
+ // e.g. '<bundle id of WDA> not found on device <udid>'
992
+ errorMsg = `Unable to launch WebDriverAgent. Original error: ${err.message}. ` +
993
+ `Make sure the application ${this.wda.bundleIdForXctest} exists and it is launchable.`;
994
+ if (this.isRealDevice()) {
995
+ errorMsg += ` ${WDA_REAL_DEV_TUTORIAL_URL} may help to complete the preparation.`;
996
+ }
997
+ ;
998
+ throw new Error(errorMsg);
999
+ }
1000
+ else {
1001
+ await quitAndUninstall(errorMsg);
1002
+ }
1003
+ }
1004
+ this.proxyReqRes = this.wda.proxyReqRes.bind(this.wda);
1005
+ this.jwpProxyActive = true;
970
1006
  try {
971
- await this.proxyCommand(`/session/${this.sessionId}`, 'DELETE');
1007
+ this.logEvent('wdaSessionAttempted');
1008
+ this.log.debug('Sending createSession command to WDA');
1009
+ this.cachedWdaStatus = this.cachedWdaStatus || (await this.proxyCommand('/status', 'GET'));
1010
+ await this.startWdaSession(this.opts.bundleId, this.opts.processArguments);
1011
+ this.logEvent('wdaSessionStarted');
972
1012
  }
973
1013
  catch (err) {
974
- // an error here should not short-circuit the rest of clean up
975
- this.log.debug(`Unable to DELETE session on WDA: '${err.message}'. Continuing shutdown.`);
1014
+ this.logEvent('wdaSessionFailed');
1015
+ this.log.debug(err.stack);
1016
+ if (err instanceof driver_1.errors.TimeoutError) {
1017
+ // Session startup timed out. There is no point to retry
1018
+ shortCircuitError = err;
1019
+ return;
1020
+ }
1021
+ let errorMsg = `Unable to start WebDriverAgent session. Original error: ${err.message}`;
1022
+ if (this.isRealDevice() && lodash_1.default.includes(err.message, 'xcodebuild')) {
1023
+ errorMsg += ` Make sure you follow the tutorial at ${WDA_REAL_DEV_TUTORIAL_URL}.`;
1024
+ }
1025
+ throw new Error(errorMsg);
976
1026
  }
1027
+ if (this.opts.clearSystemFiles && this.isXcodebuildNeeded()) {
1028
+ await (0, utils_1.markSystemFilesForCleanup)(this.wda);
1029
+ }
1030
+ // We don't restrict the version, but show what version of WDA is running on the device for debugging purposes.
1031
+ if (this.cachedWdaStatus?.build) {
1032
+ this.log.info(`WebDriverAgent version: '${this.cachedWdaStatus.build.version}'`);
1033
+ }
1034
+ else {
1035
+ this.log.warn(`WebDriverAgent does not provide any version information. ` +
1036
+ `This might indicate either a custom or an outdated build.`);
1037
+ }
1038
+ // we expect certain socket errors until this point, but now
1039
+ // mark things as fully working
1040
+ this.wda.fullyStarted = true;
1041
+ this.logEvent('wdaStarted');
1042
+ });
1043
+ if (shortCircuitError) {
1044
+ throw shortCircuitError;
977
1045
  }
978
- // The former could cache the xcodebuild, so should not quit the process.
979
- // If the session skipped the xcodebuild (this.wda.canSkipXcodebuild), the this.wda instance
980
- // should quit properly.
981
- if ((!this.wda.webDriverAgentUrl && this.opts.useNewWDA) || this.wda.canSkipXcodebuild) {
982
- await this.wda.quit();
983
- }
984
- }
985
- device_connections_factory_1.DEVICE_CONNECTIONS_FACTORY.releaseConnection(this.opts.udid);
986
- }
987
- /**
988
- *
989
- * @param {string} cmd
990
- * @param {...any} args
991
- * @returns {Promise<any>}
992
- */
993
- async executeCommand(cmd, ...args) {
994
- this.log.debug(`Executing command '${cmd}'`);
995
- if (cmd === 'receiveAsyncResponse') {
996
- return await this.receiveAsyncResponse(...args);
997
- }
998
- // TODO: once this fix gets into base driver remove from here
999
- if (cmd === 'getStatus') {
1000
- return await this.getStatus();
1001
- }
1002
- return await super.executeCommand(cmd, ...args);
1046
+ });
1003
1047
  }
1004
1048
  async configureApp() {
1005
1049
  function appIsPackageOrBundle(app) {
@@ -1021,11 +1065,11 @@ class XCUITestDriver extends driver_1.BaseDriver {
1021
1065
  switch (lodash_1.default.toLower(this.opts.app)) {
1022
1066
  case 'settings':
1023
1067
  this.opts.bundleId = 'com.apple.Preferences';
1024
- this.opts.app = null;
1068
+ this.opts.app = undefined;
1025
1069
  return;
1026
1070
  case 'calendar':
1027
1071
  this.opts.bundleId = 'com.apple.mobilecal';
1028
- this.opts.app = null;
1072
+ this.opts.app = undefined;
1029
1073
  return;
1030
1074
  }
1031
1075
  this.opts.app = await this.helpers.configureApp(this.opts.app, {
@@ -1070,7 +1114,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
1070
1114
  let isRealDeviceUdid = false;
1071
1115
  const shouldCheckAvailableRealDevices = !this.opts.webDriverAgentUrl;
1072
1116
  if (shouldCheckAvailableRealDevices) {
1073
- const devices = await (0, real_device_1.getConnectedDevices)();
1117
+ const devices = await (0, real_device_management_1.getConnectedDevices)();
1074
1118
  this.log.debug(`Available real devices: ${devices.join(', ')}`);
1075
1119
  isRealDeviceUdid = devices.includes(this.opts.udid);
1076
1120
  }
@@ -1092,7 +1136,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
1092
1136
  }
1093
1137
  }
1094
1138
  this.log.debug(`Creating iDevice object with udid '${this.opts.udid}'`);
1095
- const device = new real_device_1.RealDevice(this.opts.udid, this.log);
1139
+ const device = new real_device_management_1.RealDevice(this.opts.udid, this.log);
1096
1140
  return { device, realDevice: true, udid: this.opts.udid };
1097
1141
  }
1098
1142
  this.log.info(`No real device udid has been provided in capabilities. ` +
@@ -1115,9 +1159,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
1115
1159
  return { device, realDevice: false, udid: device.udid };
1116
1160
  }
1117
1161
  async startSim() {
1118
- /** @type {import('appium-ios-simulator').DevicePreferences} */
1119
1162
  const devicePreferences = {};
1120
- /** @type {import('appium-ios-simulator').RunOptions} */
1121
1163
  const runOpts = {
1122
1164
  scaleFactor: this.opts.scaleFactor,
1123
1165
  connectHardwareKeyboard: !!this.opts.connectHardwareKeyboard,
@@ -1146,7 +1188,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
1146
1188
  devicePreferences.SimulatorWindowRotationAngle = 0;
1147
1189
  break;
1148
1190
  }
1149
- await /** @type {Simulator} */ (this.device).run(runOpts);
1191
+ await this.device.run(runOpts);
1150
1192
  }
1151
1193
  async createSim() {
1152
1194
  this.lifecycleData.createSim = true;
@@ -1185,7 +1227,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
1185
1227
  // https://developer.apple.com/forums/thread/86951?answerId=263395022#263395022
1186
1228
  env.TZ = this.opts.appTimeZone;
1187
1229
  }
1188
- /** @type {import('appium-webdriveragent').WDACapabilities} */
1189
1230
  const wdaCaps = {
1190
1231
  bundleId: this.opts.autoLaunch === false ? undefined : bundleId,
1191
1232
  arguments: args,
@@ -1227,155 +1268,9 @@ class XCUITestDriver extends driver_1.BaseDriver {
1227
1268
  });
1228
1269
  this.log.info(`WDA session startup took ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
1229
1270
  }
1230
- // Override Proxy methods from BaseDriver
1231
- proxyActive() {
1232
- return Boolean(this.jwpProxyActive);
1233
- }
1234
- getProxyAvoidList() {
1235
- if (this.isWebview()) {
1236
- return NO_PROXY_WEB_LIST;
1237
- }
1238
- return NO_PROXY_NATIVE_LIST;
1239
- }
1240
- canProxy() {
1241
- return true;
1242
- }
1243
- /**
1244
- * @returns {boolean}
1245
- */
1246
- isSafari() {
1247
- return !!this.safari;
1248
- }
1249
- /**
1250
- * @returns {boolean}
1251
- */
1252
- isRealDevice() {
1253
- return 'devicectl' in (this.device ?? {});
1254
- }
1255
- /**
1256
- * @returns {boolean}
1257
- */
1258
- isSimulator() {
1259
- return 'simctl' in (this.device ?? {});
1260
- }
1261
- /**
1262
- * @param {string} strategy
1263
- */
1264
- validateLocatorStrategy(strategy) {
1265
- super.validateLocatorStrategy(strategy, this.isWebContext());
1266
- }
1267
- /**
1268
- * @param {any} caps
1269
- * @returns {caps is import('@appium/types').DriverCaps<XCUITestDriverConstraints>}
1270
- */
1271
- validateDesiredCaps(caps) {
1272
- if (!super.validateDesiredCaps(caps)) {
1273
- return false;
1274
- }
1275
- // make sure that the capabilities have one of `app` or `bundleId`
1276
- if (lodash_1.default.toLower(caps.browserName) !== 'safari' && !caps.app && !caps.bundleId) {
1277
- this.log.info('The desired capabilities include neither an app nor a bundleId. ' +
1278
- 'WebDriverAgent will be started without the default app');
1279
- }
1280
- if (!support_1.util.coerceVersion(String(caps.platformVersion), false)) {
1281
- this.log.warn(`'platformVersion' capability ('${caps.platformVersion}') is not a valid version number. ` +
1282
- `Consider fixing it or be ready to experience an inconsistent driver behavior.`);
1283
- }
1284
- let verifyProcessArgument = (processArguments) => {
1285
- const { args, env } = processArguments;
1286
- if (!lodash_1.default.isNil(args) && !lodash_1.default.isArray(args)) {
1287
- throw this.log.errorWithException('processArguments.args must be an array of strings');
1288
- }
1289
- if (!lodash_1.default.isNil(env) && !lodash_1.default.isPlainObject(env)) {
1290
- throw this.log.errorWithException('processArguments.env must be an object <key,value> pair {a:b, c:d}');
1291
- }
1292
- };
1293
- // `processArguments` should be JSON string or an object with arguments and/ environment details
1294
- if (caps.processArguments) {
1295
- if (lodash_1.default.isString(caps.processArguments)) {
1296
- try {
1297
- // try to parse the string as JSON
1298
- caps.processArguments = JSON.parse(caps.processArguments);
1299
- verifyProcessArgument(caps.processArguments);
1300
- }
1301
- catch (err) {
1302
- throw this.log.errorWithException(`processArguments must be a JSON format or an object with format {args : [], env : {a:b, c:d}}. ` +
1303
- `Both environment and argument can be null. Error: ${err}`);
1304
- }
1305
- }
1306
- else if (lodash_1.default.isPlainObject(caps.processArguments)) {
1307
- verifyProcessArgument(caps.processArguments);
1308
- }
1309
- else {
1310
- throw this.log.errorWithException(`'processArguments must be an object, or a string JSON object with format {args : [], env : {a:b, c:d}}. ` +
1311
- `Both environment and argument can be null.`);
1312
- }
1313
- }
1314
- // there is no point in having `keychainPath` without `keychainPassword`
1315
- if ((caps.keychainPath && !caps.keychainPassword) ||
1316
- (!caps.keychainPath && caps.keychainPassword)) {
1317
- throw this.log.errorWithException(`If 'keychainPath' is set, 'keychainPassword' must also be set (and vice versa).`);
1318
- }
1319
- // `resetOnSessionStartOnly` should be set to true by default
1320
- this.opts.resetOnSessionStartOnly =
1321
- !support_1.util.hasValue(this.opts.resetOnSessionStartOnly) || this.opts.resetOnSessionStartOnly;
1322
- this.opts.useNewWDA = support_1.util.hasValue(this.opts.useNewWDA) ? this.opts.useNewWDA : false;
1323
- if (caps.commandTimeouts) {
1324
- caps.commandTimeouts = (0, utils_1.normalizeCommandTimeouts)(caps.commandTimeouts);
1325
- }
1326
- if (lodash_1.default.isString(caps.webDriverAgentUrl)) {
1327
- const { protocol, host } = node_url_1.default.parse(caps.webDriverAgentUrl);
1328
- if (lodash_1.default.isEmpty(protocol) || lodash_1.default.isEmpty(host)) {
1329
- throw this.log.errorWithException(`'webDriverAgentUrl' capability is expected to contain a valid WebDriverAgent server URL. ` +
1330
- `'${caps.webDriverAgentUrl}' is given instead`);
1331
- }
1332
- }
1333
- if (caps.browserName) {
1334
- if (caps.bundleId) {
1335
- throw this.log.errorWithException(`'browserName' cannot be set together with 'bundleId' capability`);
1336
- }
1337
- // warn if the capabilities have both `app` and `browser, although this
1338
- // is common with selenium grid
1339
- if (caps.app) {
1340
- this.log.warn(`The capabilities should generally not include both an 'app' and a 'browserName'`);
1341
- }
1342
- }
1343
- if (caps.permissions) {
1344
- try {
1345
- for (const [bundleId, perms] of lodash_1.default.toPairs(JSON.parse(caps.permissions))) {
1346
- if (!lodash_1.default.isString(bundleId)) {
1347
- throw new Error(`'${JSON.stringify(bundleId)}' must be a string`);
1348
- }
1349
- if (!lodash_1.default.isPlainObject(perms)) {
1350
- throw new Error(`'${JSON.stringify(perms)}' must be a JSON object`);
1351
- }
1352
- }
1353
- }
1354
- catch (e) {
1355
- throw this.log.errorWithException(`'${caps.permissions}' is expected to be a valid object with format ` +
1356
- `{"<bundleId1>": {"<serviceName1>": "<serviceStatus1>", ...}, ...}. Original error: ${e.message}`);
1357
- }
1358
- }
1359
- if (caps.platformVersion && !support_1.util.coerceVersion(caps.platformVersion, false)) {
1360
- throw this.log.errorWithException(`'platformVersion' must be a valid version number. ` +
1361
- `'${caps.platformVersion}' is given instead.`);
1362
- }
1363
- // additionalWebviewBundleIds is an array, JSON array, or string
1364
- if (caps.additionalWebviewBundleIds) {
1365
- caps.additionalWebviewBundleIds = this.helpers.parseCapsArray(caps.additionalWebviewBundleIds);
1366
- }
1367
- // finally, return true since the superclass check passed, as did this
1368
- return true;
1369
- }
1370
- /**
1371
- * Check if the given app can be installed, or should uninstall before installing it.
1372
- *
1373
- * @param {AutInstallationStateOptions} [opts]
1374
- * @returns {Promise<AutInstallationState>}
1375
- */
1376
1271
  async checkAutInstallationState(opts) {
1377
1272
  const { enforceAppInstall, fullReset, noReset, bundleId, app } = opts ?? this.opts;
1378
- const wasAppInstalled = await this.device.isAppInstalled(bundleId);
1273
+ const wasAppInstalled = !!bundleId && await this.device.isAppInstalled(bundleId);
1379
1274
  if (wasAppInstalled) {
1380
1275
  this.log.info(`App '${bundleId}' is already installed`);
1381
1276
  if (noReset) {
@@ -1396,7 +1291,7 @@ class XCUITestDriver extends driver_1.BaseDriver {
1396
1291
  skipUninstall: !wasAppInstalled,
1397
1292
  };
1398
1293
  }
1399
- const candidateBundleVersion = await this.appInfosCache.extractBundleVersion(app);
1294
+ const candidateBundleVersion = app ? await this.appInfosCache.extractBundleVersion(app) : undefined;
1400
1295
  this.log.debug(`CFBundleVersion from Info.plist: ${candidateBundleVersion}`);
1401
1296
  if (!candidateBundleVersion) {
1402
1297
  return {
@@ -1405,8 +1300,8 @@ class XCUITestDriver extends driver_1.BaseDriver {
1405
1300
  };
1406
1301
  }
1407
1302
  const appBundleVersion = this.isRealDevice()
1408
- ? (await /** @type {RealDevice} */ (this.device).fetchAppInfo(bundleId))?.CFBundleVersion
1409
- : BUNDLE_VERSION_PATTERN.exec(await /** @type {Simulator} */ (this.device).simctl.appInfo(bundleId))?.[1];
1303
+ ? (await this.device.fetchAppInfo(bundleId))?.CFBundleVersion
1304
+ : BUNDLE_VERSION_PATTERN.exec(await this.device.simctl.appInfo(bundleId))?.[1];
1410
1305
  this.log.debug(`CFBundleVersion from installed app info: ${appBundleVersion}`);
1411
1306
  if (!appBundleVersion) {
1412
1307
  return {
@@ -1463,19 +1358,14 @@ class XCUITestDriver extends driver_1.BaseDriver {
1463
1358
  }
1464
1359
  if (support_1.util.hasValue(this.opts.iosInstallPause)) {
1465
1360
  // https://github.com/appium/appium/issues/6889
1466
- const pauseMs = parseInt(this.opts.iosInstallPause, 10);
1361
+ const pauseMs = this.opts.iosInstallPause;
1467
1362
  this.log.debug(`iosInstallPause set. Pausing ${pauseMs} ms before continuing`);
1468
1363
  await bluebird_1.default.delay(pauseMs);
1469
1364
  }
1470
1365
  this.logEvent('appInstalled');
1471
1366
  }
1472
1367
  }
1473
- /**
1474
- * @param {string|string[]} otherApps
1475
- * @returns {Promise<void>}
1476
- */
1477
1368
  async installOtherApps(otherApps) {
1478
- /** @type {string[]|undefined} */
1479
1369
  let appsList;
1480
1370
  try {
1481
1371
  appsList = this.helpers.parseCapsArray(otherApps);
@@ -1487,13 +1377,11 @@ class XCUITestDriver extends driver_1.BaseDriver {
1487
1377
  this.log.info(`Got zero apps from 'otherApps' capability value. Doing nothing`);
1488
1378
  return;
1489
1379
  }
1490
- /** @type {string[]} */
1491
1380
  const appPaths = await bluebird_1.default.all(appsList.map((app) => this.helpers.configureApp(app, {
1492
1381
  onPostProcess: app_utils_1.onPostConfigureApp.bind(this),
1493
1382
  onDownload: app_utils_1.onDownloadApp.bind(this),
1494
1383
  supportedExtensions: app_utils_1.SUPPORTED_EXTENSIONS,
1495
1384
  })));
1496
- /** @type {string[]} */
1497
1385
  const appIds = await bluebird_1.default.all(appPaths.map((appPath) => this.appInfosCache.extractBundleId(appPath)));
1498
1386
  for (const [appId, appPath] of lodash_1.default.zip(appIds, appPaths)) {
1499
1387
  if (this.isRealDevice()) {
@@ -1509,10 +1397,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
1509
1397
  }
1510
1398
  }
1511
1399
  }
1512
- /**
1513
- * @param {string} orientation
1514
- * @returns {Promise<void>}
1515
- */
1516
1400
  async setInitialOrientation(orientation) {
1517
1401
  const dstOrientation = lodash_1.default.toUpper(orientation);
1518
1402
  if (!SUPPORTED_ORIENATIONS.includes(dstOrientation)) {
@@ -1528,21 +1412,6 @@ class XCUITestDriver extends driver_1.BaseDriver {
1528
1412
  this.log.warn(`Setting initial orientation failed with: ${err.message}`);
1529
1413
  }
1530
1414
  }
1531
- /**
1532
- * @param {string} [cmdName]
1533
- * @returns {number|undefined}
1534
- */
1535
- _getCommandTimeout(cmdName) {
1536
- if (this.opts.commandTimeouts) {
1537
- if (cmdName && lodash_1.default.has(this.opts.commandTimeouts, cmdName)) {
1538
- return this.opts.commandTimeouts[cmdName];
1539
- }
1540
- return this.opts.commandTimeouts[utils_1.DEFAULT_TIMEOUT_KEY];
1541
- }
1542
- }
1543
- /**
1544
- * Reset the current session (run the delete session and create session subroutines)
1545
- */
1546
1415
  async reset() {
1547
1416
  throw new Error(`The reset API has been deprecated and is not supported anymore. ` +
1548
1417
  `Consider using corresponding 'mobile:' extensions to manage the state of the app under test.`);
@@ -1571,6 +1440,41 @@ class XCUITestDriver extends driver_1.BaseDriver {
1571
1440
  await simulator_management_1.installToSimulator.bind(this)(this.opts.prebuiltWDAPath, candidateBundleId);
1572
1441
  }
1573
1442
  }
1443
+ resetIos() {
1444
+ this.opts = this.opts || {};
1445
+ this._wda = null;
1446
+ this.jwpProxyActive = false;
1447
+ this.proxyReqRes = null;
1448
+ this.safari = false;
1449
+ this.cachedWdaStatus = null;
1450
+ this.curWebFrames = [];
1451
+ this._currentUrl = null;
1452
+ this.curContext = null;
1453
+ this.xcodeVersion = undefined;
1454
+ this.contexts = [];
1455
+ this.implicitWaitMs = 0;
1456
+ this.pageLoadMs = 6000;
1457
+ this.landscapeWebCoordsOffset = 0;
1458
+ this.remote = null;
1459
+ this._conditionInducerService = null;
1460
+ this._remoteXPCConditionInducerConnection = null;
1461
+ this.webElementsCache = new lru_cache_1.LRUCache({
1462
+ max: WEB_ELEMENTS_CACHE_SIZE,
1463
+ });
1464
+ this._waitingAtoms = {
1465
+ count: 0,
1466
+ alertNotifier: new node_events_1.default(),
1467
+ alertMonitor: bluebird_1.default.resolve(),
1468
+ };
1469
+ }
1470
+ _getCommandTimeout(cmdName) {
1471
+ if (this.opts.commandTimeouts) {
1472
+ if (cmdName && lodash_1.default.has(this.opts.commandTimeouts, cmdName)) {
1473
+ return this.opts.commandTimeouts[cmdName];
1474
+ }
1475
+ return this.opts.commandTimeouts[utils_1.DEFAULT_TIMEOUT_KEY];
1476
+ }
1477
+ }
1574
1478
  /*---------------+
1575
1479
  | ACTIVEAPPINFO |
1576
1480
  +---------------+*/
@@ -1946,32 +1850,4 @@ class XCUITestDriver extends driver_1.BaseDriver {
1946
1850
  }
1947
1851
  exports.XCUITestDriver = XCUITestDriver;
1948
1852
  exports.default = XCUITestDriver;
1949
- /**
1950
- * @template {import('@appium/types').Constraints} C
1951
- * @template [Ctx=string]
1952
- * @typedef {import('@appium/types').ExternalDriver<C, Ctx>} ExternalDriver
1953
- */
1954
- /**
1955
- * @typedef {Pick<XCUITestDriverOpts, 'enforceAppInstall' | 'fullReset' | 'noReset' | 'bundleId' | 'app'>} AutInstallationStateOptions
1956
- */
1957
- /**
1958
- * @typedef {Object} AutInstallationState
1959
- * @property {boolean} install - If the given app should install, or not need to install.
1960
- * @property {boolean} skipUninstall - If the installed app should be uninstalled, or not.
1961
- */
1962
- /**
1963
- * @typedef {typeof desiredCapConstraints} XCUITestDriverConstraints
1964
- * @typedef {import('@appium/types').DriverOpts<XCUITestDriverConstraints>} XCUITestDriverOpts
1965
- * @typedef {import('./commands/types').FullContext} FullContext
1966
- * @typedef {import('appium-xcode').XcodeVersion} XcodeVersion
1967
- * @typedef {import('appium-ios-simulator').Simulator} Simulator
1968
- */
1969
- /**
1970
- * @typedef {Object} DriverLogs
1971
- * @property {import('./device-log/ios-device-log').IOSDeviceLog|import('./device-log/ios-simulator-log').IOSSimulatorLog} [syslog]
1972
- * @property {import('./device-log/ios-crash-log').IOSCrashLog} [crashlog]
1973
- * @property {import('./device-log/safari-console-log').SafariConsoleLog} [safariConsole]
1974
- * @property {import('./device-log/safari-network-log').SafariNetworkLog} [safariNetwork]
1975
- * @property {import('./device-log/ios-performance-log').IOSPerformanceLog} [performance]
1976
- */
1977
1853
  //# sourceMappingURL=driver.js.map