mirror of
https://github.com/servo/servo.git
synced 2025-06-24 00:54:32 +01:00
298 lines
10 KiB
HTML
298 lines
10 KiB
HTML
<!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
|
|
|
|
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>
|