summaryrefslogtreecommitdiffstats
path: root/remote/marionette/test/xpcshell/test_json.js
diff options
context:
space:
mode:
Diffstat (limited to 'remote/marionette/test/xpcshell/test_json.js')
-rw-r--r--remote/marionette/test/xpcshell/test_json.js275
1 files changed, 275 insertions, 0 deletions
diff --git a/remote/marionette/test/xpcshell/test_json.js b/remote/marionette/test/xpcshell/test_json.js
new file mode 100644
index 0000000000..479e1fe473
--- /dev/null
+++ b/remote/marionette/test/xpcshell/test_json.js
@@ -0,0 +1,275 @@
+const { json } = ChromeUtils.importESModule(
+ "chrome://remote/content/marionette/json.sys.mjs"
+);
+const { NodeCache } = ChromeUtils.importESModule(
+ "chrome://remote/content/shared/webdriver/NodeCache.sys.mjs"
+);
+const { ShadowRoot, WebElement, WebReference } = ChromeUtils.importESModule(
+ "chrome://remote/content/marionette/element.sys.mjs"
+);
+
+function setupTest() {
+ const browser = Services.appShell.createWindowlessBrowser(false);
+ const nodeCache = new NodeCache();
+
+ const htmlEl = browser.document.createElement("video");
+ browser.document.body.appendChild(htmlEl);
+
+ const svgEl = browser.document.createElementNS(
+ "http://www.w3.org/2000/svg",
+ "rect"
+ );
+ browser.document.body.appendChild(svgEl);
+
+ const shadowRoot = htmlEl.openOrClosedShadowRoot;
+
+ const iframeEl = browser.document.createElement("iframe");
+ browser.document.body.appendChild(iframeEl);
+ const childEl = iframeEl.contentDocument.createElement("div");
+
+ return { browser, nodeCache, childEl, iframeEl, htmlEl, shadowRoot, svgEl };
+}
+
+add_task(function test_clone_generalTypes() {
+ const { nodeCache } = setupTest();
+
+ // null
+ equal(json.clone(undefined, nodeCache), null);
+ equal(json.clone(null, nodeCache), null);
+
+ // primitives
+ equal(json.clone(true, nodeCache), true);
+ equal(json.clone(42, nodeCache), 42);
+ equal(json.clone("foo", nodeCache), "foo");
+
+ // toJSON
+ equal(
+ json.clone({
+ toJSON() {
+ return "foo";
+ },
+ }),
+ "foo"
+ );
+});
+
+add_task(function test_clone_ShadowRoot() {
+ const { nodeCache, shadowRoot } = setupTest();
+
+ const shadowRootRef = nodeCache.getOrCreateNodeReference(shadowRoot);
+ deepEqual(
+ json.clone(shadowRoot, nodeCache),
+ WebReference.from(shadowRoot, shadowRootRef).toJSON()
+ );
+});
+
+add_task(function test_clone_WebElement() {
+ const { htmlEl, nodeCache, svgEl } = setupTest();
+
+ const htmlElRef = nodeCache.getOrCreateNodeReference(htmlEl);
+ deepEqual(
+ json.clone(htmlEl, nodeCache),
+ WebReference.from(htmlEl, htmlElRef).toJSON()
+ );
+
+ // Check an element with a different namespace
+ const svgElRef = nodeCache.getOrCreateNodeReference(svgEl);
+ deepEqual(
+ json.clone(svgEl, nodeCache),
+ WebReference.from(svgEl, svgElRef).toJSON()
+ );
+});
+
+add_task(function test_clone_Sequences() {
+ const { htmlEl, nodeCache } = setupTest();
+
+ const htmlElRef = nodeCache.getOrCreateNodeReference(htmlEl);
+
+ const input = [
+ null,
+ true,
+ [],
+ htmlEl,
+ {
+ toJSON() {
+ return "foo";
+ },
+ },
+ { bar: "baz" },
+ ];
+
+ const actual = json.clone(input, nodeCache);
+
+ equal(actual[0], null);
+ equal(actual[1], true);
+ deepEqual(actual[2], []);
+ deepEqual(actual[3], { [WebElement.Identifier]: htmlElRef });
+ equal(actual[4], "foo");
+ deepEqual(actual[5], { bar: "baz" });
+});
+
+add_task(function test_clone_objects() {
+ const { htmlEl, nodeCache } = setupTest();
+
+ const htmlElRef = nodeCache.getOrCreateNodeReference(htmlEl);
+
+ const input = {
+ null: null,
+ boolean: true,
+ array: [42],
+ element: htmlEl,
+ toJSON: {
+ toJSON() {
+ return "foo";
+ },
+ },
+ object: { bar: "baz" },
+ };
+
+ const actual = json.clone(input, nodeCache);
+
+ equal(actual.null, null);
+ equal(actual.boolean, true);
+ deepEqual(actual.array, [42]);
+ deepEqual(actual.element, { [WebElement.Identifier]: htmlElRef });
+ equal(actual.toJSON, "foo");
+ deepEqual(actual.object, { bar: "baz" });
+});
+
+add_task(function test_clone_сyclicReference() {
+ const { nodeCache } = setupTest();
+
+ // object
+ Assert.throws(() => {
+ const obj = {};
+ obj.reference = obj;
+ json.clone(obj, nodeCache);
+ }, /JavaScriptError/);
+
+ // array
+ Assert.throws(() => {
+ const array = [];
+ array.push(array);
+ json.clone(array, nodeCache);
+ }, /JavaScriptError/);
+
+ // array in object
+ Assert.throws(() => {
+ const array = [];
+ array.push(array);
+ json.clone({ array }, nodeCache);
+ }, /JavaScriptError/);
+
+ // object in array
+ Assert.throws(() => {
+ const obj = {};
+ obj.reference = obj;
+ json.clone([obj], nodeCache);
+ }, /JavaScriptError/);
+});
+
+add_task(function test_deserialize_generalTypes() {
+ const { browser, nodeCache } = setupTest();
+ const win = browser.document.ownerGlobal;
+
+ // null
+ equal(json.deserialize(undefined, nodeCache, win), undefined);
+ equal(json.deserialize(null, nodeCache, win), null);
+
+ // primitives
+ equal(json.deserialize(true, nodeCache, win), true);
+ equal(json.deserialize(42, nodeCache, win), 42);
+ equal(json.deserialize("foo", nodeCache, win), "foo");
+});
+
+add_task(function test_deserialize_ShadowRoot() {
+ const { browser, nodeCache, shadowRoot } = setupTest();
+ const win = browser.document.ownerGlobal;
+
+ // Fails to resolve for unknown elements
+ const unknownShadowRootId = { [ShadowRoot.Identifier]: "foo" };
+ Assert.throws(() => {
+ json.deserialize(unknownShadowRootId, nodeCache, win);
+ }, /NoSuchShadowRootError/);
+
+ const shadowRootRef = nodeCache.getOrCreateNodeReference(shadowRoot);
+ const shadowRootEl = { [ShadowRoot.Identifier]: shadowRootRef };
+
+ // Fails to resolve for missing window reference
+ Assert.throws(() => json.deserialize(shadowRootEl, nodeCache), /TypeError/);
+
+ // Previously seen element is associated with original web element reference
+ const root = json.deserialize(shadowRootEl, nodeCache, win);
+ deepEqual(root, shadowRoot);
+ deepEqual(root, nodeCache.getNode(browser.browsingContext, shadowRootRef));
+});
+
+add_task(function test_deserialize_WebElement() {
+ const { browser, htmlEl, nodeCache } = setupTest();
+ const win = browser.document.ownerGlobal;
+
+ // Fails to resolve for unknown elements
+ const unknownWebElId = { [WebElement.Identifier]: "foo" };
+ Assert.throws(() => {
+ json.deserialize(unknownWebElId, nodeCache, win);
+ }, /NoSuchElementError/);
+
+ const htmlElRef = nodeCache.getOrCreateNodeReference(htmlEl);
+ const htmlWebEl = { [WebElement.Identifier]: htmlElRef };
+
+ // Fails to resolve for missing window reference
+ Assert.throws(() => json.deserialize(htmlWebEl, nodeCache), /TypeError/);
+
+ // Previously seen element is associated with original web element reference
+ const el = json.deserialize(htmlWebEl, nodeCache, win);
+ deepEqual(el, htmlEl);
+ deepEqual(el, nodeCache.getNode(browser.browsingContext, htmlElRef));
+});
+
+add_task(function test_deserialize_Sequences() {
+ const { browser, htmlEl, nodeCache } = setupTest();
+ const win = browser.document.ownerGlobal;
+
+ const htmlElRef = nodeCache.getOrCreateNodeReference(htmlEl);
+
+ const input = [
+ null,
+ true,
+ [42],
+ { [WebElement.Identifier]: htmlElRef },
+ { bar: "baz" },
+ ];
+
+ const actual = json.deserialize(input, nodeCache, win);
+
+ equal(actual[0], null);
+ equal(actual[1], true);
+ deepEqual(actual[2], [42]);
+ deepEqual(actual[3], htmlEl);
+ deepEqual(actual[4], { bar: "baz" });
+});
+
+add_task(function test_deserialize_objects() {
+ const { browser, htmlEl, nodeCache } = setupTest();
+ const win = browser.document.ownerGlobal;
+
+ const htmlElRef = nodeCache.getOrCreateNodeReference(htmlEl);
+
+ const input = {
+ null: null,
+ boolean: true,
+ array: [42],
+ element: { [WebElement.Identifier]: htmlElRef },
+ object: { bar: "baz" },
+ };
+
+ const actual = json.deserialize(input, nodeCache, win);
+
+ equal(actual.null, null);
+ equal(actual.boolean, true);
+ deepEqual(actual.array, [42]);
+ deepEqual(actual.element, htmlEl);
+ deepEqual(actual.object, { bar: "baz" });
+
+ nodeCache.clear({ all: true });
+});