diff options
Diffstat (limited to '')
4 files changed, 1140 insertions, 0 deletions
diff --git a/remote/webdriver-bidi/test/xpcshell/test_Realm.js b/remote/webdriver-bidi/test/xpcshell/test_Realm.js new file mode 100644 index 0000000000..ff39adcd82 --- /dev/null +++ b/remote/webdriver-bidi/test/xpcshell/test_Realm.js @@ -0,0 +1,90 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { Realm } = ChromeUtils.importESModule( + "chrome://remote/content/webdriver-bidi/Realm.sys.mjs" +); + +add_test(function test_id() { + const realm1 = new Realm(); + const id1 = realm1.id; + Assert.equal(typeof id1, "string"); + + const realm2 = new Realm(); + const id2 = realm2.id; + Assert.equal(typeof id2, "string"); + + Assert.notEqual(id1, id2, "Ids for different realms are different"); + + run_next_test(); +}); + +add_test(function test_handleObjectMap() { + const realm = new Realm(); + + // Test an unknown handle. + Assert.equal( + realm.getObjectForHandle("unknown"), + undefined, + "Unknown handles return undefined" + ); + + // Test creating a simple handle. + const object = {}; + const handle = realm.getHandleForObject(object); + Assert.equal(typeof handle, "string", "Created a valid handle"); + Assert.equal( + realm.getObjectForHandle(handle), + object, + "Using the handle returned the original object" + ); + + // Test another handle for the same object. + const secondHandle = realm.getHandleForObject(object); + Assert.equal(typeof secondHandle, "string", "Created a valid handle"); + Assert.notEqual(secondHandle, handle, "A different handle was generated"); + Assert.equal( + realm.getObjectForHandle(secondHandle), + object, + "Using the second handle also returned the original object" + ); + + // Test using the handles in another realm. + const otherRealm = new Realm(); + Assert.equal( + otherRealm.getObjectForHandle(handle), + undefined, + "A realm returns undefined for handles from another realm" + ); + + // Removing an unknown handle should not throw or have any side effect on + // existing handles. + realm.removeObjectHandle("unknown"); + Assert.equal(realm.getObjectForHandle(handle), object); + Assert.equal(realm.getObjectForHandle(secondHandle), object); + + // Remove the second handle + realm.removeObjectHandle(secondHandle); + Assert.equal( + realm.getObjectForHandle(handle), + object, + "The first handle is still resolving the object" + ); + Assert.equal( + realm.getObjectForHandle(secondHandle), + undefined, + "The second handle returns undefined after calling removeObjectHandle" + ); + + // Remove the original handle + realm.removeObjectHandle(handle); + Assert.equal( + realm.getObjectForHandle(handle), + undefined, + "The first handle returns undefined as well" + ); + + run_next_test(); +}); diff --git a/remote/webdriver-bidi/test/xpcshell/test_RemoteValue.js b/remote/webdriver-bidi/test/xpcshell/test_RemoteValue.js new file mode 100644 index 0000000000..8147711417 --- /dev/null +++ b/remote/webdriver-bidi/test/xpcshell/test_RemoteValue.js @@ -0,0 +1,1016 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const browser = Services.appShell.createWindowlessBrowser(false); +const domEl = browser.document.createElement("div"); +browser.document.body.appendChild(domEl); + +const PRIMITIVE_TYPES = [ + { value: undefined, serialized: { type: "undefined" } }, + { value: null, serialized: { type: "null" } }, + { value: "foo", serialized: { type: "string", value: "foo" } }, + { value: Number.NaN, serialized: { type: "number", value: "NaN" } }, + { value: -0, serialized: { type: "number", value: "-0" } }, + { + value: Number.POSITIVE_INFINITY, + serialized: { type: "number", value: "Infinity" }, + }, + { + value: Number.NEGATIVE_INFINITY, + serialized: { type: "number", value: "-Infinity" }, + }, + { value: 42, serialized: { type: "number", value: 42 } }, + { value: false, serialized: { type: "boolean", value: false } }, + { value: 42n, serialized: { type: "bigint", value: "42" } }, +]; + +const REMOTE_SIMPLE_VALUES = [ + { + value: new RegExp(/foo/), + serialized: { + type: "regexp", + value: { + pattern: "foo", + flags: "", + }, + }, + deserializable: true, + }, + { + value: new RegExp(/foo/g), + serialized: { + type: "regexp", + value: { + pattern: "foo", + flags: "g", + }, + }, + deserializable: true, + }, + { + value: new Date(1654004849000), + serialized: { + type: "date", + value: "2022-05-31T13:47:29.000Z", + }, + deserializable: true, + }, +]; + +const REMOTE_COMPLEX_VALUES = [ + { value: Symbol("foo"), serialized: { type: "symbol" } }, + { + value: [1], + serialized: { + type: "array", + }, + }, + { + value: [1], + maxDepth: 0, + serialized: { + type: "array", + }, + }, + { + value: [1, "2", true, new RegExp(/foo/g)], + maxDepth: 1, + serialized: { + type: "array", + value: [ + { type: "number", value: 1 }, + { type: "string", value: "2" }, + { type: "boolean", value: true }, + { + type: "regexp", + value: { + pattern: "foo", + flags: "g", + }, + }, + ], + }, + deserializable: true, + }, + { + value: [1, [3, "4"]], + maxDepth: 1, + serialized: { + type: "array", + value: [{ type: "number", value: 1 }, { type: "array" }], + }, + }, + { + value: [1, [3, "4"]], + maxDepth: 2, + serialized: { + type: "array", + value: [ + { type: "number", value: 1 }, + { + type: "array", + value: [ + { type: "number", value: 3 }, + { type: "string", value: "4" }, + ], + }, + ], + }, + deserializable: true, + }, + { + value: new Map(), + maxDepth: 1, + serialized: { + type: "map", + value: [], + }, + deserializable: true, + }, + { + value: new Map([]), + maxDepth: 1, + serialized: { + type: "map", + value: [], + }, + deserializable: true, + }, + { + value: new Map([ + [1, 2], + ["2", "3"], + [true, false], + ]), + serialized: { + type: "map", + }, + }, + { + value: new Map([ + [1, 2], + ["2", "3"], + [true, false], + ]), + maxDepth: 0, + serialized: { + type: "map", + }, + }, + { + value: new Map([ + [1, 2], + ["2", "3"], + [true, false], + ]), + maxDepth: 1, + serialized: { + type: "map", + value: [ + [ + { type: "number", value: 1 }, + { type: "number", value: 2 }, + ], + ["2", { type: "string", value: "3" }], + [ + { type: "boolean", value: true }, + { type: "boolean", value: false }, + ], + ], + }, + deserializable: true, + }, + { + value: new Set(), + maxDepth: 1, + serialized: { + type: "set", + value: [], + }, + deserializable: true, + }, + { + value: new Set([]), + maxDepth: 1, + serialized: { + type: "set", + value: [], + }, + deserializable: true, + }, + { + value: new Set([1, "2", true]), + serialized: { + type: "set", + }, + }, + { + value: new Set([1, "2", true]), + maxDepth: 0, + serialized: { + type: "set", + }, + }, + { + value: new Set([1, "2", true]), + maxDepth: 1, + serialized: { + type: "set", + value: [ + { type: "number", value: 1 }, + { type: "string", value: "2" }, + { type: "boolean", value: true }, + ], + }, + deserializable: true, + }, + { value: new WeakMap([[{}, 1]]), serialized: { type: "weakmap" } }, + { value: new WeakSet([{}]), serialized: { type: "weakset" } }, + { value: new Error("error message"), serialized: { type: "error" } }, + { + value: new SyntaxError("syntax error message"), + serialized: { type: "error" }, + }, + { + value: new TypeError("type error message"), + serialized: { type: "error" }, + }, + { value: new Promise(() => true), serialized: { type: "promise" } }, + { value: new Int8Array(), serialized: { type: "typedarray" } }, + { value: new ArrayBuffer(), serialized: { type: "arraybuffer" } }, + { + value: browser.document.querySelectorAll("div"), + serialized: { type: "nodelist" }, + }, + { + value: browser.document.getElementsByTagName("div"), + serialized: { type: "htmlcollection" }, + }, + { + value: domEl, + serialized: { + type: "node", + value: { + attributes: {}, + childNodeCount: 0, + children: [], + localName: "div", + namespaceURI: "http://www.w3.org/1999/xhtml", + nodeType: 1, + }, + }, + }, + { value: browser.document.defaultView, serialized: { type: "window" } }, + { value: new URL("https://example.com"), serialized: { type: "object" } }, + { value: () => true, serialized: { type: "function" } }, + { value() {}, serialized: { type: "function" } }, + { + value: {}, + maxDepth: 1, + serialized: { + type: "object", + value: [], + }, + deserializable: true, + }, + { + value: { + "1": 1, + "2": "2", + foo: true, + }, + serialized: { + type: "object", + }, + }, + { + value: { + "1": 1, + "2": "2", + foo: true, + }, + maxDepth: 0, + serialized: { + type: "object", + }, + }, + { + value: { + "1": 1, + "2": "2", + foo: true, + }, + maxDepth: 1, + serialized: { + type: "object", + value: [ + ["1", { type: "number", value: 1 }], + ["2", { type: "string", value: "2" }], + ["foo", { type: "boolean", value: true }], + ], + }, + deserializable: true, + }, + { + value: { + "1": 1, + "2": "2", + "3": { + bar: "foo", + }, + foo: true, + }, + maxDepth: 2, + serialized: { + type: "object", + value: [ + ["1", { type: "number", value: 1 }], + ["2", { type: "string", value: "2" }], + [ + "3", + { + type: "object", + value: [["bar", { type: "string", value: "foo" }]], + }, + ], + ["foo", { type: "boolean", value: true }], + ], + }, + deserializable: true, + }, +]; + +const { Realm } = ChromeUtils.importESModule( + "chrome://remote/content/webdriver-bidi/Realm.sys.mjs" +); + +const { deserialize, serialize, stringify } = ChromeUtils.importESModule( + "chrome://remote/content/webdriver-bidi/RemoteValue.sys.mjs" +); + +add_test(function test_deserializePrimitiveTypes() { + const realm = new Realm(); + + for (const type of PRIMITIVE_TYPES) { + const { value: expectedValue, serialized } = type; + + info(`Checking '${serialized.type}'`); + const value = deserialize(realm, serialized); + + if (serialized.value == "NaN") { + ok(Number.isNaN(value), `Got expected value for ${serialized}`); + } else { + Assert.strictEqual( + value, + expectedValue, + `Got expected value for ${serialized}` + ); + } + } + + run_next_test(); +}); + +add_test(function test_deserializeDateLocalValue() { + const realm = new Realm(); + + const validaDateStrings = [ + "2009", + "2009-05", + "2009-05-19", + "2009T15:00", + "2009-05T15:00", + "2009-05-19T15:00", + "2009-05-19T15:00:15", + "2009-05-19T15:00:15.452", + "2009-05-19T15:00:15.452Z", + "2009-05-19T15:00:15.452+02:00", + "2009-05-19T15:00:15.452-02:00", + "-271821-04-20T00:00:00Z", + "+000000-01-01T00:00:00Z", + ]; + for (const dateString of validaDateStrings) { + info(`Checking '${dateString}'`); + const value = deserialize(realm, { type: "date", value: dateString }); + + Assert.equal( + value.getTime(), + new Date(dateString).getTime(), + `Got expected value for ${dateString}` + ); + } + + run_next_test(); +}); + +add_test(function test_deserializeLocalValues() { + const realm = new Realm(); + + for (const type of REMOTE_SIMPLE_VALUES.concat(REMOTE_COMPLEX_VALUES)) { + const { value: expectedValue, serialized, deserializable } = type; + + // Skip non deserializable cases + if (!deserializable) { + continue; + } + + info(`Checking '${serialized.type}'`); + const value = deserialize(realm, serialized); + assertLocalValue(serialized.type, value, expectedValue); + } + + run_next_test(); +}); + +add_test(function test_deserializeLocalValuesByHandle() { + // Create two realms, realm1 will be used to serialize values, while realm2 + // will be used as a reference empty realm without any object reference. + const realm1 = new Realm(); + const realm2 = new Realm(); + + for (const type of REMOTE_SIMPLE_VALUES.concat(REMOTE_COMPLEX_VALUES)) { + const { value: expectedValue, serialized } = type; + + // No need to skip non-deserializable cases here. + + info(`Checking '${serialized.type}'`); + // Serialize the value once to get a handle. + const serializedValue = serialize( + expectedValue, + 0, + "root", + new Map(), + realm1 + ); + + // Create a remote reference containing only the handle. + // `deserialize` should not need any other property. + const remoteReference = { handle: serializedValue.handle }; + + // Check that the remote reference can be deserialized in realm1. + const deserializedValue = deserialize(realm1, remoteReference); + assertLocalValue(serialized.type, deserializedValue, expectedValue); + + Assert.throws( + () => deserialize(realm2, remoteReference), + /InvalidArgumentError:/, + `Got expected error when using the wrong realm for deserialize` + ); + + realm1.removeObjectHandle(serializedValue.handle); + Assert.throws( + () => deserialize(realm1, remoteReference), + /InvalidArgumentError:/, + `Got expected error when after deleting the object handle` + ); + } + + run_next_test(); +}); + +add_test(function test_deserializePrimitiveTypesInvalidValues() { + const realm = new Realm(); + + const invalidValues = [ + { type: "bigint", values: [undefined, null, false, "foo", [], {}] }, + { type: "boolean", values: [undefined, null, 42, "foo", [], {}] }, + { + type: "number", + values: [undefined, null, false, "43", [], {}], + }, + { type: "string", values: [undefined, null, false, 42, [], {}] }, + ]; + + for (const invalidValue of invalidValues) { + const { type, values } = invalidValue; + + for (const value of values) { + info(`Checking '${type}' with value ${value}`); + + Assert.throws( + () => deserialize(realm, { type, value }), + /InvalidArgument/, + `Got expected error for type ${type} and value ${value}` + ); + } + } + + run_next_test(); +}); + +add_test(function test_deserializeDateLocalValueInvalidValues() { + const realm = new Realm(); + + const invalidaDateStrings = [ + "10", + "20009", + "+20009", + "2009-", + "2009-0", + "2009-15", + "2009-02-1", + "2009-02-50", + "2022-02-29", + "15:00", + "T15:00", + "9-05-19T15:00", + "2009-5-19T15:00", + "2009-05-1T15:00", + "2009-02-10T15", + "2009-05-19T15:", + "2009-05-19T1:00", + "2009-05-19T10:1", + "2022-06-31T15:00", + "2009-05-19T60:00", + "2009-05-19T15:70", + "2009-05-19T15:00.25", + "2009-05-19+10:00", + "2009-05-19Z", + "2009-05-19 15:00", + "2009-05-19t15:00Z", + "2009-05-19T15:00z", + "2009-05-19T15:00+01", + "2009-05-19T10:10+1:00", + "2009-05-19T10:10+01:1", + "2009-05-19T15:00+75:00", + "2009-05-19T15:00+02:80", + "2009-05-19T15:00-00:00", + "02009-05-19T15:00", + ]; + for (const dateString of invalidaDateStrings) { + info(`Checking '${dateString}'`); + + Assert.throws( + () => deserialize(realm, { type: "date", value: dateString }), + /InvalidArgumentError:/, + `Got expected error for date string: ${dateString}` + ); + } + + run_next_test(); +}); + +add_test(function test_deserializeLocalValuesInvalidType() { + const realm = new Realm(); + + const invalidTypes = [undefined, null, false, 42, {}]; + + for (const invalidType of invalidTypes) { + info(`Checking type: '${invalidType}'`); + + Assert.throws( + () => deserialize(realm, { type: invalidType }), + /InvalidArgumentError:/, + `Got expected error for type ${invalidType}` + ); + + Assert.throws( + () => + deserialize(realm, { + type: "array", + value: [{ type: invalidType }], + }), + /InvalidArgumentError:/, + `Got expected error for nested type ${invalidType}` + ); + } + + run_next_test(); +}); + +add_test(function test_deserializeLocalValuesInvalidValues() { + const realm = new Realm(); + + const invalidValues = [ + { type: "array", values: [undefined, null, false, 42, "foo", {}] }, + { + type: "regexp", + values: [ + undefined, + null, + false, + "foo", + 42, + [], + {}, + { pattern: null }, + { pattern: 1 }, + { pattern: true }, + { pattern: "foo", flags: null }, + { pattern: "foo", flags: 1 }, + { pattern: "foo", flags: false }, + { pattern: "foo", flags: "foo" }, + ], + }, + { + type: "date", + values: [ + undefined, + null, + false, + "foo", + "05 October 2011 14:48 UTC", + "Tue Jun 14 2022 10:46:50 GMT+0200!", + 42, + [], + {}, + ], + }, + { + type: "map", + values: [ + undefined, + null, + false, + "foo", + 42, + ["1"], + [[]], + [["1"]], + [{ "1": "2" }], + {}, + ], + }, + { + type: "set", + values: [undefined, null, false, "foo", 42, {}], + }, + { + type: "object", + values: [ + undefined, + null, + false, + "foo", + 42, + {}, + ["1"], + [[]], + [["1"]], + [{ "1": "2" }], + [ + [ + { type: "number", value: "1" }, + { type: "number", value: "2" }, + ], + ], + [ + [ + { type: "object", value: [] }, + { type: "number", value: "1" }, + ], + ], + [ + [ + { + type: "regexp", + value: { + pattern: "foo", + }, + }, + { type: "number", value: "1" }, + ], + ], + ], + }, + ]; + + for (const invalidValue of invalidValues) { + const { type, values } = invalidValue; + + for (const value of values) { + info(`Checking '${type}' with value ${value}`); + + Assert.throws( + () => deserialize(realm, { type, value }), + /InvalidArgumentError:/, + `Got expected error for type ${type} and value ${value}` + ); + } + } + + run_next_test(); +}); + +add_test(function test_serializePrimitiveTypes() { + const realm = new Realm(); + + for (const type of PRIMITIVE_TYPES) { + const { value, serialized } = type; + + const serializationInternalMap = new Map(); + const serializedValue = serialize( + value, + 0, + "none", + serializationInternalMap, + realm + ); + assertInternalIds(serializationInternalMap, 0); + Assert.deepEqual(serialized, serializedValue, "Got expected structure"); + + // For primitive values, the serialization with ownershipType=root should + // be exactly identical to the one with ownershipType=none. + const serializationInternalMapWithRoot = new Map(); + const serializedWithRoot = serialize( + value, + 0, + "root", + serializationInternalMapWithRoot, + realm + ); + assertInternalIds(serializationInternalMapWithRoot, 0); + Assert.deepEqual(serialized, serializedWithRoot, "Got expected structure"); + } + + run_next_test(); +}); + +add_test(function test_serializeRemoteSimpleValues() { + const realm = new Realm(); + + for (const type of REMOTE_SIMPLE_VALUES) { + const { value, serialized } = type; + + info(`Checking '${serialized.type}' with none ownershipType`); + const serializationInternalMapWithNone = new Map(); + const serializedValue = serialize( + value, + 0, + "none", + serializationInternalMapWithNone, + realm + ); + + assertInternalIds(serializationInternalMapWithNone, 0); + Assert.deepEqual(serialized, serializedValue, "Got expected structure"); + + info(`Checking '${serialized.type}' with root ownershipType`); + const serializationInternalMapWithRoot = new Map(); + const serializedWithRoot = serialize( + value, + 0, + "root", + serializationInternalMapWithRoot, + realm + ); + + assertInternalIds(serializationInternalMapWithRoot, 0); + Assert.equal( + typeof serializedWithRoot.handle, + "string", + "Got a handle property" + ); + Assert.deepEqual( + Object.assign({}, serialized, { handle: serializedWithRoot.handle }), + serializedWithRoot, + "Got expected structure, plus a generated handle id" + ); + } + + run_next_test(); +}); + +add_test(function test_serializeRemoteComplexValues() { + const realm = new Realm(); + + for (const type of REMOTE_COMPLEX_VALUES) { + const { value, serialized, maxDepth } = type; + + info(`Checking '${serialized.type}' with none ownershipType`); + const serializationInternalMapWithNone = new Map(); + const serializedValue = serialize( + value, + maxDepth, + "none", + serializationInternalMapWithNone, + realm + ); + + assertInternalIds(serializationInternalMapWithNone, 0); + Assert.deepEqual(serialized, serializedValue, "Got expected structure"); + + info(`Checking '${serialized.type}' with root ownershipType`); + const serializationInternalMapWithRoot = new Map(); + const serializedWithRoot = serialize( + value, + maxDepth, + "root", + serializationInternalMapWithRoot, + realm + ); + + assertInternalIds(serializationInternalMapWithRoot, 0); + Assert.equal( + typeof serializedWithRoot.handle, + "string", + "Got a handle property" + ); + Assert.deepEqual( + Object.assign({}, serialized, { handle: serializedWithRoot.handle }), + serializedWithRoot, + "Got expected structure, plus a generated handle id" + ); + } + + run_next_test(); +}); + +add_test(function test_serializeWithSerializationInternalMap() { + const dataSet = [ + { + data: [1], + serializedData: [{ type: "number", value: 1 }], + type: "array", + }, + { + data: new Map([[true, false]]), + serializedData: [ + [ + { type: "boolean", value: true }, + { type: "boolean", value: false }, + ], + ], + type: "map", + }, + { + data: new Set(["foo"]), + serializedData: [{ type: "string", value: "foo" }], + type: "set", + }, + { + data: { foo: "bar" }, + serializedData: [["foo", { type: "string", value: "bar" }]], + type: "object", + }, + ]; + const realm = new Realm(); + + for (const { type, data, serializedData } of dataSet) { + info(`Checking '${type}' with serializationInternalMap`); + + const serializationInternalMap = new Map(); + const value = [ + data, + data, + [data], + new Set([data]), + new Map([["bar", data]]), + { bar: data }, + ]; + + const serializedValue = serialize( + value, + 2, + "none", + serializationInternalMap, + realm + ); + + assertInternalIds(serializationInternalMap, 1); + + const internalId = serializationInternalMap.get(data).internalId; + + const serialized = { + type: "array", + value: [ + { + type, + value: serializedData, + internalId, + }, + { + type, + internalId, + }, + { + type: "array", + value: [{ type, internalId }], + }, + { + type: "set", + value: [{ type, internalId }], + }, + { + type: "map", + value: [["bar", { type, internalId }]], + }, + { + type: "object", + value: [["bar", { type, internalId }]], + }, + ], + }; + + Assert.deepEqual(serialized, serializedValue, "Got expected structure"); + } + + run_next_test(); +}); + +add_test(function test_serializeMultipleValuesWithSerializationInternalMap() { + const realm = new Realm(); + const serializationInternalMap = new Map(); + const obj1 = { foo: "bar" }; + const obj2 = [1, 2]; + const value = [obj1, obj2, obj1, obj2]; + + serialize(value, 2, "none", serializationInternalMap, realm); + + assertInternalIds(serializationInternalMap, 2); + + const internalId1 = serializationInternalMap.get(obj1).internalId; + const internalId2 = serializationInternalMap.get(obj2).internalId; + + Assert.notEqual( + internalId1, + internalId2, + "Internal ids for different object are also different" + ); + + run_next_test(); +}); + +add_test(function test_stringify() { + const STRINGIFY_TEST_CASES = [ + [undefined, "undefined"], + [null, "null"], + ["foobar", "foobar"], + ["2", "2"], + [-0, "0"], + [Infinity, "Infinity"], + [-Infinity, "-Infinity"], + [3, "3"], + [1.4, "1.4"], + [true, "true"], + [42n, "42"], + [{ toString: () => "bar" }, "bar", "toString: () => 'bar'"], + [{ toString: () => 4 }, "[object Object]", "toString: () => 4"], + [{ toString: undefined }, "[object Object]", "toString: undefined"], + [{ toString: null }, "[object Object]", "toString: null"], + [ + { + toString: () => { + throw new Error("toString error"); + }, + }, + "[object Object]", + "toString: () => { throw new Error('toString error'); }", + ], + ]; + + for (const [value, expectedString, description] of STRINGIFY_TEST_CASES) { + info(`Checking '${description || value}'`); + const stringifiedValue = stringify(value); + + Assert.strictEqual(expectedString, stringifiedValue, "Got expected string"); + } + + run_next_test(); +}); + +function assertLocalValue(type, value, expectedValue) { + let formattedValue = value; + let formattedExpectedValue = expectedValue; + + // Format certain types for easier assertion + if (type == "map") { + Assert.equal( + Object.prototype.toString.call(expectedValue), + "[object Map]", + "Got expected type Map" + ); + + formattedValue = Array.from(value.values()); + formattedExpectedValue = Array.from(expectedValue.values()); + } else if (type == "set") { + Assert.equal( + Object.prototype.toString.call(expectedValue), + "[object Set]", + "Got expected type Set" + ); + + formattedValue = Array.from(value); + formattedExpectedValue = Array.from(expectedValue); + } + + Assert.deepEqual( + formattedValue, + formattedExpectedValue, + "Got expected structure" + ); +} + +function assertInternalIds(serializationInternalMap, amount) { + const remoteValuesWithInternalIds = Array.from( + serializationInternalMap.values() + ).filter(remoteValue => !!remoteValue.internalId); + + Assert.equal( + remoteValuesWithInternalIds.length, + amount, + "Got expected amount of internalIds in serializationInternalMap" + ); +} diff --git a/remote/webdriver-bidi/test/xpcshell/test_WebDriverBiDiConnection.js b/remote/webdriver-bidi/test/xpcshell/test_WebDriverBiDiConnection.js new file mode 100644 index 0000000000..10b43e4ed6 --- /dev/null +++ b/remote/webdriver-bidi/test/xpcshell/test_WebDriverBiDiConnection.js @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { splitMethod } = ChromeUtils.importESModule( + "chrome://remote/content/webdriver-bidi/WebDriverBiDiConnection.sys.mjs" +); + +add_test(function test_Connection_splitMethod() { + for (const t of [42, null, true, {}, [], undefined]) { + Assert.throws(() => splitMethod(t), /TypeError/, `${typeof t} throws`); + } + for (const s of ["", ".", "foo.", ".bar", "foo.bar.baz"]) { + Assert.throws( + () => splitMethod(s), + /Invalid method format: '.*'/, + `"${s}" throws` + ); + } + deepEqual(splitMethod("foo.bar"), { + module: "foo", + command: "bar", + }); + + run_next_test(); +}); diff --git a/remote/webdriver-bidi/test/xpcshell/xpcshell.ini b/remote/webdriver-bidi/test/xpcshell/xpcshell.ini new file mode 100644 index 0000000000..8873ae646d --- /dev/null +++ b/remote/webdriver-bidi/test/xpcshell/xpcshell.ini @@ -0,0 +1,7 @@ +# 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/. + +[test_Realm.js] +[test_RemoteValue.js] +[test_WebDriverBiDiConnection.js] |