appium-xcuitest-driver
Version:
Appium driver for iOS using XCUITest for backend
131 lines • 5.78 kB
JavaScript
;
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