forked from mirrors/gecko-dev
Backed out changeset 7f0a872abb09 (bug 1811545) Backed out changeset 41daafb5d75a (bug 1811545) Backed out changeset 82dee6290057 (bug 1811545) Backed out changeset 3e0178b3e0dc (bug 1811545) Backed out changeset 55cec0043044 (bug 1811545) Backed out changeset 75eaaf96d039 (bug 1808894)
683 lines
18 KiB
JavaScript
683 lines
18 KiB
JavaScript
/* 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/. */
|
|
|
|
const {
|
|
element,
|
|
WebElement,
|
|
WebFrame,
|
|
WebReference,
|
|
WebWindow,
|
|
} = ChromeUtils.importESModule(
|
|
"chrome://remote/content/marionette/element.sys.mjs"
|
|
);
|
|
const { NodeCache } = ChromeUtils.importESModule(
|
|
"chrome://remote/content/shared/webdriver/NodeCache.sys.mjs"
|
|
);
|
|
|
|
const MemoryReporter = Cc["@mozilla.org/memory-reporter-manager;1"].getService(
|
|
Ci.nsIMemoryReporterManager
|
|
);
|
|
|
|
class Element {
|
|
constructor(tagName, attrs = {}) {
|
|
this.tagName = tagName;
|
|
this.localName = tagName;
|
|
|
|
this.isConnected = false;
|
|
this.ownerGlobal = {
|
|
document: {
|
|
isActive() {
|
|
return true;
|
|
},
|
|
},
|
|
};
|
|
|
|
for (let attr in attrs) {
|
|
this[attr] = attrs[attr];
|
|
}
|
|
}
|
|
|
|
get nodeType() {
|
|
return 1;
|
|
}
|
|
|
|
get ELEMENT_NODE() {
|
|
return 1;
|
|
}
|
|
|
|
// this is a severely limited CSS selector
|
|
// that only supports lists of tag names
|
|
matches(selector) {
|
|
let tags = selector.split(",");
|
|
return tags.includes(this.localName);
|
|
}
|
|
}
|
|
|
|
class DOMElement extends Element {
|
|
constructor(tagName, attrs = {}) {
|
|
super(tagName, attrs);
|
|
|
|
this.isConnected = true;
|
|
|
|
if (typeof this.namespaceURI == "undefined") {
|
|
this.namespaceURI = XHTML_NS;
|
|
}
|
|
|
|
if (typeof this.ownerDocument == "undefined") {
|
|
this.ownerDocument = { designMode: "off" };
|
|
}
|
|
|
|
if (typeof this.ownerDocument.documentElement == "undefined") {
|
|
this.ownerDocument.documentElement = { namespaceURI: XHTML_NS };
|
|
}
|
|
|
|
if (typeof this.type == "undefined") {
|
|
this.type = "text";
|
|
}
|
|
|
|
if (this.localName == "option") {
|
|
this.selected = false;
|
|
}
|
|
|
|
if (
|
|
this.localName == "input" &&
|
|
["checkbox", "radio"].includes(this.type)
|
|
) {
|
|
this.checked = false;
|
|
}
|
|
}
|
|
|
|
getBoundingClientRect() {
|
|
return {
|
|
top: 0,
|
|
left: 0,
|
|
width: 100,
|
|
height: 100,
|
|
};
|
|
}
|
|
}
|
|
|
|
class SVGElement extends Element {
|
|
constructor(tagName, attrs = {}) {
|
|
super(tagName, attrs);
|
|
this.namespaceURI = SVG_NS;
|
|
}
|
|
}
|
|
|
|
class XULElement extends Element {
|
|
constructor(tagName, attrs = {}) {
|
|
super(tagName, attrs);
|
|
this.namespaceURI = XUL_NS;
|
|
|
|
if (typeof this.ownerDocument == "undefined") {
|
|
this.ownerDocument = {};
|
|
}
|
|
if (typeof this.ownerDocument.documentElement == "undefined") {
|
|
this.ownerDocument.documentElement = { namespaceURI: XUL_NS };
|
|
}
|
|
}
|
|
}
|
|
|
|
const domEl = new DOMElement("p");
|
|
const svgEl = new SVGElement("rect");
|
|
const xulEl = new XULElement("text");
|
|
|
|
const domElInPrivilegedDocument = new Element("input", {
|
|
nodePrincipal: { isSystemPrincipal: true },
|
|
});
|
|
const xulElInPrivilegedDocument = new XULElement("text", {
|
|
nodePrincipal: { isSystemPrincipal: true },
|
|
});
|
|
|
|
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_findClosest() {
|
|
equal(element.findClosest(domEl, "foo"), null);
|
|
|
|
let foo = new DOMElement("foo");
|
|
let bar = new DOMElement("bar");
|
|
bar.parentNode = foo;
|
|
equal(element.findClosest(bar, "foo"), foo);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
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;
|
|
checkbox.checked = false;
|
|
ok(!element.isSelected(checkbox));
|
|
|
|
let option = new DOMElement("option");
|
|
ok(!element.isSelected(option));
|
|
option.selected = true;
|
|
ok(element.isSelected(option));
|
|
|
|
// checked is not a property of <option>
|
|
option.checked = true;
|
|
option.selected = false;
|
|
ok(!element.isSelected(option));
|
|
|
|
// anything else should not be selected
|
|
for (let typ of [domEl, undefined, null, "foo", true, [], {}]) {
|
|
ok(!element.isSelected(typ));
|
|
}
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_isElement() {
|
|
ok(element.isElement(domEl));
|
|
ok(element.isElement(svgEl));
|
|
ok(element.isElement(xulEl));
|
|
ok(!element.isElement(domWin));
|
|
ok(!element.isElement(domFrame));
|
|
for (let typ of [true, 42, {}, [], undefined, null]) {
|
|
ok(!element.isElement(typ));
|
|
}
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_isDOMElement() {
|
|
ok(element.isDOMElement(domEl));
|
|
ok(element.isDOMElement(domElInPrivilegedDocument));
|
|
ok(element.isDOMElement(svgEl));
|
|
ok(!element.isDOMElement(xulEl));
|
|
ok(!element.isDOMElement(xulElInPrivilegedDocument));
|
|
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(xulElInPrivilegedDocument));
|
|
ok(!element.isXULElement(domElInPrivilegedDocument));
|
|
ok(!element.isXULElement(domEl));
|
|
ok(!element.isXULElement(svgEl));
|
|
ok(!element.isXULElement(domWin));
|
|
ok(!element.isXULElement(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(domElInPrivilegedDocument));
|
|
ok(!element.isDOMWindow(svgEl));
|
|
ok(!element.isDOMWindow(xulEl));
|
|
for (let typ of [true, 42, {}, [], undefined, null]) {
|
|
ok(!element.isDOMWindow(typ));
|
|
}
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_isReadOnly() {
|
|
ok(!element.isReadOnly(null));
|
|
ok(!element.isReadOnly(domEl));
|
|
ok(!element.isReadOnly(new DOMElement("p", { readOnly: true })));
|
|
ok(element.isReadOnly(new DOMElement("input", { readOnly: true })));
|
|
ok(element.isReadOnly(new DOMElement("textarea", { readOnly: true })));
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_isDisabled() {
|
|
ok(!element.isDisabled(new DOMElement("p")));
|
|
ok(!element.isDisabled(new SVGElement("rect", { disabled: true })));
|
|
ok(!element.isDisabled(new XULElement("browser", { disabled: true })));
|
|
|
|
let select = new DOMElement("select", { disabled: true });
|
|
let option = new DOMElement("option");
|
|
option.parentNode = select;
|
|
ok(element.isDisabled(option));
|
|
|
|
let optgroup = new DOMElement("optgroup", { disabled: true });
|
|
option.parentNode = optgroup;
|
|
optgroup.parentNode = select;
|
|
select.disabled = false;
|
|
ok(element.isDisabled(option));
|
|
|
|
ok(element.isDisabled(new DOMElement("button", { disabled: true })));
|
|
ok(element.isDisabled(new DOMElement("input", { disabled: true })));
|
|
ok(element.isDisabled(new DOMElement("select", { disabled: true })));
|
|
ok(element.isDisabled(new DOMElement("textarea", { disabled: true })));
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_isEditingHost() {
|
|
ok(!element.isEditingHost(null));
|
|
ok(element.isEditingHost(new DOMElement("p", { isContentEditable: true })));
|
|
ok(
|
|
element.isEditingHost(
|
|
new DOMElement("p", { ownerDocument: { designMode: "on" } })
|
|
)
|
|
);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_isEditable() {
|
|
ok(!element.isEditable(null));
|
|
ok(!element.isEditable(domEl));
|
|
ok(!element.isEditable(new DOMElement("textarea", { readOnly: true })));
|
|
ok(!element.isEditable(new DOMElement("textarea", { disabled: true })));
|
|
|
|
for (let type of [
|
|
"checkbox",
|
|
"radio",
|
|
"hidden",
|
|
"submit",
|
|
"button",
|
|
"image",
|
|
]) {
|
|
ok(!element.isEditable(new DOMElement("input", { type })));
|
|
}
|
|
ok(element.isEditable(new DOMElement("input", { type: "text" })));
|
|
ok(element.isEditable(new DOMElement("input")));
|
|
|
|
ok(element.isEditable(new DOMElement("textarea")));
|
|
ok(
|
|
element.isEditable(
|
|
new DOMElement("p", { ownerDocument: { designMode: "on" } })
|
|
)
|
|
);
|
|
ok(element.isEditable(new DOMElement("p", { isContentEditable: true })));
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_isMutableFormControlElement() {
|
|
ok(!element.isMutableFormControl(null));
|
|
ok(
|
|
!element.isMutableFormControl(
|
|
new DOMElement("textarea", { readOnly: true })
|
|
)
|
|
);
|
|
ok(
|
|
!element.isMutableFormControl(
|
|
new DOMElement("textarea", { disabled: true })
|
|
)
|
|
);
|
|
|
|
const mutableStates = new Set([
|
|
"color",
|
|
"date",
|
|
"datetime-local",
|
|
"email",
|
|
"file",
|
|
"month",
|
|
"number",
|
|
"password",
|
|
"range",
|
|
"search",
|
|
"tel",
|
|
"text",
|
|
"url",
|
|
"week",
|
|
]);
|
|
for (let type of mutableStates) {
|
|
ok(element.isMutableFormControl(new DOMElement("input", { type })));
|
|
}
|
|
ok(element.isMutableFormControl(new DOMElement("textarea")));
|
|
|
|
ok(
|
|
!element.isMutableFormControl(new DOMElement("input", { type: "hidden" }))
|
|
);
|
|
ok(!element.isMutableFormControl(new DOMElement("p")));
|
|
ok(
|
|
!element.isMutableFormControl(
|
|
new DOMElement("p", { isContentEditable: true })
|
|
)
|
|
);
|
|
ok(
|
|
!element.isMutableFormControl(
|
|
new DOMElement("p", { ownerDocument: { designMode: "on" } })
|
|
)
|
|
);
|
|
|
|
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));
|
|
deepEqual({ x: 10, y: 10 }, element.coordinates(domEl, 10, 10));
|
|
deepEqual({ x: -5, y: -5 }, element.coordinates(domEl, -5, -5));
|
|
|
|
Assert.throws(() => element.coordinates(null), /node is null/);
|
|
|
|
Assert.throws(
|
|
() => element.coordinates(domEl, "string", undefined),
|
|
/Offset must be a number/
|
|
);
|
|
Assert.throws(
|
|
() => element.coordinates(domEl, undefined, "string"),
|
|
/Offset must be a number/
|
|
);
|
|
Assert.throws(
|
|
() => element.coordinates(domEl, "string", "string"),
|
|
/Offset must be a number/
|
|
);
|
|
Assert.throws(
|
|
() => element.coordinates(domEl, {}, undefined),
|
|
/Offset must be a number/
|
|
);
|
|
Assert.throws(
|
|
() => element.coordinates(domEl, undefined, {}),
|
|
/Offset must be a number/
|
|
);
|
|
Assert.throws(
|
|
() => element.coordinates(domEl, {}, {}),
|
|
/Offset must be a number/
|
|
);
|
|
Assert.throws(
|
|
() => element.coordinates(domEl, [], undefined),
|
|
/Offset must be a number/
|
|
);
|
|
Assert.throws(
|
|
() => element.coordinates(domEl, undefined, []),
|
|
/Offset must be a number/
|
|
);
|
|
Assert.throws(
|
|
() => element.coordinates(domEl, [], []),
|
|
/Offset must be a number/
|
|
);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_isNodeReferenceKnown() {
|
|
const browser = Services.appShell.createWindowlessBrowser(false);
|
|
const nodeCache = new NodeCache();
|
|
|
|
// Unknown node reference
|
|
ok(!element.isNodeReferenceKnown(browser.browsingContext, "foo", nodeCache));
|
|
|
|
// Known node reference
|
|
const el = browser.document.createElement("video");
|
|
const elRef = nodeCache.getOrCreateNodeReference(el);
|
|
ok(element.isNodeReferenceKnown(browser.browsingContext, elRef, nodeCache));
|
|
|
|
// Different top-level browsing context
|
|
const browser2 = Services.appShell.createWindowlessBrowser(false);
|
|
ok(!element.isNodeReferenceKnown(browser2.browsingContext, elRef, nodeCache));
|
|
|
|
// Different child browsing context
|
|
const iframeEl = browser.document.createElement("iframe");
|
|
browser.document.body.appendChild(iframeEl);
|
|
const childEl = iframeEl.contentDocument.createElement("div");
|
|
const childElRef = nodeCache.getOrCreateNodeReference(childEl);
|
|
const childBrowsingContext = iframeEl.contentWindow.browsingContext;
|
|
ok(element.isNodeReferenceKnown(childBrowsingContext, childElRef, nodeCache));
|
|
|
|
const iframeEl2 = browser2.document.createElement("iframe");
|
|
browser2.document.body.appendChild(iframeEl2);
|
|
const childBrowsingContext2 = iframeEl2.contentWindow.browsingContext;
|
|
ok(
|
|
!element.isNodeReferenceKnown(childBrowsingContext2, childElRef, nodeCache)
|
|
);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_getKnownElement() {
|
|
const browser = Services.appShell.createWindowlessBrowser(false);
|
|
const nodeCache = new NodeCache();
|
|
|
|
// Unknown element reference
|
|
Assert.throws(() => {
|
|
element.getKnownElement(browser.browsingContext, "foo", nodeCache);
|
|
}, /NoSuchElementError/);
|
|
|
|
// Deleted element (eg. garbage collected)
|
|
let divEl = browser.document.createElement("div");
|
|
const divElRef = nodeCache.getOrCreateNodeReference(divEl);
|
|
|
|
divEl = null;
|
|
MemoryReporter.minimizeMemoryUsage(() => {
|
|
Assert.throws(() => {
|
|
element.getKnownElement(browser.browsingContext, divElRef, nodeCache);
|
|
}, /StaleElementReferenceError/);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
// Known element reference
|
|
let imgEl = browser.document.createElement("img");
|
|
browser.document.body.appendChild(imgEl);
|
|
const imgElRef = nodeCache.getOrCreateNodeReference(imgEl);
|
|
equal(
|
|
element.getKnownElement(browser.browsingContext, imgElRef, nodeCache),
|
|
imgEl
|
|
);
|
|
});
|
|
|
|
add_test(function test_isStale() {
|
|
// Not connected to the DOM
|
|
ok(element.isStale(new Element("div")));
|
|
|
|
// Connected to the DOM
|
|
const domDivEl = new DOMElement("div");
|
|
ok(!element.isStale(domDivEl));
|
|
|
|
// Not part of the active document
|
|
domDivEl.ownerGlobal = {
|
|
document: {
|
|
isActive() {
|
|
return false;
|
|
},
|
|
},
|
|
};
|
|
ok(element.isStale(domDivEl));
|
|
|
|
// Without ownerGlobal
|
|
delete domDivEl.ownerGlobal;
|
|
ok(element.isStale(domDivEl));
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebReference_ctor() {
|
|
let el = new WebReference("foo");
|
|
equal(el.uuid, "foo");
|
|
|
|
for (let t of [42, true, [], {}, null, undefined]) {
|
|
Assert.throws(() => new WebReference(t), /to be a string/);
|
|
}
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebElemenet_is() {
|
|
let a = new WebReference("a");
|
|
let b = new WebReference("b");
|
|
|
|
ok(a.is(a));
|
|
ok(b.is(b));
|
|
ok(!a.is(b));
|
|
ok(!b.is(a));
|
|
|
|
ok(!a.is({}));
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebReference_from() {
|
|
ok(WebReference.from(domEl) instanceof WebElement);
|
|
ok(WebReference.from(xulEl) instanceof WebElement);
|
|
ok(WebReference.from(domWin) instanceof WebWindow);
|
|
ok(WebReference.from(domFrame) instanceof WebFrame);
|
|
ok(WebReference.from(domElInPrivilegedDocument) instanceof WebElement);
|
|
ok(WebReference.from(xulElInPrivilegedDocument) instanceof WebElement);
|
|
|
|
Assert.throws(() => WebReference.from({}), /InvalidArgumentError/);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebReference_fromJSON_WebElement() {
|
|
const { Identifier } = WebElement;
|
|
|
|
let ref = { [Identifier]: "foo" };
|
|
let webEl = WebReference.fromJSON(ref);
|
|
ok(webEl instanceof WebElement);
|
|
equal(webEl.uuid, "foo");
|
|
|
|
let identifierPrecedence = {
|
|
[Identifier]: "identifier-uuid",
|
|
};
|
|
let precedenceEl = WebReference.fromJSON(identifierPrecedence);
|
|
ok(precedenceEl instanceof WebElement);
|
|
equal(precedenceEl.uuid, "identifier-uuid");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebReference_fromJSON_WebWindow() {
|
|
let ref = { [WebWindow.Identifier]: "foo" };
|
|
let win = WebReference.fromJSON(ref);
|
|
ok(win instanceof WebWindow);
|
|
equal(win.uuid, "foo");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebReference_fromJSON_WebFrame() {
|
|
let ref = { [WebFrame.Identifier]: "foo" };
|
|
let frame = WebReference.fromJSON(ref);
|
|
ok(frame instanceof WebFrame);
|
|
equal(frame.uuid, "foo");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebReference_fromJSON_malformed() {
|
|
Assert.throws(() => WebReference.fromJSON({}), /InvalidArgumentError/);
|
|
Assert.throws(() => WebReference.fromJSON(null), /InvalidArgumentError/);
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebReference_fromUUID() {
|
|
let domWebEl = WebReference.fromUUID("bar");
|
|
ok(domWebEl instanceof WebElement);
|
|
equal(domWebEl.uuid, "bar");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebReference_isReference() {
|
|
for (let t of [42, true, "foo", [], {}]) {
|
|
ok(!WebReference.isReference(t));
|
|
}
|
|
|
|
ok(WebReference.isReference({ [WebElement.Identifier]: "foo" }));
|
|
ok(WebReference.isReference({ [WebWindow.Identifier]: "foo" }));
|
|
ok(WebReference.isReference({ [WebFrame.Identifier]: "foo" }));
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_generateUUID() {
|
|
equal(typeof element.generateUUID(), "string");
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebElement_toJSON() {
|
|
const { Identifier } = WebElement;
|
|
|
|
let el = new WebElement("foo");
|
|
let json = el.toJSON();
|
|
|
|
ok(Identifier in json);
|
|
equal(json[Identifier], "foo");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebElement_fromJSON() {
|
|
const { Identifier } = WebElement;
|
|
|
|
let el = WebElement.fromJSON({ [Identifier]: "foo" });
|
|
ok(el instanceof WebElement);
|
|
equal(el.uuid, "foo");
|
|
|
|
Assert.throws(() => WebElement.fromJSON({}), /InvalidArgumentError/);
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebWindow_toJSON() {
|
|
let win = new WebWindow("foo");
|
|
let json = win.toJSON();
|
|
ok(WebWindow.Identifier in json);
|
|
equal(json[WebWindow.Identifier], "foo");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebWindow_fromJSON() {
|
|
let ref = { [WebWindow.Identifier]: "foo" };
|
|
let win = WebWindow.fromJSON(ref);
|
|
ok(win instanceof WebWindow);
|
|
equal(win.uuid, "foo");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebFrame_toJSON() {
|
|
let frame = new WebFrame("foo");
|
|
let json = frame.toJSON();
|
|
ok(WebFrame.Identifier in json);
|
|
equal(json[WebFrame.Identifier], "foo");
|
|
|
|
run_next_test();
|
|
});
|
|
|
|
add_test(function test_WebFrame_fromJSON() {
|
|
let ref = { [WebFrame.Identifier]: "foo" };
|
|
let win = WebFrame.fromJSON(ref);
|
|
ok(win instanceof WebFrame);
|
|
equal(win.uuid, "foo");
|
|
|
|
run_next_test();
|
|
});
|