UNPKG

appium-android-driver

Version:

Android UiAutomator and Chrome support for Appium

136 lines (120 loc) 3.93 kB
import _ from 'lodash'; import {fs, tempDir} from '@appium/support'; /** * @this {import('../driver').AndroidDriver} * @param {string?} [language=null] * @returns {Promise<import('@appium/types').StringRecord>}} */ export async function getStrings(language = null) { if (!language) { language = await this.adb.getDeviceLanguage(); this.log.info(`No language specified, returning strings for: ${language}`); } // Clients require the resulting mapping to have both keys // and values of type string /** @param {import('@appium/types').StringRecord} mapping */ const preprocessStringsMap = (mapping) => { /** @type {import('@appium/types').StringRecord} */ const result = {}; for (const [key, value] of _.toPairs(mapping)) { result[key] = _.isString(value) ? value : JSON.stringify(value); } return result; }; return preprocessStringsMap(await extractStringsFromResources.bind(this)(language)); } /** * @this {import('../driver').AndroidDriver} * @param {string} language * @param {string} country * @param {string} [script] * @returns {Promise<void>}} */ export async function ensureDeviceLocale(language, country, script) { try { await this.settingsApp.setDeviceLocale(language, country, script); if (!(await this.adb.ensureCurrentLocale(language, country, script))) { throw new Error('Locale verification has failed'); } } catch (e) { this.log.debug(e.stack); let errMsg = `Cannot set the device locale to '${toLocaleAbbr({language, country, script})}'.`; /** @type {string[]} */ let suggestions = []; try { suggestions = (await fetchLocaleSuggestions.bind(this)(language, country)).map(toLocaleAbbr); } catch (e1) { this.log.debug(e1.stack); } if (!_.isEmpty(suggestions)) { errMsg += ` You may want to apply one of the following locales instead: ${suggestions}`; } throw new Error(errMsg); } } // #region Internal helpers /** * @this {import('../driver').AndroidDriver} * @param {string?} [language] * @param {import('../driver').AndroidDriverOpts?} [opts=null] * @returns {Promise<import('@appium/types').StringRecord>}; */ async function extractStringsFromResources(language, opts = null) { const caps = opts ?? this.opts; /** @type {string|undefined} */ let app = caps.app; let tmpRoot; try { if (!app && caps.appPackage) { tmpRoot = await tempDir.openDir(); try { app = await this.adb.pullApk(caps.appPackage, tmpRoot); } catch (e) { throw new Error( `Could not extract app strings, failed to pull an apk from '${caps.appPackage}'. Original error: ${e.message}`, ); } } if (!app || !(await fs.exists(app))) { throw new Error(`Could not extract app strings, no app or package specified`); } return (await this.adb.extractStringsFromApk(app, language ?? null)).apkStrings; } finally { if (tmpRoot) { await fs.rimraf(tmpRoot); } } } /** * @typedef {Object} Locale * @property {string} language * @property {string} country * @property {string} [script] */ /** * @this {import('../driver').AndroidDriver} * @param {string} [language] * @param {string} [country] * @returns {Promise<Locale[]>} */ async function fetchLocaleSuggestions(language, country) { const supportedLocales = await this.settingsApp.listSupportedLocales(); const suggestedLocales = supportedLocales .filter((locale) => _.toLower(language) === _.toLower(locale.language) || _.toLower(country) === _.toLower(locale.country) ); return _.isEmpty(suggestedLocales) ? supportedLocales : suggestedLocales; } /** * * @param {Locale} locale * @returns {string} */ function toLocaleAbbr({language, country, script}) { return `${language}_${country}${script ? ('-' + script) : ''}`; } // #endregion /** * @typedef {import('appium-adb').ADB} ADB */