appium-xcuitest-driver 7.6.0 → 7.7.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 (130) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/lib/commands/app-management.d.ts.map +1 -1
  3. package/build/lib/commands/app-management.js +9 -17
  4. package/build/lib/commands/app-management.js.map +1 -1
  5. package/build/lib/commands/appearance.d.ts.map +1 -1
  6. package/build/lib/commands/appearance.js +2 -4
  7. package/build/lib/commands/appearance.js.map +1 -1
  8. package/build/lib/commands/biometric.d.ts.map +1 -1
  9. package/build/lib/commands/biometric.js +3 -6
  10. package/build/lib/commands/biometric.js.map +1 -1
  11. package/build/lib/commands/certificate.d.ts +1 -1
  12. package/build/lib/commands/certificate.d.ts.map +1 -1
  13. package/build/lib/commands/certificate.js +3 -5
  14. package/build/lib/commands/certificate.js.map +1 -1
  15. package/build/lib/commands/condition.d.ts.map +1 -1
  16. package/build/lib/commands/condition.js +2 -4
  17. package/build/lib/commands/condition.js.map +1 -1
  18. package/build/lib/commands/context.d.ts.map +1 -1
  19. package/build/lib/commands/context.js +1 -2
  20. package/build/lib/commands/context.js.map +1 -1
  21. package/build/lib/commands/deviceInfo.d.ts.map +1 -1
  22. package/build/lib/commands/deviceInfo.js +1 -2
  23. package/build/lib/commands/deviceInfo.js.map +1 -1
  24. package/build/lib/commands/file-movement.d.ts.map +1 -1
  25. package/build/lib/commands/file-movement.js +14 -22
  26. package/build/lib/commands/file-movement.js.map +1 -1
  27. package/build/lib/commands/general.d.ts.map +1 -1
  28. package/build/lib/commands/general.js +1 -2
  29. package/build/lib/commands/general.js.map +1 -1
  30. package/build/lib/commands/gesture.d.ts.map +1 -1
  31. package/build/lib/commands/gesture.js +1 -2
  32. package/build/lib/commands/gesture.js.map +1 -1
  33. package/build/lib/commands/keychains.js +1 -2
  34. package/build/lib/commands/keychains.js.map +1 -1
  35. package/build/lib/commands/localization.d.ts.map +1 -1
  36. package/build/lib/commands/localization.js +1 -3
  37. package/build/lib/commands/localization.js.map +1 -1
  38. package/build/lib/commands/location.d.ts.map +1 -1
  39. package/build/lib/commands/location.js +1 -2
  40. package/build/lib/commands/location.js.map +1 -1
  41. package/build/lib/commands/log.d.ts.map +1 -1
  42. package/build/lib/commands/log.js +2 -4
  43. package/build/lib/commands/log.js.map +1 -1
  44. package/build/lib/commands/memory.d.ts.map +1 -1
  45. package/build/lib/commands/memory.js +2 -2
  46. package/build/lib/commands/memory.js.map +1 -1
  47. package/build/lib/commands/notifications.d.ts +1 -1
  48. package/build/lib/commands/notifications.d.ts.map +1 -1
  49. package/build/lib/commands/notifications.js +1 -2
  50. package/build/lib/commands/notifications.js.map +1 -1
  51. package/build/lib/commands/pasteboard.d.ts.map +1 -1
  52. package/build/lib/commands/pasteboard.js +2 -4
  53. package/build/lib/commands/pasteboard.js.map +1 -1
  54. package/build/lib/commands/pcap.d.ts.map +1 -1
  55. package/build/lib/commands/pcap.js +1 -2
  56. package/build/lib/commands/pcap.js.map +1 -1
  57. package/build/lib/commands/performance.d.ts.map +1 -1
  58. package/build/lib/commands/performance.js +4 -9
  59. package/build/lib/commands/performance.js.map +1 -1
  60. package/build/lib/commands/permissions.d.ts.map +1 -1
  61. package/build/lib/commands/permissions.js +2 -4
  62. package/build/lib/commands/permissions.js.map +1 -1
  63. package/build/lib/commands/recordscreen.d.ts.map +1 -1
  64. package/build/lib/commands/recordscreen.js +1 -2
  65. package/build/lib/commands/recordscreen.js.map +1 -1
  66. package/build/lib/commands/screenshots.d.ts +3 -2
  67. package/build/lib/commands/screenshots.d.ts.map +1 -1
  68. package/build/lib/commands/screenshots.js +8 -3
  69. package/build/lib/commands/screenshots.js.map +1 -1
  70. package/build/lib/commands/web.d.ts.map +1 -1
  71. package/build/lib/commands/web.js +1 -2
  72. package/build/lib/commands/web.js.map +1 -1
  73. package/build/lib/commands/xctest-record-screen.d.ts.map +1 -1
  74. package/build/lib/commands/xctest-record-screen.js +2 -4
  75. package/build/lib/commands/xctest-record-screen.js.map +1 -1
  76. package/build/lib/commands/xctest.d.ts.map +1 -1
  77. package/build/lib/commands/xctest.js +2 -4
  78. package/build/lib/commands/xctest.js.map +1 -1
  79. package/build/lib/devicectl.d.ts.map +1 -1
  80. package/build/lib/devicectl.js +4 -1
  81. package/build/lib/devicectl.js.map +1 -1
  82. package/build/lib/driver.d.ts +26 -8
  83. package/build/lib/driver.d.ts.map +1 -1
  84. package/build/lib/driver.js +75 -77
  85. package/build/lib/driver.js.map +1 -1
  86. package/build/lib/py-ios-device-client.d.ts +1 -1
  87. package/build/lib/real-device-management.d.ts +30 -27
  88. package/build/lib/real-device-management.d.ts.map +1 -1
  89. package/build/lib/real-device-management.js +34 -35
  90. package/build/lib/real-device-management.js.map +1 -1
  91. package/build/lib/real-device.d.ts +36 -9
  92. package/build/lib/real-device.d.ts.map +1 -1
  93. package/build/lib/real-device.js +46 -15
  94. package/build/lib/real-device.js.map +1 -1
  95. package/build/lib/simulator-management.d.ts +58 -68
  96. package/build/lib/simulator-management.d.ts.map +1 -1
  97. package/build/lib/simulator-management.js +74 -66
  98. package/build/lib/simulator-management.js.map +1 -1
  99. package/lib/commands/app-management.js +11 -18
  100. package/lib/commands/appearance.js +4 -4
  101. package/lib/commands/biometric.js +3 -6
  102. package/lib/commands/certificate.js +3 -5
  103. package/lib/commands/condition.js +2 -4
  104. package/lib/commands/context.js +1 -2
  105. package/lib/commands/deviceInfo.js +1 -2
  106. package/lib/commands/file-movement.js +14 -22
  107. package/lib/commands/general.js +1 -2
  108. package/lib/commands/gesture.js +1 -2
  109. package/lib/commands/keychains.js +2 -2
  110. package/lib/commands/localization.js +1 -4
  111. package/lib/commands/location.js +1 -2
  112. package/lib/commands/log.js +2 -4
  113. package/lib/commands/memory.js +2 -2
  114. package/lib/commands/notifications.js +1 -2
  115. package/lib/commands/pasteboard.js +4 -4
  116. package/lib/commands/pcap.js +1 -2
  117. package/lib/commands/performance.js +4 -8
  118. package/lib/commands/permissions.js +6 -4
  119. package/lib/commands/recordscreen.js +1 -2
  120. package/lib/commands/screenshots.js +8 -3
  121. package/lib/commands/web.js +1 -2
  122. package/lib/commands/xctest-record-screen.js +2 -4
  123. package/lib/commands/xctest.js +2 -4
  124. package/lib/devicectl.js +4 -1
  125. package/lib/driver.js +79 -78
  126. package/lib/real-device-management.js +37 -44
  127. package/lib/real-device.js +47 -17
  128. package/lib/simulator-management.js +83 -82
  129. package/npm-shrinkwrap.json +7 -29
  130. package/package.json +2 -2
