mirror of
https://github.com/appium/appium.git
synced 2026-02-09 11:18:51 -06:00
fix a bunch of refactoring issues
This commit is contained in:
@@ -113,6 +113,9 @@ ADB.prototype.checkAdbPresent = function(cb) {
|
||||
};
|
||||
|
||||
ADB.prototype.exec = function(cmd, cb) {
|
||||
if (!cmd) {
|
||||
return cb(new Error("You need to pass in a command to exec()"));
|
||||
}
|
||||
cmd = this.adbCmd + ' ' + cmd;
|
||||
logger.debug("executing: " + cmd);
|
||||
exec(cmd, {maxBuffer: 524288}, function(err, stdout, stderr) {
|
||||
@@ -432,7 +435,7 @@ ADB.prototype.getEmulatorPort = function(cb) {
|
||||
cb(new Error("No devices connected"));
|
||||
} else {
|
||||
// pick first device
|
||||
var port = this.getPortFromEmulatorString(devices[0]);
|
||||
var port = this.getPortFromEmulatorString(devices[0].udid);
|
||||
if (port) {
|
||||
cb(null, port);
|
||||
} else {
|
||||
@@ -454,6 +457,14 @@ ADB.prototype.push = function(localPath, remotePath, cb) {
|
||||
this.exec('push ' + localPath + ' ' + remotePath, cb);
|
||||
};
|
||||
|
||||
ADB.prototype.pull = function(remotePath, localPath, cb) {
|
||||
try {
|
||||
localPath = JSON.parse(localPath);
|
||||
} catch(e) { }
|
||||
localPath = JSON.stringify(localPath);
|
||||
this.exec('pull ' + remotePath + ' ' + localPath, cb);
|
||||
};
|
||||
|
||||
ADB.prototype.getPortFromEmulatorString = function(emStr) {
|
||||
var portPattern = /emulator-(\d+)/;
|
||||
if (portPattern.test(emStr)) {
|
||||
@@ -637,6 +648,11 @@ ADB.prototype.getLogcatLogs = function() {
|
||||
};
|
||||
|
||||
ADB.prototype.startApp = function(pkg, activity, waitActivity, cb) {
|
||||
if (typeof waitActivity === "function") {
|
||||
cb = waitActivity;
|
||||
waitActivity = false;
|
||||
}
|
||||
|
||||
var cmd = "am start -n " + pkg + "/" + activity;
|
||||
this.shell(cmd, function(err, stdout) {
|
||||
if(err) return cb(err);
|
||||
@@ -655,7 +671,11 @@ ADB.prototype.startApp = function(pkg, activity, waitActivity, cb) {
|
||||
}
|
||||
}
|
||||
|
||||
this.waitForActivity(pkg, waitActivity, cb);
|
||||
if (waitActivity) {
|
||||
this.waitForActivity(pkg, waitActivity, cb);
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
@@ -735,7 +755,7 @@ ADB.prototype.waitForActivity = function(pkg, act, waitMs, cb) {
|
||||
this.waitForActivityOrNot(pkg, act, false, waitMs, cb);
|
||||
};
|
||||
|
||||
ADB.prototype.waitForActivity = function(pkg, act, waitMs, cb) {
|
||||
ADB.prototype.waitForNotActivity = function(pkg, act, waitMs, cb) {
|
||||
this.waitForActivityOrNot(pkg, act, true, waitMs, cb);
|
||||
};
|
||||
|
||||
@@ -798,8 +818,8 @@ ADB.prototype.instrument = function(pkg, activity, instrumentWith, cb) {
|
||||
});
|
||||
};
|
||||
|
||||
ADB.prototype.checkAndSignApk = function(apk, cb) {
|
||||
this.checkApkCert(apk, function(err, appSigned) {
|
||||
ADB.prototype.checkAndSignApk = function(apk, pkg, cb) {
|
||||
this.checkApkCert(apk, pkg, function(err, appSigned) {
|
||||
if (err) return cb(err);
|
||||
if (!appSigned) {
|
||||
this.sign([apk], cb);
|
||||
@@ -809,14 +829,6 @@ ADB.prototype.checkAndSignApk = function(apk, cb) {
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
|
||||
ADB.prototype.pushAndInstallApp = function(apk, remoteApk, cb) {
|
||||
this.push(apk, remoteApk, function(err) {
|
||||
if (err) return err;
|
||||
this.installRemote(remoteApk, cb);
|
||||
});
|
||||
};
|
||||
|
||||
ADB.prototype.forceStop = function(pkg, cb) {
|
||||
this.shell('am force-stop ' + pkg, cb);
|
||||
};
|
||||
@@ -842,8 +854,9 @@ ADB.prototype.isAppInstalled = function(pkg, cb) {
|
||||
var apkInstalledRgx = new RegExp('^package:' +
|
||||
pkg.replace(/([^a-zA-Z])/g, "\\$1") + '$', 'm');
|
||||
installed = apkInstalledRgx.test(stdout);
|
||||
this.debug("App is " + (!installed ? "not" : "") + " installed");
|
||||
cb(null, installed);
|
||||
});
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ADB.prototype.back = function(cb) {
|
||||
@@ -868,7 +881,7 @@ ADB.prototype.keyevent = function(keycode, cb) {
|
||||
|
||||
ADB.prototype.isScreenLocked = function(cb) {
|
||||
var cmd = "dumpsys window";
|
||||
this.exec(cmd, function(err, stdout) {
|
||||
this.shell(cmd, function(err, stdout) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var screenLocked = /mShowingLockscreen=\w+/gi.exec(stdout);
|
||||
|
||||
@@ -47,7 +47,7 @@ androidCommon.prepareEmulator = function(cb) {
|
||||
return cb();
|
||||
}
|
||||
this.adb.launchAVD(this.avdName, cb);
|
||||
});
|
||||
}.bind(this));
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
@@ -64,12 +64,14 @@ androidCommon.prepareActiveDevice = function(cb) {
|
||||
}
|
||||
deviceId = this.udid;
|
||||
} else {
|
||||
var emPort = this.adb.getPortFromEmulatorString(devices[0].udid);
|
||||
deviceId = devices[0].udid;
|
||||
var emPort = this.adb.getPortFromEmulatorString(deviceId);
|
||||
this.adb.setEmulatorPort(emPort);
|
||||
}
|
||||
this.debug("Setting device id to " + deviceId);
|
||||
logger.info("Setting device id to " + deviceId);
|
||||
this.adb.setDeviceId(deviceId);
|
||||
});
|
||||
cb();
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
androidCommon.installApp = function(cb) {
|
||||
@@ -80,20 +82,27 @@ androidCommon.installApp = function(cb) {
|
||||
}
|
||||
|
||||
this.adb.isAppInstalled(this.appPackage, function(err, installed) {
|
||||
if (installed && this.fastReset) {
|
||||
if (installed && this.opts.fastReset) {
|
||||
this.adb.stopAndClear(this.appPackage, cb);
|
||||
} else if (!installed) {
|
||||
this.adb.checkAndSignApk(this.apkPath, this.appPackage, function(err) {
|
||||
if (err) return cb(err);
|
||||
this.adb.mkdir(this.remoteTempPath(), function(err) {
|
||||
if (err) return cb(err);
|
||||
this.getAppMd5(function(err, md5) {
|
||||
var remoteApk = this.remoteTempPath() + md5 + '.apk';
|
||||
this.getAppMd5(function(err, md5Hash) {
|
||||
var remoteApk = this.remoteTempPath() + md5Hash + '.apk';
|
||||
if (err) return cb(err);
|
||||
this.removeTempApks([md5], function(err, appExists) {
|
||||
this.removeTempApks([md5Hash], function(err, appExists) {
|
||||
if (err) return cb(err);
|
||||
if (appExists) return cb();
|
||||
this.adb.pushAndInstallApp(this.apkPath, remoteApk, cb);
|
||||
var install = function(err) {
|
||||
if (err) return cb(err);
|
||||
this.adb.installRemote(remoteApk, cb);
|
||||
}.bind(this);
|
||||
if (appExists) {
|
||||
install();
|
||||
} else {
|
||||
this.adb.push(this.apkPath, remoteApk, install);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
@@ -107,7 +116,9 @@ androidCommon.installApp = function(cb) {
|
||||
androidCommon.getAppMd5 = function(cb) {
|
||||
fs.readFile(this.apkPath, function(err, buffer) {
|
||||
if (err) return cb(err);
|
||||
cb(md5(buffer));
|
||||
var md5Hash = md5(buffer);
|
||||
logger.info("MD5 for app is " + md5Hash);
|
||||
cb(null, md5Hash);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
@@ -116,6 +127,7 @@ androidCommon.remoteTempPath = function() {
|
||||
};
|
||||
|
||||
androidCommon.removeTempApks = function(exceptMd5s, cb) {
|
||||
logger.info("Removing any old apks");
|
||||
if (typeof exceptMd5s === "function") {
|
||||
cb = exceptMd5s;
|
||||
exceptMd5s = [];
|
||||
@@ -133,31 +145,39 @@ androidCommon.removeTempApks = function(exceptMd5s, cb) {
|
||||
}.bind(this);
|
||||
|
||||
var removeApks = function(apks, cb) {
|
||||
if (apks.length < 1) {
|
||||
logger.info("No apks to examine");
|
||||
return cb();
|
||||
}
|
||||
var matchingApkFound = false;
|
||||
var noMd5Matched = true;
|
||||
var removes = [];
|
||||
_.each(apks, function(path) {
|
||||
path = path.trim();
|
||||
noMd5Matched = true;
|
||||
_.each(exceptMd5s, function(md5) {
|
||||
if (path !== '' && path.indexOf(md5) !== -1) {
|
||||
noMd5Matched = false;
|
||||
if (path !== "") {
|
||||
noMd5Matched = true;
|
||||
_.each(exceptMd5s, function(md5Hash) {
|
||||
if (path.indexOf(md5Hash) !== -1) {
|
||||
noMd5Matched = false;
|
||||
}
|
||||
});
|
||||
if (noMd5Matched) {
|
||||
removes.push('rm "' + path + '"');
|
||||
} else {
|
||||
logger.info("Found an apk we want to keep at " + path);
|
||||
matchingApkFound = true;
|
||||
}
|
||||
});
|
||||
if (noMd5Matched) {
|
||||
removes.push('rm \\"' + path + '\\"');
|
||||
} else {
|
||||
matchingApkFound = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Invoking adb shell with an empty string will open a shell console
|
||||
// so return here if there's nothing to remove.
|
||||
if (removes.length < 1) {
|
||||
logger.info("Couldn't find any apks to remove");
|
||||
return cb(null, matchingApkFound);
|
||||
}
|
||||
|
||||
var cmd = removes.join[" && "];
|
||||
var cmd = removes.join(" && ");
|
||||
this.adb.shell(cmd, function() {
|
||||
cb(null, matchingApkFound);
|
||||
});
|
||||
|
||||
@@ -348,23 +348,16 @@ androidController.setOrientation = function(orientation, cb) {
|
||||
};
|
||||
|
||||
androidController.localScreenshot = function(file, cb) {
|
||||
this.adb.requireDeviceId();
|
||||
async.series([
|
||||
function(cb) {
|
||||
this.proxy(["takeScreenshot"], cb);
|
||||
}.bind(this),
|
||||
function(cb) {
|
||||
var cmd = this.adb.adbCmd + ' pull /data/local/tmp/screenshot.png "' + file + '"';
|
||||
exec(cmd, { maxBuffer: 524288 }, function(err, stdout, stderr) {
|
||||
if (err) {
|
||||
logger.warn(stderr);
|
||||
return cb(err);
|
||||
}
|
||||
cb(null);
|
||||
});
|
||||
this.adb.pull('/data/local/tmp/screenshot.png', file, cb);
|
||||
}.bind(this),
|
||||
],
|
||||
function(){
|
||||
function(err) {
|
||||
if (err) return cb(err);
|
||||
cb(null, {
|
||||
status: status.codes.Success.code
|
||||
});
|
||||
@@ -372,57 +365,37 @@ androidController.localScreenshot = function(file, cb) {
|
||||
};
|
||||
|
||||
androidController.getScreenshot = function(cb) {
|
||||
this.adb.requireDeviceId();
|
||||
var localfile = temp.path({prefix: 'appium', suffix: '.png'});
|
||||
var b64data = "";
|
||||
|
||||
async.series([
|
||||
function(cb) {
|
||||
var png = "/data/local/tmp/screenshot.png";
|
||||
var cmd = [this.adb.adbCmd, 'shell', '"/system/bin/rm', png + ';', '/system/bin/screencap -p', png, '"'].join(' ');
|
||||
logger.debug("getScreenshot: " + cmd);
|
||||
exec(cmd, { maxBuffer: 524288 }, function(err, stdout, stderr) {
|
||||
if (err) {
|
||||
logger.warn(stderr);
|
||||
return cb(err);
|
||||
}
|
||||
cb(null);
|
||||
});
|
||||
var cmd = ['"/system/bin/rm', png + ';', '/system/bin/screencap -p',
|
||||
png, '"'].join(' ');
|
||||
this.adb.shell(cmd, cb);
|
||||
}.bind(this),
|
||||
function(cb) {
|
||||
if (fs.existsSync(localfile)) fs.unlinkSync(localfile);
|
||||
var cmd = this.adb.adbCmd + ' pull /data/local/tmp/screenshot.png "' + localfile + '"';
|
||||
logger.debug("getScreenshot: " + cmd);
|
||||
exec(cmd, { maxBuffer: 524288 }, function(err, stdout, stderr) {
|
||||
if (err) {
|
||||
logger.warn(stderr);
|
||||
return cb(err);
|
||||
}
|
||||
cb(null);
|
||||
});
|
||||
this.adb.pull('/data/local/tmp/screenshot.png', localfile, cb);
|
||||
}.bind(this),
|
||||
function(cb) {
|
||||
fs.readFile(localfile, function read(err, data) {
|
||||
if (err) {
|
||||
cb(err);
|
||||
} else {
|
||||
b64data = new Buffer(data).toString('base64');
|
||||
cb(null);
|
||||
}
|
||||
fs.readFile(localfile, function(err, data) {
|
||||
if (err) return cb(err);
|
||||
b64data = new Buffer(data).toString('base64');
|
||||
cb();
|
||||
});
|
||||
},
|
||||
function(cb) {
|
||||
fs.unlink(localfile, function(err) {
|
||||
if (err) {
|
||||
cb(err);
|
||||
} else {
|
||||
cb(null);
|
||||
}
|
||||
if (err) return cb(err);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
],
|
||||
// Top level cb
|
||||
function(err, res) {
|
||||
function(err) {
|
||||
if (err) return cb(err);
|
||||
cb(null, {
|
||||
status: status.codes.Success.code
|
||||
, value: b64data
|
||||
@@ -639,8 +612,8 @@ androidController.getCurrentActivity = function(cb) {
|
||||
androidController.fastReset = function(cb) {
|
||||
async.series([
|
||||
function(cb) { this.adb.stopAndClear(this.appPackage, cb); }.bind(this),
|
||||
this.adb.waitForNotActivity.bind(this),
|
||||
this.adb.startApp.bind(this)
|
||||
this.waitForActivityToStop.bind(this),
|
||||
this.startApp.bind(this)
|
||||
], cb);
|
||||
};
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ Android.prototype.initialize = function(opts) {
|
||||
this.udid = opts.udid;
|
||||
this.appPackage = opts.appPackage;
|
||||
this.appActivity = opts.appActivity;
|
||||
this.appWaitActivity = opts.appWaitActivity;
|
||||
this.avdName = opts.avdName;
|
||||
this.appWaitActivity = opts.appWaitActivity || opts.appActivity;
|
||||
this.avdName = opts.avdName || null;
|
||||
this.appDeviceReadyTimeout = opts.appDeviceReadyTimeout;
|
||||
this.verbose = opts.verbose;
|
||||
this.queue = [];
|
||||
@@ -73,6 +73,7 @@ Android.prototype.start = function(cb, onDie) {
|
||||
if (typeof launchCb === "undefined" || launchCb === null) {
|
||||
launchCb = cb;
|
||||
}
|
||||
// These messages are from adb.js. Must update when adb.js changes.
|
||||
var relaunchOn = [
|
||||
'Could not find a connected Android device'
|
||||
, 'Device did not become ready'
|
||||
@@ -86,7 +87,6 @@ Android.prototype.start = function(cb, onDie) {
|
||||
};
|
||||
|
||||
if (err) {
|
||||
// This message is from adb.js. Must update when adb.js changes.
|
||||
if (err.message === null ||
|
||||
typeof err.message === 'undefined' ||
|
||||
checkShouldRelaunch(err.message.toString())) {
|
||||
@@ -115,25 +115,27 @@ Android.prototype.start = function(cb, onDie) {
|
||||
|
||||
var onExit = function(code) {
|
||||
if (!didLaunch) {
|
||||
logger.error("ADB quit before it successfully launched");
|
||||
cb("ADB quit unexpectedly before successfully launching");
|
||||
var msg = "UiAutomator quit before it successfully launched";
|
||||
logger.error(msg);
|
||||
cb(new Error(msg));
|
||||
code = code || 1;
|
||||
} else if (typeof this.cbForCurrentCmd === "function") {
|
||||
var error = new UnknownError("ADB died while responding to command, " +
|
||||
"please check appium logs!");
|
||||
var error = new UnknownError("UiAutomator died while responding to " +
|
||||
"command, please check appium logs!");
|
||||
this.cbForCurrentCmd(error, null);
|
||||
code = code || 1;
|
||||
}
|
||||
|
||||
if (this.adb) {
|
||||
this.adb.uninstallApp(function() {
|
||||
this.uninstallApp(function() {
|
||||
this.adb = null;
|
||||
this.uiautomator = null;
|
||||
this.shuttingDown = false;
|
||||
this.onStop(code);
|
||||
this.onStop = null;
|
||||
}.bind(this));
|
||||
} else {
|
||||
logger.info("We're in android's exit callback but adb is gone already");
|
||||
logger.info("We're in uiautomator's exit callback but adb is gone already");
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
@@ -151,7 +153,7 @@ Android.prototype.startAppium = function(onLaunch, onExit) {
|
||||
logger.info("Starting android appium");
|
||||
this.uiautomator.onExit = onExit;
|
||||
|
||||
logger.debug("Using fast reset? " + this.fastReset);
|
||||
logger.debug("Using fast reset? " + this.opts.fastReset);
|
||||
|
||||
async.series([
|
||||
this.prepareDevice.bind(this),
|
||||
@@ -211,7 +213,7 @@ Android.prototype.pushAppium = function(cb) {
|
||||
cb(new Error("Could not find AppiumBootstrap.jar; please run " +
|
||||
"'grunt buildAndroidBootstrap'"));
|
||||
} else {
|
||||
this.adb.push(binPath, this.remoteTempDir(), cb);
|
||||
this.adb.push(binPath, this.remoteTempPath(), cb);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
@@ -360,6 +362,10 @@ Android.prototype.wakeUp = function(cb) {
|
||||
this.proxy(["wake", {}], cb);
|
||||
};
|
||||
|
||||
Android.prototype.waitForActivityToStop = function(cb) {
|
||||
this.adb.waitForNotActivity(this.appPackage, this.appWaitActivity, cb);
|
||||
};
|
||||
|
||||
Android.prototype.waitForCondition = deviceCommon.waitForCondition;
|
||||
|
||||
Android.prototype.setCommandTimeout = function(secs, cb) {
|
||||
|
||||
@@ -19,9 +19,12 @@ var ADB = require('./adb.js')
|
||||
var Selendroid = function(opts) {
|
||||
this.opts = opts;
|
||||
this.opts.devicePort = 8080;
|
||||
this.avdName = opts.avdName || null;
|
||||
this.appWaitActivity = opts.appWaitActivity;
|
||||
this.serverApk = null;
|
||||
this.appPackage = opts.appPackage;
|
||||
this.apkPath = opts.apkPath;
|
||||
this.appActivity = opts.appActivity;
|
||||
this.desiredCaps = opts.desiredCaps;
|
||||
this.onStop = function() {};
|
||||
this.selendroidSessionId = null;
|
||||
@@ -66,7 +69,7 @@ Selendroid.prototype.start = function(cb) {
|
||||
if (!modServerExists) {
|
||||
logger.info("Rebuilt selendroid server does not exist, inserting " +
|
||||
"modified manifest");
|
||||
this.insertSelendroidManifest(this.selendroidServerPath, cb);
|
||||
this.insertSelendroidManifest(this.apkPath, cb);
|
||||
} else {
|
||||
logger.info("Rebuilt selendroid server already exists, no need to " +
|
||||
"rebuild it with a new manifest");
|
||||
@@ -86,7 +89,7 @@ Selendroid.prototype.start = function(cb) {
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
|
||||
async.waterfall([
|
||||
async.series([
|
||||
this.ensureServerExists.bind(this),
|
||||
this.prepareDevice.bind(this),
|
||||
checkModServerExists,
|
||||
@@ -96,12 +99,14 @@ Selendroid.prototype.start = function(cb) {
|
||||
conditionalInstallSelendroid,
|
||||
this.installApp.bind(this),
|
||||
this.forwardPort.bind(this),
|
||||
this.pushUnlock(cb).bind(this),
|
||||
this.unlockScreen(cb).bind(this),
|
||||
this.pushSelendroid(cb).bind(this),
|
||||
this.pushUnlock.bind(this),
|
||||
this.unlockScreen.bind(this),
|
||||
this.pushSelendroid.bind(this),
|
||||
this.waitForServer.bind(this),
|
||||
this.createSession.bind(this)
|
||||
], cb);
|
||||
], function(err) {
|
||||
if (err) return cb(err);
|
||||
this.createSession(cb);
|
||||
});
|
||||
};
|
||||
|
||||
Selendroid.prototype.pushSelendroid = function(cb) {
|
||||
@@ -260,8 +265,8 @@ Selendroid.prototype.insertSelendroidManifest = function(serverPath, cb) {
|
||||
function(cb) { this.adb.checkSdkBinaryPresent("aapt", cb); }.bind(this),
|
||||
function(cb) { this.adb.compileManifest(dstManifest, newPackage,
|
||||
this.appPackage, cb); }.bind(this),
|
||||
function(cb) { this.insertManifest(dstManifest, serverPath, newServerPath,
|
||||
cb); }.bind(this)
|
||||
function(cb) { this.adb.insertManifest(dstManifest, serverPath,
|
||||
newServerPath, cb); }.bind(this)
|
||||
], cb);
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ UiAutomator.prototype.start = function(readyCb, exitCb) {
|
||||
}
|
||||
|
||||
logger.info("Running bootstrap");
|
||||
this.requireDeviceId();
|
||||
var args = ["shell", "uiautomator", "runtest", "AppiumBootstrap.jar", "-c",
|
||||
"io.appium.android.bootstrap.Bootstrap"];
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user