UNPKG

appium-doctor

Version:

Test environment for fitness to run Appium

146 lines (105 loc) 17 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.AndroidToolCheck = void 0; Object.defineProperty(exports, "EnvVarAndPathCheck", { enumerable: true, get: function () { return _env.default; } }); exports.default = exports.OptionalGstreamerCheck = exports.OptionalAppBundleCheck = exports.JavaOnPathCheck = void 0; require("source-map-support/register"); var _doctor = require("./doctor"); var _utils = require("./utils"); var _appiumSupport = require("appium-support"); var _path = _interopRequireDefault(require("path")); var _env = _interopRequireDefault(require("./env")); require("@colors/colors"); var _appiumAdb = require("appium-adb"); var _logger = _interopRequireDefault(require("./logger")); let checks = []; const javaHome = _appiumSupport.system.isWindows() ? '%JAVA_HOME%' : '$JAVA_HOME'; checks.push(new _env.default('ANDROID_HOME')); checks.push(new _env.default('JAVA_HOME')); class JavaOnPathCheck extends _doctor.DoctorCheck { async diagnose() { if (process.env.JAVA_HOME) { const javaHomeBin = _path.default.resolve(process.env.JAVA_HOME, 'bin'); return (await _appiumSupport.fs.exists(javaHomeBin)) ? (0, _utils.ok)(`'bin' subfolder exists under '${process.env.JAVA_HOME}'`) : (0, _utils.nok)(`'bin' subfolder does not exist under '${process.env.JAVA_HOME}'. ` + `Is ${javaHome} set to a proper value?`); } return (0, _utils.nok)(`Cannot check ${javaHome} requirements since the environment variable itself is not set`); } fix() { return `Set ${javaHome} environment variable to the root folder path of your local JDK installation`; } } exports.JavaOnPathCheck = JavaOnPathCheck; class AndroidToolCheck extends _doctor.DoctorCheck { constructor() { super(); this.tools = ['adb', 'android', 'emulator', `apkanalyzer${_appiumSupport.system.isWindows() ? '.bat' : ''}`]; this.noBinaries = []; } async diagnose() { const listOfTools = this.tools.join(', '); const sdkRoot = (0, _appiumAdb.getSdkRootFromEnv)(); if (!sdkRoot) { return (0, _utils.nok)(`${listOfTools} could not be found because ANDROID_HOME or ANDROID_SDK_ROOT is NOT set!`); } _logger.default.info(` Checking ${listOfTools}`); for (const binary of this.tools) { try { _logger.default.info(` '${binary}' is in ${await (0, _appiumAdb.getAndroidBinaryPath)(binary)}`); } catch (e) { this.noBinaries.push(binary); } } if (this.noBinaries.length > 0) { return (0, _utils.nok)(`${this.noBinaries.join(', ')} could NOT be found in ${sdkRoot}!`); } return (0, _utils.ok)(`${listOfTools} exist: ${sdkRoot}`); } fix() { if (typeof process.env.ANDROID_HOME === 'undefined') { return `Manually configure ${'ANDROID_HOME'.bold} and run appium-doctor again.`; } return `Manually install ${this.noBinaries.join(', ').bold} and add it to ${'PATH'.bold}. ` + 'https://developer.android.com/studio#cmdline-tools and ' + 'https://developer.android.com/studio/intro/update#sdk-manager may help to setup.'; } } exports.AndroidToolCheck = AndroidToolCheck; checks.push(new AndroidToolCheck()); checks.push(new JavaOnPathCheck()); class OptionalAppBundleCheck extends _doctor.DoctorCheck { async diagnose() { const bundletoolPath = await (0, _utils.resolveExecutablePath)('bundletool.jar'); return bundletoolPath ? (0, _utils.okOptional)(`bundletool.jar is installed at: ${bundletoolPath}`) : (0, _utils.nokOptional)('bundletool.jar cannot be found'); } async fix() { return `${'bundletool.jar'.bold} is used to handle Android App Bundle. Please read http://appium.io/docs/en/writing-running-appium/android/android-appbundle/ to install it` + `${_appiumSupport.system.isWindows() ? '. Also consider adding the ".jar" extension into your PATHEXT environment variable in order to fix the problem for Windows' : ''}`; } } exports.OptionalAppBundleCheck = OptionalAppBundleCheck; checks.push(new OptionalAppBundleCheck()); class OptionalGstreamerCheck extends _doctor.DoctorCheck { constructor(...args) { super(...args); this.GSTREAMER_BINARY = `gst-launch-1.0${_appiumSupport.system.isWindows() ? '.exe' : ''}`; this.GST_INSPECT_BINARY = `gst-inspect-1.0${_appiumSupport.system.isWindows() ? '.exe' : ''}`; } async diagnose() { const gstreamerPath = await (0, _utils.resolveExecutablePath)(this.GSTREAMER_BINARY); const gstInspectPath = await (0, _utils.resolveExecutablePath)(this.GST_INSPECT_BINARY); return gstreamerPath && gstInspectPath ? (0, _utils.okOptional)(`${this.GSTREAMER_BINARY} and ${this.GST_INSPECT_BINARY} are installed at: ${gstreamerPath} and ${gstInspectPath}`) : (0, _utils.nokOptional)(`${this.GSTREAMER_BINARY} and/or ${this.GST_INSPECT_BINARY} cannot be found`); } async fix() { return `${`${this.GSTREAMER_BINARY} and ${this.GST_INSPECT_BINARY}`.bold} are used to stream the screen of the device under test. ` + 'Please read https://appium.io/docs/en/writing-running-appium/android/android-screen-streaming/ to install them and for more details'; } } exports.OptionalGstreamerCheck = OptionalGstreamerCheck; checks.push(new OptionalGstreamerCheck()); var _default = checks; exports.default = _default;require('source-map-support').install(); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGliL2FuZHJvaWQuanMiLCJuYW1lcyI6WyJjaGVja3MiLCJqYXZhSG9tZSIsInN5c3RlbSIsImlzV2luZG93cyIsInB1c2giLCJFbnZWYXJBbmRQYXRoQ2hlY2siLCJKYXZhT25QYXRoQ2hlY2siLCJEb2N0b3JDaGVjayIsImRpYWdub3NlIiwicHJvY2VzcyIsImVudiIsIkpBVkFfSE9NRSIsImphdmFIb21lQmluIiwicGF0aCIsInJlc29sdmUiLCJmcyIsImV4aXN0cyIsIm9rIiwibm9rIiwiZml4IiwiQW5kcm9pZFRvb2xDaGVjayIsImNvbnN0cnVjdG9yIiwidG9vbHMiLCJub0JpbmFyaWVzIiwibGlzdE9mVG9vbHMiLCJqb2luIiwic2RrUm9vdCIsImdldFNka1Jvb3RGcm9tRW52IiwibG9nIiwiaW5mbyIsImJpbmFyeSIsImdldEFuZHJvaWRCaW5hcnlQYXRoIiwiZSIsImxlbmd0aCIsIkFORFJPSURfSE9NRSIsImJvbGQiLCJPcHRpb25hbEFwcEJ1bmRsZUNoZWNrIiwiYnVuZGxldG9vbFBhdGgiLCJyZXNvbHZlRXhlY3V0YWJsZVBhdGgiLCJva09wdGlvbmFsIiwibm9rT3B0aW9uYWwiLCJPcHRpb25hbEdzdHJlYW1lckNoZWNrIiwiR1NUUkVBTUVSX0JJTkFSWSIsIkdTVF9JTlNQRUNUX0JJTkFSWSIsImdzdHJlYW1lclBhdGgiLCJnc3RJbnNwZWN0UGF0aCJdLCJzb3VyY2VSb290IjoiLi4vLi4iLCJzb3VyY2VzIjpbImxpYi9hbmRyb2lkLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERvY3RvckNoZWNrIH0gZnJvbSAnLi9kb2N0b3InO1xuaW1wb3J0IHsgb2ssIG5vaywgb2tPcHRpb25hbCwgbm9rT3B0aW9uYWwsIHJlc29sdmVFeGVjdXRhYmxlUGF0aCB9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHsgc3lzdGVtLCBmcyB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IEVudlZhckFuZFBhdGhDaGVjayBmcm9tICcuL2Vudic7XG5pbXBvcnQgJ0Bjb2xvcnMvY29sb3JzJztcbmltcG9ydCB7IGdldEFuZHJvaWRCaW5hcnlQYXRoLCBnZXRTZGtSb290RnJvbUVudiB9IGZyb20gJ2FwcGl1bS1hZGInO1xuaW1wb3J0IGxvZyBmcm9tICcuL2xvZ2dlcic7XG5cbmxldCBjaGVja3MgPSBbXTtcblxuY29uc3QgamF2YUhvbWUgPSBzeXN0ZW0uaXNXaW5kb3dzKCkgPyAnJUpBVkFfSE9NRSUnIDogJyRKQVZBX0hPTUUnO1xuXG5jaGVja3MucHVzaChuZXcgRW52VmFyQW5kUGF0aENoZWNrKCdBTkRST0lEX0hPTUUnKSk7XG5jaGVja3MucHVzaChuZXcgRW52VmFyQW5kUGF0aENoZWNrKCdKQVZBX0hPTUUnKSk7XG5cbi8vIENoZWNrIHRoYXQgdGhlIFBBVEggaW5jbHVkZXMgdGhlIGpkaydzIGJpbiBkaXJlY3RvcnlcbmNsYXNzIEphdmFPblBhdGhDaGVjayBleHRlbmRzIERvY3RvckNoZWNrIHtcbiAgYXN5bmMgZGlhZ25vc2UgKCkge1xuICAgIGlmIChwcm9jZXNzLmVudi5KQVZBX0hPTUUpIHtcbiAgICAgIGNvbnN0IGphdmFIb21lQmluID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuZW52LkpBVkFfSE9NRSwgJ2JpbicpO1xuICAgICAgcmV0dXJuIGF3YWl0IGZzLmV4aXN0cyhqYXZhSG9tZUJpbilcbiAgICAgICAgPyBvayhgJ2Jpbicgc3ViZm9sZGVyIGV4aXN0cyB1bmRlciAnJHtwcm9jZXNzLmVudi5KQVZBX0hPTUV9J2ApXG4gICAgICAgIDogbm9rKGAnYmluJyBzdWJmb2xkZXIgZG9lcyBub3QgZXhpc3QgdW5kZXIgJyR7cHJvY2Vzcy5lbnYuSkFWQV9IT01FfScuIGAgK1xuICAgICAgICAgICAgICBgSXMgJHtqYXZhSG9tZX0gc2V0IHRvIGEgcHJvcGVyIHZhbHVlP2ApO1xuICAgIH1cbiAgICByZXR1cm4gbm9rKGBDYW5ub3QgY2hlY2sgJHtqYXZhSG9tZX0gcmVxdWlyZW1lbnRzIHNpbmNlIHRoZSBlbnZpcm9ubWVudCB2YXJpYWJsZSBpdHNlbGYgaXMgbm90IHNldGApO1xuICB9XG5cbiAgZml4ICgpIHtcbiAgICByZXR1cm4gYFNldCAke2phdmFIb21lfSBlbnZpcm9ubWVudCB2YXJpYWJsZSB0byB0aGUgcm9vdCBmb2xkZXIgcGF0aCBvZiB5b3VyIGxvY2FsIEpESyBpbnN0YWxsYXRpb25gO1xuICB9XG59XG5cbi8vIENoZWNrIHRvb2xzXG5jbGFzcyBBbmRyb2lkVG9vbENoZWNrIGV4dGVuZHMgRG9jdG9yQ2hlY2sge1xuICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLnRvb2xzID0gWydhZGInLCAnYW5kcm9pZCcsICdlbXVsYXRvcicsIGBhcGthbmFseXplciR7c3lzdGVtLmlzV2luZG93cygpID8gJy5iYXQnIDogJyd9YF07XG4gICAgdGhpcy5ub0JpbmFyaWVzID0gW107XG4gIH1cblxuICBhc3luYyBkaWFnbm9zZSAoKSB7XG4gICAgY29uc3QgbGlzdE9mVG9vbHMgPSB0aGlzLnRvb2xzLmpvaW4oJywgJyk7XG4gICAgY29uc3Qgc2RrUm9vdCA9IGdldFNka1Jvb3RGcm9tRW52KCk7XG4gICAgaWYgKCFzZGtSb290KSB7XG4gICAgICByZXR1cm4gbm9rKGAke2xpc3RPZlRvb2xzfSBjb3VsZCBub3QgYmUgZm91bmQgYmVjYXVzZSBBTkRST0lEX0hPTUUgb3IgQU5EUk9JRF9TREtfUk9PVCBpcyBOT1Qgc2V0IWApO1xuICAgIH1cblxuICAgIGxvZy5pbmZvKGAgICBDaGVja2luZyAke2xpc3RPZlRvb2xzfWApO1xuXG4gICAgZm9yIChjb25zdCBiaW5hcnkgb2YgdGhpcy50b29scykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbG9nLmluZm8oYCAgICAgJyR7YmluYXJ5fScgaXMgaW4gJHthd2FpdCBnZXRBbmRyb2lkQmluYXJ5UGF0aChiaW5hcnkpfWApO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLm5vQmluYXJpZXMucHVzaChiaW5hcnkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLm5vQmluYXJpZXMubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIG5vayhgJHt0aGlzLm5vQmluYXJpZXMuam9pbignLCAnKX0gY291bGQgTk9UIGJlIGZvdW5kIGluICR7c2RrUm9vdH0hYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9rKGAke2xpc3RPZlRvb2xzfSBleGlzdDogJHtzZGtSb290fWApO1xuICB9XG5cbiAgZml4ICgpIHtcbiAgICBpZiAodHlwZW9mIHByb2Nlc3MuZW52LkFORFJPSURfSE9NRSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBgTWFudWFsbHkgY29uZmlndXJlICR7J0FORFJPSURfSE9NRScuYm9sZH0gYW5kIHJ1biBhcHBpdW0tZG9jdG9yIGFnYWluLmA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGBNYW51YWxseSBpbnN0YWxsICR7dGhpcy5ub0JpbmFyaWVzLmpvaW4oJywgJykuYm9sZH0gYW5kIGFkZCBpdCB0byAkeydQQVRIJy5ib2xkfS4gYCArXG4gICAgICAnaHR0cHM6Ly9kZXZlbG9wZXIuYW5kcm9pZC5jb20vc3R1ZGlvI2NtZGxpbmUtdG9vbHMgYW5kICcgK1xuICAgICAgJ2h0dHBzOi8vZGV2ZWxvcGVyLmFuZHJvaWQuY29tL3N0dWRpby9pbnRyby91cGRhdGUjc2RrLW1hbmFnZXIgbWF5IGhlbHAgdG8gc2V0dXAuJztcbiAgfVxufVxuY2hlY2tzLnB1c2gobmV3IEFuZHJvaWRUb29sQ2hlY2soKSk7XG5jaGVja3MucHVzaChuZXcgSmF2YU9uUGF0aENoZWNrKCkpO1xuXG5jbGFzcyBPcHRpb25hbEFwcEJ1bmRsZUNoZWNrIGV4dGVuZHMgRG9jdG9yQ2hlY2sge1xuICBhc3luYyBkaWFnbm9zZSAoKSB7XG4gICAgY29uc3QgYnVuZGxldG9vbFBhdGggPSBhd2FpdCByZXNvbHZlRXhlY3V0YWJsZVBhdGgoJ2J1bmRsZXRvb2wuamFyJyk7XG4gICAgcmV0dXJuIGJ1bmRsZXRvb2xQYXRoXG4gICAgICA/IG9rT3B0aW9uYWwoYGJ1bmRsZXRvb2wuamFyIGlzIGluc3RhbGxlZCBhdDogJHtidW5kbGV0b29sUGF0aH1gKVxuICAgICAgOiBub2tPcHRpb25hbCgnYnVuZGxldG9vbC5qYXIgY2Fubm90IGJlIGZvdW5kJyk7XG4gIH1cblxuICBhc3luYyBmaXggKCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlcXVpcmUtYXdhaXRcbiAgICByZXR1cm4gYCR7J2J1bmRsZXRvb2wuamFyJy5ib2xkfSBpcyB1c2VkIHRvIGhhbmRsZSBBbmRyb2lkIEFwcCBCdW5kbGUuIFBsZWFzZSByZWFkIGh0dHA6Ly9hcHBpdW0uaW8vZG9jcy9lbi93cml0aW5nLXJ1bm5pbmctYXBwaXVtL2FuZHJvaWQvYW5kcm9pZC1hcHBidW5kbGUvIHRvIGluc3RhbGwgaXRgICtcbiAgICAgIGAke3N5c3RlbS5pc1dpbmRvd3MoKSA/ICcuIEFsc28gY29uc2lkZXIgYWRkaW5nIHRoZSBcIi5qYXJcIiBleHRlbnNpb24gaW50byB5b3VyIFBBVEhFWFQgZW52aXJvbm1lbnQgdmFyaWFibGUgaW4gb3JkZXIgdG8gZml4IHRoZSBwcm9ibGVtIGZvciBXaW5kb3dzJyA6ICcnfWA7XG4gIH1cbn1cbmNoZWNrcy5wdXNoKG5ldyBPcHRpb25hbEFwcEJ1bmRsZUNoZWNrKCkpO1xuXG5jbGFzcyBPcHRpb25hbEdzdHJlYW1lckNoZWNrIGV4dGVuZHMgRG9jdG9yQ2hlY2sge1xuICBHU1RSRUFNRVJfQklOQVJZID0gYGdzdC1sYXVuY2gtMS4wJHtzeXN0ZW0uaXNXaW5kb3dzKCkgPyAnLmV4ZScgOiAnJ31gO1xuICBHU1RfSU5TUEVDVF9CSU5BUlkgPSBgZ3N0LWluc3BlY3QtMS4wJHtzeXN0ZW0uaXNXaW5kb3dzKCkgPyAnLmV4ZScgOiAnJ31gO1xuXG4gIGFzeW5jIGRpYWdub3NlICgpIHtcbiAgICBjb25zdCBnc3RyZWFtZXJQYXRoID0gYXdhaXQgcmVzb2x2ZUV4ZWN1dGFibGVQYXRoKHRoaXMuR1NUUkVBTUVSX0JJTkFSWSk7XG4gICAgY29uc3QgZ3N0SW5zcGVjdFBhdGggPSBhd2FpdCByZXNvbHZlRXhlY3V0YWJsZVBhdGgodGhpcy5HU1RfSU5TUEVDVF9CSU5BUlkpO1xuXG4gICAgcmV0dXJuIGdzdHJlYW1lclBhdGggJiYgZ3N0SW5zcGVjdFBhdGhcbiAgICAgID8gb2tPcHRpb25hbChgJHt0aGlzLkdTVFJFQU1FUl9CSU5BUll9IGFuZCAke3RoaXMuR1NUX0lOU1BFQ1RfQklOQVJZfSBhcmUgaW5zdGFsbGVkIGF0OiAke2dzdHJlYW1lclBhdGh9IGFuZCAke2dzdEluc3BlY3RQYXRofWApXG4gICAgICA6IG5va09wdGlvbmFsKGAke3RoaXMuR1NUUkVBTUVSX0JJTkFSWX0gYW5kL29yICR7dGhpcy5HU1RfSU5TUEVDVF9CSU5BUll9IGNhbm5vdCBiZSBmb3VuZGApO1xuICB9XG5cbiAgYXN5bmMgZml4ICgpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSByZXF1aXJlLWF3YWl0XG4gICAgcmV0dXJuIGAke2Ake3RoaXMuR1NUUkVBTUVSX0JJTkFSWX0gYW5kICR7dGhpcy5HU1RfSU5TUEVDVF9CSU5BUll9YC5ib2xkfSBhcmUgdXNlZCB0byBzdHJlYW0gdGhlIHNjcmVlbiBvZiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuIGAgK1xuICAgICAgJ1BsZWFzZSByZWFkIGh0dHBzOi8vYXBwaXVtLmlvL2RvY3MvZW4vd3JpdGluZy1ydW5uaW5nLWFwcGl1bS9hbmRyb2lkL2FuZHJvaWQtc2NyZWVuLXN0cmVhbWluZy8gdG8gaW5zdGFsbCB0aGVtIGFuZCBmb3IgbW9yZSBkZXRhaWxzJztcbiAgfVxufVxuY2hlY2tzLnB1c2gobmV3IE9wdGlvbmFsR3N0cmVhbWVyQ2hlY2soKSk7XG5cbmV4cG9ydCB7IEVudlZhckFuZFBhdGhDaGVjaywgQW5kcm9pZFRvb2xDaGVjaywgSmF2YU9uUGF0aENoZWNrLCBPcHRpb25hbEFwcEJ1bmRsZUNoZWNrLCBPcHRpb25hbEdzdHJlYW1lckNoZWNrIH07XG5leHBv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