Bug 1203074: Move caret to end of textual input field before sending keys
☠☠ backed out by 856d68a4477a ☠ ☠
authorAndreas Tolfsen <ato@mozilla.com>
Wed, 09 Sep 2015 14:53:53 +0100
changeset 294386 0e4476d49a825d3c1ccf9cbbe5d17c2bb65eafec
parent 294385 86014d39a1c5eb901f1534cd683778f5763d1f8b
child 294387 be1b57ffbb743c3403b9702ebdb830c563993fef
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1203074
milestone43.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 1203074: Move caret to end of textual input field before sending keys When a TEXTAREA element is focused it returns the cursor to the last position was at, or places it last. INPUT @type="text" (or any other textual input element) places the caret at the beginning. Because of this we move the caret to the end of the input field. The next time the element is focussed, the cursor should move to the end. r=jgriffin
testing/marionette/client/marionette/tests/unit/test_typing.py
testing/marionette/sendkeys.js
--- a/testing/marionette/client/marionette/tests/unit/test_typing.py
+++ b/testing/marionette/client/marionette/tests/unit/test_typing.py
@@ -1,19 +1,24 @@
 # 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/.
 
+import urllib
+
 from marionette.marionette_test import MarionetteTestCase, skip_if_b2g
 from marionette_driver.keys import Keys
 from marionette_driver.errors import ElementNotVisibleException
 
 
+def inline(doc):
+    return "data:text/html;charset=utf-8,%s" % urllib.quote(doc)
+
+
 class TestTyping(MarionetteTestCase):
-
     def testShouldFireKeyPressEvents(self):
         test_html = self.marionette.absolute_url("javascriptPage.html")
         self.marionette.navigate(test_html)
         keyReporter = self.marionette.find_element("id", "keyReporter")
         keyReporter.send_keys("a")
         result = self.marionette.find_element("id", "result")
         self.assertTrue("press:" in result.text)
 
@@ -275,8 +280,22 @@ class TestTyping(MarionetteTestCase):
         # If we don't get an error below we are good
         self.marionette.find_element('tag name', 'body').send_keys('foo')
 
     def testShouldThrowElementNotVisibleWhenInputHidden(self):
         test_html = self.marionette.absolute_url("javascriptPage.html")
         self.marionette.navigate(test_html)
         not_displayed = self.marionette.find_element('id', 'notDisplayed')
         self.assertRaises(ElementNotVisibleException, not_displayed.send_keys, 'foo')
+
+    def test_appends_to_input_text(self):
+        self.marionette.navigate(inline("<input>"))
+        el = self.marionette.find_element("tag name", "input")
+        el.send_keys("foo")
+        el.send_keys("bar")
+        self.assertEqual("foobar", el.get_attribute("value"))
+
+    def test_appends_to_textarea(self):
+        self.marionette.navigate(inline("<textarea></textarea>"))
+        textarea = self.marionette.find_element("tag name", "textarea")
+        textarea.send_keys("foo")
+        textarea.send_keys("bar")
+        self.assertEqual("foobar", textarea.get_attribute("value"))
--- a/testing/marionette/sendkeys.js
+++ b/testing/marionette/sendkeys.js
@@ -121,27 +121,45 @@ function sendSingleKey (keyToSend, modif
     let modName = keyModifierNames[keyCode];
     modifiers[modName] = !modifiers[modName];
   } else if (modifiers.shiftKey) {
     keyCode = keyCode.toUpperCase();
   }
   utils.synthesizeKey(keyCode, modifiers, document);
 }
 
-function sendKeysToElement (document, element, keysToSend, successCallback, errorCallback, command_id, ignoreVisibility) {
+/**
+ * Focus element and, if a textual input field, move the caret to the
+ * end of the input field.
+ *
+ * @param {Element} el
+ *     Element to focus.
+ */
+function focusElement(el) {
+  let t = el.type;
+  if (t && (t == "text" || t == "textarea")) {
+    let len = el.value.length;
+    el.setSelectionRange(len, len);
+  }
+  el.focus();
+}
+
+function sendKeysToElement(document, element, keysToSend, successCallback, errorCallback, command_id, ignoreVisibility) {
   if (ignoreVisibility || checkVisible(element)) {
-    element.focus();
+    focusElement(element);
+
     let modifiers = {
       shiftKey: false,
       ctrlKey: false,
       altKey: false,
       metaKey: false
     };
     let value = keysToSend.join("");
     for (var i = 0; i < value.length; i++) {
       var c = value.charAt(i);
       sendSingleKey(c, modifiers, document);
     }
+
     successCallback(command_id);
   } else {
     errorCallback(new ElementNotVisibleError("Element is not visible"), command_id);
   }
 };