Bug 1487358 - [marionette] "Accept Alert" and "Dismiss Alert" should check for remaining user prompts. r=webdriver-reviewers,maja_zf
☠☠ backed out by c6a17846e2d2 ☠ ☠
authorHenrik Skupin <mail@hskupin.info>
Mon, 27 May 2019 19:54:21 +0000
changeset 475763 3350eb9922706b59cb7c4606eb2546f18f83baaa
parent 475762 c50e727f92456ec726473487bfcdb3e4fa9b1e8f
child 475764 c352b73db92bd0eee049ce6808b0e947e1eb1167
push id86467
push userhskupin@mozilla.com
push dateMon, 27 May 2019 20:32:34 +0000
treeherderautoland@3350eb992270 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswebdriver-reviewers, maja_zf
bugs1487358, 1477977
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1487358 - [marionette] "Accept Alert" and "Dismiss Alert" should check for remaining user prompts. r=webdriver-reviewers,maja_zf Workaround until we have a sane dynamic user prompt implementation (see bug 1477977). At least for now this patch will give us the opportunity to handle multiple open user prompts. Differential Revision: https://phabricator.services.mozilla.com/D32666
testing/marionette/driver.js
testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py
testing/marionette/harness/marionette_harness/www/test_tab_modal_dialogs.html
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -3166,17 +3166,17 @@ GeckoDriver.prototype.dismissDialog = as
 
   let dialogClosed = waitForEvent(win, "DOMModalDialogClosed");
 
   let {button0, button1} = this.dialog.ui;
   (button1 ? button1 : button0).click();
 
   await dialogClosed;
 
