Bug 1409040 - Add element.isDOMWindow. r?maja_zf draft
authorAndreas Tolfsen <ato@sny.no>
Fri, 13 Oct 2017 19:22:01 +0100
changeset 682765 3a10d857dfde878336102e8f8a222271020a3f53
parent 682759 dc5b9d0e522971ebe77cc3f52f117df03784df8a
child 682766 cd5f4be9dceeed7da9fdae6f52868b2b72f0c752
push id85136
push userbmo:ato@sny.no
push dateWed, 18 Oct 2017 18:18:02 +0000
reviewersmaja_zf
bugs1409040
milestone58.0a1
Bug 1409040 - Add element.isDOMWindow. r?maja_zf In addition to tell DOM- and XUL elements apart we will in the future need to identify WindowProxies because WebDriver expects there to be a separate "web window" serialisation for these. Telling if an abritrary object is a WindowProxy is tricky but we check if its node.toString is callable, that it returns "[object Window"], and finally that its "self" attribute is itself. This is not perfect, but good enough for now. MozReview-Commit-ID: 6FLOa3qYLPP
testing/marionette/element.js
testing/marionette/test_element.js
--- a/testing/marionette/element.js
+++ b/testing/marionette/element.js
@@ -1076,16 +1076,36 @@ element.isDOMElement = function(node) {
  */
 element.isXULElement = function(node) {
   return typeof node == "object" &&
       node !== null &&
       node.nodeType === node.ELEMENT_NODE &&
       [XBLNS, XULNS].includes(node.namespaceURI);
 };
 
+/**
+ * Ascertains whether <var>node</var> is a <code>WindowProxy</code>.
+ *
+ * @param {*} node
+ *     Node thought to be a <code>WindowProxy</code>.
+ *
+ * @return {boolean}
+ *     True if <var>node</var> is a DOM window.
+ */
+element.isDOMWindow = function(node) {
+  // TODO(ato): This should use Object.prototype.toString.call(node)
+  // but it's not clear how to write a good xpcshell test for that,
+  // seeing as we stub out a WindowProxy.
+  return typeof node == "object" &&
+      node !== null &&
+      typeof node.toString == "function" &&
+      node.toString() == "[object Window]" &&
+      node.self === node;
+};
+
 const boolEls = {
   audio: ["autoplay", "controls", "loop", "muted"],
   button: ["autofocus", "disabled", "formnovalidate"],
   details: ["open"],
   dialog: ["open"],
   fieldset: ["disabled"],
   form: ["novalidate"],
   iframe: ["allowfullscreen"],
--- a/testing/marionette/test_element.js
+++ b/testing/marionette/test_element.js
@@ -62,16 +62,26 @@ class XBLElement extends XULElement {
     this.namespaceURI = XBLNS;
   }
 }
 
 const domEl = new DOMElement("p");
 const xulEl = new XULElement("browser");
 const xblEl = new XBLElement("framebox");
 
+class WindowProxy {
+  get parent() { return this; }
+  get self() { return this; }
+  toString() { return "[object Window]"; }
+}
+const domWin = new WindowProxy();
+const domFrame = new class extends WindowProxy {
+  get parent() { return domWin; }
+};
+
 add_test(function test_isSelected() {
   let checkbox = new DOMElement("input", {type: "checkbox"});
   ok(!element.isSelected(checkbox));
   checkbox.checked = true;
   ok(element.isSelected(checkbox));
 
   // selected is not a property of <input type=checkbox>
   checkbox.selected = true;
@@ -94,34 +104,50 @@ add_test(function test_isSelected() {
   }
 
   run_next_test();
 });
 
 add_test(function test_isDOMElement() {
   ok(element.isDOMElement(domEl));
   ok(!element.isDOMElement(xulEl));
+  ok(!element.isDOMElement(domWin));
+  ok(!element.isDOMElement(domFrame));
   for (let typ of [true, 42, {}, [], undefined, null]) {
     ok(!element.isDOMElement(typ));
   }
 
   run_next_test();
 });
 
 add_test(function test_isXULElement() {
   ok(element.isXULElement(xulEl));
   ok(element.isXULElement(xblEl));
   ok(!element.isXULElement(domEl));
+  ok(!element.isDOMElement(domWin));
+  ok(!element.isDOMElement(domFrame));
   for (let typ of [true, 42, {}, [], undefined, null]) {
     ok(!element.isXULElement(typ));
   }
 
   run_next_test();
 });
 
+add_test(function test_isDOMWindow() {
+  ok(element.isDOMWindow(domWin));
+  ok(element.isDOMWindow(domFrame));
+  ok(!element.isDOMWindow(domEl));
+  ok(!element.isDOMWindow(xulEl));
+  for (let typ of [true, 42, {}, [], undefined, null]) {
+    ok(!element.isDOMWindow(typ));
+  }
+
+  run_next_test();
+});
+
 add_test(function test_coordinates() {
   let p = element.coordinates(domEl);
   ok(p.hasOwnProperty("x"));
   ok(p.hasOwnProperty("y"));
   equal("number", typeof p.x);
   equal("number", typeof p.y);
 
   deepEqual({x: 50, y: 50}, element.coordinates(domEl));