Bug 1400256 - Make element.Store work with web elements. r?whimboo draft
authorAndreas Tolfsen <ato@sny.no>
Thu, 05 Oct 2017 18:01:35 +0100
changeset 683314 07818bbb5ba78bb9281d86468e3b4bf08c414f9c
parent 683313 d6a40344deebcf3529bda13b895af412924b73f2
child 683315 5c130420a2cf9ad81edf90605fcfd2398401ed33
push id85331
push userbmo:ato@sny.no
push dateThu, 19 Oct 2017 14:55:23 +0000
reviewerswhimboo
bugs1400256
milestone58.0a1
Bug 1400256 - Make element.Store work with web elements. r?whimboo MozReview-Commit-ID: AitZAYFtpoF
testing/marionette/driver.js
testing/marionette/element.js
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -18,17 +18,20 @@ Cu.import("chrome://marionette/content/a
 Cu.import("chrome://marionette/content/atom.js");
 const {
   browser,
   Context,
 } = Cu.import("chrome://marionette/content/browser.js", {});
 Cu.import("chrome://marionette/content/capture.js");
 Cu.import("chrome://marionette/content/cert.js");
 Cu.import("chrome://marionette/content/cookie.js");
-Cu.import("chrome://marionette/content/element.js");
+const {
+  element,
+  WebElement,
+} = Cu.import("chrome://marionette/content/element.js", {});
 const {
   ElementNotInteractableError,
   InsecureCertificateError,
   InvalidArgumentError,
   InvalidCookieDomainError,
   InvalidSelectorError,
   NoAlertOpenError,
   NoSuchFrameError,
--- a/testing/marionette/element.js
+++ b/testing/marionette/element.js
@@ -68,19 +68,16 @@ const uuidGen = Cc["@mozilla.org/uuid-ge
  * The {@link element.Store} provides a mapping between web element
  * references and DOM elements for each browsing context.  It also provides
  * functionality for looking up and retrieving elements.
  *
  * @namespace
  */
 this.element = {};
 
-element.Key = "element-6066-11e4-a52e-4f735466cecf";
-element.LegacyKey = "ELEMENT";
-
 element.Strategy = {
   ClassName: "class name",
   Selector: "css selector",
   ID: "id",
   Name: "name",
   LinkText: "link text",
   PartialLinkText: "partial link text",
   TagName: "tag name",
@@ -125,102 +122,128 @@ element.Store = class {
   addAll(els) {
     let add = this.add.bind(this);
     return [...els].map(add);
   }
 
   /**
    * Make an element seen.
    *
-   * @param {Element} el
+   * @param {(Element|WindowProxy|XULElement)} el
    *    Element to add to set of seen elements.
    *
-   * @return {string}
+   * @return {WebElement}
    *     Web element reference associated with element.
+   *
+   * @throws {TypeError}
+   *     If <var>el</var> is not an {@link Element} or a {@link XULElement}.
    */
   add(el) {
+    const isDOMElement = element.isDOMElement(el);
+    const isSVGElement = element.isSVGElement(el);
+    const isDOMWindow = element.isDOMWindow(el);
+    const isXULElement = element.isXULElement(el);
+    const context = isXULElement ? "chrome" : "content";
+
+    if (!(isDOMElement || isSVGElement || isDOMWindow || isXULElement)) {
+      throw new TypeError("Expected Element, SVGElement, " +
+          pprint`WindowProxy, or XULElement, got: ${el}`);
+    }
+
     for (let i in this.els) {
       let foundEl;
       try {
         foundEl = this.els[i].get();
       } catch (e) {}
 
       if (foundEl) {
         if (new XPCNativeWrapper(foundEl) == new XPCNativeWrapper(el)) {
-          return i;
+          return WebElement.fromUUID(i, context);
         }
 
       // cleanup reference to gc'd element
       } else {
         delete this.els[i];
       }
     }
 
-    let id = element.generateUUID();
-    this.els[id] = Cu.getWeakReference(el);
-    return id;
+    let webEl = WebElement.from(el);
+    this.els[webEl.uuid] = Cu.getWeakReference(el);
+    return webEl;
   }
 
   /**
    * Determine if the provided web element reference has been seen
    * before/is in the element store.
    *
    * Unlike when getting the element, a staleness check is not
    * performed.
    *
-   * @param {string} uuid
+   * @param {WebElement} webEl
    *     Element's associated web element reference.
    *
    * @return {boolean}
    *     True if element is in the store, false otherwise.
+   *
+   * @throws {TypeError}
+   *     If <var>webEl</var> is not a {@link WebElement}.
    */
-  has(uuid) {
-    return Object.keys(this.els).includes(uuid);
+  has(webEl) {
+    if (!(webEl instanceof WebElement)) {
+      throw new TypeError(
+          pprint`Expected web element, got: ${webEl}`);
+    }
+    return Object.keys(this.els).includes(webEl.uuid);
   }
 
   /**
-   * Retrieve a DOM element by its unique web element reference/UUID.
+   * Retrieve a DOM {@link Element} or a {@link XULElement} by its
+   * unique {@link WebElement} reference.
    *
-   * Upon retrieving the element, an element staleness check is
-   * performed.
-   *
-   * @param {string} uuid
-   *     Web element reference, or UUID.
+   * @param {WebElement} webEl
+   *     Web element reference to find the associated {@link Element}
+   *     of.
    * @param {WindowProxy} window
    *     Current browsing context, which may differ from the associate
    *     browsing context of <var>el</var>.
    *
-   * @returns {Element}
+   * @returns {(Element|XULElement)}
    *     Element associated with reference.
    *
+   * @throws {TypeError}
+   *     If <var>webEl</var> is not a {@link WebElement}.
    * @throws {NoSuchElementError}
    *     If the web element reference <var>uuid</var> has not been
    *     seen before.
    * @throws {StaleElementReferenceError}
    *     If the element has gone stale, indicating it is no longer
    *     attached to the DOM, or its node document is no longer the
    *     active document.
    */
-  get(uuid, window) {
-    if (!this.has(uuid)) {
+  get(webEl, window) {
+    if (!(webEl instanceof WebElement)) {
+      throw new TypeError(
+          pprint`Expected web element, got: ${webEl}`);
+    }
+    if (!this.has(webEl)) {
       throw new NoSuchElementError(
-          "Web element reference not seen before: " + uuid);
+          "Web element reference not seen before: " + webEl.uuid);
     }
 
     let el;
-    let ref = this.els[uuid];
+    let ref = this.els[webEl.uuid];
     try {
       el = ref.get();
     } catch (e) {
-      delete this.els[uuid];
+      delete this.els[webEl.uuid];
     }
 
     if (element.isStale(el, window)) {
       throw new StaleElementReferenceError(
-          pprint`The element reference of ${el || uuid} stale; ` +
+          pprint`The element reference of ${el || webEl.uuid} is stale; ` +
               "either the element is no longer attached to the DOM, " +
               "it is not in the current frame context, " +
               "or the document has been refreshed");
     }
 
     return el;
   }
 };
@@ -658,21 +681,16 @@ element.isCollection = function(seq) {
 
 element.makeWebElement = function(uuid) {
   return {
     [element.Key]: uuid,
     [element.LegacyKey]: uuid,
   };
 };
 
-element.generateUUID = function() {
-  let uuid = uuidGen.generateUUID().toString();
-  return uuid.substring(1, uuid.length - 1);
-};
-
 /**
  * Determines if <var>el</var> is stale.
  *
  * A stale element is an element no longer attached to the DOM or which
  * node document is not the active document of the current browsing
  * context.
  *
  * The currently selected browsing context, specified through