UNPKG

appium-xcuitest-driver

Version:

Appium driver for iOS using XCUITest for backend

131 lines 5.78 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseLocalizableStrings = parseLocalizableStrings; exports.getStrings = getStrings; const node_path_1 = __importDefault(require("node:path")); const support_1 = require("appium/support"); const helpers_1 = require("./helpers"); const utils_1 = require("../utils"); const constants_1 = require("./constants"); const STRINGSDICT_RESOURCE = '.stringsdict'; const STRINGS_RESOURCE = '.strings'; /** * Extracts string resources from an app */ async function parseLocalizableStrings(opts = {}) { const { app, language = 'en', localizableStringsDir, stringFile, strictMode } = opts; if (!app) { const message = `Strings extraction is not supported if 'app' capability is not set`; if (strictMode) { throw new Error(message); } this.log.info(message); return {}; } let bundleRoot = app; const isArchive = (await support_1.fs.stat(app)).isFile(); let tmpRoot; try { if (isArchive) { tmpRoot = await support_1.tempDir.openDir(); this.log.info(`Extracting '${app}' into a temporary location to parse its resources`); await support_1.zip.extractAllTo(app, tmpRoot); const relativeBundleRoot = (await (0, helpers_1.findApps)(tmpRoot, [constants_1.APP_EXT]))[0]; this.log.info(`Selecting '${relativeBundleRoot}'`); bundleRoot = node_path_1.default.join(tmpRoot, relativeBundleRoot); } let lprojRoot; for (const subfolder of [`${language}.lproj`, localizableStringsDir, ''].filter((x) => typeof x === 'string')) { lprojRoot = node_path_1.default.resolve(bundleRoot, subfolder); if (await support_1.fs.exists(lprojRoot)) { break; } const message = `No '${lprojRoot}' resources folder has been found`; if (strictMode) { throw new Error(message); } this.log.debug(message); } if (!lprojRoot) { return {}; } this.log.info(`Retrieving resource strings from '${lprojRoot}'`); const resourcePaths = []; if (stringFile) { const dstPath = node_path_1.default.resolve(lprojRoot, stringFile); if (await support_1.fs.exists(dstPath)) { resourcePaths.push(dstPath); } else { const message = `No '${dstPath}' resource file has been found for '${app}'`; if (strictMode) { throw new Error(message); } this.log.info(message); } } if ((0, utils_1.isEmpty)(resourcePaths) && lprojRoot && (await support_1.fs.exists(lprojRoot))) { const resourceFiles = (await support_1.fs.readdir(lprojRoot)) .filter((name) => [STRINGS_RESOURCE, STRINGSDICT_RESOURCE].some((x) => name.endsWith(x))) .map((name) => node_path_1.default.resolve(lprojRoot, name)); resourcePaths.push(...resourceFiles); } this.log.info(`Got ${support_1.util.pluralize('resource file', resourcePaths.length, true)} in '${lprojRoot}'`); if ((0, utils_1.isEmpty)(resourcePaths)) { return {}; } const resultStrings = {}; const toAbsolutePath = (p) => (node_path_1.default.isAbsolute(p) ? p : node_path_1.default.resolve(process.cwd(), p)); for (const resourcePath of resourcePaths) { if (!support_1.util.isSubPath(toAbsolutePath(resourcePath), toAbsolutePath(bundleRoot))) { throw new Error(`'${resourcePath}' is expected to be located under '${bundleRoot}'`); } try { const data = await readResource(resourcePath); this.log.debug(`Parsed ${support_1.util.pluralize('string', Object.keys(data).length, true)} from '${resourcePath}'`); (0, utils_1.mergeDeep)(resultStrings, data); } catch (e) { this.log.warn(`Cannot parse '${resourcePath}' resource. Original error: ${e.message}`); } } this.log.info(`Retrieved ${support_1.util.pluralize('string', Object.keys(resultStrings).length, true)} from '${lprojRoot}'`); return resultStrings; } finally { if (tmpRoot) { await support_1.fs.rimraf(tmpRoot); } } } /** * Return the language-specific strings for an app * * @param language - The language abbreviation to fetch app strings mapping for. * If no language is provided then strings for the 'en language would be returned * @param stringFile - Relative path to the corresponding .strings * file starting from the corresponding .lproj folder, e.g., `base/main.strings`. If omitted, * then Appium will make its best guess where the file is. * * @returns A record of localized keys to localized text */ async function getStrings(language, stringFile = null) { this.log.debug(`Gettings strings for language '${language}' and string file '${stringFile}'`); return await parseLocalizableStrings.bind(this)({ ...this.opts, language, stringFile, strictMode: true, }); } async function readResource(resourcePath) { const data = await support_1.plist.parsePlistFile(resourcePath); return Object.entries(data).reduce((result, [key, value]) => { result[key] = typeof value === 'string' ? value : JSON.stringify(value); return result; }, {}); } //# sourceMappingURL=app-strings.js.map