Bug 1433463 - WebDriver:ElementSendKeys should not run unfocussing steps. r=automatedtester
authorAndreas Tolfsen <ato@sny.no>
Thu, 22 Feb 2018 11:26:01 +0000
changeset 404848 042d7adef0bdb9dc80e825c3997ace7519477c42
parent 404847 829efffc6c49ca28567d71865564edf741c44acb
child 404849 f14dbddb40c16a1ef1e065c2c31da6d1bf5dc996
push id60008
push useratolfsen@mozilla.com
push dateThu, 22 Feb 2018 14:27:19 +0000
treeherderautoland@042d7adef0bd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersautomatedtester
bugs1433463
milestone60.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 1433463 - WebDriver:ElementSendKeys should not run unfocussing steps. r=automatedtester According to the WebDriver standard the Element Send Keys command should not run the unfocussing steps. Not blurring the element causes the DOM "change" event not to fire, but the specification only expects the "input" event to fire. The standard does, however, expect the Element Clear command to run the unfocussing steps and to blur the element for historical reasons. MozReview-Commit-ID: FHD1whho0jT
testing/marionette/interaction.js
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/webdriver/tests/element_send_keys/form_controls.py
testing/web-platform/tests/webdriver/tests/element_send_keys/interactability.py
--- a/testing/marionette/interaction.js
+++ b/testing/marionette/interaction.js
@@ -572,18 +572,16 @@ async function webdriverSendKeysToElemen
   if (el.type == "file") {
     await interaction.uploadFile(el, value);
   } else if ((el.type == "date" || el.type == "time") &&
       Preferences.get("dom.forms.datetime")) {
     interaction.setFormControlValue(el, value);
   } else {
     event.sendKeysToElement(value, el, win);
   }
