diff --git a/lib/commands/keyboard.js b/lib/commands/keyboard.js index 4aee4ec0..74105717 100644 --- a/lib/commands/keyboard.js +++ b/lib/commands/keyboard.js @@ -69,7 +69,7 @@ export async function mobilePressKey(opts) { export async function mobileType(opts) { const {text} = opts; if (_.isUndefined(text)) { - throw this.log.errorAndThrow(`The 'text' argument is mandatory`); + throw this.log.errorWithException(`The 'text' argument is mandatory`); } return await this.settingsApp.typeUnicode(String(text)); } diff --git a/lib/driver.ts b/lib/driver.ts index 379d7274..d32ab87e 100644 --- a/lib/driver.ts +++ b/lib/driver.ts @@ -462,7 +462,7 @@ class AndroidUiautomator2Driver `Forwarding UiAutomator2 Server port ${DEVICE_PORT} to local port ${localPort}` ); if ((await checkPortStatus(localPort, LOCALHOST_IP4)) === 'open') { - throw this.log.errorAndThrow( + throw this.log.errorWithException( `UiAutomator2 Server cannot start because the local port #${localPort} is busy. ` + `Make sure the port you provide via 'systemPort' capability is not occupied. ` + `This situation might often be a result of an inaccurate sessions management, e.g. ` + @@ -482,7 +482,7 @@ class AndroidUiautomator2Driver try { this.systemPort = await findAPortNotInUse(startPort, endPort); } catch (e) { - throw this.log.errorAndThrow( + throw this.log.errorWithException( `Cannot find any free port in range ${startPort}..${endPort}}. ` + `Please set the available port number by providing the systemPort capability or ` + `double check the processes that are locking ports within this range and terminate ` + @@ -528,7 +528,7 @@ class AndroidUiautomator2Driver async performSessionPreExecSetup(): Promise { const apiLevel = await this.adb.getApiLevel(); if (apiLevel < 21) { - throw this.log.errorAndThrow( + throw this.log.errorWithException( 'UIAutomator2 is only supported since Android 5.0 (Lollipop). ' + 'You could still use other supported backends in order to automate older Android versions.' ); @@ -542,7 +542,7 @@ class AndroidUiautomator2Driver try { await this.adb.setHiddenApiPolicy('1', !!this.opts.ignoreHiddenApiPolicyError); } catch (err) { - throw this.log.errorAndThrow( + throw this.log.errorWithException( 'Hidden API policy (https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces) cannot be enabled. ' + 'This might be happening because the device under test is not configured properly. ' + 'Please check https://github.com/appium/appium/issues/13802 for more details. ' + @@ -697,13 +697,10 @@ class AndroidUiautomator2Driver const uiautomator2Opts = { // @ts-expect-error FIXME: maybe `address` instead of `host`? host: this.opts.remoteAdbHost || this.opts.host || LOCALHOST_IP4, - systemPort: this.systemPort, + systemPort: this.systemPort as number, devicePort: DEVICE_PORT, adb: this.adb, - apk: this.opts.app, - tmpDir: this.opts.tmpDir, - appPackage: this.opts.appPackage, - appActivity: this.opts.appActivity, + tmpDir: this.opts.tmpDir as string, disableWindowAnimation: !!this.opts.disableWindowAnimation, disableSuppressAccessibilityService: this.opts.disableSuppressAccessibilityService, readTimeout: this.opts.uiautomator2ServerReadTimeout, @@ -753,7 +750,9 @@ class AndroidUiautomator2Driver try { otherApps = utils.parseArray(this.opts.otherApps); } catch (e) { - throw this.log.errorAndThrow(`Could not parse "otherApps" capability: ${(e as Error).message}`); + throw this.log.errorWithException( + `Could not parse "otherApps" capability: ${(e as Error).message}` + ); } otherApps = await B.all( otherApps.map((app) => this.helpers.configureApp(app, [APK_EXTENSION, APKS_EXTENSION])) @@ -785,7 +784,7 @@ class AndroidUiautomator2Driver } } else { if (this.opts.fullReset) { - throw this.log.errorAndThrow( + throw this.log.errorWithException( 'Full reset requires an app capability, use fastReset if app is not provided' ); } @@ -946,7 +945,7 @@ class AndroidUiautomator2Driver async checkAppPresent() { this.log.debug('Checking whether app is actually present'); if (!this.opts.app || !(await fs.exists(this.opts.app))) { - throw this.log.errorAndThrow(`Could not find app apk at '${this.opts.app}'`); + throw this.log.errorWithException(`Could not find app apk at '${this.opts.app}'`); } } diff --git a/lib/uiautomator2.js b/lib/uiautomator2.js index 263b409c..63bc426e 100644 --- a/lib/uiautomator2.js +++ b/lib/uiautomator2.js @@ -22,6 +22,9 @@ class UIA2Proxy extends JWProxy { /** @type {boolean} */ didInstrumentationExit; + /** + * @override + */ async proxyCommand (url, method, body = null) { if (this.didInstrumentationExit) { throw new errors.InvalidContextError( @@ -52,7 +55,12 @@ class UiAutomator2Server { /** @type {import('teen_process').SubProcess|null} */ instrumentationProcess; - constructor (log, opts = {}) { + /** + * + * @param {import('@appium/types').AppiumLogger} log + * @param {UiAutomator2ServerOptions} opts + */ + constructor (log, opts) { for (let req of REQD_PARAMS) { if (!opts || !util.hasValue(opts[req])) { throw new Error(`Option '${req}' is required!`); @@ -277,9 +285,11 @@ class UiAutomator2Server { intervalMs: 1000, }); } catch (err) { - this.log.errorAndThrow(`The instrumentation process cannot be initialized within ${timeout}ms timeout. ` + throw this.log.errorWithException( + `The instrumentation process cannot be initialized within ${timeout}ms timeout. ` + 'Make sure the application under test does not crash and investigate the logcat output. ' - + `You could also try to increase the value of 'uiautomator2ServerLaunchTimeout' capability`); + + `You could also try to increase the value of 'uiautomator2ServerLaunchTimeout' capability` + ); } } if (!this.jwproxy.didInstrumentationExit) { @@ -288,8 +298,10 @@ class UiAutomator2Server { retries++; if (retries >= maxRetries) { - this.log.errorAndThrow('The instrumentation process cannot be initialized. ' - + 'Make sure the application under test does not crash and investigate the logcat output.'); + throw this.log.errorWithException( + 'The instrumentation process cannot be initialized. ' + + 'Make sure the application under test does not crash and investigate the logcat output.' + ); } this.log.warn(`The instrumentation process has been unexpectedly terminated. ` + `Retrying UiAutomator2 startup (#${retries} of ${maxRetries - 1})`); @@ -430,3 +442,16 @@ class UiAutomator2Server { export { UiAutomator2Server, INSTRUMENTATION_TARGET, SERVER_PACKAGE_ID, SERVER_TEST_PACKAGE_ID }; export default UiAutomator2Server; + +/** + * @typedef {Object} UiAutomator2ServerOptions + * @property {import('appium-adb').ADB} adb + * @property {string} tmpDir + * @property {string} host + * @property {number} systemPort + * @property {number} devicePort + * @property {boolean} disableWindowAnimation + * @property {number} [readTimeout] + * @property {boolean} [disableSuppressAccessibilityService] + * @property {string} [apk] + */ \ No newline at end of file