appium-xcuitest-driver 7.13.0 → 7.14.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.
- package/CHANGELOG.md +7 -0
- package/build/lib/app-utils.d.ts +35 -6
- package/build/lib/app-utils.d.ts.map +1 -1
- package/build/lib/app-utils.js +231 -11
- package/build/lib/app-utils.js.map +1 -1
- package/build/lib/driver.d.ts +23 -31
- package/build/lib/driver.d.ts.map +1 -1
- package/build/lib/driver.js +3 -87
- package/build/lib/driver.js.map +1 -1
- package/lib/app-utils.js +243 -10
- package/lib/driver.js +5 -105
- package/npm-shrinkwrap.json +29 -29
- package/package.json +2 -2
package/lib/app-utils.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import {plist, fs, util, tempDir, zip} from 'appium/support';
|
|
3
|
+
import {plist, fs, util, tempDir, zip, timing} from 'appium/support';
|
|
4
4
|
import log from './logger.js';
|
|
5
5
|
import {LRUCache} from 'lru-cache';
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import {exec} from 'teen_process';
|
|
8
8
|
import B from 'bluebird';
|
|
9
|
+
import {spawn} from 'node:child_process';
|
|
10
|
+
import assert from 'node:assert';
|
|
9
11
|
|
|
10
12
|
const STRINGSDICT_RESOURCE = '.stringsdict';
|
|
11
13
|
const STRINGS_RESOURCE = '.strings';
|
|
@@ -22,6 +24,9 @@ const SAFARI_OPTS_ALIASES_MAP = /** @type {const} */ ({
|
|
|
22
24
|
safariIgnoreFraudWarning: [['WarnAboutFraudulentWebsites'], (x) => Number(!x)],
|
|
23
25
|
safariOpenLinksInBackground: [['OpenLinksInBackground'], (x) => Number(Boolean(x))],
|
|
24
26
|
});
|
|
27
|
+
const MAX_ARCHIVE_SCAN_DEPTH = 1;
|
|
28
|
+
export const SUPPORTED_EXTENSIONS = [IPA_EXT, APP_EXT];
|
|
29
|
+
const MACOS_RESOURCE_FOLDER = '__MACOSX';
|
|
25
30
|
|
|
26
31
|
|
|
27
32
|
/**
|
|
@@ -261,27 +266,110 @@ export async function isAppBundle(appPath) {
|
|
|
261
266
|
}
|
|
262
267
|
|
|
263
268
|
/**
|
|
264
|
-
*
|
|
269
|
+
* @typedef {Object} UnzipInfo
|
|
270
|
+
* @property {string} rootDir
|
|
271
|
+
* @property {number} archiveSize
|
|
272
|
+
*/
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Unzips a ZIP archive on the local file system.
|
|
265
276
|
*
|
|
266
277
|
* @param {string} archivePath Full path to a .zip archive
|
|
267
|
-
* @
|
|
268
|
-
* @returns {Promise<[string, string[]]>} Tuple, where the first element points to
|
|
269
|
-
* a temporary folder root where the archive has been extracted and the second item
|
|
270
|
-
* contains a list of relative paths to matched items
|
|
278
|
+
* @returns {Promise<UnzipInfo>} temporary folder root where the archive has been extracted
|
|
271
279
|
*/
|
|
272
|
-
export async function
|
|
280
|
+
export async function unzipFile(archivePath) {
|
|
273
281
|
const useSystemUnzipEnv = process.env.APPIUM_PREFER_SYSTEM_UNZIP;
|
|
274
282
|
const useSystemUnzip =
|
|
275
283
|
_.isEmpty(useSystemUnzipEnv) || !['0', 'false'].includes(_.toLower(useSystemUnzipEnv));
|
|
276
284
|
const tmpRoot = await tempDir.openDir();
|
|
277
|
-
|
|
285
|
+
try {
|
|
286
|
+
await zip.extractAllTo(archivePath, tmpRoot, {useSystemUnzip});
|
|
287
|
+
} catch (e) {
|
|
288
|
+
await fs.rimraf(tmpRoot);
|
|
289
|
+
throw e;
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
rootDir: tmpRoot,
|
|
293
|
+
archiveSize: (await fs.stat(archivePath)).size,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Unzips a ZIP archive from a stream.
|
|
299
|
+
* Uses bdstar tool for this purpose.
|
|
300
|
+
* This allows to optimize the time needed to prepare the app under test
|
|
301
|
+
* to MAX(download, unzip) instead of SUM(download, unzip)
|
|
302
|
+
*
|
|
303
|
+
* @param {import('node:stream').Readable} zipStream
|
|
304
|
+
* @returns {Promise<UnzipInfo>}
|
|
305
|
+
*/
|
|
306
|
+
export async function unzipStream(zipStream) {
|
|
307
|
+
const tmpRoot = await tempDir.openDir();
|
|
308
|
+
const bsdtarProcess = spawn(await fs.which('bsdtar'), [
|
|
309
|
+
'-x',
|
|
310
|
+
'--exclude', MACOS_RESOURCE_FOLDER,
|
|
311
|
+
'--exclude', `${MACOS_RESOURCE_FOLDER}/*`,
|
|
312
|
+
'-',
|
|
313
|
+
], {
|
|
314
|
+
cwd: tmpRoot,
|
|
315
|
+
});
|
|
316
|
+
let archiveSize = 0;
|
|
317
|
+
bsdtarProcess.stderr.on('data', (chunk) => {
|
|
318
|
+
const stderr = chunk.toString();
|
|
319
|
+
if (_.trim(stderr)) {
|
|
320
|
+
log.warn(stderr);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
zipStream.on('data', (chunk) => {
|
|
324
|
+
archiveSize += _.size(chunk);
|
|
325
|
+
});
|
|
326
|
+
zipStream.pipe(bsdtarProcess.stdin);
|
|
327
|
+
try {
|
|
328
|
+
await new B((resolve, reject) => {
|
|
329
|
+
zipStream.once('error', reject);
|
|
330
|
+
bsdtarProcess.once('exit', (code, signal) => {
|
|
331
|
+
zipStream.unpipe(bsdtarProcess.stdin);
|
|
332
|
+
log.debug(`bsdtar process exited with code ${code}, signal ${signal}`);
|
|
333
|
+
if (code === 0) {
|
|
334
|
+
resolve();
|
|
335
|
+
} else {
|
|
336
|
+
reject(new Error('Is it a valid ZIP archive?'));
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
bsdtarProcess.once('error', (e) => {
|
|
340
|
+
zipStream.unpipe(bsdtarProcess.stdin);
|
|
341
|
+
reject(e);
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
} catch (err) {
|
|
345
|
+
bsdtarProcess.kill(9);
|
|
346
|
+
await fs.rimraf(tmpRoot);
|
|
347
|
+
throw new Error(`The response data cannot be unzipped: ${err.message}`);
|
|
348
|
+
} finally {
|
|
349
|
+
bsdtarProcess.removeAllListeners();
|
|
350
|
+
zipStream.removeAllListeners();
|
|
351
|
+
}
|
|
352
|
+
return {
|
|
353
|
+
rootDir: tmpRoot,
|
|
354
|
+
archiveSize,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Looks for items with given extensions in the given folder
|
|
360
|
+
*
|
|
361
|
+
* @param {string} appPath Full path to an app bundle
|
|
362
|
+
* @param {Array<string>} appExtensions List of matching item extensions
|
|
363
|
+
* @returns {Promise<string[]>} List of relative paths to matched items
|
|
364
|
+
*/
|
|
365
|
+
async function findApps(appPath, appExtensions) {
|
|
278
366
|
const globPattern = `**/*.+(${appExtensions.map((ext) => ext.replace(/^\./, '')).join('|')})`;
|
|
279
367
|
const sortedBundleItems = (
|
|
280
368
|
await fs.glob(globPattern, {
|
|
281
|
-
cwd:
|
|
369
|
+
cwd: appPath,
|
|
282
370
|
})
|
|
283
371
|
).sort((a, b) => a.split(path.sep).length - b.split(path.sep).length);
|
|
284
|
-
return
|
|
372
|
+
return sortedBundleItems;
|
|
285
373
|
}
|
|
286
374
|
|
|
287
375
|
/**
|
|
@@ -318,3 +406,148 @@ export function buildSafariPreferences(opts) {
|
|
|
318
406
|
}
|
|
319
407
|
return safariSettings;
|
|
320
408
|
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Unzip the given archive and find a matching .app bundle in it
|
|
412
|
+
*
|
|
413
|
+
* @this {import('./driver').XCUITestDriver}
|
|
414
|
+
* @param {string|import('node:stream').Readable} appPathOrZipStream The path to the archive.
|
|
415
|
+
* @param {number} depth [0] the current nesting depth. App bundles whose nesting level
|
|
416
|
+
* is greater than 1 are not supported.
|
|
417
|
+
* @returns {Promise<string>} Full path to the first matching .app bundle..
|
|
418
|
+
* @throws If no matching .app bundles were found in the provided archive.
|
|
419
|
+
*/
|
|
420
|
+
async function unzipApp(appPathOrZipStream, depth = 0) {
|
|
421
|
+
const errMsg = `The archive '${this.opts.app}' did not have any matching ${APP_EXT} or ${IPA_EXT} ` +
|
|
422
|
+
`bundles. Please make sure the provided package is valid and contains at least one matching ` +
|
|
423
|
+
`application bundle which is not nested.`;
|
|
424
|
+
if (depth > MAX_ARCHIVE_SCAN_DEPTH) {
|
|
425
|
+
throw new Error(errMsg);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const timer = new timing.Timer().start();
|
|
429
|
+
/** @type {string} */
|
|
430
|
+
let rootDir;
|
|
431
|
+
/** @type {number} */
|
|
432
|
+
let archiveSize;
|
|
433
|
+
try {
|
|
434
|
+
if (_.isString(appPathOrZipStream)) {
|
|
435
|
+
({rootDir, archiveSize} = await unzipFile(appPathOrZipStream));
|
|
436
|
+
} else {
|
|
437
|
+
if (depth > 0) {
|
|
438
|
+
assert.fail('Streaming unzip cannot be invoked for nested archive items');
|
|
439
|
+
}
|
|
440
|
+
({rootDir, archiveSize} = await unzipStream(appPathOrZipStream));
|
|
441
|
+
}
|
|
442
|
+
} catch (e) {
|
|
443
|
+
this.log.debug(e.stack);
|
|
444
|
+
throw new Error(
|
|
445
|
+
`Cannot prepare the application at '${this.opts.app}' for testing. Original error: ${e.message}`
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
const secondsElapsed = timer.getDuration().asSeconds;
|
|
449
|
+
this.log.info(
|
|
450
|
+
`The app '${this.opts.app}' (${util.toReadableSizeString(archiveSize)}) ` +
|
|
451
|
+
`has been ${_.isString(appPathOrZipStream) ? 'extracted' : 'downloaded and extracted'} ` +
|
|
452
|
+
`to '${rootDir}' in ${secondsElapsed.toFixed(3)}s`
|
|
453
|
+
);
|
|
454
|
+
// it does not make much sense to approximate the speed for short downloads
|
|
455
|
+
if (secondsElapsed >= 1) {
|
|
456
|
+
const bytesPerSec = Math.floor(archiveSize / secondsElapsed);
|
|
457
|
+
this.log.debug(`Approximate decompression speed: ${util.toReadableSizeString(bytesPerSec)}/s`);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const matchedPaths = await findApps(rootDir, SUPPORTED_EXTENSIONS);
|
|
461
|
+
if (_.isEmpty(matchedPaths)) {
|
|
462
|
+
this.log.debug(`'${path.basename(rootDir)}' has no bundles`);
|
|
463
|
+
} else {
|
|
464
|
+
this.log.debug(
|
|
465
|
+
`Found ${util.pluralize('bundle', matchedPaths.length, true)} in ` +
|
|
466
|
+
`'${path.basename(rootDir)}': ${matchedPaths}`,
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
try {
|
|
470
|
+
for (const matchedPath of matchedPaths) {
|
|
471
|
+
const fullPath = path.join(rootDir, matchedPath);
|
|
472
|
+
if (await isAppBundle(fullPath)) {
|
|
473
|
+
const supportedPlatforms = await fetchSupportedAppPlatforms(fullPath);
|
|
474
|
+
if (this.isSimulator() && !supportedPlatforms.some((p) => _.includes(p, 'Simulator'))) {
|
|
475
|
+
this.log.info(
|
|
476
|
+
`'${matchedPath}' does not have Simulator devices in the list of supported platforms ` +
|
|
477
|
+
`(${supportedPlatforms.join(',')}). Skipping it`,
|
|
478
|
+
);
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (this.isRealDevice() && !supportedPlatforms.some((p) => _.includes(p, 'OS'))) {
|
|
482
|
+
this.log.info(
|
|
483
|
+
`'${matchedPath}' does not have real devices in the list of supported platforms ` +
|
|
484
|
+
`(${supportedPlatforms.join(',')}). Skipping it`,
|
|
485
|
+
);
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
this.log.info(
|
|
489
|
+
`'${matchedPath}' is the resulting application bundle selected from '${rootDir}'`,
|
|
490
|
+
);
|
|
491
|
+
return await isolateAppBundle(fullPath);
|
|
492
|
+
} else if (_.endsWith(_.toLower(fullPath), IPA_EXT) && (await fs.stat(fullPath)).isFile()) {
|
|
493
|
+
try {
|
|
494
|
+
return await unzipApp.bind(this)(fullPath, depth + 1);
|
|
495
|
+
} catch (e) {
|
|
496
|
+
this.log.warn(`Skipping processing of '${matchedPath}': ${e.message}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
} finally {
|
|
501
|
+
await fs.rimraf(rootDir);
|
|
502
|
+
}
|
|
503
|
+
throw new Error(errMsg);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* @this {import('./driver').XCUITestDriver}
|
|
508
|
+
* @param {import('@appium/types').DownloadAppOptions} opts
|
|
509
|
+
* @returns {Promise<string>}
|
|
510
|
+
*/
|
|
511
|
+
export async function onDownloadApp({stream}) {
|
|
512
|
+
return await unzipApp.bind(this)(stream);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* @this {import('./driver').XCUITestDriver}
|
|
517
|
+
* @param {import('@appium/types').PostProcessOptions} opts
|
|
518
|
+
* @returns {Promise<import('@appium/types').PostProcessResult|false>}
|
|
519
|
+
*/
|
|
520
|
+
export async function onPostConfigureApp({cachedAppInfo, isUrl, appPath}) {
|
|
521
|
+
// Pick the previously cached entry if its integrity has been preserved
|
|
522
|
+
/** @type {import('@appium/types').CachedAppInfo|undefined} */
|
|
523
|
+
const appInfo = _.isPlainObject(cachedAppInfo) ? cachedAppInfo : undefined;
|
|
524
|
+
const cachedPath = appInfo ? /** @type {string} */ (appInfo.fullPath) : undefined;
|
|
525
|
+
if (
|
|
526
|
+
// If cache is present
|
|
527
|
+
appInfo && cachedPath
|
|
528
|
+
// And if the path exists
|
|
529
|
+
&& await fs.exists(cachedPath)
|
|
530
|
+
// And if hash matches to the cached one if this is a file
|
|
531
|
+
// Or count of files >= of the cached one if this is a folder
|
|
532
|
+
&& (
|
|
533
|
+
((await fs.stat(cachedPath)).isFile()
|
|
534
|
+
&& await fs.hash(cachedPath) === /** @type {any} */ (appInfo.integrity)?.file)
|
|
535
|
+
|| (await fs.glob('**/*', {cwd: cachedPath})).length >= /** @type {any} */ (
|
|
536
|
+
appInfo.integrity
|
|
537
|
+
)?.folder
|
|
538
|
+
)
|
|
539
|
+
) {
|
|
540
|
+
this.log.info(`Using '${cachedPath}' which was cached from '${appPath}'`);
|
|
541
|
+
return {appPath: cachedPath};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
const isBundleAlreadyUnpacked = await isAppBundle(/** @type {string} */(appPath));
|
|
545
|
+
// Only local .app bundles that are available in-place should not be cached
|
|
546
|
+
if (!isUrl && isBundleAlreadyUnpacked) {
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
// Cache the app while unpacking the bundle if necessary
|
|
550
|
+
return {
|
|
551
|
+
appPath: isBundleAlreadyUnpacked ? appPath : await unzipApp.bind(this)(/** @type {string} */(appPath))
|
|
552
|
+
};
|
|
553
|
+
}
|
package/lib/driver.js
CHANGED
|
@@ -12,15 +12,12 @@ import EventEmitter from 'node:events';
|
|
|
12
12
|
import path from 'node:path';
|
|
13
13
|
import url from 'node:url';
|
|
14
14
|
import {
|
|
15
|
-
|
|
16
|
-
IPA_EXT,
|
|
15
|
+
SUPPORTED_EXTENSIONS,
|
|
17
16
|
SAFARI_BUNDLE_ID,
|
|
18
17
|
extractBundleId,
|
|
19
18
|
extractBundleVersion,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
isAppBundle,
|
|
23
|
-
isolateAppBundle,
|
|
19
|
+
onPostConfigureApp,
|
|
20
|
+
onDownloadApp,
|
|
24
21
|
verifyApplicationPlatform,
|
|
25
22
|
} from './app-utils';
|
|
26
23
|
import commands from './commands';
|
|
@@ -70,8 +67,6 @@ import {
|
|
|
70
67
|
const SHUTDOWN_OTHER_FEAT_NAME = 'shutdown_other_sims';
|
|
71
68
|
const CUSTOMIZE_RESULT_BUNDLE_PATH = 'customize_result_bundle_path';
|
|
72
69
|
|
|
73
|
-
const SUPPORTED_EXTENSIONS = [IPA_EXT, APP_EXT];
|
|
74
|
-
const MAX_ARCHIVE_SCAN_DEPTH = 1;
|
|
75
70
|
const defaultServerCaps = {
|
|
76
71
|
webStorageEnabled: false,
|
|
77
72
|
locationContextEnabled: false,
|
|
@@ -1065,107 +1060,12 @@ export class XCUITestDriver extends BaseDriver {
|
|
|
1065
1060
|
}
|
|
1066
1061
|
|
|
1067
1062
|
this.opts.app = await this.helpers.configureApp(this.opts.app, {
|
|
1068
|
-
onPostProcess:
|
|
1063
|
+
onPostProcess: onPostConfigureApp.bind(this),
|
|
1064
|
+
onDownload: onDownloadApp.bind(this),
|
|
1069
1065
|
supportedExtensions: SUPPORTED_EXTENSIONS,
|
|
1070
1066
|
});
|
|
1071
1067
|
}
|
|
1072
1068
|
|
|
1073
|
-
/**
|
|
1074
|
-
* Unzip the given archive and find a matching .app bundle in it
|
|
1075
|
-
*
|
|
1076
|
-
* @param {string} appPath The path to the archive.
|
|
1077
|
-
* @param {number} depth [0] the current nesting depth. App bundles whose nesting level
|
|
1078
|
-
* is greater than 1 are not supported.
|
|
1079
|
-
* @returns {Promise<string>} Full path to the first matching .app bundle..
|
|
1080
|
-
* @throws If no matching .app bundles were found in the provided archive.
|
|
1081
|
-
*/
|
|
1082
|
-
async unzipApp(appPath, depth = 0) {
|
|
1083
|
-
if (depth > MAX_ARCHIVE_SCAN_DEPTH) {
|
|
1084
|
-
throw new Error('Nesting of package bundles is not supported');
|
|
1085
|
-
}
|
|
1086
|
-
const [rootDir, matchedPaths] = await findApps(appPath, SUPPORTED_EXTENSIONS);
|
|
1087
|
-
if (_.isEmpty(matchedPaths)) {
|
|
1088
|
-
this.log.debug(`'${path.basename(appPath)}' has no bundles`);
|
|
1089
|
-
} else {
|
|
1090
|
-
this.log.debug(
|
|
1091
|
-
`Found ${util.pluralize('bundle', matchedPaths.length, true)} in ` +
|
|
1092
|
-
`'${path.basename(appPath)}': ${matchedPaths}`,
|
|
1093
|
-
);
|
|
1094
|
-
}
|
|
1095
|
-
try {
|
|
1096
|
-
for (const matchedPath of matchedPaths) {
|
|
1097
|
-
const fullPath = path.join(rootDir, matchedPath);
|
|
1098
|
-
if (await isAppBundle(fullPath)) {
|
|
1099
|
-
const supportedPlatforms = await fetchSupportedAppPlatforms(fullPath);
|
|
1100
|
-
if (this.isSimulator() && !supportedPlatforms.some((p) => _.includes(p, 'Simulator'))) {
|
|
1101
|
-
this.log.info(
|
|
1102
|
-
`'${matchedPath}' does not have Simulator devices in the list of supported platforms ` +
|
|
1103
|
-
`(${supportedPlatforms.join(',')}). Skipping it`,
|
|
1104
|
-
);
|
|
1105
|
-
continue;
|
|
1106
|
-
}
|
|
1107
|
-
if (this.isRealDevice() && !supportedPlatforms.some((p) => _.includes(p, 'OS'))) {
|
|
1108
|
-
this.log.info(
|
|
1109
|
-
`'${matchedPath}' does not have real devices in the list of supported platforms ` +
|
|
1110
|
-
`(${supportedPlatforms.join(',')}). Skipping it`,
|
|
1111
|
-
);
|
|
1112
|
-
continue;
|
|
1113
|
-
}
|
|
1114
|
-
this.log.info(
|
|
1115
|
-
`'${matchedPath}' is the resulting application bundle selected from '${appPath}'`,
|
|
1116
|
-
);
|
|
1117
|
-
return await isolateAppBundle(fullPath);
|
|
1118
|
-
} else if (_.endsWith(_.toLower(fullPath), IPA_EXT) && (await fs.stat(fullPath)).isFile()) {
|
|
1119
|
-
try {
|
|
1120
|
-
return await this.unzipApp(fullPath, depth + 1);
|
|
1121
|
-
} catch (e) {
|
|
1122
|
-
this.log.warn(`Skipping processing of '${matchedPath}': ${e.message}`);
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
} finally {
|
|
1127
|
-
await fs.rimraf(rootDir);
|
|
1128
|
-
}
|
|
1129
|
-
throw new Error(
|
|
1130
|
-
`${this.opts.app} did not have any matching ${APP_EXT} or ${IPA_EXT} ` +
|
|
1131
|
-
`bundles. Please make sure the provided package is valid and contains at least one matching ` +
|
|
1132
|
-
`application bundle which is not nested.`,
|
|
1133
|
-
);
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
async onPostConfigureApp({cachedAppInfo, isUrl, appPath}) {
|
|
1137
|
-
// Pick the previously cached entry if its integrity has been preserved
|
|
1138
|
-
if (
|
|
1139
|
-
_.isPlainObject(cachedAppInfo) &&
|
|
1140
|
-
(await fs.stat(appPath)).isFile() &&
|
|
1141
|
-
(await fs.hash(appPath)) === cachedAppInfo.packageHash &&
|
|
1142
|
-
(await fs.exists(cachedAppInfo.fullPath)) &&
|
|
1143
|
-
(
|
|
1144
|
-
await fs.glob('**/*', {
|
|
1145
|
-
cwd: cachedAppInfo.fullPath,
|
|
1146
|
-
})
|
|
1147
|
-
).length === cachedAppInfo.integrity.folder
|
|
1148
|
-
) {
|
|
1149
|
-
this.log.info(`Using '${cachedAppInfo.fullPath}' which was cached from '${appPath}'`);
|
|
1150
|
-
return {appPath: cachedAppInfo.fullPath};
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
// Only local .app bundles that are available in-place should not be cached
|
|
1154
|
-
if (await isAppBundle(appPath)) {
|
|
1155
|
-
return false;
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
// Extract the app bundle and cache it
|
|
1159
|
-
try {
|
|
1160
|
-
return {appPath: await this.unzipApp(appPath)};
|
|
1161
|
-
} finally {
|
|
1162
|
-
// Cleanup previously downloaded archive
|
|
1163
|
-
if (isUrl) {
|
|
1164
|
-
await fs.rimraf(appPath);
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
|
|
1169
1069
|
async determineDevice() {
|
|
1170
1070
|
// in the one case where we create a sim, we will set this state
|
|
1171
1071
|
this.lifecycleData.createSim = false;
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appium-xcuitest-driver",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.14.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "appium-xcuitest-driver",
|
|
9
|
-
"version": "7.
|
|
9
|
+
"version": "7.14.0",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@colors/colors": "^1.6.0",
|
|
@@ -83,16 +83,16 @@
|
|
|
83
83
|
"npm": ">=8"
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
|
-
"appium": "^2.4
|
|
86
|
+
"appium": "^2.5.4"
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
89
|
"node_modules/@appium/base-driver": {
|
|
90
|
-
"version": "9.
|
|
91
|
-
"resolved": "https://registry.npmjs.org/@appium/base-driver/-/base-driver-9.
|
|
92
|
-
"integrity": "sha512-
|
|
90
|
+
"version": "9.6.0",
|
|
91
|
+
"resolved": "https://registry.npmjs.org/@appium/base-driver/-/base-driver-9.6.0.tgz",
|
|
92
|
+
"integrity": "sha512-8+pqWHQ4tbvtwOxNCtHa5m0SUwQIvAwHTVKq/YUbgDn18ep4nGhz5rlryvvqyNpXEgEOhbLInIRma1KIrYdX8Q==",
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@appium/support": "^4.2.
|
|
95
|
-
"@appium/types": "^0.
|
|
94
|
+
"@appium/support": "^4.2.5",
|
|
95
|
+
"@appium/types": "^0.17.0",
|
|
96
96
|
"@colors/colors": "1.6.0",
|
|
97
97
|
"@types/async-lock": "1.4.2",
|
|
98
98
|
"@types/bluebird": "3.5.42",
|
|
@@ -137,11 +137,11 @@
|
|
|
137
137
|
}
|
|
138
138
|
},
|
|
139
139
|
"node_modules/@appium/docutils": {
|
|
140
|
-
"version": "1.0.
|
|
141
|
-
"resolved": "https://registry.npmjs.org/@appium/docutils/-/docutils-1.0.
|
|
142
|
-
"integrity": "sha512-
|
|
140
|
+
"version": "1.0.7",
|
|
141
|
+
"resolved": "https://registry.npmjs.org/@appium/docutils/-/docutils-1.0.7.tgz",
|
|
142
|
+
"integrity": "sha512-cuVcE3nNKlhJZsXrleubYkrr4VrEXaVKxq0GePb5+qmgpkx2OQb18imoPx1FKBlDbxHGrV7fuLxc/5LbmsV0dA==",
|
|
143
143
|
"dependencies": {
|
|
144
|
-
"@appium/support": "^4.2.
|
|
144
|
+
"@appium/support": "^4.2.5",
|
|
145
145
|
"@appium/tsconfig": "^0.3.3",
|
|
146
146
|
"@sliphua/lilconfig-ts-loader": "3.2.2",
|
|
147
147
|
"@types/which": "3.0.3",
|
|
@@ -209,12 +209,12 @@
|
|
|
209
209
|
}
|
|
210
210
|
},
|
|
211
211
|
"node_modules/@appium/support": {
|
|
212
|
-
"version": "4.2.
|
|
213
|
-
"resolved": "https://registry.npmjs.org/@appium/support/-/support-4.2.
|
|
214
|
-
"integrity": "sha512-
|
|
212
|
+
"version": "4.2.5",
|
|
213
|
+
"resolved": "https://registry.npmjs.org/@appium/support/-/support-4.2.5.tgz",
|
|
214
|
+
"integrity": "sha512-txTDZHjJF7UjEFi4uyj23gciz3yAq7OwzXFdJgtQBzkK1cIiCnywQ6igLmBg52jZp84ki8eZIDMXsQetVUuDDg==",
|
|
215
215
|
"dependencies": {
|
|
216
216
|
"@appium/tsconfig": "^0.3.3",
|
|
217
|
-
"@appium/types": "^0.
|
|
217
|
+
"@appium/types": "^0.17.0",
|
|
218
218
|
"@colors/colors": "1.6.0",
|
|
219
219
|
"@types/archiver": "6.0.2",
|
|
220
220
|
"@types/base64-stream": "1.0.5",
|
|
@@ -265,7 +265,7 @@
|
|
|
265
265
|
"type-fest": "4.10.1",
|
|
266
266
|
"uuid": "9.0.1",
|
|
267
267
|
"which": "4.0.0",
|
|
268
|
-
"yauzl": "3.1.
|
|
268
|
+
"yauzl": "3.1.3"
|
|
269
269
|
},
|
|
270
270
|
"engines": {
|
|
271
271
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
|
|
@@ -299,9 +299,9 @@
|
|
|
299
299
|
}
|
|
300
300
|
},
|
|
301
301
|
"node_modules/@appium/types": {
|
|
302
|
-
"version": "0.
|
|
303
|
-
"resolved": "https://registry.npmjs.org/@appium/types/-/types-0.
|
|
304
|
-
"integrity": "sha512-
|
|
302
|
+
"version": "0.17.0",
|
|
303
|
+
"resolved": "https://registry.npmjs.org/@appium/types/-/types-0.17.0.tgz",
|
|
304
|
+
"integrity": "sha512-7Q9C5Y4G8ZQzdU0uJIlfVqpGMAzNqdXpNWziQTUfZyD7fHbYz9ScZrlgs2/DYMITRrHiIblmzY/5yzfu00rQuA==",
|
|
305
305
|
"dependencies": {
|
|
306
306
|
"@appium/schema": "^0.5.0",
|
|
307
307
|
"@appium/tsconfig": "^0.3.3",
|
|
@@ -922,9 +922,9 @@
|
|
|
922
922
|
}
|
|
923
923
|
},
|
|
924
924
|
"node_modules/appium-remote-debugger": {
|
|
925
|
-
"version": "11.1.
|
|
926
|
-
"resolved": "https://registry.npmjs.org/appium-remote-debugger/-/appium-remote-debugger-11.1.
|
|
927
|
-
"integrity": "sha512-
|
|
925
|
+
"version": "11.1.1",
|
|
926
|
+
"resolved": "https://registry.npmjs.org/appium-remote-debugger/-/appium-remote-debugger-11.1.1.tgz",
|
|
927
|
+
"integrity": "sha512-Fcu3U6mQtWBq+zQDb1fhnxoVTyZ5cmPi+dpM6zy+eVbYk/nR9n20v4uOQstH2ySnAknpNGVMSQVPBoZOP+YS2Q==",
|
|
928
928
|
"dependencies": {
|
|
929
929
|
"@appium/base-driver": "^9.0.0",
|
|
930
930
|
"@appium/support": "^4.0.0",
|
|
@@ -944,9 +944,9 @@
|
|
|
944
944
|
}
|
|
945
945
|
},
|
|
946
946
|
"node_modules/appium-webdriveragent": {
|
|
947
|
-
"version": "8.5.
|
|
948
|
-
"resolved": "https://registry.npmjs.org/appium-webdriveragent/-/appium-webdriveragent-8.5.
|
|
949
|
-
"integrity": "sha512-
|
|
947
|
+
"version": "8.5.6",
|
|
948
|
+
"resolved": "https://registry.npmjs.org/appium-webdriveragent/-/appium-webdriveragent-8.5.6.tgz",
|
|
949
|
+
"integrity": "sha512-9cfqCfgQ4RmVI66jWuw71Xf1u9EErVaB8KVDGMtOaYxpS3QH6DoGRTWDEzUfmhvOfOZg0mtkHnh4WM1fvscI7w==",
|
|
950
950
|
"dependencies": {
|
|
951
951
|
"@appium/base-driver": "^9.0.0",
|
|
952
952
|
"@appium/strongbox": "^0.x",
|
|
@@ -4217,9 +4217,9 @@
|
|
|
4217
4217
|
}
|
|
4218
4218
|
},
|
|
4219
4219
|
"node_modules/yauzl": {
|
|
4220
|
-
"version": "3.1.
|
|
4221
|
-
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.1.
|
|
4222
|
-
"integrity": "sha512-
|
|
4220
|
+
"version": "3.1.3",
|
|
4221
|
+
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.1.3.tgz",
|
|
4222
|
+
"integrity": "sha512-JCCdmlJJWv7L0q/KylOekyRaUrdEoUxWkWVcgorosTROCFWiS9p2NNPE9Yb91ak7b1N5SxAZEliWpspbZccivw==",
|
|
4223
4223
|
"dependencies": {
|
|
4224
4224
|
"buffer-crc32": "~0.2.3",
|
|
4225
4225
|
"pend": "~1.2.0"
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"xcuitest",
|
|
9
9
|
"xctest"
|
|
10
10
|
],
|
|
11
|
-
"version": "7.
|
|
11
|
+
"version": "7.14.0",
|
|
12
12
|
"author": "Appium Contributors",
|
|
13
13
|
"license": "Apache-2.0",
|
|
14
14
|
"repository": {
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
"singleQuote": true
|
|
132
132
|
},
|
|
133
133
|
"peerDependencies": {
|
|
134
|
-
"appium": "^2.4
|
|
134
|
+
"appium": "^2.5.4"
|
|
135
135
|
},
|
|
136
136
|
"devDependencies": {
|
|
137
137
|
"@appium/docutils": "^1.0.2",
|