mirror of
https://github.com/appium/appium.git
synced 2026-02-09 11:18:51 -06:00
Merge pull request #1562 from penguinho/doctor
Adding More Doctor Checks for Android and Dev
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
var ios = require('../lib/doctor/ios.js')
|
||||
, android = require('../lib/doctor/android.js')
|
||||
var IOSChecker = require('../lib/doctor/ios.js').IOSChecker
|
||||
, AndroidChecker = require('../lib/doctor/android.js').AndroidChecker
|
||||
, DevChecker = require('../lib/doctor/dev.js').DevChecker
|
||||
, common = require("../lib/doctor/common.js")
|
||||
, eol = require('os').EOL
|
||||
, async = require('async');
|
||||
@@ -9,6 +10,7 @@ var ios = require('../lib/doctor/ios.js')
|
||||
var argv = process.argv
|
||||
, doAndroid = argv.indexOf('--android') > -1
|
||||
, doIOS = argv.indexOf('--ios') > -1
|
||||
, doDev = argv.indexOf('--dev') > -1
|
||||
, verbose = argv.indexOf('--verbose') > -1
|
||||
, broadcast = argv.indexOf('--port') > -1
|
||||
, port = null;
|
||||
@@ -26,7 +28,7 @@ var log = new common.Log(port);
|
||||
|
||||
var runiOSChecks = function(cb) {
|
||||
if (doIOS) {
|
||||
var iosChecker = new ios.IOSChecker(log);
|
||||
var iosChecker = new IOSChecker(log);
|
||||
log.comment("Running iOS Checks");
|
||||
iosChecker.runAllChecks(function(err) {
|
||||
if (!err) {
|
||||
@@ -41,7 +43,7 @@ var runiOSChecks = function(cb) {
|
||||
|
||||
var runAndroidChecks = function(cb) {
|
||||
if (doAndroid) {
|
||||
var androidChecker = new android.AndroidChecker(log);
|
||||
var androidChecker = new AndroidChecker(log);
|
||||
log.comment("Running Android Checks");
|
||||
androidChecker.runAllChecks(function(err) {
|
||||
if (!err) {
|
||||
@@ -54,12 +56,28 @@ var runAndroidChecks = function(cb) {
|
||||
}
|
||||
};
|
||||
|
||||
var runDevChecks = function(cb) {
|
||||
if (doDev) {
|
||||
var devChecker = new DevChecker(log);
|
||||
log.comment("Running Dev Checks");
|
||||
devChecker.runAllChecks(function(err) {
|
||||
if (!err) {
|
||||
log.pass("Dev Checks were successful." + eol);
|
||||
cb();
|
||||
} else {
|
||||
log.exitDoctor();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (require.main === module) {
|
||||
|
||||
var mainMethod = function() {
|
||||
async.series([
|
||||
runiOSChecks,
|
||||
runAndroidChecks
|
||||
runAndroidChecks,
|
||||
runDevChecks
|
||||
], function(err) {
|
||||
if (!err) {
|
||||
log.pass("All Checks were successful");
|
||||
|
||||
@@ -4,6 +4,7 @@ var path = require('path')
|
||||
, env = process.env
|
||||
, exec = require('child_process').exec
|
||||
, common = require("./common.js")
|
||||
, isWindows = require("../helpers.js").isWindows()
|
||||
, async = require('async');
|
||||
|
||||
function AndroidChecker(log) {
|
||||
@@ -13,41 +14,55 @@ exports.AndroidChecker = AndroidChecker;
|
||||
|
||||
AndroidChecker.prototype.runAllChecks = function(cb) {
|
||||
async.series([
|
||||
this.IsAndroidHomeExported.bind(this),
|
||||
this.IsJavaHomeExported.bind(this)
|
||||
this.checkAndroidHomeExported.bind(this),
|
||||
this.checkJavaHomeExported.bind(this),
|
||||
this.checkADBExists.bind(this),
|
||||
this.checkAndroidExists.bind(this),
|
||||
this.checkEmulatorExists.bind(this)
|
||||
], cb);
|
||||
};
|
||||
|
||||
AndroidChecker.prototype.IsAndroidHomeExported = function(cb) {
|
||||
var msg;
|
||||
AndroidChecker.prototype.checkAndroidHomeExported = function(cb) {
|
||||
if (env.ANDROID_HOME === null) {
|
||||
msg = 'ANDROID_HOME is not set';
|
||||
this.log.fail(msg);
|
||||
cb(msg, msg);
|
||||
this.log.fail('ANDROID_HOME is not set', cb);
|
||||
} else if (fs.existsSync(env.ANDROID_HOME)) {
|
||||
msg = 'ANDROID_HOME is set to "' + env.ANDROID_HOME + '"';
|
||||
this.log.pass(msg);
|
||||
cb(null, msg);
|
||||
this.log.pass('ANDROID_HOME is set to "' + env.ANDROID_HOME + '"', cb);
|
||||
} else {
|
||||
msg = 'ANDROID_HOME is set but does not exist on the file system at "' + env.ANDROID_HOME + '"';
|
||||
this.log.fail(msg);
|
||||
cb(msg, msg);
|
||||
this.log.fail('ANDROID_HOME is set but does not exist on the file system at "' + env.ANDROID_HOME + '"', cb);
|
||||
}
|
||||
};
|
||||
|
||||
AndroidChecker.prototype.IsJavaHomeExported = function(cb) {
|
||||
var msg;
|
||||
AndroidChecker.prototype.checkJavaHomeExported = function(cb) {
|
||||
if (env.JAVA_HOME === null) {
|
||||
this.log.fail(msg);
|
||||
msg = 'JAVA_HOME is not set';
|
||||
cb(msg, msg);
|
||||
this.log.fail('JAVA_HOME is not set', cb);
|
||||
} else if (fs.existsSync(env.JAVA_HOME)) {
|
||||
msg = 'JAVA_HOME is set to "' + env.JAVA_HOME + '."';
|
||||
this.log.pass(msg);
|
||||
cb(null, msg);
|
||||
this.log.pass('JAVA_HOME is set to "' + env.JAVA_HOME + '."', cb);
|
||||
} else {
|
||||
msg = 'JAVA_HOME is set but does not exist on the file system at "' + env.JAVA_HOME + '"';
|
||||
this.log.fail(msg);
|
||||
cb(msg, msg);
|
||||
this.log.fail('JAVA_HOME is set but does not exist on the file system at "' + env.JAVA_HOME + '"', cb);
|
||||
}
|
||||
};
|
||||
|
||||
AndroidChecker.prototype.checkADBExists = function(cb) {
|
||||
this.checkAndroidSDKBinaryExists("ADB", path.join("platform-tools", (isWindows ? 'adb.exe' : 'adb')), cb);
|
||||
};
|
||||
|
||||
AndroidChecker.prototype.checkAndroidExists = function(cb) {
|
||||
this.checkAndroidSDKBinaryExists("Android", path.join("tools", (isWindows ? 'android.bat' : 'android')), cb);
|
||||
};
|
||||
|
||||
AndroidChecker.prototype.checkEmulatorExists = function(cb) {
|
||||
this.checkAndroidSDKBinaryExists("Emulator", path.join("tools", (isWindows ? 'emulator.exe' : 'emulator')), cb);
|
||||
};
|
||||
|
||||
AndroidChecker.prototype.checkAndroidSDKBinaryExists = function(toolName, relativeToolPath, cb) {
|
||||
if (env.ANDROID_HOME !== null) {
|
||||
var adbPath = path.resolve(env.ANDROID_HOME, relativeToolPath);
|
||||
if (fs.existsSync(adbPath)) {
|
||||
this.log.pass(toolName + " exists at " + adbPath, cb);
|
||||
} else {
|
||||
this.log.fail(toolName + " could not be found at " + adbPath, cb);
|
||||
}
|
||||
} else {
|
||||
this.log.fail(toolName + " could not be found because ANDROID_HOME is not set.", cb);
|
||||
}
|
||||
};
|
||||
@@ -15,12 +15,18 @@ function Log(port) {
|
||||
}
|
||||
exports.Log = Log;
|
||||
|
||||
Log.prototype.pass = function(msg) {
|
||||
Log.prototype.pass = function(msg, cb) {
|
||||
this.logEntry('\u2714 '.green + msg.white);
|
||||
if (cb) {
|
||||
cb(null, msg);
|
||||
}
|
||||
};
|
||||
|
||||
Log.prototype.fail = function(msg) {
|
||||
Log.prototype.fail = function(msg, cb) {
|
||||
this.logEntry('\u2716 '.red + msg.white);
|
||||
if (cb) {
|
||||
cb(msg, msg);
|
||||
}
|
||||
};
|
||||
|
||||
Log.prototype.warning = function(msg) {
|
||||
|
||||
35
lib/doctor/dev.js
Normal file
35
lib/doctor/dev.js
Normal file
@@ -0,0 +1,35 @@
|
||||
"use strict";
|
||||
var path = require('path')
|
||||
, fs = require('fs')
|
||||
, env = process.env
|
||||
, exec = require('child_process').exec
|
||||
, common = require("./common.js")
|
||||
, isWindows = require("../helpers.js").isWindows()
|
||||
, eol = require('os').EOL
|
||||
, async = require('async');
|
||||
|
||||
function DevChecker(log) {
|
||||
this.log = log;
|
||||
}
|
||||
exports.DevChecker = DevChecker;
|
||||
|
||||
DevChecker.prototype.runAllChecks = function(cb) {
|
||||
async.series([
|
||||
this.checkMavenExistsInPath.bind(this)
|
||||
], cb);
|
||||
};
|
||||
|
||||
DevChecker.prototype.checkMavenExistsInPath = function(cb) {
|
||||
exec(isWindows ? "where mvn.bat" : "which mvn", { maxBuffer: 524288 }, function(err, stdout) {
|
||||
if (!err) {
|
||||
var mvnPath = isWindows ? stdout.split(eol)[0] : stdout.replace(eol, "");
|
||||
if (fs.existsSync(mvnPath)) {
|
||||
this.log.pass("Maven was found at " + mvnPath, cb);
|
||||
} else {
|
||||
this.log.fail("Maven does not exist at path " + mvnPath, cb);
|
||||
}
|
||||
} else {
|
||||
this.log.fail("Could not find mvn in path.", cb);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
@@ -18,12 +18,12 @@ IOSChecker.prototype.runAllChecks = function(cb) {
|
||||
this.checkForXcode.bind(this),
|
||||
this.checkForXcodeCommandLineTools.bind(this),
|
||||
this.checkDevToolsSecurity.bind(this),
|
||||
this.checkAuthorizationDB.bind(this)
|
||||
this.checkAuthorizationDB.bind(this),
|
||||
this.checkForNodeBinary.bind(this)
|
||||
], cb);
|
||||
};
|
||||
|
||||
IOSChecker.prototype.getMacOSXVersion = function(cb) {
|
||||
var msg;
|
||||
exec("sw_vers -productVersion", function(err, stdout) {
|
||||
if (err === null) {
|
||||
if (stdout.match('10.8') !== null) {
|
||||
@@ -33,14 +33,10 @@ IOSChecker.prototype.getMacOSXVersion = function(cb) {
|
||||
this.osVersion = '10.9';
|
||||
cb(null, "Mac OS X 10.9 is installed.");
|
||||
} else {
|
||||
msg = "Could not detect Mac OS X Version";
|
||||
this.log.fail(msg);
|
||||
cb(msg, msg);
|
||||
this.log.fail("Could not detect Mac OS X Version", cb);
|
||||
}
|
||||
} else {
|
||||
msg = "Unknown SW Version Command: " + err;
|
||||
this.log.fail(msg);
|
||||
cb(msg, msg);
|
||||
this.log.fail("Unknown SW Version Command: " + err, cb);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
@@ -51,9 +47,7 @@ IOSChecker.prototype.checkForXcode = function(cb) {
|
||||
if (err === null) {
|
||||
var xcodePath = stdout.replace("\n","");
|
||||
if(fs.existsSync(xcodePath)) {
|
||||
msg = "Xcode is installed at " + xcodePath;
|
||||
this.log.pass(msg);
|
||||
cb(null, msg);
|
||||
this.log.pass("Xcode is installed at " + xcodePath, cb);
|
||||
} else {
|
||||
msg = "Xcode is not installed.";
|
||||
this.log.fail(msg);
|
||||
@@ -82,9 +76,7 @@ IOSChecker.prototype.checkForXcodeCommandLineTools = function(cb) {
|
||||
if (err === null) {
|
||||
var match = stdout.match(/install-time/);
|
||||
if (match !== null) {
|
||||
msg = "Xcode Command Line Tools are installed.";
|
||||
this.log.pass(msg);
|
||||
cb(null, msg);
|
||||
this.log.pass("Xcode Command Line Tools are installed.", cb);
|
||||
} else {
|
||||
msg = "Xcode Command Line Tools are NOT installed.";
|
||||
this.log.fail(msg);
|
||||
@@ -110,9 +102,7 @@ IOSChecker.prototype.checkDevToolsSecurity = function(cb) {
|
||||
var msg;
|
||||
exec("DevToolsSecurity", { maxBuffer: 524288}, function(err, stdout) {
|
||||
if (err === null && stdout.match(/enabled/) !== null) {
|
||||
msg = "DevToolsSecurity is enabled.";
|
||||
this.log.pass(msg);
|
||||
cb(null, msg);
|
||||
this.log.pass("DevToolsSecurity is enabled.", cb);
|
||||
} else {
|
||||
msg = 'DevToolsSecurity is not enabled.';
|
||||
this.log.fail(msg);
|
||||
@@ -129,9 +119,7 @@ IOSChecker.prototype.checkAuthorizationDB = function(cb) {
|
||||
var msg;
|
||||
exec("security authorizationdb read system.privilege.taskport", { maxBuffer: 524288}, function(err, stdout) {
|
||||
if (err === null && stdout.match(/is-developer/) !== null) {
|
||||
msg = "The Authorization DB is set up properly.";
|
||||
this.log.pass(msg);
|
||||
cb(null, msg);
|
||||
this.log.pass("The Authorization DB is set up properly.", cb);
|
||||
} else {
|
||||
msg = 'The Authorization DB is NOT set up properly.';
|
||||
this.log.fail(msg);
|
||||
@@ -144,6 +132,114 @@ IOSChecker.prototype.checkAuthorizationDB = function(cb) {
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
IOSChecker.prototype.checkForNodeBinary = function(cb) {
|
||||
this.checkForNodeBinaryInCommonPlaces(function(err, msg) {
|
||||
if (!err) {
|
||||
cb(null, msg);
|
||||
} else {
|
||||
this.checkForNodeBinaryUsingWhichCommand(function(err, msg) {
|
||||
if (!err) {
|
||||
cb(null, msg);
|
||||
} else {
|
||||
this.checkForNodeBinaryUsingAppleScript(function(err, msg) {
|
||||
if (!err) {
|
||||
cb(null, msg);
|
||||
} else {
|
||||
this.checkForNodeBinaryUsingAppiumConfigFile(function(err, msg) {
|
||||
if (!err) {
|
||||
cb(null, msg);
|
||||
} else {
|
||||
msg = 'The node binary could not be found.';
|
||||
this.log.fail(msg);
|
||||
this.log.promptToFix("The node binary could not be found.", function() {
|
||||
this.setupNodeBinaryPath(cb);
|
||||
}.bind(this), function() {
|
||||
cb(msg, msg);
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
IOSChecker.prototype.checkForNodeBinaryInCommonPlaces = function(cb) {
|
||||
if (env.NODE_BIN !== null && fs.existsSync(env.NODE_BIN)) {
|
||||
this.log.pass("Node binary found using NODE_BIN environment variable at " + env.NODE_BIN, cb);
|
||||
} else if (fs.existsSync('/usr/local/bin/node')) {
|
||||
this.log.pass("Node binary found at /usr/local/bin/node", cb);
|
||||
} else if (fs.existsSync('/opt/local/bin/node')) {
|
||||
this.log.pass("Node binary found at /opt/local/bin/node", cb);
|
||||
} else {
|
||||
var msg = 'Node binary could not be found in the usual places';
|
||||
cb(msg, msg);
|
||||
}
|
||||
};
|
||||
|
||||
IOSChecker.prototype.checkForNodeBinaryUsingWhichCommand = function(cb) {
|
||||
var msg;
|
||||
exec("which node", { maxBuffer: 524288}, function(err, stdout) {
|
||||
if (err === null && fs.existsSync(stdout.replace("\n",""))) {
|
||||
this.log.pass("Node binary found using which command at " + stdout.replace("\n",""), cb);
|
||||
} else {
|
||||
msg = 'Node binary not found using the which command.';
|
||||
cb(msg, msg);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
IOSChecker.prototype.checkForNodeBinaryUsingAppleScript = function(cb) {
|
||||
var msg;
|
||||
var appScript = [
|
||||
'try'
|
||||
, ' set appiumIsRunning to false'
|
||||
, ' tell application "System Events"'
|
||||
, ' set appiumIsRunning to name of every process contains "Appium"'
|
||||
, ' end tell'
|
||||
, ' if appiumIsRunning then'
|
||||
, ' tell application "Appium" to return node path'
|
||||
, ' end if'
|
||||
, 'end try'
|
||||
, 'return "NULL"'
|
||||
].join("\n");
|
||||
exec("osascript -e '" + appScript + "'", { maxBuffer: 524288}, function(err, stdout) {
|
||||
if (err === null && fs.existsSync(stdout.replace("\n",""))) {
|
||||
this.log.pass("Node binary found using AppleScript at " + stdout.replace("\n",""), cb);
|
||||
} else {
|
||||
msg = 'Node binary not found using AppleScript.';
|
||||
cb(msg, msg);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
IOSChecker.prototype.checkForNodeBinaryUsingAppiumConfigFile = function(cb) {
|
||||
var msg = 'Node binary not found in the .appiumconfig file.';
|
||||
var appiumConfigPath = path.resolve(__dirname, "../..", ".appiumconfig");
|
||||
if (fs.existsSync(appiumConfigPath)) {
|
||||
fs.readFile(appiumConfigPath, 'utf8', function(err, data) {
|
||||
if (err === null) {
|
||||
try {
|
||||
var jsonobj = JSON.parse(data);
|
||||
if (jsonobj.node_bin !== undefined && fs.existsSync(jsonobj.node_bin)) {
|
||||
this.log.pass("Node binary found using .appiumconfig at " + jsonobj.node_bin, cb);
|
||||
} else {
|
||||
cb(msg, msg);
|
||||
}
|
||||
} catch (jsonErr) {
|
||||
cb(msg, msg);
|
||||
}
|
||||
} else {
|
||||
cb(msg, msg);
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
cb(msg, msg);
|
||||
}
|
||||
};
|
||||
|
||||
IOSChecker.prototype.installXcode = function(cb) {
|
||||
exec("xcode-select --install", { maxBuffer: 524288}, function() {
|
||||
this.log.promptToConfirmFix(function() {
|
||||
@@ -162,7 +258,7 @@ IOSChecker.prototype.installXcodeCommandLineTools = function(cb) {
|
||||
|
||||
IOSChecker.prototype.authorizeIOS = function(outerCb, innerCb) {
|
||||
var authorizePath = path.resolve(__dirname, "../../bin", "authorize-ios.js");
|
||||
exec("'" + process.execPath + "' '" + authorizePath + "'" , { maxBuffer: 524288}, function(err,stdout) {
|
||||
exec("'" + process.execPath + "' '" + authorizePath + "'" , { maxBuffer: 524288}, function(err) {
|
||||
if(err) {
|
||||
this.log.error('Could not authorize iOS: ' + err);
|
||||
}
|
||||
@@ -172,3 +268,29 @@ IOSChecker.prototype.authorizeIOS = function(outerCb, innerCb) {
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
IOSChecker.prototype.setupNodeBinaryPath = function(cb) {
|
||||
var appiumConfigPath = path.resolve(__dirname, "../../", ".appiumconfig");
|
||||
if (fs.existsSync(appiumConfigPath)) {
|
||||
fs.readFile(appiumConfigPath, 'utf8', function(err, data) {
|
||||
if (!err) {
|
||||
try {
|
||||
var jsonobj = JSON.parse(data);
|
||||
jsonobj.node_bin = process.execPath;
|
||||
fs.writeFile(appiumConfigPath, JSON.stringify(jsonobj), function() {
|
||||
this.checkForNodeBinary(cb);
|
||||
}.bind(this));
|
||||
} catch (jsonErr) {
|
||||
this.log.error("Could not setup node binary path in .appiumconfig. Error parsing JSON: " + jsonErr );
|
||||
this.checkForNodeBinary(cb);
|
||||
}
|
||||
} else {
|
||||
this.log.error("Could not setup node binary path in .appiumconfig. Error reading config: " + err );
|
||||
this.checkForNodeBinary(cb);
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
this.log.error('The .appiumconfig file was not found at ' + appiumConfigPath);
|
||||
this.exitDoctor();
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user