Bug 1254629 - Add "hide on input" test case; r=esawin
authorJim Chen <nchen@mozilla.com>
Fri, 11 Mar 2016 13:47:22 -0500
changeset 288330 a21940e738361589daeeef7368e02a0a291fff4e
parent 288329 3b0c3fcc410bef8bdbb04af647ab4528bfeb2e7e
child 288331 ef38f6f97d2f1cdad49149d48bf9989432f1f7c5
push id30079
push userryanvm@gmail.com
push dateSat, 12 Mar 2016 20:24:19 +0000
treeherdermozilla-central@d1d47ba19ce9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersesawin
bugs1254629
milestone48.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 1254629 - Add "hide on input" test case; r=esawin The bug happens when an input is hidden (e.g. through 'display' style) inside an input or key event handler.
mobile/android/tests/browser/robocop/robocop_input.html
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputConnection.java
--- a/mobile/android/tests/browser/robocop/robocop_input.html
+++ b/mobile/android/tests/browser/robocop/robocop_input.html
@@ -1,58 +1,74 @@
 <!DOCTYPE html>
 <html>
   <head>
     <title>Robocop Input</title>
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
   </head>
   <body>
-    <p><input id="input" type="text"></p>
-    <p><input id="resetting-input" type="text"></p>
+    <p>Input: <input id="input" type="text"></p>
+    <p>Resetting input: <input id="resetting-input" type="text"></p>
+    <p>Hiding input: <input id="hiding-input" type="text"></p>
     <script type="application/javascript;version=1.8" src="robocop_head.js"></script>
     <script type="application/javascript;version=1.8">
       let input = document.getElementById("input");
 
       // An input that resets the editor on every input by resetting the value property.
       let resetting_input = document.getElementById("resetting-input");
-      resetting_input.addEventListener('input', function () {
-          this.value = this.value;
+      resetting_input.addEventListener('input', function() {
+        this.value = this.value;
+      });
+
+      // An input that hides on input.
+      let hiding_input = document.getElementById("hiding-input");
+      hiding_input.addEventListener('keydown', function(e) {
+        if (e.key === "!") { // '!' key event as sent by testInputConnection.java.
+          this.value = "";
+          this.style.display = "none";
+        }
       });
 
       let test = {
         focus_input: function(val) {
           input.value = val;
           input.focus();
         },
 
         test_reflush_changes: function() {
           let inputEditable = SpecialPowers.wrap(input).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
           let inputIme = inputEditable.editor.QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport);
           do_check_true(inputIme.composing);
 
           // Ending the composition then setting the input value triggers the bug.
           inputIme.forceCompositionEnd();
-          input.value = "good";
+          input.value = "good"; // Value that testInputConnection.java expects.
         },
 
         test_set_selection: function() {
           let inputEditable = SpecialPowers.wrap(input).QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement);
           let inputIme = inputEditable.editor.QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport);
           do_check_true(inputIme.composing);
 
           // Ending the composition then setting the selection triggers the bug.
           inputIme.forceCompositionEnd();
-          input.setSelectionRange(3, 3);
+          input.setSelectionRange(3, 3); // Offsets that testInputConnection.java expects.
         },
 
         focus_resetting_input: function(val) {
           resetting_input.value = val;
           resetting_input.focus();
         },
 
+        focus_hiding_input: function(val) {
+          hiding_input.value = val;
+          hiding_input.style.display = "";
+          hiding_input.focus();
+        },
+
         finish_test: function() {
           java.disconnect();
         },
       };
 
       var java = new JavaBridge(test);
     </script>
   </body>
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputConnection.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputConnection.java
@@ -44,16 +44,22 @@ public class testInputConnection extends
             .testInputConnection(new BasicInputConnectionTest());
 
         // Then switch focus to the resetting input field, and run tests there.
         getJS().syncCall("focus_resetting_input", "");
         mGeckoView.mTextInput
             .waitForInputConnection()
             .testInputConnection(new ResettingInputConnectionTest());
 
+        // Then switch focus to the hiding input field, and run tests there.
+        getJS().syncCall("focus_hiding_input", "");
+        mGeckoView.mTextInput
+            .waitForInputConnection()
+            .testInputConnection(new HidingInputConnectionTest());
+
         getJS().syncCall("finish_test");
     }
 
     private class BasicInputConnectionTest extends InputConnectionTest {
         @Override
         public void test(InputConnection ic, EditorInfo info) {
             // Test initial text provided by the hash in the test page URL
             assertText("Initial text matches URL hash", ic, INITIAL_TEXT);
@@ -249,9 +255,39 @@ public class testInputConnection extends
 
             ic.finishComposingText();
             assertTextAndSelectionAt("Can finish composing text (resetting)", ic, "baz", 3);
 
             ic.deleteSurroundingText(3, 0);
             assertTextAndSelectionAt("Can clear text", ic, "", 0);
         }
     }
+
+    /**
+     * HidingInputConnectionTest performs tests on the hiding input in
+     * robocop_input.html. Any test that uses the normal input should be put in
+     * BasicInputConnectionTest.
+     */
+    private class HidingInputConnectionTest extends InputConnectionTest {
+        @Override
+        public void test(final InputConnection ic, EditorInfo info) {
+            waitFor("focus change", new Condition() {
+                @Override
+                public boolean isSatisfied() {
+                    return "".equals(getText(ic));
+                }
+            });
+
+            // Bug 1254629, crash when hiding input during input.
+            ic.commitText("foo", 1);
+            assertTextAndSelectionAt("Can commit text (hiding)", ic, "foo", 3);
+
+            ic.commitText("!", 1);
+            // The '!' key causes the input to hide in robocop_input.html,
+            // and there won't be a text/selection update as a result.
+            assertTextAndSelectionAt("Can handle hiding input", ic, "foo", 3);
+
+            // Make sure we don't leave behind stale events for the following test.
+            processGeckoEvents(ic);
+            processInputConnectionEvents();
+        }
+    }
 }