Bug 1348872 - Marionette unit tests should test real modal dialogs. draft
authorHenrik Skupin <mail@hskupin.info>
Tue, 28 Mar 2017 22:23:24 +0200
changeset 552700 17510b4defd7ebcacb66e2a153d047fbdd598935
parent 552699 6b0d43b9d891fd7173efc548d081756146d12b1c
child 552701 f7c32dfbeb88fc2c2da03d3154442f2fd59ab9ea
push id51424
push userbmo:hskupin@gmail.com
push dateTue, 28 Mar 2017 20:52:34 +0000
bugs1348872
milestone55.0a1
Bug 1348872 - Marionette unit tests should test real modal dialogs. Until now the unit tests only covered modal dialogs as shown when disabling the preference `prompts.tab_modal.enabled`. This actually tests an unsupported feature. Replacing it with a real modal dialog like HTTP authentication is what we really want here. MozReview-Commit-ID: 9FBxVuGJiEB
testing/marionette/harness/marionette_harness/runner/httpd.py
testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py
testing/marionette/harness/marionette_harness/www/modal_dialogs.html
testing/marionette/harness/marionette_harness/www/test_tab_modal_dialogs.html
--- a/testing/marionette/harness/marionette_harness/runner/httpd.py
+++ b/testing/marionette/harness/marionette_harness/runner/httpd.py
@@ -11,32 +11,59 @@ Marionette.
 
 import argparse
 import os
 import select
 import sys
 import time
 import urlparse
 
-from wptserve import server, handlers, routes as default_routes
+from wptserve import (
+    handlers,
+    request,
+    routes as default_routes,
+    server
+)
 
 
 root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
 default_doc_root = os.path.join(root, "www")
 default_ssl_cert = os.path.join(root, "certificates", "test.cert")
 default_ssl_key = os.path.join(root, "certificates", "test.key")
 
 
 @handlers.handler
+def http_auth_handler(req, response):
+    # Allow the test to specify the username and password
+    params = dict(urlparse.parse_qsl(req.url_parts.query))
+    username = params.get("username", "guest")
+    password = params.get("password", "guest")
+
+    auth = request.Authentication(req.headers)
+    content = """<!doctype html>
+<title>HTTP Authentication</title>
+<p id="status">{}</p>"""
+
+    if auth.username == username and auth.password == password:
+        response.status = 200
+        response.content = content.format("success")
+
+    else:
+        response.status = 401
+        response.headers.set("WWW-Authenticate", "Basic realm=\"secret\"")
+        response.content = content.format("restricted")
+
+
+@handlers.handler
 def upload_handler(request, response):
     return 200, [], [request.headers.get("Content-Type")] or []
 
 
 @handlers.handler
