summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/dom/traversal/TreeWalker.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
commit0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch)
treea31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /testing/web-platform/tests/dom/traversal/TreeWalker.html
parentInitial commit. (diff)
downloadfirefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz
firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/dom/traversal/TreeWalker.html')
-rw-r--r--testing/web-platform/tests/dom/traversal/TreeWalker.html324
1 files changed, 324 insertions, 0 deletions
diff --git a/testing/web-platform/tests/dom/traversal/TreeWalker.html b/testing/web-platform/tests/dom/traversal/TreeWalker.html
new file mode 100644
index 0000000000..093c781447
--- /dev/null
+++ b/testing/web-platform/tests/dom/traversal/TreeWalker.html
@@ -0,0 +1,324 @@
+<!doctype html>
+<title>TreeWalker tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+// TODO .previousNode, .nextNode
+
+test(function() {
+ var depth = 0;
+ var walker = document.createTreeWalker(document, NodeFilter.SHOW_ALL,
+ function() {
+ if (depth == 0) {
+ depth++;
+ walker.firstChild();
+ }
+ return NodeFilter.FILTER_ACCEPT;
+ });
+ walker.currentNode = document.body;
+ assert_throws_dom("InvalidStateError", function() { walker.parentNode() });
+ depth--;
+ assert_throws_dom("InvalidStateError", function() { walker.firstChild() });
+ depth--;
+ assert_throws_dom("InvalidStateError", function() { walker.lastChild() });
+ depth--;
+ assert_throws_dom("InvalidStateError", function() { walker.previousSibling() });
+ depth--;
+ assert_throws_dom("InvalidStateError", function() { walker.nextSibling() });
+ depth--;
+ assert_throws_dom("InvalidStateError", function() { walker.previousNode() });
+ depth--;
+ assert_throws_dom("InvalidStateError", function() { walker.nextNode() });
+}, "Recursive filters need to throw");
+
+function filterNode(node, whatToShow, filter) {
+ // "If active flag is set throw an "InvalidStateError"."
+ // Ignore active flag for these tests, we aren't calling recursively
+ // TODO Test me
+
+ // "Let n be node's nodeType attribute value minus 1."
+ var n = node.nodeType - 1;
+
+ // "If the nth bit (where 0 is the least significant bit) of whatToShow is
+ // not set, return FILTER_SKIP."
+ if (!(whatToShow & (1 << n))) {
+ return NodeFilter.FILTER_SKIP;
+ }
+
+ // "If filter is null, return FILTER_ACCEPT."
+ if (!filter) {
+ return NodeFilter.FILTER_ACCEPT;
+ }
+
+ // "Set the active flag."
+ //
+ // "Let result be the return value of invoking filter."
+ //
+ // "Unset the active flag."
+ //
+ // "If an exception was thrown, re-throw the exception."
+ // TODO Test me
+ //
+ // "Return result."
+ return filter(node);
+}
+
+function testTraverseChildren(type, walker, root, whatToShow, filter) {
+ // TODO We don't test .currentNode other than the root
+ walker.currentNode = root;
+ assert_equals(walker.currentNode, root, "Setting .currentNode");
+
+ var expectedReturn = null;
+ var expectedCurrentNode = root;
+
+ // "To traverse children of type type, run these steps:
+ //
+ // "Let node be the value of the currentNode attribute."
+ var node = walker.currentNode;
+
+ // "Set node to node's first child if type is first, and node's last child
+ // if type is last."
+ node = type == "first" ? node.firstChild : node.lastChild;
+
+ // "Main: While node is not null, run these substeps:"
+ while (node) {
+ // "Filter node and let result be the return value."
+ var result = filterNode(node, whatToShow, filter);
+
+ // "If result is FILTER_ACCEPT, then set the currentNode attribute to
+ // node and return node."
+ if (result == NodeFilter.FILTER_ACCEPT) {
+ expectedCurrentNode = expectedReturn = node;
+ break;
+ }
+
+ // "If result is FILTER_SKIP, run these subsubsteps:"
+ if (result == NodeFilter.FILTER_SKIP) {
+ // "Let child be node's first child if type is first, and node's
+ // last child if type is last."
+ var child = type == "first" ? node.firstChild : node.lastChild;
+
+ // "If child is not null, set node to child and goto Main."
+ if (child) {
+ node = child;
+ continue;
+ }
+ }
+
+ // "While node is not null, run these subsubsteps:"
+ while (node) {
+ // "Let sibling be node's next sibling if type is first, and node's
+ // previous sibling if type is last."
+ var sibling = type == "first" ? node.nextSibling
+ : node.previousSibling;
+
+ // "If sibling is not null, set node to sibling and goto Main."
+ if (sibling) {
+ node = sibling;
+ break;
+ }
+
+ // "Let parent be node's parent."
+ var parent = node.parentNode;
+
+ // "If parent is null, parent is root, or parent is currentNode
+ // attribute's value, return null."
+ if (!parent || parent == root || parent == walker.currentNode) {
+ expectedReturn = node = null;
+ break;
+ } else {
+ // "Otherwise, set node to parent."
+ node = parent;
+ }
+ }
+ }
+
+ if (type == "first") {
+ assert_equals(walker.firstChild(), expectedReturn, ".firstChild()");
+ assert_equals(walker.currentNode, expectedCurrentNode,
+ ".currentNode after .firstChild()");
+ } else {
+ assert_equals(walker.lastChild(), expectedReturn, ".lastChild()");
+ assert_equals(walker.currentNode, expectedCurrentNode,
+ ".currentNode after .lastChild()");
+ }
+}
+
+function testTraverseSiblings(type, walker, root, whatToShow, filter) {
+ // TODO We don't test .currentNode other than the root's first or last child
+ if (!root.firstChild) {
+ // Nothing much to test
+
+ walker.currentNode = root;
+ assert_equals(walker.currentNode, root, "Setting .currentNode");
+
+ if (type == "next") {
+ assert_equals(walker.nextSibling(), null, ".nextSibling()");
+ assert_equals(walker.currentNode, root,
+ ".currentNode after .nextSibling()")
+ } else {
+ assert_equals(walker.previousSibling(), null, ".previousSibling()");
+ assert_equals(walker.currentNode, root,
+ ".currentNode after .previousSibling()")
+ }
+ return;
+ }
+
+ if (type == "next") {
+ walker.currentNode = root.firstChild;
+ assert_equals(walker.currentNode, root.firstChild,
+ "Setting .currentNode");
+ } else {
+ walker.currentNode = root.lastChild;
+ assert_equals(walker.currentNode, root.lastChild,
+ "Setting .currentNode");
+ }
+
+ var expectedReturn = null;
+ var expectedCurrentNode = type == "next" ? root.firstChild : root.lastChild;
+
+ // "To traverse siblings of type type run these steps:"
+ (function() {
+ // "Let node be the value of the currentNode attribute."
+ var node = type == "next" ? root.firstChild : root.lastChild;
+
+ // "If node is root, return null.
+ //
+ // "Run these substeps:
+ do {
+ // "Let sibling be node's next sibling if type is next, and node's
+ // previous sibling if type is previous."
+ var sibling = type == "next" ? node.nextSibling :
+ node.previousSibling;
+
+ // "While sibling is not null, run these subsubsteps:"
+ while (sibling) {
+ // "Set node to sibling."
+ node = sibling;
+
+ // "Filter node and let result be the return value."
+ var result = filterNode(node, whatToShow, filter);
+
+ // "If result is FILTER_ACCEPT, then set the currentNode
+ // attribute to node and return node."
+ if (result == NodeFilter.FILTER_ACCEPT) {
+ expectedCurrentNode = expectedReturn = node;
+ return;
+ }
+
+ // "Set sibling to node's first child if type is next, and
+ // node's last child if type is previous."
+ sibling = type == "next" ? node.firstChild : node.lastChild;
+
+ // "If result is FILTER_REJECT or sibling is null, then set
+ // sibling to node's next sibling if type is next, and node's
+ // previous sibling if type is previous."
+ if (result == NodeFilter.FILTER_REJECT || !sibling) {
+ sibling = type == "next" ? node.nextSibling :
+ node.previousSibling;
+ }
+ }
+
+ // "Set node to its parent."
+ node = node.parentNode;
+
+ // "If node is null or is root, return null.
+ if (!node || node == root) {
+ return;
+ }
+ // "Filter node and if the return value is FILTER_ACCEPT, then
+ // return null."
+ if (filterNode(node, whatToShow, filter)) {
+ return;
+ }
+
+ // "Run these substeps again."
+ } while (true);
+ })();
+
+ if (type == "next") {
+ assert_equals(walker.nextSibling(), expectedReturn, ".nextSibling()");
+ assert_equals(walker.currentNode, expectedCurrentNode,
+ ".currentNode after .nextSibling()");
+ } else {
+ assert_equals(walker.previousSibling(), expectedReturn, ".previousSibling()");
+ assert_equals(walker.currentNode, expectedCurrentNode,
+ ".currentNode after .previousSibling()");
+ }
+}
+
+function testWalker(root, whatToShow, filter) {
+ var walker = document.createTreeWalker(root, whatToShow, filter);
+
+ assert_equals(walker.root, root, ".root");
+ assert_equals(walker.whatToShow, whatToShow, ".whatToShow");
+ assert_equals(walker.filter, filter, ".filter");
+ assert_equals(walker.currentNode, root, ".currentNode");
+
+ var expectedReturn = null;
+ var expectedCurrentNode = walker.currentNode;
+ // "The parentNode() method must run these steps:"
+ //
+ // "Let node be the value of the currentNode attribute."
+ var node = walker.currentNode;
+
+ // "While node is not null and is not root, run these substeps:"
+ while (node && node != root) {
+ // "Let node be node's parent."
+ node = node.parentNode;
+
+ // "If node is not null and filtering node returns FILTER_ACCEPT, then
+ // set the currentNode attribute to node, return node."
+ if (node && filterNode(node, whatToShow, filter) ==
+ NodeFilter.FILTER_ACCEPT) {
+ expectedCurrentNode = expectedReturn = node;
+ }
+ }
+ assert_equals(walker.parentNode(), expectedReturn, ".parentNode()");
+ assert_equals(walker.currentNode, expectedCurrentNode,
+ ".currentNode after .parentNode()");
+
+ testTraverseChildren("first", walker, root, whatToShow, filter);
+ testTraverseChildren("last", walker, root, whatToShow, filter);
+
+ testTraverseSiblings("next", walker, root, whatToShow, filter);
+ testTraverseSiblings("previous", walker, root, whatToShow, filter);
+}
+
+var whatToShows = [
+ "0",
+ "0xFFFFFFFF",
+ "NodeFilter.SHOW_ELEMENT",
+ "NodeFilter.SHOW_ATTRIBUTE",
+ "NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT",
+];
+
+var callbacks = [
+ "null",
+ "(function(node) { return true })",
+ "(function(node) { return false })",
+ "(function(node) { return node.nodeName[0] == '#' })",
+];
+
+var tests = [];
+for (var i = 0; i < testNodes.length; i++) {
+ for (var j = 0; j < whatToShows.length; j++) {
+ for (var k = 0; k < callbacks.length; k++) {
+ tests.push([
+ "document.createTreeWalker(" + testNodes[i] +
+ ", " + whatToShows[j] + ", " + callbacks[k] + ")",
+ eval(testNodes[i]), eval(whatToShows[j]), eval(callbacks[k])
+ ]);
+ }
+ }
+}
+generate_tests(testWalker, tests);
+
+testDiv.style.display = "none";
+</script>