-
-  el.blur();
 }
 
 async function legacySendKeysToElement(el, value, a11y) {
   const win = getWindow(el);
 
   if (el.type == "file") {
     await interaction.uploadFile(el, value);
   } else if ((el.type == "date" || el.type == "time") &&
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -584736,17 +584736,17 @@
    "bea28e051bc747d863dad9d1fd4ef8ffce432b54",
    "testharness"
   ],
   "service-workers/service-worker/state.https.html": [
    "ecb0e2fd22e7c92a98ae612a2032a92edf8520d9",
    "testharness"
   ],
   "service-workers/service-worker/svg-target-reftest.https.html": [
-   "c8d97ffed68ca40b4154bde36d9a0ca65d2e3816",
+   "9eb665d5cd1f62f2591130e372fd6dc1e9c61f64",
    "reftest"
   ],
   "service-workers/service-worker/synced-state.https.html": [
    "c6a3d6e8aa7a70e1bc670f89192240bac081bfe9",
    "testharness"
   ],
   "service-workers/service-worker/uncontrolled-page.https.html": [
    "881f51c7f9c64f6d69746e1e195c11cf6e29fb3e",
@@ -592480,21 +592480,21 @@
    "7d40a7641dbf04cd78f1dba630afa2e8d80dad13",
    "wdspec"
   ],
   "webdriver/tests/element_send_keys/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/element_send_keys/form_controls.py": [
-   "7c4a249f9575a69268b5f2970a5623fc1724e6e1",
+   "a1ade96c599a336684ee5a46dbc1716aac8ed9ae",
    "wdspec"
   ],
   "webdriver/tests/element_send_keys/interactability.py": [
-   "bd5d26173017dc3cbdc282809028639a7b4a214a",
+   "197bf11c6cae354d9f3cc07f836a857345046e1c",
    "wdspec"
   ],
   "webdriver/tests/element_send_keys/scroll_into_view.py": [
    "fb192d5d1d93aa729b07cadcadfa630587bd0b39",
    "wdspec"
   ],
   "webdriver/tests/execute_async_script/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
@@ -598772,17 +598772,17 @@
    "b0e679dd7720701364abeaca6870d94db5d7ee74",
    "support"
   ],
   "workers/support/iframe_sw_dataUrl.html": [
    "2cd66112b612e7b861af00af5ccc26cc7c5a76f8",
    "support"
   ],
   "workers/support/name-as-accidental-global.js": [
-   "530670268fae610b60066773ee475743b8498b53",
+   "5f75e855287f1a8b391498a3c567b68c75f56416",
    "support"
   ],
   "workers/support/name.js": [
    "27fa41f445888125f84dab8a57ca62b41c09e506",
    "support"
   ],
   "workers/support/nosiniff-error-worker.py": [
    "aa81cbafc77ccc9407cba3ac0bd4498e5076bf2b",
--- a/testing/web-platform/tests/webdriver/tests/element_send_keys/form_controls.py
+++ b/testing/web-platform/tests/webdriver/tests/element_send_keys/form_controls.py
@@ -1,53 +1,60 @@
 import pytest
 
-from tests.support.asserts import assert_error, assert_same_element, assert_success
+from tests.support.asserts import (
+    assert_element_has_focus,
+    assert_error,
+    assert_same_element,
+    assert_success,
+)
 from tests.support.inline import inline
 
 
 def element_send_keys(session, element, text):
     return session.transport.send(
         "POST",
         "/session/{session_id}/element/{element_id}/value".format(
             session_id=session.session_id,
             element_id=element.id),
         {"text": text})
 
 
 def add_event_listeners(element):
     element.session.execute_script("""
         let [target] = arguments;
         window.events = [];
-        for (let expected of ["focus", "blur", "change", "keypress", "keydown", "keyup", "input"]) {
+        for (let expected of ["focus", "change", "keypress", "keydown", "keyup", "input"]) {
           target.addEventListener(expected, ({type}) => window.events.push(type));
         }
         """, args=(element,))
 
 
 def get_events(session):
     return session.execute_script("return window.events")
 
 
 def test_input(session):
     session.url = inline("<input>")
     element = session.find.css("input", all=False)
     assert element.property("value") == ""
 
     element_send_keys(session, element, "foo")
     assert element.property("value") == "foo"
+    assert_element_has_focus(element)
 
 
 def test_textarea(session):
     session.url = inline("<textarea>")
     element = session.find.css("textarea", all=False)
     assert element.property("value") == ""
 
     element_send_keys(session, element, "foo")
     assert element.property("value") == "foo"
+    assert_element_has_focus(element)
 
 
 def test_input_append(session):
     session.url = inline("<input value=a>")
     element = session.find.css("input", all=False)
     assert element.property("value") == "a"
 
     element_send_keys(session, element, "b")
@@ -84,11 +91,18 @@ def test_events(session, tag):
                                    "keyup",
                                    "keydown",
                                    "keypress",
                                    "input",
                                    "keyup",
                                    "keydown",
                                    "keypress",
                                    "input",
-                                   "keyup",
-                                   "change",
-                                   "blur"]
+                                   "keyup"]
+
+
+@pytest.mark.parametrize("tag", ["input", "textarea"])
+def test_not_blurred(session, tag):
+    session.url = inline("<%s>" % tag)
+    element = session.find.css(tag, all=False)
+
+    element_send_keys(session, element, "")
+    assert_element_has_focus(element)
--- a/testing/web-platform/tests/webdriver/tests/element_send_keys/interactability.py
+++ b/testing/web-platform/tests/webdriver/tests/element_send_keys/interactability.py
@@ -1,86 +1,86 @@
-from tests.support.asserts import assert_error, assert_same_element, assert_success
+from tests.support.asserts import assert_error, assert_success
 from tests.support.inline import iframe, inline
 
 
 def send_keys_to_element(session, element, text):
     return session.transport.send(
         "POST",
         "/session/{session_id}/element/{element_id}/value".format(
             session_id=session.session_id,
             element_id=element.id),
         {"text": text})
 
 
 def test_body_is_interactable(session):
     session.url = inline("""
-        <body onkeypress="document.getElementById('result').value += event.key">
-          <input type="text" id="result"/>
+        <body onkeypress="document.querySelector('input').value += event.key">
+          <input>
         </body>
     """)
 
     element = session.find.css("body", all=False)
     result = session.find.css("input", all=False)
 
     # By default body is the active element
