diff options
Diffstat (limited to 'testing/web-platform/tests/dom/traversal/NodeIterator.html')
-rw-r--r-- | testing/web-platform/tests/dom/traversal/NodeIterator.html | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/testing/web-platform/tests/dom/traversal/NodeIterator.html b/testing/web-platform/tests/dom/traversal/NodeIterator.html new file mode 100644 index 0000000000..fb81676cc5 --- /dev/null +++ b/testing/web-platform/tests/dom/traversal/NodeIterator.html @@ -0,0 +1,215 @@ +<!doctype html> +<title>NodeIterator 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"; + +function check_iter(iter, root, whatToShowValue) { + whatToShowValue = whatToShowValue === undefined ? 0xFFFFFFFF : whatToShowValue; + + assert_equals(iter.toString(), '[object NodeIterator]', 'toString'); + assert_equals(iter.root, root, 'root'); + assert_equals(iter.whatToShow, whatToShowValue, 'whatToShow'); + assert_equals(iter.filter, null, 'filter'); + assert_equals(iter.referenceNode, root, 'referenceNode'); + assert_equals(iter.pointerBeforeReferenceNode, true, 'pointerBeforeReferenceNode'); + assert_readonly(iter, 'root'); + assert_readonly(iter, 'whatToShow'); + assert_readonly(iter, 'filter'); + assert_readonly(iter, 'referenceNode'); + assert_readonly(iter, 'pointerBeforeReferenceNode'); +} + +test(function() { + var iter = document.createNodeIterator(document); + iter.detach(); + iter.detach(); +}, "detach() should be a no-op"); + +test(function() { + var iter = document.createNodeIterator(document); + check_iter(iter, document); +}, "createNodeIterator() parameter defaults"); + +test(function() { + var iter = document.createNodeIterator(document, null, null); + check_iter(iter, document, 0); +}, "createNodeIterator() with null as arguments"); + +test(function() { + var iter = document.createNodeIterator(document, undefined, undefined); + check_iter(iter, document); +}, "createNodeIterator() with undefined as arguments"); + +test(function() { + var err = {name: "failed"}; + var iter = document.createNodeIterator(document, NodeFilter.SHOW_ALL, + function() { throw err; }); + assert_throws_exactly(err, function() { iter.nextNode() }); +}, "Propagate exception from filter function"); + +test(function() { + var depth = 0; + var iter = document.createNodeIterator(document, NodeFilter.SHOW_ALL, + function() { + if (iter.referenceNode != document && depth == 0) { + depth++; + iter.nextNode(); + } + return NodeFilter.FILTER_ACCEPT; + }); + iter.nextNode(); + iter.nextNode(); + assert_throws_dom("InvalidStateError", function() { iter.nextNode() }); + depth--; + assert_throws_dom("InvalidStateError", function() { iter.previousNode() }); +}, "Recursive filters need to throw"); + +function testIterator(root, whatToShow, filter) { + var iter = document.createNodeIterator(root, whatToShow, filter); + + assert_equals(iter.root, root, ".root"); + assert_equals(iter.referenceNode, root, "Initial .referenceNode"); + assert_equals(iter.pointerBeforeReferenceNode, true, + ".pointerBeforeReferenceNode"); + assert_equals(iter.whatToShow, whatToShow, ".whatToShow"); + assert_equals(iter.filter, filter, ".filter"); + + var expectedReferenceNode = root; + var expectedBeforeNode = true; + // "Let node be the value of the referenceNode attribute." + var node = root; + // "Let before node be the value of the pointerBeforeReferenceNode + // attribute." + var beforeNode = true; + var i = 1; + // Each loop iteration runs nextNode() once. + while (node) { + do { + if (!beforeNode) { + // "If before node is false, let node be the first node following node + // in the iterator collection. If there is no such node return null." + node = nextNode(node); + if (!isInclusiveDescendant(node, root)) { + node = null; + break; + } + } else { + // "If before node is true, set it to false." + beforeNode = false; + } + // "Filter node and let result be the return value. + // + // "If result is FILTER_ACCEPT, go to the next step in the overall set of + // steps. + // + // "Otherwise, run these substeps again." + if (!((1 << (node.nodeType - 1)) & whatToShow) + || (filter && filter(node) != NodeFilter.FILTER_ACCEPT)) { + continue; + } + + // "Set the referenceNode attribute to node, set the + // pointerBeforeReferenceNode attribute to before node, and return node." + expectedReferenceNode = node; + expectedBeforeNode = beforeNode; + + break; + } while (true); + + assert_equals(iter.nextNode(), node, ".nextNode() " + i + " time(s)"); + assert_equals(iter.referenceNode, expectedReferenceNode, + ".referenceNode after nextNode() " + i + " time(s)"); + assert_equals(iter.pointerBeforeReferenceNode, expectedBeforeNode, + ".pointerBeforeReferenceNode after nextNode() " + i + " time(s)"); + + i++; + } + + // Same but for previousNode() (mostly copy-pasted, oh well) + var iter = document.createNodeIterator(root, whatToShow, filter); + + var expectedReferenceNode = root; + var expectedBeforeNode = true; + // "Let node be the value of the referenceNode attribute." + var node = root; + // "Let before node be the value of the pointerBeforeReferenceNode + // attribute." + var beforeNode = true; + var i = 1; + // Each loop iteration runs previousNode() once. + while (node) { + do { + if (beforeNode) { + // "If before node is true, let node be the first node preceding node + // in the iterator collection. If there is no such node return null." + node = previousNode(node); + if (!isInclusiveDescendant(node, root)) { + node = null; + break; + } + } else { + // "If before node is false, set it to true." + beforeNode = true; + } + // "Filter node and let result be the return value. + // + // "If result is FILTER_ACCEPT, go to the next step in the overall set of + // steps. + // + // "Otherwise, run these substeps again." + if (!((1 << (node.nodeType - 1)) & whatToShow) + || (filter && filter(node) != NodeFilter.FILTER_ACCEPT)) { + continue; + } + + // "Set the referenceNode attribute to node, set the + // pointerBeforeReferenceNode attribute to before node, and return node." + expectedReferenceNode = node; + expectedBeforeNode = beforeNode; + + break; + } while (true); + + assert_equals(iter.previousNode(), node, ".previousNode() " + i + " time(s)"); + assert_equals(iter.referenceNode, expectedReferenceNode, + ".referenceNode after previousNode() " + i + " time(s)"); + assert_equals(iter.pointerBeforeReferenceNode, expectedBeforeNode, + ".pointerBeforeReferenceNode after previousNode() " + i + " time(s)"); + + i++; + } +} + +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] == '#' })", +]; + +for (var i = 0; i < testNodes.length; i++) { + for (var j = 0; j < whatToShows.length; j++) { + for (var k = 0; k < callbacks.length; k++) { + test(() => { + testIterator(eval(testNodes[i]), eval(whatToShows[j]), eval(callbacks[k])); + }, "document.createNodeIterator(" + testNodes[i] + ", " + whatToShows[j] + ", " + callbacks[k] + ")"); + } + } +} + +testDiv.style.display = "none"; +</script> |