mirror of
https://github.com/appium/appium.git
synced 2026-04-26 05:18:53 -05:00
pull out remote debugger related ios functionality into its own file
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
"use strict";
|
||||
|
||||
var logger = require('../../server/logger.js').get('appium')
|
||||
, _ = require('underscore')
|
||||
, deviceCommon = require('../common.js')
|
||||
, rd = require('./remote-debugger.js')
|
||||
, wkrd = require('./webkit-remote-debugger.js');
|
||||
|
||||
var iOSHybrid = {};
|
||||
|
||||
iOSHybrid.navToInitialWebview = function(cb) {
|
||||
if (this.autoWebview) {
|
||||
this.navToFirstAvailWebview(cb);
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
|
||||
iOSHybrid.navToFirstAvailWebview = function(cb) {
|
||||
logger.info("Navigating to first available webview");
|
||||
this.getWindowHandles(function(err, res) {
|
||||
if (res.status !== 0) {
|
||||
cb("Could not navigate to webview! Code: " + res.status);
|
||||
} else if (res.value.length === 0) {
|
||||
cb("Could not navigate to webview; there aren't any!");
|
||||
} else {
|
||||
logger.info("Picking webview " + res.value[0]);
|
||||
this.setWindow(res.value[0], function(err) {
|
||||
if (err) {
|
||||
cb(err);
|
||||
} else {
|
||||
cb(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
|
||||
iOSHybrid.closeAlertBeforeTest = function(cb) {
|
||||
this.proxy("au.alertIsPresent()", function(err, res) {
|
||||
if (!err && res !== null && typeof res.value !== "undefined" && res.value === true) {
|
||||
logger.info("Alert present before starting test, let's banish it");
|
||||
this.proxy("au.dismissAlert()", function() {
|
||||
logger.info("Alert banished!");
|
||||
cb(true);
|
||||
});
|
||||
} else {
|
||||
cb(false);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
iOSHybrid.listWebFrames = function(cb, exitCb) {
|
||||
var isDone = false;
|
||||
if (!this.bundleId && !this.isSafariLauncherApp) {
|
||||
logger.error("Can't enter web frame without a bundle ID");
|
||||
return cb(new Error("Tried to enter web frame without a bundle ID"));
|
||||
}
|
||||
var onDone = function(res) {
|
||||
this.processingRemoteCmd = false;
|
||||
isDone = true;
|
||||
cb(res);
|
||||
}.bind(this);
|
||||
|
||||
this.processingRemoteCmd = true;
|
||||
if (this.remote !== null && this.bundleId !== null) {
|
||||
if (this.udid !== null) {
|
||||
this.remote.pageArrayFromJson(function(pageArray) {
|
||||
cb(pageArray);
|
||||
});
|
||||
} else {
|
||||
this.remote.selectApp(this.bundleId, onDone);
|
||||
}
|
||||
} else {
|
||||
if (this.udid !== null) {
|
||||
this.remote = wkrd.init(exitCb);
|
||||
this.remote.pageArrayFromJson(function(pageArray) {
|
||||
cb(pageArray);
|
||||
});
|
||||
} else {
|
||||
this.remote = new rd.init(exitCb);
|
||||
this.remote.connect(function(appDict) {
|
||||
if(!_.has(appDict, this.bundleId)) {
|
||||
logger.error("Remote debugger did not list " + this.bundleId + " among " +
|
||||
"its available apps");
|
||||
if(_.has(appDict, "com.apple.mobilesafari")) {
|
||||
logger.info("Using mobile safari instead");
|
||||
this.remote.selectApp("com.apple.mobilesafari", onDone);
|
||||
} else {
|
||||
onDone([]);
|
||||
}
|
||||
} else {
|
||||
this.remote.selectApp(this.bundleId, onDone);
|
||||
}
|
||||
}.bind(this), this.onPageChange.bind(this));
|
||||
var loopCloseRuns = 0;
|
||||
var loopClose = function() {
|
||||
loopCloseRuns++;
|
||||
if (!isDone && loopCloseRuns < 3) {
|
||||
this.closeAlertBeforeTest(function(didDismiss) {
|
||||
if (!didDismiss) {
|
||||
setTimeout(loopClose, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}.bind(this);
|
||||
setTimeout(loopClose, 4000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
iOSHybrid.onPageChange = function(pageArray) {
|
||||
logger.info("Remote debugger notified us of a new page listing");
|
||||
if (this.selectingNewPage) {
|
||||
logger.info("We're in the middle of selecting a page, ignoring");
|
||||
return;
|
||||
}
|
||||
var newIds = []
|
||||
, keyId = null;
|
||||
_.each(pageArray, function(page) {
|
||||
newIds.push(page.id.toString());
|
||||
if (page.isKey) {
|
||||
keyId = page.id.toString();
|
||||
}
|
||||
});
|
||||
var newPages = [];
|
||||
var cachedHandles = _.pluck(this.windowHandleCache, 'id');
|
||||
_.each(newIds, function(id) {
|
||||
if (!_.contains(cachedHandles, id)) {
|
||||
newPages.push(id);
|
||||
}
|
||||
});
|
||||
var newPage = null;
|
||||
if (this.curWindowHandle === null) {
|
||||
logger.info("We don't appear to have window set yet, ignoring");
|
||||
} else if (newPages.length) {
|
||||
logger.info("We have new pages, going to select page " + newPages[0]);
|
||||
newPage = newPages[0];
|
||||
} else if (!_.contains(newIds, this.curWindowHandle.toString())) {
|
||||
logger.info("New page listing from remote debugger doesn't contain " +
|
||||
"current window, let's assume it's closed");
|
||||
if (keyId !== null) {
|
||||
logger.info("Debugger already selected page " + keyId + ", " +
|
||||
"confirming that choice.");
|
||||
} else {
|
||||
logger.error("Don't have our current window anymore, and there " +
|
||||
"aren't any more to load! Doing nothing...");
|
||||
}
|
||||
this.curWindowHandle = keyId;
|
||||
this.remote.pageIdKey = parseInt(keyId, 10);
|
||||
} else {
|
||||
var dirty = function() {
|
||||
var item = function(arr) {
|
||||
return _.filter(arr, function(obj) {
|
||||
return obj.id == this.curWindowHandle;
|
||||
}, this)[0];
|
||||
}.bind(this);
|
||||
|
||||
var win = item(pageArray);
|
||||
var ret = false;
|
||||
_.each(item(this.windowHandleCache), function(el, idx, l) {
|
||||
if (l[idx] !== win[idx]) {
|
||||
ret = true;
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}.bind(this);
|
||||
|
||||
// If a window gets navigated to an anchor it doesn't always fire a page callback event
|
||||
// Let's check if we wound up in such a situation.
|
||||
if (dirty()) {
|
||||
this.remote.pageLoad();
|
||||
}
|
||||
|
||||
logger.info("New page listing is same as old, doing nothing");
|
||||
}
|
||||
|
||||
if (newPage !== null) {
|
||||
this.selectingNewPage = true;
|
||||
this.remote.selectPage(parseInt(newPage, 10), function() {
|
||||
this.selectingNewPage = false;
|
||||
this.curWindowHandle = newPage;
|
||||
if (this.onPageChangeCb !== null) {
|
||||
this.onPageChangeCb();
|
||||
this.onPageChangeCb = null;
|
||||
}
|
||||
}.bind(this));
|
||||
} else if (this.onPageChangeCb !== null) {
|
||||
this.onPageChangeCb();
|
||||
this.onPageChangeCb = null;
|
||||
}
|
||||
this.windowHandleCache = _.map(pageArray, this.massagePage);
|
||||
};
|
||||
|
||||
iOSHybrid.getAtomsElement = deviceCommon.getAtomsElement;
|
||||
|
||||
iOSHybrid.stopRemote = function() {
|
||||
if (!this.remote) {
|
||||
logger.error("We don't appear to be in a web frame");
|
||||
throw new Error("Tried to leave a web frame but weren't in one");
|
||||
} else {
|
||||
this.remote.disconnect();
|
||||
this.curWindowHandle = null;
|
||||
this.curWebFrames = [];
|
||||
this.curWebCoords = null;
|
||||
this.remote = null;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = iOSHybrid;
|
||||
+6
-203
@@ -12,14 +12,13 @@ var path = require('path')
|
||||
, xmlplist = require('plist')
|
||||
, instruments = require('./instruments.js')
|
||||
, helpers = require('../../helpers.js')
|
||||
, rd = require('./remote-debugger.js')
|
||||
, wkrd = require('./webkit-remote-debugger.js')
|
||||
, errors = require('../../server/errors.js')
|
||||
, deviceCommon = require('../common.js')
|
||||
, status = require("../../server/status.js")
|
||||
, IDevice = require('node-idevice')
|
||||
, async = require('async')
|
||||
, iOSController = require('./ios-controller.js')
|
||||
, iOSHybrid = require('./ios-hybrid.js')
|
||||
, UnknownError = errors.UnknownError;
|
||||
|
||||
var IOS = function(args) {
|
||||
@@ -246,14 +245,6 @@ IOS.prototype.setInitialOrientation = function(cb) {
|
||||
}
|
||||
};
|
||||
|
||||
IOS.prototype.navToInitialWebview = function(cb) {
|
||||
if (this.autoWebview) {
|
||||
this.navToFirstAvailWebview(cb);
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
|
||||
IOS.prototype.onInstrumentsExit = function(code, traceDir, launchCb) {
|
||||
if (!this.instrumentsDidLaunch) {
|
||||
logger.error("Instruments did not launch successfully, failing session");
|
||||
@@ -474,40 +465,6 @@ IOS.prototype.parseLocalizableStrings = function(cb) {
|
||||
};
|
||||
|
||||
|
||||
IOS.prototype.navToFirstAvailWebview = function(cb) {
|
||||
logger.info("Navigating to first available webview");
|
||||
this.getWindowHandles(function(err, res) {
|
||||
if (res.status !== 0) {
|
||||
cb("Could not navigate to webview! Code: " + res.status);
|
||||
} else if (res.value.length === 0) {
|
||||
cb("Could not navigate to webview; there aren't any!");
|
||||
} else {
|
||||
logger.info("Picking webview " + res.value[0]);
|
||||
this.setWindow(res.value[0], function(err) {
|
||||
if (err) {
|
||||
cb(err);
|
||||
} else {
|
||||
cb(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
IOS.prototype.closeAlertBeforeTest = function(cb) {
|
||||
this.proxy("au.alertIsPresent()", function(err, res) {
|
||||
if (!err && res !== null && typeof res.value !== "undefined" && res.value === true) {
|
||||
logger.info("Alert present before starting test, let's banish it");
|
||||
this.proxy("au.dismissAlert()", function() {
|
||||
logger.info("Alert banished!");
|
||||
cb(true);
|
||||
});
|
||||
} else {
|
||||
cb(false);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
IOS.prototype.getSimulatorApplications = function(cb) {
|
||||
var user = process.env.USER;
|
||||
var simDir = "/Users/" + user + "/Library/Application\\ " +
|
||||
@@ -566,164 +523,6 @@ IOS.prototype.cleanupAppState = function(cb) {
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
IOS.prototype.listWebFrames = function(cb, exitCb) {
|
||||
var isDone = false;
|
||||
if (!this.bundleId && !this.isSafariLauncherApp) {
|
||||
logger.error("Can't enter web frame without a bundle ID");
|
||||
return cb(new Error("Tried to enter web frame without a bundle ID"));
|
||||
}
|
||||
var onDone = function(res) {
|
||||
this.processingRemoteCmd = false;
|
||||
isDone = true;
|
||||
cb(res);
|
||||
}.bind(this);
|
||||
|
||||
this.processingRemoteCmd = true;
|
||||
if (this.remote !== null && this.bundleId !== null) {
|
||||
if (this.udid !== null) {
|
||||
this.remote.pageArrayFromJson(function(pageArray) {
|
||||
cb(pageArray);
|
||||
});
|
||||
} else {
|
||||
this.remote.selectApp(this.bundleId, onDone);
|
||||
}
|
||||
} else {
|
||||
if (this.udid !== null) {
|
||||
this.remote = wkrd.init(exitCb);
|
||||
this.remote.pageArrayFromJson(function(pageArray) {
|
||||
cb(pageArray);
|
||||
});
|
||||
} else {
|
||||
this.remote = new rd.init(exitCb);
|
||||
this.remote.connect(function(appDict) {
|
||||
if(!_.has(appDict, this.bundleId)) {
|
||||
logger.error("Remote debugger did not list " + this.bundleId + " among " +
|
||||
"its available apps");
|
||||
if(_.has(appDict, "com.apple.mobilesafari")) {
|
||||
logger.info("Using mobile safari instead");
|
||||
this.remote.selectApp("com.apple.mobilesafari", onDone);
|
||||
} else {
|
||||
onDone([]);
|
||||
}
|
||||
} else {
|
||||
this.remote.selectApp(this.bundleId, onDone);
|
||||
}
|
||||
}.bind(this), this.onPageChange.bind(this));
|
||||
var loopCloseRuns = 0;
|
||||
var loopClose = function() {
|
||||
loopCloseRuns++;
|
||||
if (!isDone && loopCloseRuns < 3) {
|
||||
this.closeAlertBeforeTest(function(didDismiss) {
|
||||
if (!didDismiss) {
|
||||
setTimeout(loopClose, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}.bind(this);
|
||||
setTimeout(loopClose, 4000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IOS.prototype.onPageChange = function(pageArray) {
|
||||
logger.info("Remote debugger notified us of a new page listing");
|
||||
if (this.selectingNewPage) {
|
||||
logger.info("We're in the middle of selecting a page, ignoring");
|
||||
return;
|
||||
}
|
||||
var newIds = []
|
||||
, keyId = null;
|
||||
_.each(pageArray, function(page) {
|
||||
newIds.push(page.id.toString());
|
||||
if (page.isKey) {
|
||||
keyId = page.id.toString();
|
||||
}
|
||||
});
|
||||
var newPages = [];
|
||||
var cachedHandles = _.pluck(this.windowHandleCache, 'id');
|
||||
_.each(newIds, function(id) {
|
||||
if (!_.contains(cachedHandles, id)) {
|
||||
newPages.push(id);
|
||||
}
|
||||
});
|
||||
var newPage = null;
|
||||
if (this.curWindowHandle === null) {
|
||||
logger.info("We don't appear to have window set yet, ignoring");
|
||||
} else if (newPages.length) {
|
||||
logger.info("We have new pages, going to select page " + newPages[0]);
|
||||
newPage = newPages[0];
|
||||
} else if (!_.contains(newIds, this.curWindowHandle.toString())) {
|
||||
logger.info("New page listing from remote debugger doesn't contain " +
|
||||
"current window, let's assume it's closed");
|
||||
if (keyId !== null) {
|
||||
logger.info("Debugger already selected page " + keyId + ", " +
|
||||
"confirming that choice.");
|
||||
} else {
|
||||
logger.error("Don't have our current window anymore, and there " +
|
||||
"aren't any more to load! Doing nothing...");
|
||||
}
|
||||
this.curWindowHandle = keyId;
|
||||
this.remote.pageIdKey = parseInt(keyId, 10);
|
||||
} else {
|
||||
var dirty = function() {
|
||||
var item = function(arr) {
|
||||
return _.filter(arr, function(obj) {
|
||||
return obj.id == this.curWindowHandle;
|
||||
}, this)[0];
|
||||
}.bind(this);
|
||||
|
||||
var win = item(pageArray);
|
||||
var ret = false;
|
||||
_.each(item(this.windowHandleCache), function(el, idx, l) {
|
||||
if (l[idx] !== win[idx]) {
|
||||
ret = true;
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}.bind(this);
|
||||
|
||||
// If a window gets navigated to an anchor it doesn't always fire a page callback event
|
||||
// Let's check if we wound up in such a situation.
|
||||
if (dirty()) {
|
||||
this.remote.pageLoad();
|
||||
}
|
||||
|
||||
logger.info("New page listing is same as old, doing nothing");
|
||||
}
|
||||
|
||||
if (newPage !== null) {
|
||||
this.selectingNewPage = true;
|
||||
this.remote.selectPage(parseInt(newPage, 10), function() {
|
||||
this.selectingNewPage = false;
|
||||
this.curWindowHandle = newPage;
|
||||
if (this.onPageChangeCb !== null) {
|
||||
this.onPageChangeCb();
|
||||
this.onPageChangeCb = null;
|
||||
}
|
||||
}.bind(this));
|
||||
} else if (this.onPageChangeCb !== null) {
|
||||
this.onPageChangeCb();
|
||||
this.onPageChangeCb = null;
|
||||
}
|
||||
this.windowHandleCache = _.map(pageArray, this.massagePage);
|
||||
};
|
||||
|
||||
IOS.prototype.getAtomsElement = deviceCommon.getAtomsElement;
|
||||
|
||||
IOS.prototype.stopRemote = function() {
|
||||
if (!this.remote) {
|
||||
logger.error("We don't appear to be in a web frame");
|
||||
throw new Error("Tried to leave a web frame but weren't in one");
|
||||
} else {
|
||||
this.remote.disconnect();
|
||||
this.curWindowHandle = null;
|
||||
this.curWebFrames = [];
|
||||
this.curWebCoords = null;
|
||||
this.remote = null;
|
||||
}
|
||||
};
|
||||
|
||||
IOS.prototype.postCleanup = function(cb) {
|
||||
this.curCoords = null;
|
||||
this.curOrientation = null;
|
||||
@@ -745,7 +544,7 @@ IOS.prototype.postCleanup = function(cb) {
|
||||
|
||||
IOS.prototype.endSimulator = function(cb) {
|
||||
var cmd = 'killall -9 "iPhone Simulator"';
|
||||
exec(cmd, { maxBuffer: 524288 }, function(err, stdout, stderr) {
|
||||
exec(cmd, { maxBuffer: 524288 }, function(err) {
|
||||
cb(err);
|
||||
});
|
||||
};
|
||||
@@ -875,6 +674,10 @@ IOS.prototype.unpackApp = function(req, cb) {
|
||||
deviceCommon.unpackApp(req, '.app', cb);
|
||||
};
|
||||
|
||||
_.each(_.keys(iOSHybrid), function(method) {
|
||||
IOS.prototype[method] = iOSHybrid[method];
|
||||
});
|
||||
|
||||
_.each(_.keys(iOSController), function(method) {
|
||||
IOS.prototype[method] = iOSController[method];
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user