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 |