-def slow_loading_document(request, response):
+def slow_loading_handler(request, response):
     time.sleep(5)
     return """<!doctype html>
 <title>ok</title>
 <p>ok"""
 
 
 class NotAliveError(Exception):
     """Occurs when attempting to run a function that requires the HTTPD
@@ -59,17 +86,19 @@ class FixtureServer(object):
 
         scheme, host, port = url.scheme, url.hostname, url.port
         if host is None:
             host = "127.0.0.1"
         if port is None:
             port = 0
 
         routes = [("POST", "/file_upload", upload_handler),
-                  ("GET", "/slow", slow_loading_document)]
+                  ("GET", "/http_auth", http_auth_handler),
+                  ("GET", "/slow", slow_loading_handler),
+                  ]
         routes.extend(default_routes.routes)
 
         self._httpd = server.WebTestHttpd(host=host,
                                           port=port,
                                           bind_hostname=True,
                                           doc_root=doc_root,
                                           routes=routes,
                                           use_ssl=True if scheme == "https" else False,
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_modal_dialogs.py
@@ -2,197 +2,233 @@
 # 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 marionette_driver.by import By
 from marionette_driver.errors import NoAlertPresentException, ElementNotInteractableException
 from marionette_driver.marionette import Alert
 from marionette_driver.wait import Wait
 
-from marionette_harness import MarionetteTestCase, skip_if_e10s
+from marionette_harness import MarionetteTestCase, skip_if_e10s, WindowManagerMixin
 
 
-class TestTabModals(MarionetteTestCase):
-
-    def setUp(self):
-        super(TestTabModals, self).setUp()
-        self.marionette.set_pref("prompts.tab_modal.enabled", True)
-        self.marionette.navigate(self.marionette.absolute_url('modal_dialogs.html'))
-
-    def tearDown(self):
-        # Ensure an alert is absent before proceeding past this test.
-        Wait(self.marionette).until(lambda _: not self.alert_present())
-        self.marionette.execute_script("window.onbeforeunload = null;")
-        self.marionette.clear_pref("prompts.tab_modal.enabled")
-        super(TestTabModals, self).tearDown()
+class BaseAlertTestCase(WindowManagerMixin, MarionetteTestCase):
 
     def alert_present(self):
         try:
             Alert(self.marionette).text
             return True
         except NoAlertPresentException:
             return False
 
     def wait_for_alert(self):
         Wait(self.marionette).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.marionette.navigate(self.marionette.absolute_url("test_tab_modal_dialogs.html"))
+
+    def tearDown(self):
+        self.marionette.execute_script("window.onbeforeunload = null;")
+
+        # Ensure to close a possible remaining tab modal dialog
+        try:
+            alert = self.marionette.switch_to_alert()
+            alert.dismiss()
+
+            self.wait_for_alert_closed()
+        except:
+            pass
+
+        super(TestTabModalAlerts, self).tearDown()
+
     def test_no_alert_raises(self):
         self.assertRaises(NoAlertPresentException, Alert(self.marionette).accept)
         self.assertRaises(NoAlertPresentException, Alert(self.marionette).dismiss)
 
     def test_alert_accept(self):
-        self.marionette.find_element(By.ID, 'modal-alert').click()
+        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, 'modal-alert').click()
+        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, 'modal-confirm').click()
+        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')
+        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, 'modal-confirm').click()
+        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')
+        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, 'modal-prompt').click()
+        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 == '')
+        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, 'modal-prompt').click()
+        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')
+        self.wait_for_condition(
+            lambda mn: mn.find_element(By.ID, "prompt-result").text == "null")
 
     def test_alert_text(self):
         with self.assertRaises(NoAlertPresentException):
             alert = self.marionette.switch_to_alert()
             alert.text
-        self.marionette.find_element(By.ID, 'modal-alert').click()
+        self.marionette.find_element(By.ID, "tab-modal-alert").click()
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
-        self.assertEqual(alert.text, 'Marionette alert')
+        self.assertEqual(alert.text, "Marionette alert")
         alert.accept()
 
     def test_prompt_text(self):
         with self.assertRaises(NoAlertPresentException):
             alert = self.marionette.switch_to_alert()
             alert.text
-        self.marionette.find_element(By.ID, 'modal-prompt').click()
+        self.marionette.find_element(By.ID, "tab-modal-prompt").click()
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
-        self.assertEqual(alert.text, 'Marionette prompt')
+        self.assertEqual(alert.text, "Marionette prompt")
         alert.accept()
 
     def test_confirm_text(self):
         with self.assertRaises(NoAlertPresentException):
             alert = self.marionette.switch_to_alert()
             alert.text
-        self.marionette.find_element(By.ID, 'modal-confirm').click()
+        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')
+        self.assertEqual(alert.text, "Marionette confirm")
         alert.accept()
 
     def test_set_text_throws(self):
         self.assertRaises(NoAlertPresentException, Alert(self.marionette).send_keys, "Foo")
-        self.marionette.find_element(By.ID, 'modal-alert').click()
+        self.marionette.find_element(By.ID, "tab-modal-alert").click()
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
         self.assertRaises(ElementNotInteractableException, alert.send_keys, "Foo")
         alert.accept()
 
     def test_set_text_accept(self):
-        self.marionette.find_element(By.ID, 'modal-prompt').click()
+        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("Some text!")
         alert.accept()
-        self.wait_for_condition(lambda mn: mn.find_element(By.ID, 'prompt-result').text == 'Some text!')
+        self.wait_for_condition(
+            lambda mn: mn.find_element(By.ID, "prompt-result").text == "Some text!")
 
     def test_set_text_dismiss(self):
-        self.marionette.find_element(By.ID, 'modal-prompt').click()
+        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("Some text!")
         alert.dismiss()
-        self.wait_for_condition(lambda mn: mn.find_element(By.ID, 'prompt-result').text == 'null')
+        self.wait_for_condition(
+            lambda mn: mn.find_element(By.ID, "prompt-result").text == "null")
 
     def test_onbeforeunload_dismiss(self):
         start_url = self.marionette.get_url()
-        self.marionette.find_element(By.ID, 'onbeforeunload-handler').click()
+        self.marionette.find_element(By.ID, "onbeforeunload-handler").click()
         self.wait_for_condition(
             lambda mn: mn.execute_script("""
               return window.onbeforeunload !== null;
             """))
         self.marionette.navigate("about:blank")
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
         self.assertTrue(alert.text.startswith("This page is asking you to confirm"))
         alert.dismiss()
         self.assertTrue(self.marionette.get_url().startswith(start_url))
 
     def test_onbeforeunload_accept(self):
-        self.marionette.find_element(By.ID, 'onbeforeunload-handler').click()
+        self.marionette.find_element(By.ID, "onbeforeunload-handler").click()
         self.wait_for_condition(
             lambda mn: mn.execute_script("""
               return window.onbeforeunload !== null;
             """))
         self.marionette.navigate("about:blank")
         self.wait_for_alert()
         alert = self.marionette.switch_to_alert()
         self.assertTrue(alert.text.startswith("This page is asking you to confirm"))
         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
-        self.assertEqual(text, '')
+        click_handler = self.marionette.find_element(By.ID, "click-handler")
+        text = self.marionette.find_element(By.ID, "click-result").text
+        self.assertEqual(text, "")
 
-        self.marionette.find_element(By.ID, 'modal-alert').click()
+        self.marionette.find_element(By.ID, "tab-modal-alert").click()
         self.wait_for_alert()
 
         # Commands succeed, but because the dialog blocks the event loop,
         # our actions aren't reflected on the page.
-        text = self.marionette.find_element(By.ID, 'click-result').text
-        self.assertEqual(text, '')
+        text = self.marionette.find_element(By.ID, "click-result").text
+        self.assertEqual(text, "")
         click_handler.click()
-        text = self.marionette.find_element(By.ID, 'click-result').text
-        self.assertEqual(text, '')
+        text = self.marionette.find_element(By.ID, "click-result").text
+        self.assertEqual(text, "")
 
         alert = self.marionette.switch_to_alert()
         alert.accept()
 
-        Wait(self.marionette).until(lambda _: not self.alert_present())
+        self.wait_for_alert_closed()
 
         click_handler.click()
-        text = self.marionette.find_element(By.ID, 'click-result').text
-        self.assertEqual(text, 'result')
+        text = self.marionette.find_element(By.ID, "click-result").text
+        self.assertEqual(text, "result")
 
 
-class TestGlobalModals(TestTabModals):
+class TestModalAlerts(BaseAlertTestCase):
 
     def setUp(self):
-        super(TestGlobalModals, self).setUp()
-        self.marionette.set_pref("prompts.tab_modal.enabled", False)
+        super(TestModalAlerts, self).setUp()
+
+    def tearDown(self):
+        # Ensure to close a possible remaining modal dialog
+        self.close_all_windows()
+
+        super(TestModalAlerts, self).tearDown()
 
-    def test_unrelated_command_when_alert_present(self):
-        # The assumptions in this test do not hold on certain platforms, and not when
-        # e10s is enabled.
-        pass
+    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")
rename from testing/marionette/harness/marionette_harness/www/modal_dialogs.html
rename to testing/marionette/harness/marionette_harness/www/test_tab_modal_dialogs.html
--- a/testing/marionette/harness/marionette_harness/www/modal_dialogs.html
+++ b/testing/marionette/harness/marionette_harness/www/test_tab_modal_dialogs.html
@@ -22,18 +22,18 @@
     }
 
     function onBeforeUnload () {
       window.onbeforeunload = function () { return "Are you sure?"; }
     }
   </script>
 </head>
 <body>
-   <a href="#" id="modal-alert" onclick="handleAlert()">Open an alert dialog.</a>
-   <a href="#" id="modal-confirm" onclick="handleConfirm()">Open a confirm dialog.</a>
-   <a href="#" id="modal-prompt" onclick="handlePrompt()">Open a prompt dialog.</a>
+   <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="onbeforeunload-handler" onclick="onBeforeUnload()">Add an onbeforeunload handler.</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>
 </body>
 </html>