@@ -2,7 +2,7 @@ import {fs, timing, util} from 'appium/support';
2
2
  import path from 'path';
3
3
  import {services, utilities, INSTRUMENT_CHANNEL} from 'appium-ios-device';
4
4
  import B from 'bluebird';
5
- import log from './logger';
5
+ import defaultLogger from './logger';
6
6
  import _ from 'lodash';
7
7
  import {exec} from 'teen_process';
8
8
  import {extractBundleId} from './app-utils';
@@ -20,12 +20,27 @@ const APP_INSTALL_STRATEGY = Object.freeze({
20
20
  IOS_DEPLOY,
21
21
  });
22
22
 
23
- class RealDevice {
23
+ export class RealDevice {
24
+ /**
25
+ * @param {string} udid
26
+ * @param {import('@appium/types').AppiumLogger} [logger]
27
+ */
24
28
  constructor(udid, logger) {
25
29
  this.udid = udid;
26
- this.devicectl = new Devicectl(this.udid, logger);
30
+ this._log = logger ?? defaultLogger;
31
+ this.devicectl = new Devicectl(this.udid, this._log);
32
+ }
33
+
34
+ /**
35
+ * @returns {import('@appium/types').AppiumLogger}
36
+ */
37
+ get log() {
38
+ return this._log;
27
39
  }
28
40
 
41
+ /**
42
+ * @param {string} bundleId
43
+ */
29
44
  async remove(bundleId) {
30
45
  const service = await services.startInstallationProxyService(this.udid);
31
46
  try {
@@ -35,6 +50,9 @@ class RealDevice {
35
50
  }
36
51
  }
37
52
 
53
+ /**
54
+ * @param {string} bundleId
55
+ */
38
56
  async removeApp(bundleId) {
39
57
  await this.remove(bundleId);
40
58
  }
@@ -56,7 +74,7 @@ class RealDevice {
56
74
  `Only the following strategies are supported: ${_.values(APP_INSTALL_STRATEGY)}`,
57
75
  );
58
76
  }
59
- log.debug(
77
+ this.log.debug(
60
78
  `Using '${strategy ?? APP_INSTALL_STRATEGY.SERIAL}' app deployment strategy. ` +
61
79
  `You could change it by providing another value to the 'appInstallStrategy' capability`,
62
80
  );
@@ -94,11 +112,11 @@ class RealDevice {
94
112
  await this.isAppInstalled(bundleId),
95
113
  );
96
114
  } catch (err) {
97
- log.warn(`Error installing app '${app}': ${err.message}`);
115
+ this.log.warn(`Error installing app '${app}': ${err.message}`);
98
116
  if (err instanceof B.TimeoutError) {
99
- log.warn(`Consider increasing the value of 'appPushTimeout' capability`);
117
+ this.log.warn(`Consider increasing the value of 'appPushTimeout' capability`);
100
118
  }
101
- log.warn(`Falling back to '${IOS_DEPLOY}' usage`);
119
+ this.log.warn(`Falling back to '${IOS_DEPLOY}' usage`);
102
120
  try {
103
121
  await installWithIosDeploy();
104
122
  } catch (err1) {
@@ -110,9 +128,13 @@ class RealDevice {
110
128
  afcService.close();
111
129
  }
112
130
  }
113
- log.info(`App installation succeeded after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
131
+ this.log.info(`App installation succeeded after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
114
132
  }
115
133
 
134
+ /**
135
+ * @param {string} bundlePathOnPhone
136
+ * @param {boolean} [isUpgrade=false]
137
+ */
116
138
  async installOrUpgradeApplication(bundlePathOnPhone, isUpgrade = false) {
117
139
  const notificationService = await services.startNotificationProxyService(this.udid);
118
140
  const installationService = await services.startInstallationProxyService(this.udid);
@@ -124,10 +146,10 @@ class RealDevice {
124
146
  const clientOptions = {PackageType: 'Developer'};
125
147
  try {
126
148
  if (isUpgrade) {
127
- log.debug(`An upgrade of the existing application is going to be performed`);
149
+ this.log.debug(`An upgrade of the existing application is going to be performed`);
128
150
  await installationService.upgradeApplication(bundlePathOnPhone, clientOptions);
129
151
  } else {
130
- log.debug(`A new application installation is going to be performed`);
152
+ this.log.debug(`A new application installation is going to be performed`);
131
153
  await installationService.installApplication(bundlePathOnPhone, clientOptions);
132
154
  }
133
155
  try {
@@ -137,7 +159,7 @@ class RealDevice {
137
159
  `${APPLICATION_NOTIFICATION_TIMEOUT_MS}ms but we will continue`,
138
160
  );
139
161
  } catch (e) {
140
- log.warn(`Failed to receive the notification. Error: ${e.message}`);
162
+ this.log.warn(`Failed to receive the notification. Error: ${e.message}`);
141
163
  }
142
164
  } finally {
143
165
  installationService.close();
@@ -194,6 +216,11 @@ class RealDevice {
194
216
  }
195
217
  }
196
218
 
219
+ /**
220
+ * @param {string} bundleId
221
+ * @param {string} platformVersion
222
+ * @returns {Promise<boolean>}
223
+ */
197
224
  async terminateApp(bundleId, platformVersion) {
198
225
  let instrumentService;
199
226
  let installProxyService;
@@ -203,22 +230,22 @@ class RealDevice {
203
230
  returnAttributes: ['CFBundleIdentifier', 'CFBundleExecutable']
204
231
  });
205
232
  if (!apps[bundleId]) {
206
- log.info(`The bundle id '${bundleId}' did not exist`);
233
+ this.log.info(`The bundle id '${bundleId}' did not exist`);
207
234
  return false;
208
235
  }
209
236
  const executableName = apps[bundleId].CFBundleExecutable;
210
- log.debug(`The executable name for the bundle id '${bundleId}' was '${executableName}'`);
237
+ this.log.debug(`The executable name for the bundle id '${bundleId}' was '${executableName}'`);
211
238
 
212
239
  // 'devicectl' has overhead (generally?) than the instrument service via appium-ios-device,
213
240
  // so hre uses the 'devicectl' only for iOS 17+.
214
241
  if (util.compareVersions(platformVersion, '>=', '17.0')) {
215
- log.debug(`Calling devicectl to kill the process`);
242
+ this.log.debug(`Calling devicectl to kill the process`);
216
243
 
217
244
  const pids = (await this.devicectl.listProcesses())
218
245
  .filter(({executable}) => executable.endsWith(`/${executableName}`))
219
246
  .map(({processIdentifier}) => processIdentifier);
220
247
  if (_.isEmpty(pids)) {
221
- log.info(`The process of the bundle id '${bundleId}' was not running`);
248
+ this.log.info(`The process of the bundle id '${bundleId}' was not running`);
222
249
  return false;
223
250
  }
224
251
  await this.devicectl.sendSignalToProcess(pids[0], 2);
@@ -230,7 +257,7 @@ class RealDevice {
230
257
  );
231
258
  const process = processes.selector.find((process) => process.name === executableName);
232
259
  if (!process) {
233
- log.info(`The process of the bundle id '${bundleId}' was not running`);
260
+ this.log.info(`The process of the bundle id '${bundleId}' was not running`);
234
261
  return false;
235
262
  }
236
263
  await instrumentService.callChannel(
@@ -240,7 +267,7 @@ class RealDevice {
240
267
  );
241
268
  }
242
269
  } catch (err) {
243
- log.warn(`Failed to kill '${bundleId}'. Original error: ${err.stderr || err.message}`);
270
+ this.log.warn(`Failed to kill '${bundleId}'. Original error: ${err.stderr || err.message}`);
244
271
  return false;
245
272
  } finally {
246
273
  if (installProxyService) {
@@ -280,6 +307,9 @@ class RealDevice {
280
307
  }
281
308
  }
282
309
 
310
+ /**
311
+ * @returns {Promise<string>}
312
+ */
283
313
  async getPlatformVersion() {
284
314
  return await utilities.getOSVersion(this.udid);
285
315
  }
@@ -2,7 +2,6 @@ import {getSimulator} from 'appium-ios-simulator';
2
2
  import Simctl from 'node-simctl';
3
3
  import {resetTestProcesses} from 'appium-webdriveragent';
4
4
  import _ from 'lodash';
5
- import log from './logger';
6
5
  import {util, timing} from 'appium/support';
7
6
  import {UDID_AUTO, normalizePlatformName} from './utils';
8
7
 
@@ -16,22 +15,15 @@ const SAFARI_OPTS_ALIASES_MAP = /** @type {const} */ ({
16
15
  safariOpenLinksInBackground: [['OpenLinksInBackground'], (x) => Number(Boolean(x))],
17
16
  });
18
17
 
19
- /**
20
- * @typedef {Object} SimulatorCreationOptions
21
- * @property {string} deviceName - A name for the device
22
- * @property {string} platformVersion - The version of iOS to use
23
- * @property {string} [simulatorDevicesSetPath]
24
- * @property {string} [platformName]
25
- */
26
18
  /**
27
19
  * Create a new simulator with `appiumTest-` prefix and return the object.
28
20
  *
29
- * @param {Partial<SimulatorCreationOptions>} caps - Capability set by a user. The options available are:
21
+ * @this {import('./driver').XCUITestDriver}
30
22
  * @returns {Promise<object>} Simulator object associated with the udid passed in.
31
23
  */
32
- async function createSim(caps) {
33
- const {simulatorDevicesSetPath: devicesSetPath, deviceName, platformVersion} = caps;
34
- const platform = normalizePlatformName(caps.platformName);
24
+ export async function createSim() {
25
+ const {simulatorDevicesSetPath: devicesSetPath, deviceName, platformVersion} = this.opts;
26
+ const platform = normalizePlatformName(this.opts.platformName);
35
27
  const simctl = new Simctl({devicesSetPath});
36
28
  if (!deviceName) {
37
29
  let deviceNames = 'none';
@@ -51,12 +43,13 @@ async function createSim(caps) {
51
43
  }
52
44
 
53
45
  const simName = `${APPIUM_SIM_PREFIX}-${util.uuidV4().toUpperCase()}-${deviceName}`;
54
- log.debug(`Creating a temporary Simulator device '${simName}'`);
46
+ this.log.debug(`Creating a temporary Simulator device '${simName}'`);
55
47
  const udid = await simctl.createDevice(simName, deviceName, platformVersion, {platform});
56
48
  return await getSimulator(udid, {
57
49
  platform,
58
50
  checkExistence: false,
59
51
  devicesSetPath,
52
+ logger: this.log,
60
53
  });
61
54
  }
62
55
 
@@ -72,24 +65,31 @@ async function createSim(caps) {
72
65
  /**
73
66
  * Get an existing simulator matching the provided capabilities.
74
67
  *
75
- * @param {SimulatorLookupOptions} opts
76
- * @returns {Promise<any|null>} The matched Simulator instance or `null` if no matching device is found.
68
+ * @this {import('./driver').XCUITestDriver}
69
+ * @returns {Promise<import('./driver').Simulator|null>} The matched Simulator instance or `null` if no matching device is found.
77
70
  */
78
- async function getExistingSim(opts = /** @type {SimulatorLookupOptions} */ ({})) {
79
- const {platformVersion, deviceName, udid, simulatorDevicesSetPath: devicesSetPath} = opts;
71
+ export async function getExistingSim() {
72
+ const {
73
+ platformVersion,
74
+ deviceName,
75
+ udid,
76
+ simulatorDevicesSetPath: devicesSetPath,
77
+ platformName,
78
+ } = this.opts;
80
79
 
81
- const platform = normalizePlatformName(opts.platformName);
80
+ const platform = normalizePlatformName(platformName);
82
81
  const selectSim = async (/** @type {{ udid: string; platform: string; }} */ dev) =>
83
82
  await getSimulator(dev.udid, {
84
83
  platform,
85
84
  checkExistence: false,
86
85
  devicesSetPath,
86
+ logger: this.log,
87
87
  });
88
88
 
89
89
  const simctl = new Simctl({devicesSetPath});
90
90
  let devicesMap;
91
91
  if (udid && _.toLower(udid) !== UDID_AUTO) {
92
- log.debug(`Looking for an existing Simulator with UDID '${udid}'`);
92
+ this.log.debug(`Looking for an existing Simulator with UDID '${udid}'`);
93
93
  devicesMap = await simctl.getDevices(null, platform);
94
94
  for (const device of _.flatMap(_.values(devicesMap))) {
95
95
  if (device.udid === udid) {
@@ -100,7 +100,7 @@ async function getExistingSim(opts = /** @type {SimulatorLookupOptions} */ ({}))
100
100
  }
101
101
 
102
102
  if (!platformVersion) {
103
- log.debug(
103
+ this.log.debug(
104
104
  `Provide 'platformVersion' capability if you prefer an existing Simulator to be selected`,
105
105
  );
106
106
  return null;
@@ -108,14 +108,14 @@ async function getExistingSim(opts = /** @type {SimulatorLookupOptions} */ ({}))
108
108
 
109
109
  const devices =
110
110
  devicesMap?.[platformVersion] ?? (await simctl.getDevices(platformVersion, platform));
111
- log.debug(
111
+ this.log.debug(
112
112
  `Looking for an existing Simulator with platformName: ${platform}, ` +
113
113
  `platformVersion: ${platformVersion}, deviceName: ${deviceName}`,
114
114
  );
115
115
  for (const device of devices) {
116
116
  if ((deviceName && device.name === deviceName) || !deviceName) {
117
117
  if (!deviceName) {
118
- log.debug(
118
+ this.log.debug(
119
119
  `The 'deviceName' capability value is empty. ` +
120
120
  `Selecting the first matching device '${device.name}' having the ` +
121
121
  `'platformVersion' set to ${platformVersion}`,
@@ -127,13 +127,22 @@ async function getExistingSim(opts = /** @type {SimulatorLookupOptions} */ ({}))
127
127
  return null;
128
128
  }
129
129
 
130
- async function shutdownSimulator(device) {
130
+ /**
131
+ * @this {import('./driver').XCUITestDriver}
132
+ */
133
+ export async function shutdownSimulator() {
134
+ const device = /** @type {import('./driver').Simulator} */ (this.device);
131
135
  // stop XCTest processes if running to avoid unexpected side effects
132
136
  await resetTestProcesses(device.udid, true);
133
137
  await device.shutdown();
134
138
  }
135
139
 
136
- async function runSimulatorReset(device, opts) {
140
+ /**
141
+ * @this {import('./driver').XCUITestDriver}
142
+ * @property {boolean} [enforceSimulatorShutdown=false]
143
+ * @returns {Promise<void>}
144
+ */
145
+ export async function runSimulatorReset(enforceSimulatorShutdown = false) {
137
146
  const {
138
147
  noReset,
139
148
  fullReset,
@@ -142,29 +151,29 @@ async function runSimulatorReset(device, opts) {
142
151
  bundleId,
143
152
  app,
144
153
  browserName,
145
- enforceSimulatorShutdown,
146
- } = opts;
154
+ } = this.opts;
147
155
  if (noReset && !fullReset) {
148
156
  // noReset === true && fullReset === false
149
- log.debug('Reset: noReset is on. Leaving simulator as is');
157
+ this.log.debug('Reset: noReset is on. Leaving simulator as is');
150
158
  return;
151
159
  }
152
- if (!device) {
153
- log.debug('Reset: no device available. Skipping');
160
+ const device = /** @type {import('./driver').Simulator} */ (this.device);
161
+
162
+ if (!this.device) {
163
+ this.log.debug('Reset: no device available. Skipping');
154
164
  return;
155
165
  }
156
166
 
157
167
  if (fullReset) {
158
- log.debug('Reset: fullReset is on. Cleaning simulator');
159
- await shutdownSimulator(device);
160
- const isKeychainsBackupSuccessful =
161
- (keychainsExcludePatterns || keepKeyChains) && (await device.backupKeychains());
168
+ this.log.debug('Reset: fullReset is on. Cleaning simulator');
169
+ await shutdownSimulator.bind(this)();
170
+ const isKeychainsBackupSuccessful = (keychainsExcludePatterns || keepKeyChains) && (await device.backupKeychains());
162
171
  await device.clean();
163
172
  if (isKeychainsBackupSuccessful) {
164
173
  await device.restoreKeychains(keychainsExcludePatterns || []);
165
- log.info(`Successfully restored keychains after full reset`);
174
+ this.log.info(`Successfully restored keychains after full reset`);
166
175
  } else if (keychainsExcludePatterns || keepKeyChains) {
167
- log.warn(
176
+ this.log.warn(
168
177
  'Cannot restore keychains after full reset, because ' +
169
178
  'the backup operation did not succeed',
170
179
  );
@@ -176,32 +185,32 @@ async function runSimulatorReset(device, opts) {
176
185
  try {
177
186
  await device.terminateApp(bundleId);
178
187
  } catch (err) {
179
- log.warn(`Reset: failed to terminate Simulator application with id "${bundleId}"`);
188
+ this.log.warn(`Reset: failed to terminate Simulator application with id "${bundleId}"`);
180
189
  }
181
190
 
182
191
  if (app) {
183
- log.info('Not scrubbing third party app in anticipation of uninstall');
192
+ this.log.info('Not scrubbing third party app in anticipation of uninstall');
184
193
  } else {
185
194
  const isSafari = _.toLower(browserName) === 'safari';
186
195
  try {
187
196
  if (isSafari) {
188
- await device.scrubSafari();
197
+ await device.scrubSafari(true);
189
198
  } else {
190
199
  await device.scrubApp(bundleId);
191
200
  }
192
201
  } catch (err) {
193
- log.debug(err.stack);
194
- log.warn(err.message);
195
- log.warn(
202
+ this.log.debug(err.stack);
203
+ this.log.warn(err.message);
204
+ this.log.warn(
196
205
  `Reset: could not scrub ${
197
- isSafari ? 'Safari browser' : 'application with id "' + opts.bundleId + '"'
206
+ isSafari ? 'Safari browser' : 'application with id "' + this.opts.bundleId + '"'
198
207
  }. ` + `Leaving as is.`,
199
208
  );
200
209
  }
201
210
  }
202
211
 
203
212
  if (enforceSimulatorShutdown && (await device.isRunning())) {
204
- await shutdownSimulator(device);
213
+ await shutdownSimulator.bind(this)(device);
205
214
  }
206
215
  }
207
216
  }
@@ -214,48 +223,52 @@ async function runSimulatorReset(device, opts) {
214
223
  */
215
224
 
216
225
  /**
217
- * @param {any} device The simulator device object
226
+ * @this {import('./driver').XCUITestDriver}
218
227
  * @param {string} app The app to the path
219
228
  * @param {string} [bundleId] The bundle id to ensure it is already installed and uninstall it
220
- * @param {InstallOptions} opts
229
+ * @param {InstallOptions} [opts={}]
221
230
  */
222
- async function installToSimulator(
223
- device,
231
+ export async function installToSimulator(
224
232
  app,
225
233
  bundleId,
226
- opts = /** @type {InstallOptions} */ ({}),
234
+ opts = {},
227
235
  ) {
228
236
  if (!app) {
229
- log.debug('No app path is given. Nothing to install.');
237
+ this.log.debug('No app path is given. Nothing to install.');
230
238
  return;
231
239
  }
232
240
 
233
241
  const {skipUninstall, newSimulator = false} = opts;
242
+ const device = /** @type {import('./driver').Simulator} */ (this.device);
234
243
 
235
244
  if (!skipUninstall && !newSimulator && bundleId && (await device.isAppInstalled(bundleId))) {
236
- log.debug(`Reset requested. Removing app with id '${bundleId}' from the device`);
245
+ this.log.debug(`Reset requested. Removing app with id '${bundleId}' from the device`);
237
246
  await device.removeApp(bundleId);
238
247
  }
239
248
 
240
- log.debug(`Installing '${app}' on Simulator with UUID '${device.udid}'...`);
249
+ this.log.debug(`Installing '${app}' on Simulator with UUID '${device.udid}'...`);
241
250
  const timer = new timing.Timer().start();
242
251
  await device.installApp(app);
243
- log.info(`The app has been successfully installed in ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
252
+ this.log.info(`The app has been successfully installed in ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`);
244
253
  }
245
254
 
246
- async function shutdownOtherSimulators(currentDevice) {
255
+ /**
256
+ * @this {import('./driver').XCUITestDriver}
257
+ */
258
+ export async function shutdownOtherSimulators() {
259
+ const device = /** @type {import('./driver').Simulator} */ (this.device);
247
260
  const simctl = new Simctl({
248
- devicesSetPath: currentDevice.devicesSetPath,
261
+ devicesSetPath: device.devicesSetPath,
249
262
  });
250
263
  const allDevices = _.flatMap(_.values(await simctl.getDevices()));
251
264
  const otherBootedDevices = allDevices.filter(
252
- (device) => device.udid !== currentDevice.udid && device.state === 'Booted',
265
+ (device) => device.udid !== device.udid && device.state === 'Booted',
253
266
  );
254
267
  if (_.isEmpty(otherBootedDevices)) {
255
- log.info('No other running simulators have been detected');
268
+ this.log.info('No other running simulators have been detected');
256
269
  return;
257
270
  }
258
- log.info(
271
+ this.log.info(
259
272
  `Detected ${otherBootedDevices.length} other running ${util.pluralize(
260
273
  'Simulator',
261
274
  otherBootedDevices.length,
@@ -273,40 +286,39 @@ async function shutdownOtherSimulators(currentDevice) {
273
286
  /**
274
287
  * Configures Safari options based on the given session capabilities
275
288
  *
276
- * @param {any} sim Simulator instance
277
- * @param {object} opts Session capabilities
289
+ * @this {import('./driver').XCUITestDriver}
278
290
  * @return {Promise<boolean>} true if any preferences have been updated
279
291
  */
280
- async function setSafariPrefs(sim, opts = {}) {
281
- const safariSettings = _.cloneDeep(opts.safariGlobalPreferences ?? {});
292
+ export async function setSafariPrefs() {
293
+ const safariSettings = _.cloneDeep(this.opts.safariGlobalPreferences ?? {});
282
294
 
283
295
  for (const [name, [aliases, valueConverter]] of _.toPairs(SAFARI_OPTS_ALIASES_MAP)) {
284
- if (!_.has(opts, name)) {
296
+ if (!_.has(this.opts, name)) {
285
297
  continue;
286
298
  }
287
299
 
288
300
  for (const alias of aliases) {
289
- safariSettings[alias] = valueConverter(opts[name]);
301
+ safariSettings[alias] = valueConverter(this.opts[name]);
290
302
  }
291
303
  }
292
304
  if (_.isEmpty(safariSettings)) {
293
305
  return false;
294
306
  }
295
307
 
296
- log.debug(`About to update Safari preferences: ${JSON.stringify(safariSettings)}`);
297
- await sim.updateSafariSettings(safariSettings);
308
+ this.log.debug(`About to update Safari preferences: ${JSON.stringify(safariSettings)}`);
309
+ await /** @type {import('./driver').Simulator} */ (this.device).updateSafariSettings(safariSettings);
298
310
  return true;
299
311
  }
300
312
 
301
313
  /**
302
314
  * Changes Simulator localization preferences
303
315
  *
304
- * @param {any} sim Simulator instance
305
- * @param {object} opts Session capabilities
316
+ * @this {import('./driver').XCUITestDriver}
306
317
  * @returns {Promise<boolean>} True if preferences were changed
307
318
  */
308
- async function setLocalizationPrefs(sim, opts = {}) {
309
- const {language, locale, calendarFormat, skipSyncUiDialogTranslation} = opts;
319
+ export async function setLocalizationPrefs() {
320
+ const {language, locale, calendarFormat, skipSyncUiDialogTranslation} = this.opts;
321
+ /** @type {import('appium-ios-simulator').LocalizationOptions} */
310
322
  const l10nConfig = {};
311
323
  if (language) {
312
324
  l10nConfig.language = {name: language, skipSyncUiDialogTranslation };
@@ -321,18 +333,7 @@ async function setLocalizationPrefs(sim, opts = {}) {
321
333
  return false;
322
334
  }
323
335
 
324
- log.debug(`About to update localization preferences: ${JSON.stringify(l10nConfig)}`);
325
- await sim.configureLocalization(l10nConfig);
336
+ this.log.debug(`About to update localization preferences: ${JSON.stringify(l10nConfig)}`);
337
+ await /** @type {import('./driver').Simulator} */ (this.device).configureLocalization(l10nConfig);
326
338
  return true;
327
339
  }
328
-
329
- export {
330
- createSim,
331
- getExistingSim,
332
- runSimulatorReset,
333
- installToSimulator,
334
- shutdownSimulator,
335
- shutdownOtherSimulators,
336
- setSafariPrefs,
337
- setLocalizationPrefs,
338
- };
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "appium-xcuitest-driver",
3
- "version": "7.6.0",
3
+ "version": "7.7.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "appium-xcuitest-driver",
9
- "version": "7.6.0",
9
+ "version": "7.7.0",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@colors/colors": "^1.6.0",
13
13
  "appium-idb": "^1.6.13",
14
14
  "appium-ios-device": "^2.5.4",
15
- "appium-ios-simulator": "^5.5.1",
15
+ "appium-ios-simulator": "^6.1.2",
16
16
  "appium-remote-debugger": "^11.0.0",
17
17
  "appium-webdriveragent": "^8.1.0",
18
18
  "appium-xcode": "^5.1.4",
@@ -955,9 +955,9 @@
955
955
  }
956
956
  },
957
957
  "node_modules/appium-ios-simulator": {
958
- "version": "5.5.3",
959
- "resolved": "https://registry.npmjs.org/appium-ios-simulator/-/appium-ios-simulator-5.5.3.tgz",
960
- "integrity": "sha512-dP3MMFXcewYIfd6Efewae6X0o/XU8/GPyY2alhMCMqdLucoR/tx7+mL7UJyMEPJsvPVRPXrej7yKOoljDVEU0w==",
958
+ "version": "6.1.2",
959
+ "resolved": "https://registry.npmjs.org/appium-ios-simulator/-/appium-ios-simulator-6.1.2.tgz",
960
+ "integrity": "sha512-uE/qHQvf5WfogsjpPFo+iJE6NVTFCJReV3RxP0TwN/qYvbRWxJFMwpHzx6VGy7Lp86B2O+0ZWgkTDPZ1iJxAKw==",
961
961
  "dependencies": {
962
962
  "@appium/support": "^4.0.0",
963
963
  "@xmldom/xmldom": "^0.x",
@@ -966,7 +966,7 @@
966
966
  "asyncbox": "^3.0.0",
967
967
  "bluebird": "^3.5.1",
968
968
  "lodash": "^4.2.1",
969
- "node-simctl": "^7.1.0",
969
+ "node-simctl": "^7.4.1",
970
970
  "semver": "^7.0.0",
971
971
  "source-map-support": "^0.x",
972
972
  "teen_process": "^2.0.0"
@@ -1021,28 +1021,6 @@
1021
1021
  "npm": ">=8"
1022
1022
  }
1023
1023
  },
1024
- "node_modules/appium-webdriveragent/node_modules/appium-ios-simulator": {
1025
- "version": "6.1.1",
1026
- "resolved": "https://registry.npmjs.org/appium-ios-simulator/-/appium-ios-simulator-6.1.1.tgz",
1027
- "integrity": "sha512-fXTY29QCYRuTj2ZFXscOc6FzOUfogg9zHtakSP7EYlRtvFg60qPl7y3kE4JMbHERaL0lq+0k0lnlaHVzTEsPPw==",
1028
- "dependencies": {
1029
- "@appium/support": "^4.0.0",
1030
- "@xmldom/xmldom": "^0.x",
1031
- "appium-xcode": "^5.0.0",
1032
- "async-lock": "^1.0.0",
1033
- "asyncbox": "^3.0.0",
1034
- "bluebird": "^3.5.1",
1035
- "lodash": "^4.2.1",
1036
- "node-simctl": "^7.4.1",
1037
- "semver": "^7.0.0",
1038
- "source-map-support": "^0.x",
1039
- "teen_process": "^2.0.0"
1040
- },
1041
- "engines": {
1042
- "node": ">=14",
1043
- "npm": ">=8"
1044
- }
1045
- },
1046
1024
  "node_modules/appium-xcode": {
1047
1025
  "version": "5.2.11",
1048
1026
  "resolved": "https://registry.npmjs.org/appium-xcode/-/appium-xcode-5.2.11.tgz",
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "xcuitest",
9
9
  "xctest"
10
10
  ],
11
- "version": "7.6.0",
11
+ "version": "7.7.0",
12
12
  "author": "Appium Contributors",
13
13
  "license": "Apache-2.0",
14
14
  "repository": {
@@ -79,7 +79,7 @@
79
79
  "@colors/colors": "^1.6.0",
80
80
  "appium-idb": "^1.6.13",
81
81
  "appium-ios-device": "^2.5.4",
82
- "appium-ios-simulator": "^5.5.1",
82
+ "appium-ios-simulator": "^6.1.2",
83
83
  "appium-remote-debugger": "^11.0.0",
84
84
  "appium-webdriveragent": "^8.1.0",
85
85
  "appium-xcode": "^5.1.4",