diff --git a/tests/wpt/dom/nodes/Element-closest.html b/tests/wpt/dom/nodes/Element-closest.html new file mode 100644 index 00000000..386e3bd2 --- /dev/null +++ b/tests/wpt/dom/nodes/Element-closest.html @@ -0,0 +1,73 @@ + + +Test for Element.closest + + + + +
+ diff --git a/tests/wpt/dom/nodes/Element-insertAdjacentElement.html b/tests/wpt/dom/nodes/Element-insertAdjacentElement.html new file mode 100644 index 00000000..9eafee6a --- /dev/null +++ b/tests/wpt/dom/nodes/Element-insertAdjacentElement.html @@ -0,0 +1,91 @@ + + + + + + +
+
+
+ + + + + diff --git a/tests/wpt/dom/nodes/Element-insertAdjacentText.html b/tests/wpt/dom/nodes/Element-insertAdjacentText.html new file mode 100644 index 00000000..be744fd4 --- /dev/null +++ b/tests/wpt/dom/nodes/Element-insertAdjacentText.html @@ -0,0 +1,76 @@ + + + + + + +
+
+
+ + diff --git a/tests/wpt/dom/nodes/Element-matches-init.js b/tests/wpt/dom/nodes/Element-matches-init.js new file mode 100644 index 00000000..254af615 --- /dev/null +++ b/tests/wpt/dom/nodes/Element-matches-init.js @@ -0,0 +1,65 @@ +function init(e, method) { + /* + * This test suite tests Selectors API methods in 4 different contexts: + * 1. Document node + * 2. In-document Element node + * 3. Detached Element node (an element with no parent, not in the document) + * 4. Document Fragment node + * + * For each context, the following tests are run: + * + * The interface check tests ensure that each type of node exposes the Selectors API methods. + * + * The matches() tests are run + * All the selectors tested for both the valid and invalid selector tests are found in selectors.js. + * See comments in that file for documentation of the format used. + * + * The level2-lib.js file contains all the common test functions for running each of the aforementioned tests + */ + + var docType = "html"; // Only run tests suitable for HTML + + // Prepare the nodes for testing + var doc = e.target.contentDocument; // Document Node tests + + var element = doc.getElementById("root"); // In-document Element Node tests + + //Setup the namespace tests + setupSpecialElements(doc, element); + + var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document + // Element tests, but after running the Document tests. This + // tests that no elements that are not descendants of element + // are selected. + + traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying + elem.setAttribute("data-clone", ""); // that none of these elements ever match. + }); + + + var detached = element.cloneNode(true); // Detached Element Node tests + + var fragment = doc.createDocumentFragment(); // Fragment Node tests + fragment.appendChild(element.cloneNode(true)); + + // Setup Tests + interfaceCheckMatches(method, "Document", doc); + interfaceCheckMatches(method, "Detached Element", detached); + interfaceCheckMatches(method, "Fragment", fragment); + interfaceCheckMatches(method, "In-document Element", element); + + runSpecialMatchesTests(method, "DIV Element", element); + runSpecialMatchesTests(method, "NULL Element", document.createElement("null")); + runSpecialMatchesTests(method, "UNDEFINED Element", document.createElement("undefined")); + + runInvalidSelectorTestMatches(method, "Document", doc, invalidSelectors); + runInvalidSelectorTestMatches(method, "Detached Element", detached, invalidSelectors); + runInvalidSelectorTestMatches(method, "Fragment", fragment, invalidSelectors); + runInvalidSelectorTestMatches(method, "In-document Element", element, invalidSelectors); + + runMatchesTest(method, "In-document", doc, validSelectors, "html"); + runMatchesTest(method, "Detached", detached, validSelectors, "html"); + runMatchesTest(method, "Fragment", fragment, validSelectors, "html"); + + runMatchesTest(method, "In-document", doc, scopedSelectors, "html"); +} diff --git a/tests/wpt/dom/nodes/Element-matches-namespaced-elements.html b/tests/wpt/dom/nodes/Element-matches-namespaced-elements.html new file mode 100644 index 00000000..e61b11ca --- /dev/null +++ b/tests/wpt/dom/nodes/Element-matches-namespaced-elements.html @@ -0,0 +1,24 @@ + + +matches/webkitMatchesSelector must work when an element has a namespace + + + + + diff --git a/tests/wpt/dom/nodes/Element-matches.html b/tests/wpt/dom/nodes/Element-matches.html new file mode 100644 index 00000000..de234b66 --- /dev/null +++ b/tests/wpt/dom/nodes/Element-matches.html @@ -0,0 +1,22 @@ + + +Selectors-API Level 2 Test Suite: HTML with Selectors Level 3 + + + + + + + + + +
This test requires JavaScript.
+ + diff --git a/tests/wpt/dom/nodes/Element-matches.js b/tests/wpt/dom/nodes/Element-matches.js new file mode 100644 index 00000000..a1455c67 --- /dev/null +++ b/tests/wpt/dom/nodes/Element-matches.js @@ -0,0 +1,135 @@ +/* + * Check that the matches() method exists on the given Node + */ +function interfaceCheckMatches(method, type, obj) { + if (obj.nodeType === obj.ELEMENT_NODE) { + test(function() { + assert_idl_attribute(obj, method, type + " supports " + method); + }, type + " supports " + method) + } else { + test(function() { + assert_false(method in obj, type + " supports " + method); + }, type + " should not support " + method) + } +} + +function runSpecialMatchesTests(method, type, element) { + test(function() { // 1 + if (element.tagName.toLowerCase() === "null") { + assert_true(element[method](null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match."); + } else { + assert_false(element[method](null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match."); + } + }, type + "." + method + "(null)") + + test(function() { // 2 + if (element.tagName.toLowerCase() === "undefined") { + assert_true(element[method](undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match."); + } else { + assert_false(element[method](undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match."); + } + }, type + "." + method + "(undefined)") + + test(function() { // 3 + assert_throws_js(element.ownerDocument.defaultView.TypeError, function() { + element[method](); + }, "This should throw a TypeError.") + }, type + "." + method + " no parameter") +} + +/* + * Execute queries with the specified invalid selectors for matches() + * Only run these tests when errors are expected. Don't run for valid selector tests. + */ +function runInvalidSelectorTestMatches(method, type, root, selectors) { + if (root.nodeType === root.ELEMENT_NODE) { + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + + test(function() { + assert_throws_dom( + "SyntaxError", + root.ownerDocument.defaultView.DOMException, + function() { + root[method](q) + } + ); + }, type + "." + method + ": " + n + ": " + q); + } + } +} + +function runMatchesTest(method, type, root, selectors, docType) { + var nodeType = getNodeType(root); + + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + var e = s["expect"]; + var u = s["unexpected"]; + + var ctx = s["ctx"]; + var ref = s["ref"]; + + if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) + && (s["testType"] & TEST_MATCH) ) { + + if (ctx && !ref) { + test(function() { + var j, element, refNode; + for (j = 0; j < e.length; j++) { + element = root.querySelector("#" + e[j]); + refNode = root.querySelector(ctx); + assert_true(element[method](q, refNode), "The element #" + e[j] + " should match the selector.") + } + + if (u) { + for (j = 0; j < u.length; j++) { + element = root.querySelector("#" + u[j]); + refNode = root.querySelector(ctx); + assert_false(element[method](q, refNode), "The element #" + u[j] + " should not match the selector.") + } + } + }, type + " Element." + method + ": " + n + " (with refNode Element): " + q); + } + + if (ref) { + test(function() { + var j, element, refNodes; + for (j = 0; j < e.length; j++) { + element = root.querySelector("#" + e[j]); + refNodes = root.querySelectorAll(ref); + assert_true(element[method](q, refNodes), "The element #" + e[j] + " should match the selector.") + } + + if (u) { + for (j = 0; j < u.length; j++) { + element = root.querySelector("#" + u[j]); + refNodes = root.querySelectorAll(ref); + assert_false(element[method](q, refNodes), "The element #" + u[j] + " should not match the selector.") + } + } + }, type + " Element." + method + ": " + n + " (with refNodes NodeList): " + q); + } + + if (!ctx && !ref) { + test(function() { + for (var j = 0; j < e.length; j++) { + var element = root.querySelector("#" + e[j]); + assert_true(element[method](q), "The element #" + e[j] + " should match the selector.") + } + + if (u) { + for (j = 0; j < u.length; j++) { + element = root.querySelector("#" + u[j]); + assert_false(element[method](q), "The element #" + u[j] + " should not match the selector.") + } + } + }, type + " Element." + method + ": " + n + " (with no refNodes): " + q); + } + } + } +} diff --git a/tests/wpt/dom/nodes/Element-remove.html b/tests/wpt/dom/nodes/Element-remove.html new file mode 100644 index 00000000..ab642d66 --- /dev/null +++ b/tests/wpt/dom/nodes/Element-remove.html @@ -0,0 +1,16 @@ + + +Element.remove + + + + +
+ diff --git a/tests/wpt/dom/nodes/Element-siblingElement-null-svg.svg b/tests/wpt/dom/nodes/Element-siblingElement-null-svg.svg new file mode 100644 index 00000000..48c981b8 --- /dev/null +++ b/tests/wpt/dom/nodes/Element-siblingElement-null-svg.svg @@ -0,0 +1,20 @@ + + +Null test + + + +Test of previousElementSibling and nextElementSibling returning null +The result of this test is unknown. + + +test(function() { + var fec = document.getElementById("first_element_child"); + assert_equals(fec.previousElementSibling, null) + assert_equals(fec.nextElementSibling, null) +}) + + diff --git a/tests/wpt/dom/nodes/Element-siblingElement-null-xhtml.xhtml b/tests/wpt/dom/nodes/Element-siblingElement-null-xhtml.xhtml new file mode 100644 index 00000000..fcf4d54f --- /dev/null +++ b/tests/wpt/dom/nodes/Element-siblingElement-null-xhtml.xhtml @@ -0,0 +1,20 @@ + + + +Null Test + + + + +

Test of previousElementSibling and nextElementSibling returning null

+
+

The result of this test is unknown.

+ + + diff --git a/tests/wpt/dom/nodes/Element-siblingElement-null.html b/tests/wpt/dom/nodes/Element-siblingElement-null.html new file mode 100644 index 00000000..a7920b4f --- /dev/null +++ b/tests/wpt/dom/nodes/Element-siblingElement-null.html @@ -0,0 +1,16 @@ + + +Null test + + +

Test of previousElementSibling and nextElementSibling returning null

+
+

The result of this test is unknown.

+ + diff --git a/tests/wpt/dom/nodes/Element-tagName.html b/tests/wpt/dom/nodes/Element-tagName.html new file mode 100644 index 00000000..43e7a2d2 --- /dev/null +++ b/tests/wpt/dom/nodes/Element-tagName.html @@ -0,0 +1,57 @@ + +Element.tagName + + +
+ diff --git a/tests/wpt/dom/nodes/Element-webkitMatchesSelector.html b/tests/wpt/dom/nodes/Element-webkitMatchesSelector.html new file mode 100644 index 00000000..107f8102 --- /dev/null +++ b/tests/wpt/dom/nodes/Element-webkitMatchesSelector.html @@ -0,0 +1,22 @@ + + +Selectors-API Level 2 Test Suite: HTML with Selectors Level 3 + + + + + + + + + +
This test requires JavaScript.
+ + diff --git a/tests/wpt/dom/nodes/NodeList-Iterable.html b/tests/wpt/dom/nodes/NodeList-Iterable.html new file mode 100644 index 00000000..fcbee175 --- /dev/null +++ b/tests/wpt/dom/nodes/NodeList-Iterable.html @@ -0,0 +1,61 @@ + + +NodeList Iterable Test + + +

+

+

+

+

+ +
123
+ diff --git a/tests/wpt/dom/nodes/NodeList-live-mutations.window.js b/tests/wpt/dom/nodes/NodeList-live-mutations.window.js new file mode 100644 index 00000000..a11fed1e --- /dev/null +++ b/tests/wpt/dom/nodes/NodeList-live-mutations.window.js @@ -0,0 +1,79 @@ +function testNodeList(name, hooks) { + test(() => { + const nodes = { + root: document.createElement("div"), + div1: document.createElement("div"), + div2: document.createElement("div"), + p: document.createElement("p") + }; + + const list = nodes.root.childNodes; + + hooks.initial(list, nodes); + + nodes.root.appendChild(nodes.div1); + nodes.root.appendChild(nodes.p); + nodes.root.appendChild(nodes.div2); + + hooks.afterInsertion(list, nodes); + + nodes.root.removeChild(nodes.div1); + + hooks.afterRemoval(list, nodes); + }, `NodeList live mutations: ${name}`); +} + +testNodeList("NodeList.length", { + initial(list) { + assert_equals(list.length, 0); + }, + afterInsertion(list) { + assert_equals(list.length, 3); + }, + afterRemoval(list) { + assert_equals(list.length, 2); + } +}); + +testNodeList("NodeList.item(index)", { + initial(list) { + assert_equals(list.item(0), null); + }, + afterInsertion(list, nodes) { + assert_equals(list.item(0), nodes.div1); + assert_equals(list.item(1), nodes.p); + assert_equals(list.item(2), nodes.div2); + }, + afterRemoval(list, nodes) { + assert_equals(list.item(0), nodes.p); + assert_equals(list.item(1), nodes.div2); + } +}); + +testNodeList("NodeList[index]", { + initial(list) { + assert_equals(list[0], undefined); + }, + afterInsertion(list, nodes) { + assert_equals(list[0], nodes.div1); + assert_equals(list[1], nodes.p); + assert_equals(list[2], nodes.div2); + }, + afterRemoval(list, nodes) { + assert_equals(list[0], nodes.p); + assert_equals(list[1], nodes.div2); + } +}); + +testNodeList("NodeList ownPropertyNames", { + initial(list) { + assert_object_equals(Object.getOwnPropertyNames(list), []); + }, + afterInsertion(list) { + assert_object_equals(Object.getOwnPropertyNames(list), ["0", "1", "2"]); + }, + afterRemoval(list) { + assert_object_equals(Object.getOwnPropertyNames(list), ["0", "1"]); + } +}); + diff --git a/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-1.html b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-1.html new file mode 100644 index 00000000..c5c58f9d --- /dev/null +++ b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-1.html @@ -0,0 +1,22 @@ + + + +NodeList (static collection) "length" getter tampered + + + + + + + diff --git a/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-2.html b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-2.html new file mode 100644 index 00000000..bac05112 --- /dev/null +++ b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-2.html @@ -0,0 +1,22 @@ + + + +NodeList (static collection) "length" getter tampered + + + + + + + diff --git a/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-3.html b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-3.html new file mode 100644 index 00000000..9690aab3 --- /dev/null +++ b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-3.html @@ -0,0 +1,22 @@ + + + +NodeList (static collection) "length" getter tampered + + + + + + + diff --git a/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-1.html b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-1.html new file mode 100644 index 00000000..5ce41467 --- /dev/null +++ b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-1.html @@ -0,0 +1,22 @@ + + + +NodeList (static collection) "length" getter tampered (Array.prototype.indexOf) + + + + + + + diff --git a/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-2.html b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-2.html new file mode 100644 index 00000000..57814ed5 --- /dev/null +++ b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-2.html @@ -0,0 +1,22 @@ + + + +NodeList (static collection) "length" getter tampered (Array.prototype.indexOf) + + + + + + + diff --git a/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-3.html b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-3.html new file mode 100644 index 00000000..838f376d --- /dev/null +++ b/tests/wpt/dom/nodes/NodeList-static-length-getter-tampered-indexOf-3.html @@ -0,0 +1,22 @@ + + + +NodeList (static collection) "length" getter tampered (Array.prototype.indexOf) + + + + + + + diff --git a/tests/wpt/dom/nodes/support/NodeList-static-length-tampered.js b/tests/wpt/dom/nodes/support/NodeList-static-length-tampered.js new file mode 100644 index 00000000..51167e2d --- /dev/null +++ b/tests/wpt/dom/nodes/support/NodeList-static-length-tampered.js @@ -0,0 +1,46 @@ +"use strict"; + +function makeStaticNodeList(length) { + const fooRoot = document.createElement("div"); + + for (var i = 0; i < length; i++) { + const el = document.createElement("span"); + el.className = "foo"; + fooRoot.append(el); + } + + document.body.append(fooRoot); + return fooRoot.querySelectorAll(".foo"); +} + +const indexOfNodeList = new Function("nodeList", ` + const __cacheBust = ${Math.random()}; + + const el = nodeList[50]; + + let index = -1; + + for (var i = 0; i < 1e5 / 2; i++) { + for (var j = 0; j < nodeList.length; j++) { + if (nodeList[j] === el) { + index = j; + break; + } + } + } + + return index; +`); + +const arrayIndexOfNodeList = new Function("nodeList", ` + const __cacheBust = ${Math.random()}; + + const el = nodeList[50]; + const {indexOf} = Array.prototype; + + for (var i = 0; i < 1e5; i++) { + var index = indexOf.call(nodeList, el); + } + + return index; +`);