appium-xcuitest-driver
Version:
Appium driver for iOS using XCUITest for backend
140 lines • 5.28 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SAFARI_BUNDLE_ID = void 0;
exports.unzipFile = unzipFile;
exports.unzipStream = unzipStream;
exports.buildSafariPreferences = buildSafariPreferences;
exports.findApps = findApps;
const node_path_1 = __importDefault(require("node:path"));
const utils_1 = require("../../utils");
const support_1 = require("appium/support");
const logger_1 = require("../../logger");
const node_child_process_1 = require("node:child_process");
exports.SAFARI_BUNDLE_ID = 'com.apple.mobilesafari';
const SAFARI_OPTS_ALIASES_MAP = {
safariAllowPopups: [
['WebKitJavaScriptCanOpenWindowsAutomatically', 'JavaScriptCanOpenWindowsAutomatically'],
(x) => Number(Boolean(x)),
],
safariIgnoreFraudWarning: [['WarnAboutFraudulentWebsites'], (x) => Number(!x)],
safariOpenLinksInBackground: [['OpenLinksInBackground'], (x) => Number(Boolean(x))],
};
const MACOS_RESOURCE_FOLDER = '__MACOSX';
/**
* Unzips a ZIP archive on the local file system.
*
* @param archivePath Full path to a .zip archive
* @returns Temporary folder root where the archive has been extracted
*/
async function unzipFile(archivePath) {
const useSystemUnzipEnv = process.env.APPIUM_PREFER_SYSTEM_UNZIP;
const useSystemUnzip = (0, utils_1.isEmpty)(useSystemUnzipEnv) || !['0', 'false'].includes(String(useSystemUnzipEnv).toLowerCase());
const tmpRoot = await support_1.tempDir.openDir();
try {
await support_1.zip.extractAllTo(archivePath, tmpRoot, {
useSystemUnzip,
// https://github.com/appium/appium/issues/14100
fileNamesEncoding: 'utf8',
});
}
catch (e) {
await support_1.fs.rimraf(tmpRoot);
throw e;
}
return {
rootDir: tmpRoot,
archiveSize: (await support_1.fs.stat(archivePath)).size,
};
}
/**
* Unzips a ZIP archive from a stream.
* Uses bdstar tool for this purpose.
* This allows to optimize the time needed to prepare the app under test
* to MAX(download, unzip) instead of SUM(download, unzip)
*/
async function unzipStream(zipStream) {
const tmpRoot = await support_1.tempDir.openDir();
const bsdtarProcess = (0, node_child_process_1.spawn)(await support_1.fs.which('bsdtar'), ['-x', '--exclude', MACOS_RESOURCE_FOLDER, '--exclude', `${MACOS_RESOURCE_FOLDER}/*`, '-'], {
cwd: tmpRoot,
});
let archiveSize = 0;
bsdtarProcess.stderr.on('data', (chunk) => {
const stderr = chunk.toString();
if (stderr.trim()) {
logger_1.log.warn(stderr);
}
});
bsdtarProcess.stdin.on('error', (e) => {
logger_1.log.warn(`Error occurred while writing to bsdtar stdin: ${e.message}`);
});
zipStream.on('data', (chunk) => {
archiveSize += chunk.length;
});
zipStream.pipe(bsdtarProcess.stdin);
try {
await new Promise((resolve, reject) => {
zipStream.once('error', reject);
bsdtarProcess.once('exit', (code, signal) => {
zipStream.unpipe(bsdtarProcess.stdin);
logger_1.log.debug(`bsdtar process exited with code ${code}, signal ${signal}`);
if (code === 0) {
resolve(undefined);
}
else {
reject(new Error('Is it a valid ZIP archive?'));
}
});
bsdtarProcess.once('error', (e) => {
zipStream.unpipe(bsdtarProcess.stdin);
reject(e);
});
});
}
catch (err) {
bsdtarProcess.kill(9);
await support_1.fs.rimraf(tmpRoot);
throw new Error(`The response data cannot be unzipped: ${err.message}`, { cause: err });
}
finally {
bsdtarProcess.removeAllListeners();
zipStream.removeAllListeners();
}
return {
rootDir: tmpRoot,
archiveSize,
};
}
/**
* Builds Safari preferences object based on the given session capabilities
*/
function buildSafariPreferences(opts) {
const safariSettings = structuredClone(opts?.safariGlobalPreferences ?? {});
for (const [name, [aliases, valueConverter]] of Object.entries(SAFARI_OPTS_ALIASES_MAP)) {
const optName = name;
if (!Object.hasOwn(opts, optName)) {
continue;
}
for (const alias of aliases) {
safariSettings[alias] = valueConverter(opts[optName]);
}
}
return safariSettings;
}
/**
* Looks for items with given extensions in the given folder.
*
* @param appPath Full path to an app bundle
* @param appExtensions List of matching item extensions
* @returns List of relative paths to matched items
*/
async function findApps(appPath, appExtensions) {
const globPattern = `**/*.+(${appExtensions.map((ext) => ext.replace(/^\./, '')).join('|')})`;
const sortedBundleItems = (await support_1.fs.glob(globPattern, {
cwd: appPath,
})).sort((a, b) => a.split(node_path_1.default.sep).length - b.split(node_path_1.default.sep).length);
return sortedBundleItems;
}
//# sourceMappingURL=app.js.map