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