-    assert_same_element(session, element, session.active_element)
+    assert session.active_element is element
 
     response = send_keys_to_element(session, element, "foo")
     assert_success(response)
-    assert_same_element(session, element, session.active_element)
+    assert session.active_element is element
     assert result.property("value") == "foo"
 
 
 def test_document_element_is_interactable(session):
     session.url = inline("""
-        <html onkeypress="document.getElementById('result').value += event.key">
-          <input type="text" id="result"/>
+        <html onkeypress="document.querySelector('input').value += event.key">
+          <input>
         </html>
     """)
 
     body = session.find.css("body", all=False)
     element = session.find.css(":root", all=False)
     result = session.find.css("input", all=False)
 
     # By default body is the active element
-    assert_same_element(session, body, session.active_element)
+    assert session.active_element is body
 
     response = send_keys_to_element(session, element, "foo")
     assert_success(response)
-    assert_same_element(session, body, session.active_element)
+    assert session.active_element is element
     assert result.property("value") == "foo"
 
 
 def test_iframe_is_interactable(session):
     session.url = inline(iframe("""
-        <body onkeypress="document.getElementById('result').value += event.key">
-          <input type="text" id="result"/>
+        <body onkeypress="document.querySelector('input').value += event.key">
+          <input>
         </body>
     """))
 
     body = session.find.css("body", all=False)
     frame = session.find.css("iframe", all=False)
 
     # By default the body has the focus
-    assert_same_element(session, body, session.active_element)
+    assert session.active_element is body
 
     response = send_keys_to_element(session, frame, "foo")
     assert_success(response)
-    assert_same_element(session, body, session.active_element)
+    assert session.active_element is frame
 
     # Any key events are immediately routed to the nested
     # browsing context's active document.
     session.switch_frame(frame)
     result = session.find.css("input", all=False)
     assert result.property("value") == "foo"
 
 
 def test_transparent_element(session):
-    session.url = inline("<input style=\"opacity: 0;\">")
+    session.url = inline("""<input style="opacity: 0">""")
     element = session.find.css("input", all=False)
 
     response = send_keys_to_element(session, element, "foo")
     assert_success(response)
     assert element.property("value") == "foo"
 
 
 def test_readonly_element(session):
@@ -89,18 +89,18 @@ def test_readonly_element(session):
 
     response = send_keys_to_element(session, element, "foo")
     assert_success(response)
     assert element.property("value") == ""
 
 
 def test_obscured_element(session):
     session.url = inline("""
-      <input type="text" />
-      <div style="position: relative; top: -3em; height: 5em; background-color: blue"></div>
+      <input>
+      <div style="position: relative; top: -3em; height: 5em; background: blue;"></div>
     """)
     element = session.find.css("input", all=False)
 
     response = send_keys_to_element(session, element, "foo")
     assert_success(response)
     assert element.property("value") == "foo"
 
 
@@ -108,29 +108,29 @@ def test_not_a_focusable_element(session
     session.url = inline("<div>foo</div>")
     element = session.find.css("div", all=False)
 
     response = send_keys_to_element(session, element, "foo")
     assert_error(response, "element not interactable")
 
 
 def test_not_displayed_element(session):
-    session.url = inline("<input style=\"display: none\">")
+    session.url = inline("""<input style="display: none">""")
     element = session.find.css("input", all=False)
 
     response = send_keys_to_element(session, element, "foo")
     assert_error(response, "element not interactable")
 
 
 def test_hidden_element(session):
-    session.url = inline("<input style=\"visibility: hidden\">")
+    session.url = inline("""<input style="visibility: hidden">""")
     element = session.find.css("input", all=False)
 
     response = send_keys_to_element(session, element, "foo")
     assert_error(response, "element not interactable")
 
 
 def test_disabled_element(session):
-    session.url = inline("<input disabled=\"false\">")
+    session.url = inline("""<input disabled>""")
     element = session.find.css("input", all=False)
 
     response = send_keys_to_element(session, element, "foo")
     assert_error(response, "element not interactable")