UNPKG

appium-espresso-driver

Version:
194 lines (176 loc) 6.8 kB
import type {EspressoDriver} from '../../driver.js'; import {qualifyActivityName, getPackageInfo} from '../../utils/index.js'; import {DEVICE_PORT} from './constants.js'; import {EspressoRunner} from './runner.js'; /** * Start an Espresso session: device setup, server install, and session launch. */ export async function startSession(this: EspressoDriver): Promise<void> { const {manifestPayload} = await getPackageInfo(); this.log.info(`EspressoDriver version: ${manifestPayload.version}`); // Read https://github.com/appium/appium-android-driver/pull/461 what happens if there is no setHiddenApiPolicy for Android P+ if ((await this.adb.getApiLevel()) >= 28) { // Android P this.log.warn('Relaxing hidden api policy'); await this.adb.setHiddenApiPolicy('1', !!this.opts.ignoreHiddenApiPolicyError); } // get appPackage et al from manifest if necessary let appInfo = await this.getLaunchInfo(); if (appInfo) { // and get it onto our 'opts' object so we use it from now on Object.assign(this.opts, appInfo); } else { appInfo = this.opts; } // start an avd, set the language/locale, pick an emulator, etc... if (this.opts.hideKeyboard) { this._originalIme = await this.adb.defaultIME(); } await this.initDevice(); // Default state is window animation disabled. await this.setWindowAnimationState(this.caps.disableWindowAnimation === false); // set actual device name, udid this.caps.deviceName = this.adb.curDeviceId; const {udid, systemPort} = this.opts; if (!udid) { throw this.log.errorWithException('udid is required'); } if (systemPort == null) { throw this.log.errorWithException('systemPort is required'); } this.caps.deviceUDID = udid; // set up the modified espresso server etc this.initEspressoServer(); // Further prepare the device by forwarding the espresso port this.log.debug(`Forwarding Espresso Server port ${DEVICE_PORT} to ${systemPort}`); await this.adb.forwardPort(systemPort, DEVICE_PORT); if (!this.opts.skipUnlock) { // unlock the device to prepare it for testing await this.unlock(); } else { this.log.debug(`'skipUnlock' capability set, so skipping device unlock`); } // set up app under test // prepare our actual AUT, get it on the device, etc... await this.initAUT(); //Adding AUT package name in the capabilities if package name not exist in caps if (!this.caps.appPackage) { this.caps.appPackage = appInfo.appPackage; } const appPackage = this.caps.appPackage; if (!appPackage) { throw this.log.errorWithException('appPackage is required'); } if (!this.caps.appWaitPackage) { this.caps.appWaitPackage = appInfo.appWaitPackage || appInfo.appPackage || appPackage; } const appWaitPackage = this.caps.appWaitPackage; if (!appWaitPackage) { throw this.log.errorWithException('appWaitPackage is required'); } if (this.caps.appActivity) { this.caps.appActivity = qualifyActivityName(this.caps.appActivity, appPackage); } else { const appActivity = appInfo.appActivity; if (!appActivity) { throw this.log.errorWithException('appActivity is required'); } this.caps.appActivity = qualifyActivityName(appActivity, appPackage); } if (this.caps.appWaitActivity) { this.caps.appWaitActivity = qualifyActivityName(this.caps.appWaitActivity, appWaitPackage); } else { this.caps.appWaitActivity = qualifyActivityName( appInfo.appWaitActivity || appInfo.appActivity || this.caps.appActivity, appWaitPackage, ); } // launch espresso and wait till its online and we have a session await this.espresso.startSession(this.caps); if (this.caps.autoLaunch === false) { this.log.info( `Not waiting for the application activity to start because 'autoLaunch' is disabled`, ); } else { await this.adb.waitForActivity( appWaitPackage, this.caps.appWaitActivity, this.opts.appWaitDuration, ); } // if we want to immediately get into a webview, set our context // appropriately if (this.opts.autoWebview) { await this.initWebview(); } // now that everything has started successfully, turn on proxying so all // subsequent session requests go straight to/from espresso this.jwpProxyActive = true; await this.addDeviceInfoToCaps(); } /** * Create the Espresso runner and wire proxy handlers on the driver. */ export function initServer(this: EspressoDriver): void { const {systemPort, tmpDir, appPackage} = this.opts; if (systemPort == null) { throw this.log.errorWithException('systemPort is required'); } if (!tmpDir) { throw this.log.errorWithException('tmpDir is required'); } if (!appPackage) { throw this.log.errorWithException('appPackage is required'); } // now that we have package and activity, we can create an instance of // espresso with the appropriate data this.espresso = new EspressoRunner(this.log, { host: this.opts.remoteAdbHost || '127.0.0.1', systemPort, devicePort: DEVICE_PORT, adb: this.adb, tmpDir, appPackage, forceEspressoRebuild: !!this.opts.forceEspressoRebuild, espressoBuildConfig: this.opts.espressoBuildConfig, showGradleLog: !!this.opts.showGradleLog, serverLaunchTimeout: this.opts.espressoServerLaunchTimeout, androidInstallTimeout: this.opts.androidInstallTimeout, useKeystore: this.opts.useKeystore, keystorePath: this.opts.keystorePath, keystorePassword: this.opts.keystorePassword, keyAlias: this.opts.keyAlias, keyPassword: this.opts.keyPassword, disableSuppressAccessibilityService: this.opts.disableSuppressAccessibilityService, reqBasePath: this.basePath, }); this.proxyReqRes = this.espresso.proxyReqRes.bind(this.espresso); this.proxyCommand = this.espresso.proxyCommand.bind(this.espresso); } /** * Tear down the Espresso server session and clear the runner reference. */ export async function teardown(driver: EspressoDriver): Promise<void> { if (driver.espresso) { if (driver.jwpProxyActive) { await driver.espresso.deleteSession(); } (driver as {espresso: EspressoRunner | null}).espresso = null; } driver.jwpProxyActive = false; } /** * Remove the ADB port forward for the Espresso server system port. */ export async function removePortForward(driver: EspressoDriver): Promise<void> { if (driver.opts.systemPort) { try { await driver.adb.removePortForward(driver.opts.systemPort); } catch (error: unknown) { const message = error instanceof Error ? error.message : String(error); driver.log.warn(`Unable to remove port forward '${message}'`); // Ignore, this block will also be called when we fall in catch block // and before even port forward. } } }