| OLD | NEW |
| (Empty) |
| 1 <!doctype html> | |
| 2 <title>TreeWalker tests</title> | |
| 3 <link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name> | |
| 4 <meta name=timeout content=long> | |
| 5 <div id=log></div> | |
| 6 <script src=../../../../resources/testharness.js></script> | |
| 7 <script src=../../../../resources/testharnessreport.js></script> | |
| 8 <script src=../common.js></script> | |
| 9 <script> | |
| 10 "use strict"; | |
| 11 | |
| 12 // TODO .previousNode, .nextNode | |
| 13 | |
| 14 function filterNode(node, whatToShow, filter) { | |
| 15 // "If active flag is set throw an "InvalidStateError"." | |
| 16 // Ignore active flag for these tests, we aren't calling recursively | |
| 17 // TODO Test me | |
| 18 | |
| 19 // "Let n be node's nodeType attribute value minus 1." | |
| 20 var n = node.nodeType - 1; | |
| 21 | |
| 22 // "If the nth bit (where 0 is the least significant bit) of whatToShow is | |
| 23 // not set, return FILTER_SKIP." | |
| 24 if (!(whatToShow & (1 << n))) { | |
| 25 return NodeFilter.FILTER_SKIP; | |
| 26 } | |
| 27 | |
| 28 // "If filter is null, return FILTER_ACCEPT." | |
| 29 if (!filter) { | |
| 30 return NodeFilter.FILTER_ACCEPT; | |
| 31 } | |
| 32 | |
| 33 // "Set the active flag." | |
| 34 // | |
| 35 // "Let result be the return value of invoking filter." | |
| 36 // | |
| 37 // "Unset the active flag." | |
| 38 // | |
| 39 // "If an exception was thrown, re-throw the exception." | |
| 40 // TODO Test me | |
| 41 // | |
| 42 // "Return result." | |
| 43 return filter(node); | |
| 44 } | |
| 45 | |
| 46 function testTraverseChildren(type, walker, root, whatToShow, filter) { | |
| 47 // TODO We don't test .currentNode other than the root | |
| 48 walker.currentNode = root; | |
| 49 assert_equals(walker.currentNode, root, "Setting .currentNode"); | |
| 50 | |
| 51 var expectedReturn = null; | |
| 52 var expectedCurrentNode = root; | |
| 53 | |
| 54 // "To traverse children of type type, run these steps: | |
| 55 // | |
| 56 // "Let node be the value of the currentNode attribute." | |
| 57 var node = walker.currentNode; | |
| 58 | |
| 59 // "Set node to node's first child if type is first, and node's last child | |
| 60 // if type is last." | |
| 61 node = type == "first" ? node.firstChild : node.lastChild; | |
| 62 | |
| 63 // "Main: While node is not null, run these substeps:" | |
| 64 while (node) { | |
| 65 // "Filter node and let result be the return value." | |
| 66 var result = filterNode(node, whatToShow, filter); | |
| 67 | |
| 68 // "If result is FILTER_ACCEPT, then set the currentNode attribute to | |
| 69 // node and return node." | |
| 70 if (result == NodeFilter.FILTER_ACCEPT) { | |
| 71 expectedCurrentNode = expectedReturn = node; | |
| 72 break; | |
| 73 } | |
| 74 | |
| 75 // "If result is FILTER_SKIP, run these subsubsteps:" | |
| 76 if (result == NodeFilter.FILTER_SKIP) { | |
| 77 // "Let child be node's first child if type is first, and node's | |
| 78 // last child if type is last." | |
| 79 var child = type == "first" ? node.firstChild : node.lastChild; | |
| 80 | |
| 81 // "If child is not null, set node to child and goto Main." | |
| 82 if (child) { | |
| 83 node = child; | |
| 84 continue; | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 // "While node is not null, run these subsubsteps:" | |
| 89 while (node) { | |
| 90 // "Let sibling be node's next sibling if type is first, and node's | |
| 91 // previous sibling if type is last." | |
| 92 var sibling = type == "first" ? node.nextSibling | |
| 93 : node.previousSibling; | |
| 94 | |
| 95 // "If sibling is not null, set node to sibling and goto Main." | |
| 96 if (sibling) { | |
| 97 node = sibling; | |
| 98 break; | |
| 99 } | |
| 100 | |
| 101 // "Let parent be node's parent." | |
| 102 var parent = node.parentNode; | |
| 103 | |
| 104 // "If parent is null, parent is root, or parent is currentNode | |
| 105 // attribute's value, return null." | |
| 106 if (!parent || parent == root || parent == walker.currentNode) { | |
| 107 expectedReturn = node = null; | |
| 108 break; | |
| 109 } else { | |
| 110 // "Otherwise, set node to parent." | |
| 111 node = parent; | |
| 112 } | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 if (type == "first") { | |
| 117 assert_equals(walker.firstChild(), expectedReturn, ".firstChild()"); | |
| 118 assert_equals(walker.currentNode, expectedCurrentNode, | |
| 119 ".currentNode after .firstChild()"); | |
| 120 } else { | |
| 121 assert_equals(walker.lastChild(), expectedReturn, ".lastChild()"); | |
| 122 assert_equals(walker.currentNode, expectedCurrentNode, | |
| 123 ".currentNode after .lastChild()"); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 function testTraverseSiblings(type, walker, root, whatToShow, filter) { | |
| 128 // TODO We don't test .currentNode other than the root's first or last child | |
| 129 if (!root.firstChild) { | |
| 130 // Nothing much to test | |
| 131 | |
| 132 walker.currentNode = root; | |
| 133 assert_equals(walker.currentNode, root, "Setting .currentNode"); | |
| 134 | |
| 135 if (type == "next") { | |
| 136 assert_equals(walker.nextSibling(), null, ".nextSibling()"); | |
| 137 assert_equals(walker.currentNode, root, | |
| 138 ".currentNode after .nextSibling()") | |
| 139 } else { | |
| 140 assert_equals(walker.previousSibling(), null, ".previousSibling()"); | |
| 141 assert_equals(walker.currentNode, root, | |
| 142 ".currentNode after .previousSibling()") | |
| 143 } | |
| 144 return; | |
| 145 } | |
| 146 | |
| 147 if (type == "next") { | |
| 148 walker.currentNode = root.firstChild; | |
| 149 assert_equals(walker.currentNode, root.firstChild, | |
| 150 "Setting .currentNode"); | |
| 151 } else { | |
| 152 walker.currentNode = root.lastChild; | |
| 153 assert_equals(walker.currentNode, root.lastChild, | |
| 154 "Setting .currentNode"); | |
| 155 } | |
| 156 | |
| 157 var expectedReturn = null; | |
| 158 var expectedCurrentNode = type == "next" ? root.firstChild : root.lastChild; | |
| 159 | |
| 160 // "To traverse siblings of type type run these steps:" | |
| 161 (function() { | |
| 162 // "Let node be the value of the currentNode attribute." | |
| 163 var node = type == "next" ? root.firstChild : root.lastChild; | |
| 164 | |
| 165 // "If node is root, return null. | |
| 166 // | |
| 167 // "Run these substeps: | |
| 168 do { | |
| 169 // "Let sibling be node's next sibling if type is next, and node's | |
| 170 // previous sibling if type is previous." | |
| 171 var sibling = type == "next" ? node.nextSibling : | |
| 172 node.previousSibling; | |
| 173 | |
| 174 // "While sibling is not null, run these subsubsteps:" | |
| 175 while (sibling) { | |
| 176 // "Set node to sibling." | |
| 177 node = sibling; | |
| 178 | |
| 179 // "Filter node and let result be the return value." | |
| 180 var result = filterNode(node, whatToShow, filter); | |
| 181 | |
| 182 // "If result is FILTER_ACCEPT, then set the currentNode | |
| 183 // attribute to node and return node." | |
| 184 if (result == NodeFilter.FILTER_ACCEPT) { | |
| 185 expectedCurrentNode = expectedReturn = node; | |
| 186 return; | |
| 187 } | |
| 188 | |
| 189 // "Set sibling to node's first child if type is next, and | |
| 190 // node's last child if type is previous." | |
| 191 sibling = type == "next" ? node.firstChild : node.lastChild; | |
| 192 | |
| 193 // "If result is FILTER_REJECT or sibling is null, then set | |
| 194 // sibling to node's next sibling if type is next, and node's | |
| 195 // previous sibling if type is previous." | |
| 196 if (result == NodeFilter.FILTER_REJECT || !sibling) { | |
| 197 sibling = type == "next" ? node.nextSibling : | |
| 198 node.previousSibling; | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 // "Set node to its parent." | |
| 203 node = node.parentNode; | |
| 204 | |
| 205 // "If node is null or is root, return null. | |
| 206 if (!node || node == root) { | |
| 207 return; | |
| 208 } | |
| 209 // "Filter node and if the return value is FILTER_ACCEPT, then | |
| 210 // return null." | |
| 211 if (filterNode(node, whatToShow, filter)) { | |
| 212 return; | |
| 213 } | |
| 214 | |
| 215 // "Run these substeps again." | |
| 216 } while (true); | |
| 217 })(); | |
| 218 | |
| 219 if (type == "next") { | |
| 220 assert_equals(walker.nextSibling(), expectedReturn, ".nextSibling()"); | |
| 221 assert_equals(walker.currentNode, expectedCurrentNode, | |
| 222 ".currentNode after .nextSibling()"); | |
| 223 } else { | |
| 224 assert_equals(walker.previousSibling(), expectedReturn, ".previousSiblin
g()"); | |
| 225 assert_equals(walker.currentNode, expectedCurrentNode, | |
| 226 ".currentNode after .previousSibling()"); | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 function testWalker(root, whatToShow, filter) { | |
| 231 var walker = document.createTreeWalker(root, whatToShow, filter); | |
| 232 | |
| 233 assert_equals(walker.root, root, ".root"); | |
| 234 assert_equals(walker.whatToShow, whatToShow, ".whatToShow"); | |
| 235 assert_equals(walker.filter, filter, ".filter"); | |
| 236 assert_equals(walker.currentNode, root, ".currentNode"); | |
| 237 | |
| 238 var expectedReturn = null; | |
| 239 var expectedCurrentNode = walker.currentNode; | |
| 240 // "The parentNode() method must run these steps:" | |
| 241 // | |
| 242 // "Let node be the value of the currentNode attribute." | |
| 243 var node = walker.currentNode; | |
| 244 | |
| 245 // "While node is not null and is not root, run these substeps:" | |
| 246 while (node && node != root) { | |
| 247 // "Let node be node's parent." | |
| 248 node = node.parentNode; | |
| 249 | |
| 250 // "If node is not null and filtering node returns FILTER_ACCEPT, then | |
| 251 // set the currentNode attribute to node, return node." | |
| 252 if (node && filterNode(node, whatToShow, filter) == | |
| 253 NodeFilter.FILTER_ACCEPT) { | |
| 254 expectedCurrentNode = expectedReturn = node; | |
| 255 } | |
| 256 } | |
| 257 assert_equals(walker.parentNode(), expectedReturn, ".parentNode()"); | |
| 258 assert_equals(walker.currentNode, expectedCurrentNode, | |
| 259 ".currentNode after .parentNode()"); | |
| 260 | |
| 261 testTraverseChildren("first", walker, root, whatToShow, filter); | |
| 262 testTraverseChildren("last", walker, root, whatToShow, filter); | |
| 263 | |
| 264 testTraverseSiblings("next", walker, root, whatToShow, filter); | |
| 265 testTraverseSiblings("previous", walker, root, whatToShow, filter); | |
| 266 } | |
| 267 | |
| 268 var whatToShows = [ | |
| 269 "0", | |
| 270 "0xFFFFFFFF", | |
| 271 "NodeFilter.SHOW_ELEMENT", | |
| 272 "NodeFilter.SHOW_ATTRIBUTE", | |
| 273 "NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT", | |
| 274 ]; | |
| 275 | |
| 276 var callbacks = [ | |
| 277 "null", | |
| 278 "(function(node) { return true })", | |
| 279 "(function(node) { return false })", | |
| 280 "(function(node) { return node.nodeName[0] == '#' })", | |
| 281 ]; | |
| 282 | |
| 283 var tests = []; | |
| 284 for (var i = 0; i < testNodes.length; i++) { | |
| 285 for (var j = 0; j < whatToShows.length; j++) { | |
| 286 for (var k = 0; k < callbacks.length; k++) { | |
| 287 tests.push([ | |
| 288 "document.createTreeWalker(" + testNodes[i] + | |
| 289 ", " + whatToShows[j] + ", " + callbacks[k] + ")", | |
| 290 eval(testNodes[i]), eval(whatToShows[j]), eval(callbacks[k]) | |
| 291 ]); | |
| 292 } | |
| 293 } | |
| 294 } | |
| 295 generate_tests(testWalker, tests); | |
| 296 | |
| 297 testDiv.style.display = "none"; | |
| 298 </script> | |
| OLD | NEW |