Permalink
Browse files

close() window for mobile safari iphone

  • Loading branch information...
1 parent e0846c0 commit e2d004e761ab54e83bdf8509122658e8cdadcdf0 @jlipps committed Mar 22, 2013
Showing with 155 additions and 36 deletions.
  1. +4 −0 app/android.js
  2. +4 −0 app/controller.js
  3. +4 −2 app/hybrid/ios/remote-debugger.js
  4. +116 −33 app/ios.js
  5. +1 −1 app/routing.js
  6. +26 −0 test/functional/safari/safari.js
View
@@ -518,6 +518,10 @@ Android.prototype.setWindow = function(name, cb) {
cb(new NotYetImplementedError(), null);
};
+Android.prototype.closeWindow = function(cb) {
+ cb(new NotYetImplementedError(), null);
+};
+
Android.prototype.clearWebView = function(cb) {
cb(new NotYetImplementedError(), null);
};
View
@@ -541,6 +541,10 @@ exports.setWindow = function(req, res) {
}
};
+exports.closeWindow = function(req, res) {
+ req.device.closeWindow(getResponseHandler(req, res));
+};
+
exports.getWindowHandles = function(req, res) {
req.device.getWindowHandles(getResponseHandler(req, res));
};
@@ -103,6 +103,7 @@ RemoteDebugger.prototype.selectApp = function(appIdKey, cb) {
logger.info("Selecting app");
this.send(connectToApp, _.bind(function(pageDict) {
cb(this.pageArrayFromDict(pageDict));
+ this.specialCbs['_rpc_forwardGetListing:'] = _.bind(this.onPageChange, this);
}, this));
};
@@ -113,6 +114,7 @@ RemoteDebugger.prototype.pageArrayFromDict = function(pageDict) {
id: dict.WIRPageIdentifierKey
, title: dict.WIRTitleKey
, url: dict.WIRURLKey
+ , isKey: typeof dict.WIRConnectionIdentifierKey !== "undefined"
});
});
return newPageArray;
@@ -133,9 +135,8 @@ RemoteDebugger.prototype.selectPage = function(pageIdKey, cb) {
if (err || res.result.value == 'loading') {
me.pageUnload();
}
- me.specialCbs['_rpc_forwardGetListing:'] = _.bind(me.onPageChange, me);
cb();
- }, 0);
+ });
});
});
};
@@ -242,6 +243,7 @@ RemoteDebugger.prototype.handleSpecialMessage = function(specialCb) {
if (fn) {
if (specialCb != "_rpc_forwardGetListing:") {
this.specialCbs[specialCb] = null;
+ } else {
}
fn.apply(this, _.rest(arguments));
}
View
@@ -39,6 +39,7 @@ var IOS = function(args) {
this.cbForCurrentCmd = null;
this.remote = null;
this.curWindowHandle = null;
+ this.selectingNewPage = false;
this.windowHandleCache = [];
this.webElementIds = [];
this.implicitWaitMs = 0;
@@ -263,49 +264,77 @@ IOS.prototype.listWebFrames = function(cb, exitCb) {
logger.error("Can't enter web frame without a bundle ID");
throw new Error("Tried to enter web frame without a bundle ID");
}
- this.remote = rd.init(exitCb);
- this.remote.connect(function(appDict) {
- if(!_.has(appDict, me.bundleId)) {
- logger.error("Remote debugger did not list " + me.bundleId + " among " +
- "its available apps");
- if(_.has(appDict, "com.apple.mobilesafari")) {
- logger.info("Using mobile safari instead");
- me.remote.selectApp("com.apple.mobilesafari", cb);
+ if (this.remote !== null && this.bundleId !== null) {
+ this.remote.selectApp(this.bundleId, cb);
+ } else {
+ this.remote = rd.init(exitCb);
+ this.remote.connect(function(appDict) {
+ if(!_.has(appDict, me.bundleId)) {
+ logger.error("Remote debugger did not list " + me.bundleId + " among " +
+ "its available apps");
+ if(_.has(appDict, "com.apple.mobilesafari")) {
+ logger.info("Using mobile safari instead");
+ me.remote.selectApp("com.apple.mobilesafari", cb);
+ } else {
+ cb([]);
+ }
} else {
- cb([]);
+ me.remote.selectApp(me.bundleId, cb);
}
- } else {
- me.remote.selectApp(me.bundleId, cb);
- }
- }, _.bind(me.onPageChange, me));
+ }, _.bind(me.onPageChange, me));
+ }
};
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
, me = this;
_.each(pageArray, function(page) {
newIds.push(page.id.toString());
+ if (page.isKey) {
+ keyId = page.id.toString();
+ }
});
var newPages = [];
_.each(newIds, function(id) {
if (!_.contains(me.windowHandleCache, 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]);
- this.remote.selectPage(newPages[0], function() {
- me.curWindowHandle = newPages[0];
- });
- } else if (!_.contains(me.windowHandleCache, me.curWindowHandle.toString())) {
- logger.error("New page listing from remote debugger doesn't contain " +
- "current window, not sure how to proceed");
+ newPage = newPages[0];
+ } else if (!_.contains(newIds, me.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...");
+ }
+ me.curWindowHandle = keyId;
+ me.remote.pageIdKey = parseInt(keyId, 10);
} else {
logger.info("New page listing is same as old, doing nothing");
}
+
+ if (newPage !== null) {
+ this.selectingNewPage = true;
+ this.remote.selectPage(newPage, function() {
+ me.selectingNewPage = false;
+ me.curWindowHandle = newPage;
+ });
+ }
this.windowHandleCache = newIds;
};
@@ -379,6 +408,13 @@ IOS.prototype.push = function(elem) {
var me = this;
var next = function() {
+ if (me.selectingNewPage && me.curWindowHandle) {
+ logger.info("We're in the middle of selecting a new page, " +
+ "waiting to run next command until done");
+ setTimeout(next, 500);
+ return;
+ }
+
if (me.queue.length <= 0 || me.progress > 0) {
return;
}
@@ -529,7 +565,7 @@ IOS.prototype.findAndAct = function(strategy, selector, index, action, actionPar
// app/uiauto/appium/app.js:elemForAction
, supportedActions = ["tap", "isEnabled", "isValid", "isVisible",
"value", "name", "label", "setValue", "click",
- "selectPage"]
+ "selectPage", "rect"]
, many = index > 0;
if (action === "click") { action = "tap"; }
@@ -545,10 +581,15 @@ IOS.prototype.findAndAct = function(strategy, selector, index, action, actionPar
cmd += strParams.join(', ');
cmd += ")";
me.proxy(cmd, function(err, res) {
- if (!err && res.value !== null) {
- findCb(true, err, res);
- } else {
+ if (err || res.status === status.codes.NoSuchElement.code) {
findCb(false, err, res);
+ } else if (many && res.value === []) {
+ findCb(false, err, {
+ status: status.codes.NoSuchElement.code
+ , value: "Could not find element in findAndAct"
+ });
+ } else {
+ findCb(true, err, res);
}
});
};
@@ -1178,25 +1219,26 @@ IOS.prototype.setWindow = function(name, cb) {
}
};
+IOS.prototype.closeWindow = function(cb) {
+ if (this.curWindowHandle) {
+ this.closeSafariWindow(cb);
+ } else {
+ cb(new NotImplementedError(), null);
+ }
+};
+
IOS.prototype.setSafariWindow = function(windowId, cb) {
var me = this;
- var success = function(err, res, cb) {
- if (err || res.status !== status.codes.Success.code) {
- cb(err, res);
- return false;
- }
- return true;
- };
me.findAndAct('name', 'Pages', 0, 'value', [], function(err, res) {
- if (success(err, res, cb)) {
+ if (me.checkSuccess(err, res, cb)) {
if (res.value === "") {
cb(err, res);
} else {
me.findAndAct('name', 'Pages', 0, 'tap', [], function(err, res) {
- if (success(err, res, cb)) {
+ if (me.checkSuccess(err, res, cb)) {
me.findAndAct('tag name', 'pageIndicator', 0, 'selectPage', [windowId], function(err, res) {
- if (success(err, res, cb)) {
+ if (me.checkSuccess(err, res, cb)) {
me.findAndAct('name', 'Done', 0, 'tap', [], cb);
}
});
@@ -1207,6 +1249,47 @@ IOS.prototype.setSafariWindow = function(windowId, cb) {
});
};
+IOS.prototype.checkSuccess = function(err, res, cb) {
+ if (err || res.status !== status.codes.Success.code) {
+ cb(err, res);
+ return false;
+ }
+ return true;
+};
+
+IOS.prototype.closeSafariWindow = function(cb) {
+ var me = this;
+ me.findAndAct('name', 'Pages', 0, 'tap', [], function(err, res) {
+ if (me.checkSuccess(err, res, cb)) {
+ me.findAndAct('name', 'Close page', 0, 'click', [], function(err, res) {
+ if (me.checkSuccess(err, res, cb)) {
+ var oldImplicitWait = me.implicitWaitMs;
+ me.implicitWaitMs = 0;
+ me.findUIElementOrElements('name', 'Done', null, false, function(err, res) {
+ me.implicitWaitMs = oldImplicitWait;
+ if (res.status === status.codes.Success.code) {
+ var command = ["au.getElement('", res.value.ELEMENT,
+ "').tap()"].join('');
+ // don't care if it fails
+ me.proxy(command, function() {
+ cb(null, {
+ status: status.codes.Success.code
+ , value: null
+ });
+ });
+ } else {
+ cb(null, {
+ status: status.codes.Success.code
+ , value: null
+ });
+ }
+ });
+ }
+ });
+ }
+ });
+};
+
IOS.prototype.clearWebView = function(cb) {
if (this.curWindowHandle === null) {
cb(new NotImplementedError(), null);
View
@@ -58,6 +58,7 @@ module.exports = function(appium) {
rest.get('/wd/hub/session/:sessionId?/window_handle', controller.getWindowHandle);
rest.get('/wd/hub/session/:sessionId?/window_handles', controller.getWindowHandles);
rest.post('/wd/hub/session/:sessionId?/window', controller.setWindow);
+ rest.delete('/wd/hub/session/:sessionId?/window', controller.closeWindow);
rest.get('/wd/hub/session/:sessionId?/window/:windowhandle?/size', controller.getWindowSize);
rest.post('/wd/hub/session/:sessionId?/execute', controller.execute);
rest.get('/wd/hub/session/:sessionId?/title', controller.title);
@@ -102,7 +103,6 @@ var routeNotYetImplemented = function(rest) {
rest.get('/wd/hub/session/:sessionId?/ime/activated', controller.notYetImplemented);
rest.post('/wd/hub/session/:sessionId?/ime/deactivate', controller.notYetImplemented);
rest.post('/wd/hub/session/:sessionId?/ime/activate', controller.notYetImplemented);
- rest.delete('/wd/hub/session/:sessionId?/window', controller.notYetImplemented);
rest.post('/wd/hub/session/:sessionId?/window/:windowhandle/size', controller.notYetImplemented);
rest.post('/wd/hub/session/:sessionId?/window/:windowhandle/position', controller.notYetImplemented);
rest.get('/wd/hub/session/:sessionId?/window/:windowhandle/position', controller.notYetImplemented);
@@ -72,6 +72,32 @@ _.each(devices, function(sim) {
});
});
});
+
+ it("should be able to close windows", function(done) {
+ loadWebView("safari", h.driver, function() {
+ h.driver.elementById('blanklink', function(err, link) {
+ link.click(function() {
+ spinTitle("I am another page title", h.driver, function(err) {
+ should.not.exist(err);
+ h.driver.windowHandles(function(err, handles) {
+ var handles1 = handles.length;
+ h.driver.close(function(err) {
+ should.not.exist(err);
+ h.driver.windowHandles(function(err, handles) {
+ var handles2 = handles.length;
+ handles1.should.be.above(handles2);
+ spinTitle("I am a page title", h.driver, function(err) {
+ should.not.exist(err);
+ done();
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
}, null, null, {device: sim + " Simulator"});
});

0 comments on commit e2d004e

Please sign in to comment.