diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /testing/web-platform/tests/dom/traversal/TreeWalker.html | |
parent | Initial commit. (diff) | |
download | firefox-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.html | 324 |
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> |