Bug 1348782: Updated expected key parameter for sendKeysToElement. r?ato draft
authorDavid Burns <dburns@mozilla.com>
Fri, 24 Mar 2017 21:37:43 +0000
changeset 552468 d689f6ecfa90fbbb1f69007e5ccb3c718e6c5062
parent 552467 5a479113bc0fe5cbeec4aaf297ff3d9b9155c6c9
child 621812 4cbb989e70037c75652cac6bf536baf767b987a5
push id51347
push userbmo:dburns@mozilla.com
push dateTue, 28 Mar 2017 12:54:55 +0000
reviewersato
bugs1348782
milestone55.0a1
Bug 1348782: Updated expected key parameter for sendKeysToElement. r?ato The expected command parameter has been updated from `value` to `text`. This aligns marionette with W3C WebDriver Send Keys To Element command. MozReview-Commit-ID: EkQ1UJ58V7f
testing/marionette/client/marionette_driver/marionette.py
testing/marionette/driver.js
testing/marionette/event.js
testing/marionette/listener.js
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -93,20 +93,25 @@ class HTMLElement(object):
         self.marionette._send_message("singleTap", body)
 
     @property
     def text(self):
         """Returns the visible text of the element, and its child elements."""
         body = {"id": self.id}
         return self.marionette._send_message("getElementText", body, key="value")
 
-    def send_keys(self, *string):
-        """Sends the string via synthesized keypresses to the element."""
-        keys = Marionette.convert_keys(*string)
-        body = {"id": self.id, "value": keys}
+    def send_keys(self, *strings):
+        """Sends the string via synthesized keypresses to the element.
+           If an array is passed in like `marionette.send_keys(Keys.SHIFT, "a")` it
+           will be joined into a string.
+           If an integer is passed in like `marionette.send_keys(1234)` it will be
+           coerced into a string.
+        """
+        keys = Marionette.convert_keys(*strings)
+        body = {"id": self.id, "text": keys}
         self.marionette._send_message("sendKeysToElement", body)
 
     def clear(self):
         """Clears the input of the element."""
         self.marionette._send_message("clearElement", {"id": self.id})
 
     def is_selected(self):
         """Returns True if the element is selected."""
@@ -830,17 +835,17 @@ class Marionette(object):
                 typing.append(val)
             elif isinstance(val, int):
                 val = str(val)
                 for i in range(len(val)):
                     typing.append(val[i])
             else:
                 for i in range(len(val)):
                     typing.append(val[i])
-        return typing
+        return "".join(typing)
 
     def get_permission(self, perm):
         script = """
         let value = {
           'url': document.nodePrincipal.URI.spec,
           'appId': document.nodePrincipal.appId,
           'isInIsolatedMozBrowserElement': document.nodePrincipal.isInIsolatedMozBrowserElement,
           'type': arguments[0]
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2090,29 +2090,28 @@ GeckoDriver.prototype.getElementRect = f
  *
  * @param {string} id
  *     Reference ID to the element that will be checked.
  * @param {string} value
  *     Value to send to the element.
  */
 GeckoDriver.prototype.sendKeysToElement = function*(cmd, resp) {
   let win = assert.window(this.getCurrentWindow());
-
-  let {id, value} = cmd.parameters;
-  assert.defined(value, `Expected character sequence: ${value}`);
+  let {id, text} = cmd.parameters;
+  assert.string(text);
 
   switch (this.context) {
     case Context.CHROME:
       let el = this.curBrowser.seenEls.get(id, {frame: win});
       yield interaction.sendKeysToElement(
-          el, value, true, this.a11yChecks);
+          el, text, true, this.a11yChecks);
       break;
 
     case Context.CONTENT:
-      yield this.listener.sendKeysToElement(id, value);
+      yield this.listener.sendKeysToElement(id, text);
       break;
   }
 };
 
 /** Sets the test name.  The test name is used for logging purposes. */
 GeckoDriver.prototype.setTestName = function*(cmd, resp) {
   assert.window(this.getCurrentWindow());
 
--- a/testing/marionette/event.js
+++ b/testing/marionette/event.js
@@ -1278,36 +1278,35 @@ function focusElement(element) {
       let len = element.value.length;
       element.setSelectionRange(len, len);
     }
   }
   element.focus();
 }
 
 /**
- * @param {Array.<string>} keySequence
+ * @param {string} keyString
  * @param {Element} element
  * @param {Object.<string, boolean>=} opts
  * @param {Window=} window
  */
 event.sendKeysToElement = function (
-    keySequence, el, opts = {}, window = undefined) {
+    keyString, el, opts = {}, window = undefined) {
 
   if (opts.ignoreVisibility || element.isVisible(el)) {
     focusElement(el);
 
     // make Object.<modifier, false> map
     let modifiers = Object.create(event.Modifiers);
     for (let modifier in event.Modifiers) {
       modifiers[modifier] = false;
     }
 
-    let value = keySequence.join("");
-    for (let i = 0; i < value.length; i++) {
-      let c = value.charAt(i);
+    for (let i = 0; i < keyString.length; i++) {
+      let c = keyString.charAt(i);
       event.sendSingleKey(c, modifiers, window);
     }
 
   } else {
     throw new ElementNotInteractableError("Element is not visible");
   }
 };
 
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -1457,18 +1457,17 @@ function isElementSelected(id) {
   let el = seenEls.get(id, curContainer);
   return interaction.isElementSelected(
       el, capabilities.get("moz:accessibilityChecks"));
 }
 
 function* sendKeysToElement(id, val) {
   let el = seenEls.get(id, curContainer);
   if (el.type == "file") {
-    let path = val.join("");
-    yield interaction.uploadFile(el, path);
+    yield interaction.uploadFile(el, val);
   } else {
     yield interaction.sendKeysToElement(
         el, val, false, capabilities.get("moz:accessibilityChecks"));
   }
 }
 
 /**
  * Clear the text of an element.