diff --git a/lib/doctor/checks.js b/lib/doctor/checks.js index cba8541d..d354c5bf 100644 --- a/lib/doctor/checks.js +++ b/lib/doctor/checks.js @@ -1,5 +1,5 @@ -import {ok, nok, okOptional, nokOptional, resolveExecutablePath} from './utils'; -import {system, fs, logger} from '@appium/support'; +import {resolveExecutablePath} from './utils'; +import {system, fs, logger, doctor} from '@appium/support'; import path from 'path'; import '@colors/colors'; import {getAndroidBinaryPath, getSdkRootFromEnv} from 'appium-adb'; @@ -23,6 +23,7 @@ const FFMPEG_INSTALL_LINK = 'https://www.ffmpeg.org/download.html'; * the path is expected to be a valid file */ +/** @satisfies {import('@appium/types').IDoctorCheck} */ class EnvVarAndPathCheck { /** * @param {string} varName @@ -36,7 +37,7 @@ class EnvVarAndPathCheck { async diagnose() { const varValue = process.env[this.varName]; if (!varValue) { - return nok(`${this.varName} environment variable is NOT set!`); + return doctor.nok(`${this.varName} environment variable is NOT set!`); } if (!await fs.exists(varValue)) { @@ -44,18 +45,18 @@ class EnvVarAndPathCheck { if (system.isWindows() && varValue.includes('%')) { errMsg += ` Consider replacing all references to other environment variables with absolute paths.`; } - return nok(errMsg); + return doctor.nok(errMsg); } const stat = await fs.stat(varValue); if (this.opts.expectDir && !stat.isDirectory()) { - return nok(`${this.varName} is expected to be a valid folder, got a file path instead`); + return doctor.nok(`${this.varName} is expected to be a valid folder, got a file path instead`); } if (this.opts.expectFile && stat.isDirectory()) { - return nok(`${this.varName} is expected to be a valid file, got a folder path instead`); + return doctor.nok(`${this.varName} is expected to be a valid file, got a folder path instead`); } - return ok(`${this.varName} is set to: ${varValue}`); + return doctor.ok(`${this.varName} is set to: ${varValue}`); } async fix() { @@ -64,35 +65,53 @@ class EnvVarAndPathCheck { `Refer ${ENVIRONMENT_VARS_TUTORIAL_URL} for more details.` ); } + + hasAutofix() { + return false; + } + + isOptional() { + return false; + } } export const androidHomeCheck = new EnvVarAndPathCheck('ANDROID_HOME', {expectDir: true}); export const javaHomeCheck = new EnvVarAndPathCheck('JAVA_HOME', {expectDir: true}); +/** @satisfies {import('@appium/types').IDoctorCheck} */ export class JavaHomeValueCheck { async diagnose() { const envVar = process.env.JAVA_HOME; if (!envVar) { - return nok(`${JAVA_HOME_VAR_NAME} environment variable must be set`); + return doctor.nok(`${JAVA_HOME_VAR_NAME} environment variable must be set`); } const javaBinaryRelativePath = path.join('bin', `java${system.isWindows() ? '.exe' : ''}`); const javaBinary = path.join(envVar, javaBinaryRelativePath); if (!await fs.exists(javaBinary)) { - return nok( + return doctor.nok( `${JAVA_HOME_VAR_NAME} is set to an invalid value. ` + `It must be pointing to a folder containing ${javaBinaryRelativePath}` ); } - return ok(`'${javaBinaryRelativePath}' exists under '${envVar}'`); + return doctor.ok(`'${javaBinaryRelativePath}' exists under '${envVar}'`); } async fix() { return `Set ${JAVA_HOME_VAR_NAME} environment variable to the root folder path of your local JDK installation. ` + `Read ${JAVA_HOME_TUTORIAL}`; } + + hasAutofix() { + return false; + } + + isOptional() { + return false; + } } export const javaHomeValueCheck = new JavaHomeValueCheck(); +/** @satisfies {import('@appium/types').IDoctorCheck} */ export class AndroidSdkCheck { TOOL_NAMES = ['adb', 'emulator', `apkanalyzer${system.isWindows() ? '.bat' : ''}`]; @@ -100,7 +119,7 @@ export class AndroidSdkCheck { const listOfTools = this.TOOL_NAMES.join(', '); const sdkRoot = getSdkRootFromEnv(); if (!sdkRoot) { - return nok( + return doctor.nok( `${listOfTools} could not be found because ANDROID_HOME is NOT set!` ); } @@ -116,10 +135,10 @@ export class AndroidSdkCheck { } if (missingBinaries.length > 0) { - return nok(`${missingBinaries.join(', ')} could NOT be found in '${sdkRoot}'!`); + return doctor.nok(`${missingBinaries.join(', ')} could NOT be found in '${sdkRoot}'!`); } - return ok(`${listOfTools} exist in '${sdkRoot}'`); + return doctor.ok(`${listOfTools} exist in '${sdkRoot}'`); } async fix() { @@ -128,15 +147,24 @@ export class AndroidSdkCheck { `Read ${[ANDROID_SDK_LINK1, ANDROID_SDK_LINK2].join(' and ')}.` ); } + + hasAutofix() { + return false; + } + + isOptional() { + return false; + } } export const androidSdkCheck = new AndroidSdkCheck(); +/** @satisfies {import('@appium/types').IDoctorCheck} */ export class OptionalBundletoolCheck { async diagnose() { const bundletoolPath = await resolveExecutablePath('bundletool.jar'); return bundletoolPath - ? okOptional(`bundletool.jar is installed at: ${bundletoolPath}`) - : nokOptional('bundletool.jar cannot be found'); + ? doctor.okOptional(`bundletool.jar is installed at: ${bundletoolPath}`) + : doctor.nokOptional('bundletool.jar cannot be found'); } async fix() { @@ -147,9 +175,18 @@ export class OptionalBundletoolCheck { `are currently present in PATH: ${process.env.PATH}` ); } + + hasAutofix() { + return false; + } + + isOptional() { + return true; + } } export const optionalBundletoolCheck = new OptionalBundletoolCheck(); +/** @satisfies {import('@appium/types').IDoctorCheck} */ export class OptionalGstreamerCheck { GSTREAMER_BINARY = `gst-launch-1.0${system.isWindows() ? '.exe' : ''}`; GST_INSPECT_BINARY = `gst-inspect-1.0${system.isWindows() ? '.exe' : ''}`; @@ -159,10 +196,10 @@ export class OptionalGstreamerCheck { const gstInspectPath = await resolveExecutablePath(this.GST_INSPECT_BINARY); return gstreamerPath && gstInspectPath - ? okOptional( + ? doctor.okOptional( `${this.GSTREAMER_BINARY} and ${this.GST_INSPECT_BINARY} are installed at: ${gstreamerPath} and ${gstInspectPath}` ) - : nokOptional(`${this.GSTREAMER_BINARY} and/or ${this.GST_INSPECT_BINARY} cannot be found`); + : doctor.nokOptional(`${this.GSTREAMER_BINARY} and/or ${this.GST_INSPECT_BINARY} cannot be found`); } async fix() { @@ -173,9 +210,18 @@ export class OptionalGstreamerCheck { `Please read ${GSTREAMER_INSTALL_LINK}.` ); } + + hasAutofix() { + return false; + } + + isOptional() { + return true; + } } export const optionalGstreamerCheck = new OptionalGstreamerCheck(); +/** @satisfies {import('@appium/types').IDoctorCheck} */ export class OptionalFfmpegCheck { FFMPEG_BINARY = `ffmpeg${system.isWindows() ? '.exe' : ''}`; @@ -183,8 +229,8 @@ export class OptionalFfmpegCheck { const ffmpegPath = await resolveExecutablePath(this.FFMPEG_BINARY); return ffmpegPath - ? okOptional(`${this.FFMPEG_BINARY} exists at '${ffmpegPath}'`) - : nokOptional(`${this.FFMPEG_BINARY} cannot be found`); + ? doctor.okOptional(`${this.FFMPEG_BINARY} exists at '${ffmpegPath}'`) + : doctor.nokOptional(`${this.FFMPEG_BINARY} cannot be found`); } async fix() { @@ -193,5 +239,13 @@ export class OptionalFfmpegCheck { `Please read ${FFMPEG_INSTALL_LINK}.` ); } + + hasAutofix() { + return false; + } + + isOptional() { + return true; + } } export const optionalFfmpegCheck = new OptionalFfmpegCheck(); diff --git a/lib/doctor/utils.js b/lib/doctor/utils.js index fb5f811f..bac53a9b 100644 --- a/lib/doctor/utils.js +++ b/lib/doctor/utils.js @@ -1,33 +1,5 @@ import {fs} from '@appium/support'; -/** - * @param {string} message - */ -export function ok(message) { - return {ok: true, optional: false, message}; -} - -/** - * @param {string} message - */ -export function nok(message) { - return {ok: false, optional: false, message}; -} - -/** - * @param {string} message - */ -export function okOptional(message) { - return {ok: true, optional: true, message}; -} - -/** - * @param {string} message - */ -export function nokOptional(message) { - return {ok: false, optional: true, message}; -} - /** * Return an executable path of cmd * diff --git a/package.json b/package.json index 2eaefaca..c20120ea 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "singleQuote": true }, "dependencies": { + "@appium/support": "^4.2.0", "@colors/colors": "1.6.0", "appium-adb": "^11.0.1", "appium-chromedriver": "^5.5.1", @@ -76,7 +77,6 @@ "devDependencies": { "@appium/eslint-config-appium": "^8.0.4", "@appium/eslint-config-appium-ts": "^0.x", - "@appium/support": "^4.1.2", "@appium/test-support": "^3.0.20", "@appium/tsconfig": "^0.x", "@appium/types": "^0.x",