appium-adb-test
Version:
Android Debug Bridge interface
231 lines (208 loc) • 7.77 kB
JavaScript
import path from 'path';
import { system, fs } from 'appium-support';
import log from './logger.js';
import AdmZip from 'adm-zip';
import { exec } from 'teen_process';
import _ from 'lodash';
const rootDir = path.resolve(__dirname, process.env.NO_PRECOMPILE ? '..' : '../..');
const androidPlatforms = ['android-4.2', 'android-17', 'android-4.3', 'android-18',
'android-4.4', 'android-19', 'android-L', 'android-20',
'android-5.0', 'android-21', 'android-22', 'android-MNC',
'android-23', 'android-6.0'];
async function getDirectories (rootPath) {
let files = await fs.readdir(rootPath);
let dirs = [];
for (let file of files) {
let pathString = path.resolve(rootPath, file);
if ((await fs.lstat(pathString)).isDirectory()) {
dirs.push(file);
}
}
// It is not a clean way to sort it, but in this case would work fine because
// we have numerics and alphanumeric
// will return some thing like this
// ["17.0.0", "18.0.1", "19.0.0", "19.0.1", "19.1.0", "20.0.0",
// "android-4.2.2", "android-4.3", "android-4.4"]
return dirs.sort();
}
async function getAndroidPlatformAndPath () {
const androidHome = process.env.ANDROID_HOME;
if (!_.isString(androidHome)) {
log.error("ANDROID_HOME was not exported!");
return null;
}
// get the latest platform and path
let platforms = path.resolve(androidHome, 'platforms');
for (let platform of _.clone(androidPlatforms).reverse()) {
let platformPath = path.resolve(platforms, platform);
if (await fs.exists(platformPath)) {
return {platform, platformPath};
}
}
return null;
}
async function unzipFile (zipPath) {
log.debug(`Unzipping ${zipPath}`);
try {
await assertZipArchive(zipPath);
if (system.isWindows()) {
let zip = new AdmZip(zipPath);
zip.extractAllTo(path.dirname(zipPath), true);
log.debug("Unzip successful");
} else {
await exec('unzip', ['-o', zipPath], {cwd: path.dirname(zipPath)});
log.debug("Unzip successful");
}
} catch (e) {
throw new Error(`Error occurred while unzipping. Original error: ${e.message}`);
}
}
async function assertZipArchive (zipPath) {
log.debug(`Testing zip archive: ${zipPath}`);
if (system.isWindows()) {
if (await fs.exists(zipPath)) {
log.debug("Zip archive tested clean");
} else {
throw new Error(`Zip archive not present at ${zipPath}`);
}
} else {
let execOpts = {cwd: path.dirname(zipPath)};
await exec('unzip', ['-tq', zipPath], execOpts);
}
}
function getIMEListFromOutput (stdout) {
let engines = [];
for (let line of stdout.split('\n')) {
if (line.length > 0 && line[0] !== ' ') {
// remove newline and trailing colon, and add to the list
engines.push(line.trim().replace(/:$/, ''));
}
}
return engines;
}
function getJavaForOs () {
const sep = path.sep;
let java = `${getJavaHome()}${sep}bin${sep}java`;
if (system.isWindows()) {
java = java + '.exe';
}
return java;
}
function getJavaHome () {
if (process.env.JAVA_HOME) {
return process.env.JAVA_HOME;
}
throw new Error("JAVA_HOME is not set currently. Please set JAVA_HOME.");
}
/*
* Checks mShowingLockscreen in dumpsys output to determine if lock screen is showing
*/
function isShowingLockscreen (dumpsys) {
let m = /mShowingLockscreen=\w+/gi.exec(dumpsys);
let ret = (m && m.length && m[0].split('=')[1] === 'true') || false;
return ret;
}
/*
* Checks mCurrentFocus in dumpsys output to determine if Keyguard is activated
*/
function isCurrentFocusOnKeyguard (dumpsys) {
let m = /mCurrentFocus.+Keyguard/gi.exec(dumpsys);
return (m && m.length && m[0]) ? true : false;
}
/*
* Reads SurfaceOrientation in dumpsys output
*/
function getSurfaceOrientation (dumpsys) {
let m = /SurfaceOrientation: \d/gi.exec(dumpsys);
return m && parseInt(m[0].split(':')[1]);
}
/*
* Checks mScreenOnFully in dumpsys output to determine if screen is showing
* Default is true
*/
function isScreenOnFully (dumpsys) {
let m = /mScreenOnFully=\w+/gi.exec(dumpsys);
return !m || // if information is missing we assume screen is fully on
(m && m.length > 0 && m[0].split('=')[1] === 'true') || false;
}
function buildStartCmd (startAppOptions, apiLevel) {
let cmd = ['am', 'start', '-W', '-n', `${startAppOptions.pkg}/${startAppOptions.activity}`];
if (startAppOptions.stopApp && apiLevel >= 15) {
cmd.push('-S');
}
if (startAppOptions.action) {
cmd.push('-a', startAppOptions.action);
}
if (startAppOptions.category) {
cmd.push('-c', startAppOptions.category);
}
if (startAppOptions.flags) {
cmd.push('-f', startAppOptions.flags);
}
if (startAppOptions.optionalIntentArguments) {
// expect optionalIntentArguments to be a single string of the form:
// "-flag key"
// "-flag key value"
// or a combination of these (e.g., "-flag1 key1 -flag2 key2 value2")
// take a string and parse out the part before any spaces, and anything after
// the first space
let parseKeyValue = function (str) {
str = str.trim();
let space = str.indexOf(' ');
if (space === -1) {
return str.length ? [str] : [];
} else {
return [str.substring(0, space).trim(), str.substring(space + 1).trim()];
}
};
// cycle through the optionalIntentArguments and pull out the arguments
// add a space initially so flags can be distinguished from arguments that
// have internal hyphens
let optionalIntentArguments = ` ${startAppOptions.optionalIntentArguments}`;
let re = / (-[^\s]+) (.+)/;
while (true) { // eslint-disable-line no-constant-condition
let args = re.exec(optionalIntentArguments);
if (!args) {
if (optionalIntentArguments.length) {
// no more flags, so the remainder can be treated as 'key' or 'key value'
cmd.push.apply(cmd, parseKeyValue(optionalIntentArguments));
}
// we are done
break;
}
// take the flag and see if it is at the beginning of the string
// if it is not, then it means we have been through already, and
// what is before the flag is the argument for the previous flag
let flag = args[1];
let flagPos = optionalIntentArguments.indexOf(flag);
if (flagPos !== 0) {
let prevArgs = optionalIntentArguments.substring(0, flagPos);
cmd.push.apply(cmd, parseKeyValue(prevArgs));
}
// add the flag, as there are no more earlier arguments
cmd.push(flag);
// make optionalIntentArguments hold the remainder
optionalIntentArguments = args[2];
}
}
return cmd;
}
// turns pkg.activity.name to .activity.name
// also turns activity.name to .activity.name
function getPossibleActivityNames (pkgName, activityName) {
let names = [activityName];
// need to beware of namespaces with overlapping chars:
// com.foo.bar
// com.foo.barx
if (activityName.indexOf(`${pkgName}.`) === 0) {
names.push(activityName.substring(pkgName.length));
}
if (activityName[0] !== '.') {
names.push(`.${activityName}`);
}
return names;
}
export { getDirectories, getAndroidPlatformAndPath, unzipFile, assertZipArchive,
getIMEListFromOutput, getJavaForOs, isShowingLockscreen, isCurrentFocusOnKeyguard,
getSurfaceOrientation, isScreenOnFully, buildStartCmd, getPossibleActivityNames,
getJavaHome, rootDir, androidPlatforms };