Bug 1254629 - Add "hide on input" test case; r=esawin
authorJim Chen <nchen@mozilla.com>
Fri, 11 Mar 2016 13:47:22 -0500
changeset 312104 a21940e738361589daeeef7368e02a0a291fff4e
parent 312103 3b0c3fcc410bef8bdbb04af647ab4528bfeb2e7e
child 312105 ef38f6f97d2f1cdad49149d48bf9989432f1f7c5
push id9480
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 17:12:58 +0000
treeherdermozilla-aurora@0d6a91c76a9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersesawin
bugs1254629
milestone48.0a1
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();
+        }
+    }
 }