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
--- 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));