diff --git a/testing/marionette/driver.js b/testing/marionette/driver.js
index 726b8499d441..5a21a79023ff 100644
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -1897,25 +1897,7 @@ GeckoDriver.prototype.clickElement = function*(cmd, resp) {
// listen for it and then just send an error back. The person making the
// call should be aware something isnt right and handle accordingly
this.addFrameCloseListener("click");
-
- let click = this.listener.clickElement({id: id, pageTimeout: this.timeouts.pageLoad});
-
- // If a remoteness update interrupts our page load, this will never return
- // We need to re-issue this request to correctly poll for readyState and
- // send errors.
- this.curBrowser.pendingCommands.push(() => {
- let parameters = {
- // TODO(ato): Bug 1242595
- command_id: this.listener.activeMessageId,
- pageTimeout: this.timeouts.pageLoad,
- startTime: new Date().getTime(),
- };
- this.mm.broadcastAsyncMessage(
- "Marionette:waitForPageLoaded" + this.curBrowser.curFrameId,
- parameters);
- });
-
- yield click;
+ yield this.listener.clickElement(id);
break;
}
};
diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_click.py b/testing/marionette/harness/marionette_harness/tests/unit/test_click.py
index 513c29a7c325..43e6377dce0d 100644
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_click.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_click.py
@@ -8,7 +8,7 @@ from marionette_driver.by import By
from marionette_driver import errors
from marionette_driver.wait import Wait
-from marionette_harness import MarionetteTestCase, run_if_e10s
+from marionette_harness import MarionetteTestCase
def inline(doc):
@@ -97,7 +97,11 @@ class TestLegacyClick(MarionetteTestCase):
test_html = self.marionette.absolute_url("clicks.html")
self.marionette.navigate(test_html)
self.marionette.find_element(By.LINK_TEXT, "333333").click()
- self.marionette.find_element(By.ID, "username")
+ # Bug 1335778 - Missing implicit wait for page being loaded
+ Wait(self.marionette, timeout=self.marionette.timeout.page_load,
+ ignored_exceptions=errors.NoSuchElementException).until(
+ lambda m: m.find_element(By.ID, "username"),
+ message="Username field hasn't been found")
self.assertEqual(self.marionette.title, "XHTML Test Page")
def test_clicking_an_element_that_is_not_displayed_raises(self):
@@ -111,7 +115,11 @@ class TestLegacyClick(MarionetteTestCase):
test_html = self.marionette.absolute_url("clicks.html")
self.marionette.navigate(test_html)
self.marionette.find_element(By.ID, "overflowLink").click()
- self.marionette.find_element(By.ID, "username")
+ # Bug 1335778 - Missing implicit wait for page being loaded
+ Wait(self.marionette, timeout=self.marionette.timeout.page_load,
+ ignored_exceptions=errors.NoSuchElementException).until(
+ lambda m: m.find_element(By.ID, "username"),
+ message="Username field hasn't been found")
self.assertEqual(self.marionette.title, "XHTML Test Page")
def test_scroll_into_view_near_end(self):
@@ -252,45 +260,3 @@ class TestClick(TestLegacyClick):
with self.assertRaises(errors.ElementClickInterceptedException):
obscured.click()
self.assertFalse(self.marionette.execute_script("return window.clicked", sandbox=None))
-
-
-class TestClickNavigation(MarionetteTestCase):
-
- def setUp(self):
- super(TestClickNavigation, self).setUp()
-
- def test_click_link_page_load(self):
- test_html = self.marionette.absolute_url("clicks.html")
- self.marionette.navigate(test_html)
- self.marionette.find_element(By.LINK_TEXT, "333333").click()
- self.assertNotEqual(self.marionette.get_url(), test_html)
- self.assertEqual(self.marionette.title, "XHTML Test Page")
-
- def test_click_link_anchor(self):
- test_html = self.marionette.absolute_url("clicks.html")
- self.marionette.navigate(test_html)
- self.marionette.find_element(By.ID, "anchor").click()
- self.assertEqual(self.marionette.get_url(), "{}#".format(test_html))
-
- def test_click_no_link(self):
- test_html = self.marionette.absolute_url("clicks.html")
- self.marionette.navigate(test_html)
- self.marionette.find_element(By.ID, "showbutton").click()
- self.assertEqual(self.marionette.get_url(), test_html)
-
- @run_if_e10s("Requires e10s mode enabled")
- def test_click_remoteness_change(self):
- test_html = self.marionette.absolute_url("clicks.html")
-
- self.marionette.navigate("about:robots")
- self.marionette.navigate(test_html)
- self.marionette.find_element(By.ID, "anchor")
- self.marionette.navigate("about:robots")
- with self.assertRaises(errors.NoSuchElementException):
- self.marionette.find_element(By.ID, "anchor")
-
- self.marionette.go_back()
- self.marionette.find_element(By.ID, "anchor")
- self.marionette.find_element(By.ID, "history-back").click()
- with self.assertRaises(errors.NoSuchElementException):
- self.marionette.find_element(By.ID, "anchor")
diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py b/testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py
index 5d8bff3813e3..abfd248a3214 100644
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py
@@ -8,7 +8,7 @@ from marionette_driver.expected import element_present
from marionette_driver.marionette import Alert
from marionette_driver.wait import Wait
-from marionette_harness import MarionetteTestCase, WindowManagerMixin
+from marionette_harness import MarionetteTestCase, skip_if_e10s, WindowManagerMixin
class BaseAlertTestCase(WindowManagerMixin, MarionetteTestCase):
@@ -194,6 +194,7 @@ class TestTabModalAlerts(BaseAlertTestCase):
alert.accept()
self.wait_for_condition(lambda mn: mn.get_url() == "about:blank")
+ @skip_if_e10s("Bug 1325044")
def test_unrelated_command_when_alert_present(self):
click_handler = self.marionette.find_element(By.ID, "click-handler")
text = self.marionette.find_element(By.ID, "click-result").text
diff --git a/testing/marionette/harness/marionette_harness/www/clicks.html b/testing/marionette/harness/marionette_harness/www/clicks.html
index bb2ffc931e21..e48cb1b2f7d6 100644
--- a/testing/marionette/harness/marionette_harness/www/clicks.html
+++ b/testing/marionette/harness/marionette_harness/www/clicks.html
@@ -17,8 +17,6 @@
I'm a normal link
-Back in browser history
-Forward in browser history
I go to an anchor
I open a window with javascript
Click me
diff --git a/testing/marionette/listener.js b/testing/marionette/listener.js
index 96b5ce2e57ac..a3b4d8597490 100644
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -117,10 +117,8 @@ var sandboxName = "default";
*/
var loadListener = {
command_id: null,
- seenUnload: null,
timeout: null,
- timerPageLoad: null,
- timerPageUnload: null,
+ timer: null,
/**
* Start listening for page unload/load events.
@@ -138,44 +136,35 @@ var loadListener = {
this.command_id = command_id;
this.timeout = timeout;
- this.seenUnload = false;
-
- this.timerPageLoad = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
- this.timerPageUnload = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
// In case of a remoteness change, only wait the remaining time
timeout = startTime + timeout - new Date().getTime();
if (timeout <= 0) {
- this.notify(this.timerPageLoad);
+ this.notify();
return;
}
+ this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ this.timer.initWithCallback(this, timeout, Ci.nsITimer.TYPE_ONE_SHOT);
+
if (waitForUnloaded) {
- addEventListener("beforeunload", this, false);
addEventListener("hashchange", this, false);
addEventListener("pagehide", this, false);
} else {
addEventListener("DOMContentLoaded", loadListener, false);
addEventListener("pageshow", loadListener, false);
}
-
- this.timerPageLoad.initWithCallback(this, timeout, Ci.nsITimer.TYPE_ONE_SHOT);
},
/**
* Stop listening for page unload/load events.
*/
stop: function () {
- if (this.timerPageLoad) {
- this.timerPageLoad.cancel();
+ if (this.timer) {
+ this.timer.cancel();
+ this.timer = null;
}
- if (this.timerPageUnload) {
- this.timerPageUnload.cancel();
- }
-
- removeEventListener("beforeunload", this);
removeEventListener("hashchange", this);
removeEventListener("pagehide", this);
removeEventListener("DOMContentLoaded", this);
@@ -187,13 +176,8 @@ var loadListener = {
*/
handleEvent: function (event) {
switch (event.type) {
- case "beforeunload":
- this.seenUnload = true;
- break;
-
case "pagehide":
if (event.originalTarget === curContainer.frame.document) {
- removeEventListener("beforeunload", this);
removeEventListener("hashchange", this);
removeEventListener("pagehide", this);
@@ -239,22 +223,9 @@ var loadListener = {
* Callback for navigation timeout timer.
*/
notify: function (timer) {
- switch (timer) {
- // If the page unload timer is raised, ensure to properly stop the load
- // listener, and return from the currently active command.
- case this.timerPageUnload:
- if (!this.seenUnload) {
- this.stop();
- sendOk(this.command_id);
- }
- break;
-
- case this.timerPageLoad:
- this.stop();
- sendError(new TimeoutError(`Timeout loading page after ${this.timeout}ms`),
- this.command_id);
- break;
- }
+ this.stop();
+ sendError(new TimeoutError("Timeout loading page after " + this.timeout + "ms"),
+ this.command_id);
},
/**
@@ -281,13 +252,22 @@ var loadListener = {
* ID of the currently handled message between the driver and listener.
* @param {number} pageTimeout
* Timeout in milliseconds the method has to wait for the page being finished loading.
- * @param {boolean=} loadEventExpected
- * TODO
* @param {string=} url
* Optional URL, which is used to check if a page load is expected.
*/
- navigate: function (trigger, command_id, timeout, loadEventExpected = true,
- useUnloadTimer = false) {
+ navigate: function (trigger, command_id, timeout, url = undefined) {
+ let loadEventExpected = true;
+
+ if (typeof url == "string") {
+ try {
+ let requestedURL = new URL(url).toString();
+ loadEventExpected = navigate.isLoadEventExpected(requestedURL);
+ } catch (e) {
+ sendError(new InvalidArgumentError("Malformed URL: " + e.message), command_id);
+ return;
+ }
+ }
+
if (loadEventExpected) {
let startTime = new Date().getTime();
this.start(command_id, timeout, startTime, true);
@@ -297,13 +277,7 @@ var loadListener = {
yield trigger();
}).then(val => {
- if (loadEventExpected) {
- // Setup timer to detect a possible page load
- // TODO: Make it optional to wait + time with multiplier
- if (useUnloadTimer) {
- this.timerPageUnload.initWithCallback(this, "200", Ci.nsITimer.TYPE_ONE_SHOT);
- }
- } else {
+ if (!loadEventExpected) {
sendOk(command_id);
}
@@ -427,6 +401,7 @@ function removeMessageListenerId(messageName, handler) {
var getTitleFn = dispatch(getTitle);
var getPageSourceFn = dispatch(getPageSource);
var getActiveElementFn = dispatch(getActiveElement);
+var clickElementFn = dispatch(clickElement);
var getElementAttributeFn = dispatch(getElementAttribute);
var getElementPropertyFn = dispatch(getElementProperty);
var getElementTextFn = dispatch(getElementText);
@@ -481,7 +456,7 @@ function startListeners() {
addMessageListenerId("Marionette:findElementContent", findElementContentFn);
addMessageListenerId("Marionette:findElementsContent", findElementsContentFn);
addMessageListenerId("Marionette:getActiveElement", getActiveElementFn);
- addMessageListenerId("Marionette:clickElement", clickElement);
+ addMessageListenerId("Marionette:clickElement", clickElementFn);
addMessageListenerId("Marionette:getElementAttribute", getElementAttributeFn);
addMessageListenerId("Marionette:getElementProperty", getElementPropertyFn);
addMessageListenerId("Marionette:getElementText", getElementTextFn);
@@ -586,7 +561,7 @@ function deleteSession(msg) {
removeMessageListenerId("Marionette:findElementContent", findElementContentFn);
removeMessageListenerId("Marionette:findElementsContent", findElementsContentFn);
removeMessageListenerId("Marionette:getActiveElement", getActiveElementFn);
- removeMessageListenerId("Marionette:clickElement", clickElement);
+ removeMessageListenerId("Marionette:clickElement", clickElementFn);
removeMessageListenerId("Marionette:getElementAttribute", getElementAttributeFn);
removeMessageListenerId("Marionette:getElementProperty", getElementPropertyFn);
removeMessageListenerId("Marionette:getElementText", getElementTextFn);
@@ -1125,26 +1100,15 @@ function waitForPageLoaded(msg) {
*/
function get(msg) {
let {command_id, pageTimeout, url} = msg.json;
- let loadEventExpected = true;
try {
- if (typeof url == "string") {
- try {
- let requestedURL = new URL(url).toString();
- loadEventExpected = navigate.isLoadEventExpected(requestedURL);
- } catch (e) {
- sendError(new InvalidArgumentError("Malformed URL: " + e.message), command_id);
- return;
- }
- }
-
// We need to move to the top frame before navigating
sendSyncMessage("Marionette:switchedToFrame", {frameValue: null});
curContainer.frame = content;
loadListener.navigate(() => {
curContainer.frame.location = url;
- }, command_id, pageTimeout, loadEventExpected);
+ }, command_id, pageTimeout, url);
} catch (e) {
sendError(e, command_id);
@@ -1290,36 +1254,15 @@ function getActiveElement() {
/**
* Send click event to element.
*
- * @param {number} command_id
- * ID of the currently handled message between the driver and listener.
* @param {WebElement} id
* Reference to the web element to click.
- * @param {number} pageTimeout
- * Timeout in milliseconds the method has to wait for the page being finished loading.
*/
-function clickElement(msg) {
- let {command_id, id, pageTimeout} = msg.json;
-
- try {
- let loadEventExpected = true;
-
- let target = getElementAttribute(id, "target");
-
- if (target === "_blank") {
- loadEventExpected = false;
- }
-
- loadListener.navigate(() => {
- return interaction.clickElement(
- seenEls.get(id, curContainer),
- capabilities.get("moz:accessibilityChecks"),
- capabilities.get("specificationLevel") >= 1
- );
- }, command_id, pageTimeout, loadEventExpected, true);
-
- } catch (e) {
- sendError(e, command_id);
- }
+function clickElement(id) {
+ let el = seenEls.get(id, curContainer);
+ return interaction.clickElement(
+ el,
+ capabilities.get("moz:accessibilityChecks"),
+ capabilities.get("specificationLevel") >= 1);
}
function getElementAttribute(id, name) {