-  this.dialog = null;
+  this.dialog = modal.findModalDialogs(this.curBrowser);
 };
 
 /**
  * Accepts a currently displayed tab modal, or returns no such alert if
  * no modal is displayed.
  */
 GeckoDriver.prototype.acceptDialog = async function() {
   let win = assert.open(this.getCurrentWindow());
@@ -3184,17 +3184,17 @@ GeckoDriver.prototype.acceptDialog = asy
 
   let dialogClosed = waitForEvent(win, "DOMModalDialogClosed");
 
   let {button0} = this.dialog.ui;
   button0.click();
 
   await dialogClosed;
 
-  this.dialog = null;
+  this.dialog = modal.findModalDialogs(this.curBrowser);
 };
 
 /**
  * Returns the message shown in a currently displayed modal, or returns
  * a no such alert error if no modal is currently displayed.
  */
 GeckoDriver.prototype.getTextFromDialog = function() {
   assert.open(this.getCurrentWindow());
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py
@@ -1,230 +1,193 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
 from __future__ import absolute_import
 
 from marionette_driver.by import By
 from marionette_driver.expected import element_present
 from marionette_driver import errors
 from marionette_driver.marionette import Alert
 from marionette_driver.wait import Wait
 
-from marionette_harness import MarionetteTestCase, WindowManagerMixin
+from marionette_harness import MarionetteTestCase, parameterized, WindowManagerMixin
 
 
 class BaseAlertTestCase(WindowManagerMixin, MarionetteTestCase):
 
     @property
     def alert_present(self):
         try:
             Alert(self.marionette).text
             return True
         except errors.NoAlertPresentException:
             return False
 
     def wait_for_alert(self, timeout=None):
         Wait(self.marionette, timeout=timeout).until(
             lambda _: self.alert_present)
 
-    def wait_for_alert_closed(self, timeout=None):
-        Wait(self.marionette, timeout=timeout).until(
-            lambda _: not self.alert_present)
-
 
 class TestTabModalAlerts(BaseAlertTestCase):
 
     def setUp(self):
         super(TestTabModalAlerts, self).setUp()
         self.assertTrue(self.marionette.get_pref("prompts.tab_modal.enabled",
                         "Tab modal alerts should be enabled by default."))
 
         self.test_page = self.marionette.absolute_url("test_tab_modal_dialogs.html")
         self.marionette.navigate(self.test_page)
 
     def tearDown(self):
-        # Ensure to close a possible remaining tab modal dialog
+        # Ensure to close all possible remaining tab modal dialogs
         try:
-            alert = self.marionette.switch_to_alert()
-            alert.dismiss()
-
-            self.wait_for_alert_closed()
-        except:
+            while True:
+                alert = self.marionette.switch_to_alert()
+                alert.dismiss()
+        except errors.NoAlertPresentException:
             pass
 
         super(TestTabModalAlerts, self).tearDown()
 
     def test_no_alert_raises(self):
         with self.assertRaises(errors.NoAlertPresentException):
             Alert(self.marionette).accept()
         with self.assertRaises(errors.NoAlertPresentException):
             Alert(self.marionette).dismiss()
 
-    def test_alert_accept(self):
-        self.marionette.find_element(By.ID, "tab-modal-alert").click()
-        self.wait_for_alert()
-        alert = self.marionette.switch_to_alert()
-        alert.accept()
-
-    def test_alert_dismiss(self):
-        self.marionette.find_element(By.ID, "tab-modal-alert").click()
-        self.wait_for_alert()
-        alert = self.marionette.switch_to_alert()
-        alert.dismiss()
-
-    def test_confirm_accept(self):
-        self.marionette.find_element(By.ID, "tab-modal-confirm").click()
-        self.wait_for_alert()
-        alert = self.marionette.switch_to_alert()
-        alert.accept()
-        self.wait_for_condition(
-            lambda mn: mn.find_element(By.ID, "confirm-result").text == "true")
-
-    def test_confirm_dismiss(self):
-        self.marionette.find_element(By.ID, "tab-modal-confirm").click()
-        self.wait_for_alert()
-        alert = self.marionette.switch_to_alert()
-        alert.dismiss()
-        self.wait_for_condition(
-            lambda mn: mn.find_element(By.ID, "confirm-result").text == "false")
-
-    def test_prompt_accept(self):
-        self.marionette.find_element(By.ID, "tab-modal-prompt").click()
-        self.wait_for_alert()
-        alert = self.marionette.switch_to_alert()
-        alert.accept()
-        self.wait_for_condition(
-            lambda mn: mn.find_element(By.ID, "prompt-result").text == "")
-
-    def test_prompt_dismiss(self):
-        self.marionette.find_element(By.ID, "tab-modal-prompt").click()
-        self.wait_for_alert()
-        alert = self.marionette.switch_to_alert()
-        alert.dismiss()
-        self.wait_for_condition(
-            lambda mn: mn.find_element(By.ID, "prompt-result").text == "null")
-
     def test_alert_opened_before_session_starts(self):
         self.marionette.find_element(By.ID, "tab-modal-alert").click()
         self.wait_for_alert()
 
         # Restart the session to ensure we still find the formerly left-open dialog.
         self.marionette.delete_session()
         self.marionette.start_session()
 
         alert = self.marionette.switch_to_alert()
         alert.dismiss()
 
-    def test_alert_text(self):
-        with self.assertRaises(errors.NoAlertPresentException):
-            alert = self.marionette.switch_to_alert()
-            alert.text
-        self.marionette.find_element(By.ID, "tab-modal-alert").click()
+    @parameterized("alert", "alert", "undefined")
+    @parameterized("confirm", "confirm", "true")
+    @parameterized("prompt", "prompt", "")
+    def test_accept(self, value, result):
+        self.marionette.find_element(By.ID, "tab-modal-{}".format(value)).click()
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
-        self.assertEqual(alert.text, "Marionette alert")
         alert.accept()
+        self.assertEqual(self.marionette.find_element(By.ID, "text").text, result)
 
-    def test_prompt_text(self):
+    @parameterized("alert", "alert", "undefined")
+    @parameterized("confirm", "confirm", "false")
+    @parameterized("prompt", "prompt", "null")
+    def test_dismiss(self, value, result):
+        self.marionette.find_element(By.ID, "tab-modal-{}".format(value)).click()
+        self.wait_for_alert()
+        alert = self.marionette.switch_to_alert()
+        alert.dismiss()
+        self.assertEqual(self.marionette.find_element(By.ID, "text").text, result)
+
+    @parameterized("alert", "alert", "Marionette alert")
+    @parameterized("confirm", "confirm", "Marionette confirm")
+    @parameterized("prompt", "prompt", "Marionette prompt")
+    def test_text(self, value, text):
         with self.assertRaises(errors.NoAlertPresentException):
             alert = self.marionette.switch_to_alert()
             alert.text
-        self.marionette.find_element(By.ID, "tab-modal-prompt").click()
+        self.marionette.find_element(By.ID, "tab-modal-{}".format(value)).click()
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
-        self.assertEqual(alert.text, "Marionette prompt")
+        self.assertEqual(alert.text, text)
         alert.accept()
 
-    def test_confirm_text(self):
-        with self.assertRaises(errors.NoAlertPresentException):
-            alert = self.marionette.switch_to_alert()
-            alert.text
-        self.marionette.find_element(By.ID, "tab-modal-confirm").click()
-        self.wait_for_alert()
-        alert = self.marionette.switch_to_alert()
-        self.assertEqual(alert.text, "Marionette confirm")
-        alert.accept()
-
-    def test_set_text_throws(self):
+    @parameterized("alert", "alert")
+    @parameterized("confirm", "confirm")
+    def test_set_text_throws(self, value):
         with self.assertRaises(errors.NoAlertPresentException):
             Alert(self.marionette).send_keys("Foo")
-        self.marionette.find_element(By.ID, "tab-modal-alert").click()
+        self.marionette.find_element(By.ID, "tab-modal-{}".format(value)).click()
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
         with self.assertRaises(errors.ElementNotInteractableException):
             alert.send_keys("Foo")
         alert.accept()
 
     def test_set_text_accept(self):
         self.marionette.find_element(By.ID, "tab-modal-prompt").click()
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
-        alert.send_keys("Some text!")
+        alert.send_keys("Foo bar")
         alert.accept()
-        self.wait_for_condition(
-            lambda mn: mn.find_element(By.ID, "prompt-result").text == "Some text!")
+        self.assertEqual(self.marionette.find_element(By.ID, "text").text, "Foo bar")
 
     def test_set_text_dismiss(self):
         self.marionette.find_element(By.ID, "tab-modal-prompt").click()
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
         alert.send_keys("Some text!")
         alert.dismiss()
-        self.wait_for_condition(
-            lambda mn: mn.find_element(By.ID, "prompt-result").text == "null")
+        self.assertEqual(self.marionette.find_element(By.ID, "text").text, "null")
 
     def test_unrelated_command_when_alert_present(self):
         self.marionette.find_element(By.ID, "tab-modal-alert").click()
         self.wait_for_alert()
         with self.assertRaises(errors.UnexpectedAlertOpen):
-            self.marionette.find_element(By.ID, "click-result")
+            self.marionette.find_element(By.ID, "text")
 
     def test_modal_is_dismissed_after_unexpected_alert(self):
         self.marionette.find_element(By.ID, "tab-modal-alert").click()
         self.wait_for_alert()
         with self.assertRaises(errors.UnexpectedAlertOpen):
-            self.marionette.find_element(By.ID, "click-result")
+            self.marionette.find_element(By.ID, "text")
 
         assert not self.alert_present
 
+    def test_handle_two_modal_dialogs(self):
+        self.marionette.find_element(By.ID, "open-two-dialogs").click()
+
+        self.wait_for_alert()
+        alert1 = self.marionette.switch_to_alert()
+        alert1.send_keys("foo")
+        alert1.accept()
+
+        alert2 = self.marionette.switch_to_alert()
+        alert2.send_keys("bar")
+        alert2.accept()
+
+        self.assertEqual(self.marionette.find_element(By.ID, "text1").text, "foo")
+        self.assertEqual(self.marionette.find_element(By.ID, "text2").text, "bar")
+
 
 class TestModalAlerts(BaseAlertTestCase):
 
     def setUp(self):
         super(TestModalAlerts, self).setUp()
-        self.marionette.set_pref("network.auth.non-web-content-triggered-resources-http-auth-allow",
-                                 True)
+        self.marionette.set_pref(
+            "network.auth.non-web-content-triggered-resources-http-auth-allow",
+            True)
 
     def tearDown(self):
         # Ensure to close a possible remaining modal dialog
         self.close_all_windows()
-        self.marionette.clear_pref("network.auth.non-web-content-triggered-resources-http-auth-allow")
+        self.marionette.clear_pref(
+            "network.auth.non-web-content-triggered-resources-http-auth-allow")
 
         super(TestModalAlerts, self).tearDown()
 
     def test_http_auth_dismiss(self):
         self.marionette.navigate(self.marionette.absolute_url("http_auth"))
         self.wait_for_alert(timeout=self.marionette.timeout.page_load)
 
         alert = self.marionette.switch_to_alert()
         alert.dismiss()
 
-        self.wait_for_alert_closed()
-
         status = Wait(self.marionette, timeout=self.marionette.timeout.page_load).until(
             element_present(By.ID, "status")
         )
         self.assertEqual(status.text, "restricted")
 
     def test_alert_opened_before_session_starts(self):
         self.marionette.navigate(self.marionette.absolute_url("http_auth"))
         self.wait_for_alert(timeout=self.marionette.timeout.page_load)
 
         # Restart the session to ensure we still find the formerly left-open dialog.
         self.marionette.delete_session()
         self.marionette.start_session()
 
         alert = self.marionette.switch_to_alert()
         alert.dismiss()
-
-        self.wait_for_alert_closed()
--- a/testing/marionette/harness/marionette_harness/www/test_tab_modal_dialogs.html
+++ b/testing/marionette/harness/marionette_harness/www/test_tab_modal_dialogs.html
@@ -2,33 +2,42 @@
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!DOCTYPE html>
 <html>
 <head>
   <title>Dialog Test</title>
   <script type="text/javascript">
+    function setInnerText(id, value) {
+      document.getElementById(id).innerHTML = "<p>" + value + "</p>";
+    }
+
     function handleAlert () {
-      window.alert('Marionette alert');
+      setInnerText("text", alert("Marionette alert"));
     }
 
     function handleConfirm () {
-      var alertAccepted = window.confirm('Marionette confirm');
-      document.getElementById('confirm-result').innerHTML = alertAccepted;
+      setInnerText("text", confirm("Marionette confirm"));
     }
 
     function handlePrompt () {
-      var promptText = window.prompt('Marionette prompt');
-      document.getElementById('prompt-result').innerHTML = promptText === null ? 'null' : promptText;
+      setInnerText("text", prompt("Marionette prompt"));
+    }
+
+    function handleTwoDialogs() {
+      setInnerText("text1", prompt("First"));
+      setInnerText("text2", prompt("Second"));
     }
   </script>
 </head>
 <body>
-   <a href="#" id="tab-modal-alert" onclick="handleAlert()">Open an alert dialog.</a>
-   <a href="#" id="tab-modal-confirm" onclick="handleConfirm()">Open a confirm dialog.</a>
-   <a href="#" id="tab-modal-prompt" onclick="handlePrompt()">Open a prompt dialog.</a>
-   <a href="#" id="click-handler" onclick="document.getElementById('click-result').innerHTML='result';">Make text appear.</a>
-   <div id="confirm-result"></div>
-   <div id="prompt-result"></div>
-   <div id="click-result"></div>
+  <a href="#" id="tab-modal-alert" onclick="handleAlert()">Open an alert dialog.</a>
+  <a href="#" id="tab-modal-confirm" onclick="handleConfirm()">Open a confirm dialog.</a>
+  <a href="#" id="tab-modal-prompt" onclick="handlePrompt()">Open a prompt dialog.</a>
+  <a href="#" id="open-two-dialogs" onclick="handleTwoDialogs()">Open two prompts.</a>
+  <a href="#" id="click-handler" onclick="document.getElementById('text').innerHTML='result';">Make text appear.</a>
+
+  <div id="text"></div>
+  <div id="text1"></div>
+  <div id="text2"></div>
 </body>
 </html>