appium-ios-simulator 8.0.13 → 8.1.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 (48) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/build/lib/defaults-utils.d.ts +24 -24
  3. package/build/lib/defaults-utils.d.ts.map +1 -1
  4. package/build/lib/defaults-utils.js +61 -65
  5. package/build/lib/defaults-utils.js.map +1 -1
  6. package/build/lib/extensions/applications.d.ts.map +1 -1
  7. package/build/lib/extensions/applications.js +6 -7
  8. package/build/lib/extensions/applications.js.map +1 -1
  9. package/build/lib/extensions/biometric.d.ts.map +1 -1
  10. package/build/lib/extensions/biometric.js +3 -6
  11. package/build/lib/extensions/biometric.js.map +1 -1
  12. package/build/lib/extensions/keychain.d.ts.map +1 -1
  13. package/build/lib/extensions/keychain.js +7 -6
  14. package/build/lib/extensions/keychain.js.map +1 -1
  15. package/build/lib/extensions/permissions.d.ts.map +1 -1
  16. package/build/lib/extensions/permissions.js +16 -18
  17. package/build/lib/extensions/permissions.js.map +1 -1
  18. package/build/lib/extensions/safari.d.ts.map +1 -1
  19. package/build/lib/extensions/safari.js +2 -4
  20. package/build/lib/extensions/safari.js.map +1 -1
  21. package/build/lib/extensions/settings.d.ts.map +1 -1
  22. package/build/lib/extensions/settings.js +52 -50
  23. package/build/lib/extensions/settings.js.map +1 -1
  24. package/build/lib/simulator-xcode-14.d.ts +37 -37
  25. package/build/lib/simulator-xcode-14.d.ts.map +1 -1
  26. package/build/lib/simulator-xcode-14.js +57 -59
  27. package/build/lib/simulator-xcode-14.js.map +1 -1
  28. package/build/lib/simulator-xcode-15.d.ts.map +1 -1
  29. package/build/lib/simulator-xcode-15.js +3 -5
  30. package/build/lib/simulator-xcode-15.js.map +1 -1
  31. package/build/lib/types.d.ts +8 -8
  32. package/build/lib/types.d.ts.map +1 -1
  33. package/build/lib/utils.d.ts +11 -3
  34. package/build/lib/utils.d.ts.map +1 -1
  35. package/build/lib/utils.js +50 -35
  36. package/build/lib/utils.js.map +1 -1
  37. package/lib/defaults-utils.ts +69 -68
  38. package/lib/extensions/applications.ts +6 -7
  39. package/lib/extensions/biometric.ts +3 -3
  40. package/lib/extensions/keychain.ts +11 -6
  41. package/lib/extensions/permissions.ts +17 -19
  42. package/lib/extensions/safari.ts +2 -4
  43. package/lib/extensions/settings.ts +71 -62
  44. package/lib/simulator-xcode-14.ts +70 -71
  45. package/lib/simulator-xcode-15.ts +3 -5
  46. package/lib/types.ts +9 -9
  47. package/lib/utils.ts +52 -37
  48. package/package.json +1 -5
@@ -1,10 +1,9 @@
1
- import _ from 'lodash';
2
1
  import {NSUserDefaults, generateDefaultsCommandArgs} from '../defaults-utils';
3
- import B from 'bluebird';
4
2
  import path from 'node:path';
5
3
  import {exec} from 'teen_process';
6
4
  import AsyncLock from 'async-lock';
7
5
  import {fs} from '@appium/support';
