UNPKG

appium-doctor

Version:

Test environment for fitness to run Appium

154 lines (139 loc) 3.93 kB
import 'colors'; import _ from 'lodash'; import log from './logger'; import { version } from '../../package.json'; // eslint-disable-line import/no-unresolved class FixSkippedError extends Error { } class DoctorCheck { constructor (opts={}) { this.autofix = !!opts.autofix; } diagnose () { throw new Error('Not Implemented!'); } fix () { // return string for manual fixes. throw new Error('Not Implemented!'); } } class Doctor { constructor () { this.checks = []; this.toFix = []; } register (checks) { checks = Array.isArray(checks) ? checks : [checks]; this.checks = this.checks.concat(checks); } async diagnose () { log.info('### Diagnostic starting ###'); this.toFix = []; for (let check of this.checks) { let res = await check.diagnose(); if (res.ok) { log.info(` ${'\u2714'.green} ${res.message}`); } else { let errorMessage = ` ${'\u2716'.red} ${res.message}`; log.warn(errorMessage); this.toFix.push({ error: errorMessage, check }); } } let fixMessage; switch (this.toFix.length) { case 0: fixMessage = 'no fix needed'; break; case 1: fixMessage = 'one fix needed'; break; default: fixMessage = `${this.toFix.length} fixes needed`; } log.info(`### Diagnostic completed, ${fixMessage}. ###`); log.info(''); } async reportSuccess () { if (this.toFix.length === 0) { log.info('Everything looks good, bye!'); log.info(''); return true; } else { return false; } } async reportManualFixes () { let manualFixes = _.filter(this.toFix, (f) => {return !f.check.autofix;}); if (manualFixes.length >0) { log.info('### Manual Fixes Needed ###'); log.info('The configuration cannot be automatically fixed, please do the following first:'); // for manual fixes, the fix method always return a string let fixMessages = []; for (let f of manualFixes) { fixMessages.push(await f.check.fix()); } for (let m of _.uniq(fixMessages)) { log.warn(`- ${m}`); } log.info('###'); log.info(''); log.info('Bye! Run appium-doctor again when all manual fixes have been applied!'); log.info(''); return true; } else { return false; } } async runAutoFix (f) { log.info(`### Fixing: ${f.error} ###`); try { await f.check.fix(); } catch (err) { if (err instanceof FixSkippedError) { log.info(`### Skipped fix ###`); return; } else { log.warn(`${err}`.replace(/\n$/g, '')); log.info(`### Fix did not succeed ###`); return; } } log.info('Checking if this was fixed:'); let res = await f.check.diagnose(); if (res.ok) { f.fixed = true; log.info(` ${'\u2714'.green} ${res.message}`); log.info(`### Fix was successfully applied ###`); } else { log.info(` ${'\u2716'.red} ${res.message}`); log.info(`### Fix was applied but issue remains ###`); } } async runAutoFixes () { let autoFixes = _.filter(this.toFix, (f) => {return f.check.autofix;}); for (let f of autoFixes) { await this.runAutoFix(f); log.info(''); } if (_.find(autoFixes, (f) => { return !f.fixed; })) { // a few issues remain. log.info('Bye! A few issues remain, fix manually and/or rerun appium-doctor!'); } else { // nothing left to fix. log.info('Bye! All issues have been fixed!'); } log.info(''); } async run () { log.info(`Appium Doctor v.${version}`); await this.diagnose(); if (await this.reportSuccess()) { return; } if (await this.reportManualFixes()) { return; } await this.runAutoFixes(); } } export { Doctor, DoctorCheck, FixSkippedError };