6
+ import {isPlainObject} from '../utils';
8
7
  import type {
9
8
  CoreSimulator,
10
9
  HasSettings,
@@ -90,12 +89,12 @@ export async function updateSettings(
90
89
  domain: string,
91
90
  updates: StringRecord,
92
91
  ): Promise<boolean> {
93
- if (_.isEmpty(updates)) {
92
+ if (Object.keys(updates).length === 0) {
94
93
  return false;
95
94
  }
96
95
 
97
96
  const argChunks = generateDefaultsCommandArgs(updates);
98
- await B.all(
97
+ await Promise.all(
99
98
  argChunks.map((args) => this.simctl.spawnProcess(['defaults', 'write', domain, ...args])),
100
99
  );
101
100
  return true;
@@ -111,7 +110,7 @@ export async function updateSettings(
111
110
  * @since Xcode SDK 11.4
112
111
  */
113
112
  export async function setAppearance(this: CoreSimulatorWithSettings, value: string): Promise<void> {
114
- await this.simctl.setAppearance(_.toLower(value));
113
+ await this.simctl.setAppearance(value.toLowerCase());
115
114
  }
116
115
 
117
116
  /**
@@ -203,14 +202,14 @@ export async function configureLocalization(
203
202
  this: CoreSimulatorWithSettings,
204
203
  opts: LocalizationOptions = {},
205
204
  ): Promise<boolean> {
206
- if (_.isEmpty(opts)) {
205
+ if (Object.keys(opts).length === 0) {
207
206
  return false;
208
207
  }
209
208
 
210
209
  const {language, locale, keyboard} = opts;
211
210
  const globalPrefs: Record<string, any> = {};
212
211
  let keyboardId: string | null = null;
213
- if (_.isPlainObject(keyboard) && keyboard) {
212
+ if (isPlainObject(keyboard)) {
214
213
  const {name, layout, hardware} = keyboard;
215
214
  if (!name) {
216
215
  throw new Error(`The 'keyboard' field must have a valid name set`);
@@ -224,14 +223,14 @@ export async function configureLocalization(
224
223
  }
225
224
  globalPrefs.AppleKeyboards = [keyboardId];
226
225
  }
227
- if (_.isPlainObject(language) && language) {
226
+ if (isPlainObject(language)) {
228
227
  const {name} = language;
229
228
  if (!name) {
230
229
  throw new Error(`The 'language' field must have a valid name set`);
231
230
  }
232
231
  globalPrefs.AppleLanguages = [name];
233
232
  }
234
- if (_.isPlainObject(locale) && locale) {
233
+ if (isPlainObject(locale)) {
235
234
  const {name, calendar} = locale;
236
235
  if (!name) {
237
236
  throw new Error(`The 'locale' field must have a valid name set`);
@@ -242,7 +241,7 @@ export async function configureLocalization(
242
241
  }
243
242
  globalPrefs.AppleLocale = localeId;
244
243
  }
245
- if (_.isEmpty(globalPrefs)) {
244
+ if (Object.keys(globalPrefs).length === 0) {
246
245
  return false;
247
246
  }
248
247
 
@@ -265,7 +264,7 @@ export async function configureLocalization(
265
264
  }
266
265
 
267
266
  const argChunks = generateDefaultsCommandArgs(globalPrefs, true);
268
- await B.all(
267
+ await Promise.all(
269
268
  argChunks.map((args) =>
270
269
  this.simctl.spawnProcess(['defaults', 'write', GLOBAL_PREFS_PLIST, ...args]),
271
270
  ),
@@ -280,7 +279,7 @@ export async function configureLocalization(
280
279
  },
281
280
  true,
282
281
  );
283
- await B.all(
282
+ await Promise.all(
284
283
  argChunks.map((args) =>
285
284
  this.simctl.spawnProcess(['defaults', 'write', 'com.apple.Preferences', ...args]),
286
285
  ),
@@ -288,7 +287,7 @@ export async function configureLocalization(
288
287
  }
289
288
 
290
289
  if (globalPrefs.AppleLanguages) {
291
- if (_.isEqual(previousAppleLanguages, globalPrefs.AppleLanguages)) {
290
+ if (JSON.stringify(previousAppleLanguages) === JSON.stringify(globalPrefs.AppleLanguages)) {
292
291
  this.log.info(
293
292
  `The 'AppleLanguages' preference is already set to '${globalPrefs.AppleLanguages}'. ` +
294
293
  `Skipping services reset`,
@@ -303,7 +302,7 @@ export async function configureLocalization(
303
302
  `${SERVICES_FOR_TRANSLATION}. This might have unexpected side effects, ` +
304
303
  `see https://github.com/appium/appium/issues/19440 for more details`,
305
304
  );
306
- await B.all(
305
+ await Promise.all(
307
306
  SERVICES_FOR_TRANSLATION.map((arg) => this.simctl.spawnProcess(['launchctl', 'stop', arg])),
308
307
  );
309
308
  }
@@ -343,12 +342,12 @@ export async function updatePreferences(
343
342
  devicePrefs: DevicePreferences = {},
344
343
  commonPrefs: CommonPreferences = {},
345
344
  ): Promise<boolean> {
346
- if (!_.isEmpty(devicePrefs)) {
345
+ if (Object.keys(devicePrefs).length > 0) {
347
346
  this.log.debug(
348
347
  `Setting preferences of ${this.udid} Simulator to ${JSON.stringify(devicePrefs)}`,
349
348
  );
350
349
  }
351
- if (!_.isEmpty(commonPrefs)) {
350
+ if (Object.keys(commonPrefs).length > 0) {
352
351
  this.log.debug(`Setting common Simulator preferences to ${JSON.stringify(commonPrefs)}`);
353
352
  }
354
353
  const homeFolderPath = process.env.HOME;
@@ -368,16 +367,16 @@ export async function updatePreferences(
368
367
  );
369
368
  return await PREFERENCES_PLIST_GUARD.acquire(this.constructor.name, async () => {
370
369
  const defaults = new NSUserDefaults(plistPath);
371
- const prefsToUpdate = _.clone(commonPrefs);
370
+ const prefsToUpdate = {...commonPrefs};
372
371
  try {
373
- if (!_.isEmpty(devicePrefs)) {
372
+ if (Object.keys(devicePrefs).length > 0) {
374
373
  let existingDevicePrefs: any;
375
374
  const udidKey = this.udid.toUpperCase();
376
375
  if (await fs.exists(plistPath)) {
377
376
  const currentPlistContent = await defaults.asJson();
378
377
  if (
379
- _.isPlainObject(currentPlistContent.DevicePreferences) &&
380
- _.isPlainObject(currentPlistContent.DevicePreferences[udidKey])
378
+ isPlainObject(currentPlistContent.DevicePreferences) &&
379
+ isPlainObject(currentPlistContent.DevicePreferences[udidKey])
381
380
  ) {
382
381
  existingDevicePrefs = currentPlistContent.DevicePreferences[udidKey];
383
382
  }
@@ -427,22 +426,26 @@ export function compileSimulatorPreferences(
427
426
  AttachBootedOnStart: true,
428
427
  };
429
428
  const devicePreferences: DevicePreferences = opts.devicePreferences
430
- ? _.cloneDeep(opts.devicePreferences)
429
+ ? structuredClone(opts.devicePreferences)
431
430
  : {};
432
431
  if (scaleFactor) {
433
432
  devicePreferences.SimulatorWindowLastScale = parseFloat(scaleFactor);
434
433
  }
435
- if (_.isBoolean(connectHardwareKeyboard) || _.isNil(connectHardwareKeyboard)) {
434
+ if (
435
+ typeof connectHardwareKeyboard === 'boolean' ||
436
+ connectHardwareKeyboard === null ||
437
+ connectHardwareKeyboard === undefined
438
+ ) {
436
439
  devicePreferences.ConnectHardwareKeyboard = connectHardwareKeyboard ?? false;
437
440
  commonPreferences.ConnectHardwareKeyboard = connectHardwareKeyboard ?? false;
438
441
  }
439
- if (_.isBoolean(tracePointer)) {
442
+ if (typeof tracePointer === 'boolean') {
440
443
  commonPreferences.ShowSingleTouches = tracePointer;
441
444
  commonPreferences.ShowPinches = tracePointer;
442
445
  commonPreferences.ShowPinchPivotPoint = tracePointer;
443
446
  commonPreferences.HighlightEdgeGestures = tracePointer;
444
447
  }
445
- switch (_.lowerCase(pasteboardAutomaticSync || '')) {
448
+ switch ((pasteboardAutomaticSync || '').toLowerCase()) {
446
449
  case 'on':
447
450
  commonPreferences.PasteboardAutomaticSync = true;
448
451
  break;
@@ -475,52 +478,58 @@ export function verifyDevicePreferences(
475
478
  this: CoreSimulatorWithSettings,
476
479
  prefs: DevicePreferences = {},
477
480
  ): void {
478
- if (_.isEmpty(prefs)) {
481
+ if (Object.keys(prefs).length === 0) {
479
482
  return;
480
483
  }
481
484
 
482
- if (!_.isUndefined(prefs.SimulatorWindowLastScale)) {
483
- if (!_.isNumber(prefs.SimulatorWindowLastScale) || prefs.SimulatorWindowLastScale <= 0) {
484
- throw this.log.errorWithException(
485
- `SimulatorWindowLastScale is expected to be a positive float value. ` +
486
- `'${prefs.SimulatorWindowLastScale}' is assigned instead.`,
487
- );
488
- }
485
+ // https://regex101.com/r/2ZXOij/2
486
+ const simulatorWindowCenterPattern = /{-?\d+(\.\d+)?,-?\d+(\.\d+)?}/;
487
+ const acceptableSimulatorWindowOrientations = [
488
+ 'Portrait',
489
+ 'LandscapeLeft',
490
+ 'PortraitUpsideDown',
491
+ 'LandscapeRight',
492
+ ];
493
+
494
+ if (
495
+ prefs.SimulatorWindowLastScale !== undefined &&
496
+ (typeof prefs.SimulatorWindowLastScale !== 'number' || prefs.SimulatorWindowLastScale <= 0)
497
+ ) {
498
+ throw this.log.errorWithException(
499
+ `SimulatorWindowLastScale is expected to be a positive float value. ` +
500
+ `'${prefs.SimulatorWindowLastScale}' is assigned instead.`,
501
+ );
489
502
  }
490
503
 
491
- if (!_.isUndefined(prefs.SimulatorWindowCenter)) {
492
- // https://regex101.com/r/2ZXOij/2
493
- const verificationPattern = /{-?\d+(\.\d+)?,-?\d+(\.\d+)?}/;
494
- if (
495
- !_.isString(prefs.SimulatorWindowCenter) ||
496
- !verificationPattern.test(prefs.SimulatorWindowCenter)
497
- ) {
498
- throw this.log.errorWithException(
499
- `SimulatorWindowCenter is expected to match "{floatXPosition,floatYPosition}" format (without spaces). ` +
500
- `'${prefs.SimulatorWindowCenter}' is assigned instead.`,
501
- );
502
- }
504
+ if (
505
+ prefs.SimulatorWindowCenter !== undefined &&
506
+ (typeof prefs.SimulatorWindowCenter !== 'string' ||
507
+ !simulatorWindowCenterPattern.test(prefs.SimulatorWindowCenter))
508
+ ) {
509
+ throw this.log.errorWithException(
510
+ `SimulatorWindowCenter is expected to match "{floatXPosition,floatYPosition}" format (without spaces). ` +
511
+ `'${prefs.SimulatorWindowCenter}' is assigned instead.`,
512
+ );
503
513
  }
504
514
 
505
- if (!_.isUndefined(prefs.SimulatorWindowOrientation)) {
506
- const acceptableValues = ['Portrait', 'LandscapeLeft', 'PortraitUpsideDown', 'LandscapeRight'];
507
- if (
508
- !prefs.SimulatorWindowOrientation ||
509
- !acceptableValues.includes(prefs.SimulatorWindowOrientation)
510
- ) {
511
- throw this.log.errorWithException(
512
- `SimulatorWindowOrientation is expected to be one of ${acceptableValues}. ` +
513
- `'${prefs.SimulatorWindowOrientation}' is assigned instead.`,
514
- );
515
- }
515
+ if (
516
+ prefs.SimulatorWindowOrientation !== undefined &&
517
+ (!prefs.SimulatorWindowOrientation ||
518
+ !acceptableSimulatorWindowOrientations.includes(prefs.SimulatorWindowOrientation))
519
+ ) {
520
+ throw this.log.errorWithException(
521
+ `SimulatorWindowOrientation is expected to be one of ${acceptableSimulatorWindowOrientations}. ` +
522
+ `'${prefs.SimulatorWindowOrientation}' is assigned instead.`,
523
+ );
516
524
  }
517
525
 
518
- if (!_.isUndefined(prefs.SimulatorWindowRotationAngle)) {
519
- if (!_.isNumber(prefs.SimulatorWindowRotationAngle)) {
520
- throw this.log.errorWithException(
521
- `SimulatorWindowRotationAngle is expected to be a valid number. ` +
522
- `'${prefs.SimulatorWindowRotationAngle}' is assigned instead.`,
523
- );
524
- }
526
+ if (
527
+ prefs.SimulatorWindowRotationAngle !== undefined &&
528
+ typeof prefs.SimulatorWindowRotationAngle !== 'number'
529
+ ) {
530
+ throw this.log.errorWithException(
531
+ `SimulatorWindowRotationAngle is expected to be a valid number. ` +
532
+ `'${prefs.SimulatorWindowRotationAngle}' is assigned instead.`,
533
+ );
525
534
  }
526
535
  }
@@ -5,9 +5,7 @@ import {exec} from 'teen_process';
5
5
  import {log as defaultLog} from './logger';
6
6
  import EventEmitter from 'node:events';
7
7
  import AsyncLock from 'async-lock';
8
- import _ from 'lodash';
9
8
  import path from 'node:path';
10
- import B from 'bluebird';
11
9
  import {getPath as getXcodePath} from 'appium-xcode';
12
10
  import {Simctl} from 'node-simctl';
13
11
  import * as appExtensions from './extensions/applications';
@@ -57,6 +55,57 @@ export class SimulatorXcode14
57
55
  _keychainsBackupPath: string | null | undefined;
58
56
  _platformVersion: string | null | undefined;
59
57
  _webInspectorSocket: string | null | undefined;
58
+
59
+ // Extension methods
60
+ installApp = appExtensions.installApp;
61
+ getUserInstalledBundleIdsByBundleName = appExtensions.getUserInstalledBundleIdsByBundleName;
62
+ isAppInstalled = appExtensions.isAppInstalled;
63
+ removeApp = appExtensions.removeApp;
64
+ launchApp = appExtensions.launchApp;
65
+ terminateApp = appExtensions.terminateApp;
66
+ isAppRunning = appExtensions.isAppRunning;
67
+ scrubApp = appExtensions.scrubApp;
68
+
69
+ openUrl = safariExtensions.openUrl;
70
+ scrubSafari = safariExtensions.scrubSafari;
71
+ updateSafariSettings = safariExtensions.updateSafariSettings;
72
+ getWebInspectorSocket = safariExtensions.getWebInspectorSocket as unknown as () => Promise<
73
+ string | null
74
+ >;
75
+
76
+ isBiometricEnrolled = biometricExtensions.isBiometricEnrolled;
77
+ enrollBiometric = biometricExtensions.enrollBiometric;
78
+ sendBiometricMatch = biometricExtensions.sendBiometricMatch;
79
+
80
+ backupKeychains = keychainExtensions.backupKeychains as unknown as () => Promise<boolean>;
81
+ restoreKeychains = keychainExtensions.restoreKeychains as unknown as (
82
+ excludePatterns: string[],
83
+ ) => Promise<boolean>;
84
+ clearKeychains = keychainExtensions.clearKeychains;
85
+
86
+ setGeolocation = geolocationExtensions.setGeolocation;
87
+
88
+ shake = miscExtensions.shake;
89
+ addCertificate = miscExtensions.addCertificate;
90
+ pushNotification = miscExtensions.pushNotification;
91
+
92
+ setPermission = permissionsExtensions.setPermission;
93
+ setPermissions = permissionsExtensions.setPermissions;
94
+ getPermission = permissionsExtensions.getPermission;
95
+
96
+ updateSettings = settingsExtensions.updateSettings;
97
+ setAppearance = settingsExtensions.setAppearance;
98
+ getAppearance = settingsExtensions.getAppearance;
99
+ setIncreaseContrast = settingsExtensions.setIncreaseContrast;
100
+ getIncreaseContrast = settingsExtensions.getIncreaseContrast;
101
+ setContentSize = settingsExtensions.setContentSize;
102
+ getContentSize = settingsExtensions.getContentSize;
103
+ configureLocalization = settingsExtensions.configureLocalization;
104
+ setAutoFillPasswords = settingsExtensions.setAutoFillPasswords;
105
+ setReduceMotion = settingsExtensions.setReduceMotion;
106
+ setReduceTransparency = settingsExtensions.setReduceTransparency;
107
+ disableKeyboardIntroduction = settingsExtensions.disableKeyboardIntroduction;
108
+
60
109
  private readonly _udid: string;
61
110
  private readonly _simctl: Simctl;
62
111
  private readonly _xcodeVersion: XcodeVersion;
@@ -193,7 +242,7 @@ export class SimulatorXcode14
193
242
  */
194
243
  async stat(): Promise<DeviceStat | StringRecord<never>> {
195
244
  const devices = await this.simctl.getDevices();
196
- for (const [sdk, deviceArr] of _.toPairs(devices)) {
245
+ for (const [sdk, deviceArr] of Object.entries(devices)) {
197
246
  for (const device of deviceArr as any[]) {
198
247
  if (device.udid === this.udid) {
199
248
  device.sdk = sdk;
@@ -246,7 +295,7 @@ export class SimulatorXcode14
246
295
  await this.simctl.getEnv('dummy');
247
296
  return false;
248
297
  } catch (e: any) {
249
- return _.includes(e.stderr, 'Current state: Shutdown');
298
+ return String(e.stderr).includes('Current state: Shutdown');
250
299
  }
251
300
  }
252
301
 
@@ -276,7 +325,7 @@ export class SimulatorXcode14
276
325
  * @returns True if UI client is running or false otherwise.
277
326
  */
278
327
  async isUIClientRunning(): Promise<boolean> {
279
- return !_.isNull(await this.getUIClientPid());
328
+ return (await this.getUIClientPid()) !== null;
280
329
  }
281
330
 
282
331
  /**
@@ -307,14 +356,14 @@ export class SimulatorXcode14
307
356
  shouldPreboot: true,
308
357
  });
309
358
  try {
310
- await new B<void>((resolve, reject) => {
359
+ await new Promise<void>((resolve, reject) => {
311
360
  // Historically this call was always asynchronous,
312
361
  // e.g. it was not waiting until Simulator is fully booted.
313
362
  // So we preserve that behavior, and if no errors are received for a while
314
363
  // then we assume the Simulator booting is still in progress.
315
364
  setTimeout(resolve, 3000);
316
365
  bootEventsEmitter.once('failure', (err: Error) => {
317
- if (_.includes(err?.message, 'state: Booted')) {
366
+ if (String(err?.message).includes('state: Booted')) {
318
367
  resolve();
319
368
  } else {
320
369
  reject(err);
@@ -402,16 +451,16 @@ export class SimulatorXcode14
402
451
  * @param opts - Simulator startup options.
403
452
  */
404
453
  async startUIClient(opts: StartUiClientOptions = {}): Promise<void> {
405
- opts = _.cloneDeep(opts);
406
- _.defaultsDeep(opts, {
454
+ const startUiOpts = {
407
455
  startupTimeout: this.startupTimeout,
408
- });
456
+ ...opts,
457
+ };
409
458
 
410
459
  const simulatorApp = path.resolve(await getXcodePath(), 'Applications', SIMULATOR_APP_NAME);
411
460
  const args = ['-Fn', simulatorApp];
412
461
  this.log.info(`Starting Simulator UI: ${util.quote(['open', ...args])}`);
413
462
  try {
414
- await exec('open', args, {timeout: opts.startupTimeout});
463
+ await exec('open', args, {timeout: startUiOpts.startupTimeout});
415
464
  } catch (err: any) {
416
465
  throw new Error(
417
466
  `Got an unexpected error while opening Simulator UI: ` + err.stderr ||
@@ -428,21 +477,21 @@ export class SimulatorXcode14
428
477
  * @param opts - One or more of available Simulator options.
429
478
  */
430
479
  async run(opts: RunOptions = {}): Promise<void> {
431
- opts = _.cloneDeep(opts);
432
- _.defaultsDeep(opts, {
480
+ const runOpts: RunOptions = {
433
481
  isHeadless: false,
434
482
  startupTimeout: this.startupTimeout,
435
- });
483
+ ...structuredClone(opts),
484
+ };
436
485
 
437
486
  const [devicePreferences, commonPreferences] =
438
- settingsExtensions.compileSimulatorPreferences.bind(this)(opts);
487
+ settingsExtensions.compileSimulatorPreferences.bind(this)(runOpts);
439
488
  await settingsExtensions.updatePreferences.bind(this)(devicePreferences, commonPreferences);
440
489
 
441
490
  const timer = new timing.Timer().start();
442
491
  const shouldWaitForBoot = await STARTUP_LOCK.acquire(this.uiClientBundleId, async () => {
443
492
  const isServerRunning = await this.isRunning();
444
493
  const uiClientPid = await this.getUIClientPid();
445
- if (opts.isHeadless) {
494
+ if (runOpts.isHeadless) {
446
495
  if (isServerRunning && !uiClientPid) {
447
496
  this.log.info(`Simulator with UDID '${this.udid}' is already booted in headless mode.`);
448
497
  return false;
@@ -485,19 +534,19 @@ export class SimulatorXcode14
485
534
  );
486
535
  await this.shutdown({timeout: SIMULATOR_SHUTDOWN_TIMEOUT});
487
536
  }
488
- await this.launchWindow(Boolean(uiClientPid), opts);
537
+ await this.launchWindow(Boolean(uiClientPid), runOpts);
489
538
  }
490
539
  return true;
491
540
  });
492
541
 
493
- if (shouldWaitForBoot && opts.startupTimeout) {
494
- await this.waitForBoot(opts.startupTimeout);
542
+ if (shouldWaitForBoot && runOpts.startupTimeout) {
543
+ await this.waitForBoot(runOpts.startupTimeout);
495
544
  this.log.info(
496
545
  `Simulator with UDID ${this.udid} booted in ${timer.getDuration().asSeconds.toFixed(3)}s`,
497
546
  );
498
547
  }
499
548
 
500
- (async () => {
549
+ void (async () => {
501
550
  try {
502
551
  await this.disableKeyboardIntroduction();
503
552
  } catch (e: any) {
@@ -573,7 +622,7 @@ export class SimulatorXcode14
573
622
 
574
623
  const result: ProcessInfo[] = [];
575
624
  for (const line of stdout.split('\n')) {
576
- const trimmedLine = _.trim(line);
625
+ const trimmedLine = line.trim();
577
626
  if (!trimmedLine) {
578
627
  continue;
579
628
  }
@@ -616,54 +665,4 @@ export class SimulatorXcode14
616
665
  'LaunchDaemons',
617
666
  );
618
667
  }
619
-
620
- // Extension methods
621
- installApp = appExtensions.installApp;
622
- getUserInstalledBundleIdsByBundleName = appExtensions.getUserInstalledBundleIdsByBundleName;
623
- isAppInstalled = appExtensions.isAppInstalled;
624
- removeApp = appExtensions.removeApp;
625
- launchApp = appExtensions.launchApp;
626
- terminateApp = appExtensions.terminateApp;
627
- isAppRunning = appExtensions.isAppRunning;
628
- scrubApp = appExtensions.scrubApp;
629
-
630
- openUrl = safariExtensions.openUrl;
631
- scrubSafari = safariExtensions.scrubSafari;
632
- updateSafariSettings = safariExtensions.updateSafariSettings;
633
- getWebInspectorSocket = safariExtensions.getWebInspectorSocket as unknown as () => Promise<
634
- string | null
635
- >;
636
-
637
- isBiometricEnrolled = biometricExtensions.isBiometricEnrolled;
638
- enrollBiometric = biometricExtensions.enrollBiometric;
639
- sendBiometricMatch = biometricExtensions.sendBiometricMatch;
640
-
641
- backupKeychains = keychainExtensions.backupKeychains as unknown as () => Promise<boolean>;
642
- restoreKeychains = keychainExtensions.restoreKeychains as unknown as (
643
- excludePatterns: string[],
644
- ) => Promise<boolean>;
645
- clearKeychains = keychainExtensions.clearKeychains;
646
-
647
- setGeolocation = geolocationExtensions.setGeolocation;
648
-
649
- shake = miscExtensions.shake;
650
- addCertificate = miscExtensions.addCertificate;
651
- pushNotification = miscExtensions.pushNotification;
652
-
653
- setPermission = permissionsExtensions.setPermission;
654
- setPermissions = permissionsExtensions.setPermissions;
655
- getPermission = permissionsExtensions.getPermission;
656
-
657
- updateSettings = settingsExtensions.updateSettings;
658
- setAppearance = settingsExtensions.setAppearance;
659
- getAppearance = settingsExtensions.getAppearance;
660
- setIncreaseContrast = settingsExtensions.setIncreaseContrast;
661
- getIncreaseContrast = settingsExtensions.getIncreaseContrast;
662
- setContentSize = settingsExtensions.setContentSize;
663
- getContentSize = settingsExtensions.getContentSize;
664
- configureLocalization = settingsExtensions.configureLocalization;
665
- setAutoFillPasswords = settingsExtensions.setAutoFillPasswords;
666
- setReduceMotion = settingsExtensions.setReduceMotion;
667
- setReduceTransparency = settingsExtensions.setReduceTransparency;
668
- disableKeyboardIntroduction = settingsExtensions.disableKeyboardIntroduction;
669
668
  }
@@ -1,8 +1,6 @@
1
1
  import {fs} from '@appium/support';
2
2
  import {exec} from 'teen_process';
3
3
  import path from 'node:path';
4
- import _ from 'lodash';
5
- import B from 'bluebird';
6
4
  import {SimulatorXcode14} from './simulator-xcode-14';
7
5
 
8
6
  export class SimulatorXcode15 extends SimulatorXcode14 {
@@ -102,7 +100,7 @@ export class SimulatorXcode15 extends SimulatorXcode14 {
102
100
  if (!simRoot) {
103
101
  throw new Error('The IPHONE_SIMULATOR_ROOT environment variable value cannot be retrieved');
104
102
  }
105
- return _.trim(simRoot);
103
+ return simRoot.trim();
106
104
  }
107
105
 
108
106
  /**
@@ -124,7 +122,7 @@ export class SimulatorXcode15 extends SimulatorXcode14 {
124
122
  'print CFBundleIdentifier',
125
123
  infoPlistPath,
126
124
  ]);
127
- return _.trim(stdout);
125
+ return stdout.trim();
128
126
  } catch {
129
127
  return null;
130
128
  }
@@ -132,7 +130,7 @@ export class SimulatorXcode15 extends SimulatorXcode14 {
132
130
  const allApps = (await fs.readdir(appsRoot))
133
131
  .filter((x) => x.endsWith('.app'))
134
132
  .map((x) => path.join(appsRoot, x));
135
- const bundleIds = await B.all(allApps.map(fetchBundleId));
133
+ const bundleIds = await Promise.all(allApps.map(fetchBundleId));
136
134
  this._systemAppBundleIds = new Set(bundleIds.filter((x): x is string => x !== null));
137
135
  return this._systemAppBundleIds;
138
136
  }
package/lib/types.ts CHANGED
@@ -212,15 +212,6 @@ export interface InteractsWithSafariBrowser {
212
212
  getWebInspectorSocket(): Promise<string | null>;
213
213
  }
214
214
 
215
- interface KeyboardOptions {
216
- /** The name of the keyboard locale, for example `en_US` or `de_CH` */
217
- name: string;
218
- /** The keyboard layout, for example `QUERTY` or `Ukrainian` */
219
- layout: string;
220
- /** hardware Could either be `Automatic` or `null` */
221
- hardware?: string | null;
222
- }
223
-
224
215
  export interface LanguageOptions {
225
216
  /** The name of the language, for example `de` or `zh-Hant-CN` */
226
217
  name: string;
@@ -298,3 +289,12 @@ export type Simulator = CoreSimulator &
298
289
  InteractsWithKeychain &
299
290
  SupportsAppPermissions &
300
291
  HasMiscFeatures;
292
+
293
+ interface KeyboardOptions {
294
+ /** The name of the keyboard locale, for example `en_US` or `de_CH` */
295
+ name: string;
296
+ /** The keyboard layout, for example `QUERTY` or `Ukrainian` */
297
+ layout: string;
298
+ /** hardware Could either be `Automatic` or `null` */
299
+ hardware?: string | null;
300
+ }