1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.dom;
16
17 import org.htmlunit.WebDriverTestCase;
18 import org.htmlunit.junit.annotation.Alerts;
19 import org.junit.jupiter.api.Test;
20
21
22
23
24
25
26
27
28 public class TreeWalkerTest extends WebDriverTestCase {
29 private static final String CONTENT_START = DOCTYPE_HTML
30 + "<html><head><title></title>\n"
31 + "<script>\n"
32 + LOG_TITLE_FUNCTION
33 + "function safeTagName(o) {\n"
34 + " return o ? o.tagName : undefined\n"
35 + "}\n"
36 + "function alertTreeWalker(tw) {\n"
37 + " log(safeTagName(tw.root));\n"
38 + " log(safeTagName(tw.currentNode));\n"
39 + " log(tw.whatToShow);\n"
40 + " log(tw.expandEntityReferences);\n"
41 + "}\n"
42 + "function test() {\n"
43 + " try {\n";
44
45 private static final String CONTENT_END = "\n } catch(e) { logEx(e) }\n"
46 + "\n}\n</script></head>\n"
47 + "<body onload='test()'>\n"
48 + "<div id='theDiv'>Hello, <span id='theSpan'>this is a test for"
49 + "<a id='theA' href='http://htmlunit.sf.net'>HtmlUnit</a> support"
50 + "</div>\n"
51 + "<p id='theP'>for TreeWalker's</p>\n"
52 + "</body></html>";
53
54 private void test(final String script) throws Exception {
55 final String html = CONTENT_START + script + CONTENT_END;
56
57 loadPageVerifyTitle2(html);
58 }
59
60 private static final String CONTENT_START2 =
61 "<html><head><title></title>\n"
62 + "<script>\n"
63 + LOG_TITLE_FUNCTION
64 + "function safeTagName(o) {\n"
65 + " return o ? o.tagName : undefined\n"
66 + "}\n"
67 + "function test() {\n"
68 + " try {\n";
69
70 private static final String CONTENT_END2 = "\n } catch(e) { logEx(e) }\n"
71 + "\n}\n</script></head>\n"
72 + "<body onload='test()'>\n"
73 + "<div id='theDiv'>Hello, <span id='theSpan'>this is a test for"
74 + "<a id='theA' href='http://htmlunit.sf.net'>HtmlUnit</a> support"
75 + "</div>\n"
76 + "<p id='theP'>for <br/>TreeWalkers<span>something</span>that is <a>important to me</a></p>\n"
77 + "<span>something <code>codey</code>goes <pre> here</pre></span>\n"
78 + "</body></html>";
79
80 private void test2(final String script) throws Exception {
81 final String html = CONTENT_START2 + script + CONTENT_END2;
82
83 loadPageVerifyTitle2(html);
84 }
85
86
87
88
89 @Test
90 @Alerts({"BODY", "BODY", "1", "undefined"})
91 public void getters1() throws Exception {
92 final String script = "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, false);"
93 + "alertTreeWalker(tw);";
94
95 test(script);
96 }
97
98
99
100
101 @Test
102 @Alerts({"A", "A", "4294967295", "undefined"})
103
104 public void getters2() throws Exception {
105 final String script = "var theA = document.getElementById('theA');\n"
106 + "var tw = document.createTreeWalker(theA, NodeFilter.SHOW_ALL, null, true);\n"
107 + "alertTreeWalker(tw);\n";
108
109 test(script);
110 }
111
112
113
114
115 @Test
116 @Alerts({"BODY", "DIV", "1", "undefined"})
117 public void firstChild() throws Exception {
118 final String script =
119 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
120 + "tw.firstChild();\n"
121 + "alertTreeWalker(tw);\n";
122
123 test(script);
124 }
125
126
127
128
129 @Test
130 @Alerts({"BODY", "SPAN", "1", "undefined"})
131 public void firstChild2() throws Exception {
132 final String script =
133 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
134 + "tw.currentNode = document.getElementById('theDiv');\n"
135 + "tw.firstChild();\n"
136 + "alertTreeWalker(tw);\n";
137
138 test(script);
139 }
140
141
142
143
144 @Test
145 @Alerts({"BODY", "P", "1", "undefined"})
146 public void lastChild() throws Exception {
147 final String script =
148 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
149 + "tw.lastChild();\n"
150 + "alertTreeWalker(tw);\n";
151
152 test(script);
153 }
154
155
156
157
158 @Test
159 @Alerts({"BODY", "SPAN", "1", "undefined"})
160 public void lastChild2() throws Exception {
161 final String script =
162 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
163 + "tw.currentNode = document.getElementById('theDiv');\n"
164 + "tw.lastChild();\n"
165 + "alertTreeWalker(tw);\n";
166
167 test(script);
168 }
169
170
171
172
173 @Test
174 @Alerts({"BODY", "BODY", "1", "undefined", "null"})
175 public void parentNode() throws Exception {
176 final String script =
177 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
178 + "tw.currentNode = document.getElementById('theDiv');\n"
179 + "tw.parentNode();\n"
180 + "alertTreeWalker(tw);\n"
181 + "log(tw.parentNode());";
182
183 test(script);
184 }
185
186
187
188
189 @Test
190 @Alerts({"BODY", "DIV", "1", "undefined"})
191 public void parentNode2() throws Exception {
192 final String script =
193 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
194 + "tw.currentNode = document.getElementById('theSpan');\n"
195 + "tw.parentNode();\n"
196 + "alertTreeWalker(tw);";
197
198 test(script);
199 }
200
201
202
203
204 @Test
205 @Alerts({"BODY", "P", "1", "undefined", "null"})
206 public void siblings() throws Exception {
207 final String script =
208 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
209 + "tw.currentNode = document.getElementById('theDiv');\n"
210 + "tw.nextSibling();\n"
211 + "alertTreeWalker(tw);\n"
212 + "log(tw.nextSibling());\n";
213
214 test(script);
215 }
216
217
218
219
220 @Test
221 @Alerts({"BODY", "DIV", "1", "undefined", "null"})
222 public void siblings2() throws Exception {
223 final String script1 =
224 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
225 + "tw.currentNode = document.getElementById('theP');\n"
226 + "tw.previousSibling();\n"
227 + "alertTreeWalker(tw);\n"
228 + "log(tw.previousSibling());\n";
229
230 test(script1);
231 }
232
233
234
235
236 @Test
237 @Alerts({"BODY", "DIV", "SPAN", "A", "P", "undefined", "P"})
238 public void next() throws Exception {
239 final String script =
240 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
241 + "log(safeTagName(tw.currentNode));\n"
242 + "log(safeTagName(tw.nextNode()));\n"
243 + "log(safeTagName(tw.nextNode()));\n"
244 + "log(safeTagName(tw.nextNode()));\n"
245 + "log(safeTagName(tw.nextNode()));\n"
246 + "log(safeTagName(tw.nextNode()));\n"
247 + "log(safeTagName(tw.currentNode));\n";
248
249 test(script);
250 }
251
252
253
254
255 @Test
256 @Alerts({"P", "A", "SPAN", "DIV", "BODY", "undefined", "BODY"})
257 public void previous() throws Exception {
258 final String script =
259 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
260 + "tw.currentNode = document.getElementById('theP');\n"
261 + "log(safeTagName(tw.currentNode));\n"
262 + "log(safeTagName(tw.previousNode()));\n"
263 + "log(safeTagName(tw.previousNode()));\n"
264 + "log(safeTagName(tw.previousNode()));\n"
265 + "log(safeTagName(tw.previousNode()));\n"
266 + "log(safeTagName(tw.previousNode()));\n"
267 + "log(safeTagName(tw.currentNode));\n";
268
269 test(script);
270 }
271
272
273
274
275 @Test
276 @Alerts({"DIV", "SPAN", "A", "undefined", "P", "BODY", "undefined", "SPAN", "undefined",
277 "P", "SPAN", "CODE", "PRE", "undefined"})
278 public void walking() throws Exception {
279 final String script = "var tw = document.createTreeWalker(document.body, 1, null, true);\n"
280 + "log(safeTagName(tw.firstChild()));\n"
281 + "log(safeTagName(tw.firstChild()));\n"
282 + "log(safeTagName(tw.lastChild()));\n"
283 + "log(safeTagName(tw.lastChild()));\n"
284 + "log(safeTagName(tw.nextNode()));\n"
285 + "log(safeTagName(tw.parentNode()));\n"
286 + "log(safeTagName(tw.parentNode()));\n"
287 + "log(safeTagName(tw.lastChild()));\n"
288 + "log(safeTagName(tw.nextSibling()));\n"
289 + "log(safeTagName(tw.previousSibling()));\n"
290 + "log(safeTagName(tw.nextSibling()));\n"
291 + "log(safeTagName(tw.nextNode()));\n"
292 + "log(safeTagName(tw.nextNode()));\n"
293 + "log(safeTagName(tw.nextNode()));\n";
294
295 test2(script);
296 }
297
298
299
300
301 @Test
302 @Alerts({"TITLE", "SCRIPT", "HEAD", "HTML", "HEAD", "BODY", "undefined"})
303 public void walkingOutsideTheRoot() throws Exception {
304 final String script =
305 "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, null, true);\n"
306 + "tw.currentNode = document.firstChild.firstChild;\n"
307 + "log(safeTagName(tw.firstChild()));\n"
308 + "log(safeTagName(tw.nextNode()));\n"
309 + "log(safeTagName(tw.parentNode()));\n"
310 + "log(safeTagName(tw.previousNode()));\n"
311 + "log(safeTagName(tw.firstChild()));\n"
312 + "log(safeTagName(tw.nextSibling()));\n"
313 + "log(safeTagName(tw.previousSibling()));\n";
314
315 test2(script);
316 }
317
318
319
320
321 @Test
322 @Alerts("TypeError")
323 public void nullRoot() throws Exception {
324 final String script = "try {\n"
325 + "var tw = document.createTreeWalker(null, NodeFilter.SHOW_ELEMENT, null, true);\n"
326 + "} catch(e) { logEx(e); }\n";
327
328 test2(script);
329 }
330
331
332
333
334 @Test
335 @Alerts({"TITLE", "undefined", "HEAD", "HTML", "HEAD", "BODY", "undefined"})
336 public void simpleFilter() throws Exception {
337 final String script = "var noScripts = {\n"
338 + " acceptNode: function(node) {\n"
339 + " if (node.tagName == 'SCRIPT')\n"
340 + " return NodeFilter.FILTER_REJECT;\n"
341
342 + " return 1; // NodeFilter.FILTER_ACCEPT \n"
343 + " }\n"
344 + "}\n"
345 + "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, noScripts, true);\n"
346 + "tw.currentNode = document.firstChild.firstChild;\n"
347 + "log(safeTagName(tw.firstChild()));\n"
348 + "log(safeTagName(tw.nextSibling()));\n"
349 + "log(safeTagName(tw.parentNode()));\n"
350 + "log(safeTagName(tw.previousNode()));\n"
351 + "log(safeTagName(tw.firstChild()));\n"
352 + "log(safeTagName(tw.nextSibling()));\n"
353 + "log(safeTagName(tw.previousSibling()));\n";
354
355 test2(script);
356 }
357
358
359
360
361 @Test
362 @Alerts({"TITLE", "undefined", "HEAD", "HTML", "HEAD", "BODY", "undefined"})
363 public void simpleFilter_asAFunction() throws Exception {
364 final String script = "var noScripts = function(node) {\n"
365 + " if (node.tagName == 'SCRIPT')\n"
366 + " return NodeFilter.FILTER_REJECT;\n"
367 + " return 1;\n"
368 + "}\n"
369 + "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, noScripts, true);\n"
370 + "tw.currentNode = document.firstChild.firstChild;\n"
371 + "log(safeTagName(tw.firstChild()));\n"
372 + "log(safeTagName(tw.nextSibling()));\n"
373 + "log(safeTagName(tw.parentNode()));\n"
374 + "log(safeTagName(tw.previousNode()));\n"
375 + "log(safeTagName(tw.firstChild()));\n"
376 + "log(safeTagName(tw.nextSibling()));\n"
377 + "log(safeTagName(tw.previousSibling()));\n";
378
379 test2(script);
380 }
381
382
383
384
385 @Test
386 @Alerts("TypeError")
387 public void emptyFilter() throws Exception {
388 final String script = "try {\n"
389 + "var tw = document.createTreeWalker(null, NodeFilter.SHOW_ELEMENT, {}, true);\n"
390 + "} catch(e) { logEx(e); }\n";
391
392 test2(script);
393 }
394
395
396
397
398 @Test
399 @Alerts({"P", "undefined"})
400 public void secondFilterReject() throws Exception {
401 final String script = ""
402 + "var noScripts = {\n"
403 + " acceptNode: function(node) {\n"
404 + " if (node.tagName == 'SPAN' || node.tagName == 'DIV') {\n"
405 + " return NodeFilter.FILTER_REJECT;\n"
406 + " }\n"
407 + " return NodeFilter.FILTER_ACCEPT;\n"
408 + " }\n"
409 + "}\n"
410 + "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, noScripts, true);\n"
411 + "log(safeTagName(tw.firstChild()));\n"
412 + "log(safeTagName(tw.nextSibling()));\n";
413
414 test2(script);
415 }
416
417
418
419
420 @Test
421 @Alerts({"A", "P", "CODE", "PRE", "undefined"})
422 public void secondFilterSkip() throws Exception {
423 final String script = "var noScripts = {acceptNode: function(node) {if (node.tagName == 'SPAN' ||"
424 + "node.tagName == 'DIV') return NodeFilter.FILTER_SKIP;"
425 + "return NodeFilter.FILTER_ACCEPT}};\n"
426 + "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, noScripts, true);\n"
427 + "log(safeTagName(tw.firstChild()));\n"
428 + "log(safeTagName(tw.nextSibling()));\n"
429 + "log(safeTagName(tw.nextSibling()));\n"
430 + "log(safeTagName(tw.nextSibling()));\n"
431 + "log(safeTagName(tw.nextSibling()));\n";
432
433 test2(script);
434 }
435
436
437
438
439 @Test
440 @Alerts({"P", "undefined"})
441 public void secondFilterRejectReverse() throws Exception {
442 final String script = "var noScripts = {acceptNode: function(node) {if (node.tagName == 'SPAN' ||"
443 + "node.tagName == 'DIV') return NodeFilter.FILTER_REJECT;"
444 + "return NodeFilter.FILTER_ACCEPT}};\n"
445 + "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, noScripts, true);\n"
446 + "log(safeTagName(tw.lastChild()));\n"
447 + "log(safeTagName(tw.previousSibling()));\n";
448
449 test2(script);
450 }
451
452
453
454
455 @Test
456 @Alerts({"PRE", "CODE", "P", "A", "undefined"})
457 public void secondFilterSkipReverse() throws Exception {
458 final String script = "var noScripts = {acceptNode: function(node) {if (node.tagName == 'SPAN' ||"
459 + "node.tagName == 'DIV') return NodeFilter.FILTER_SKIP; return NodeFilter.FILTER_ACCEPT}};\n"
460 + "var tw = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, noScripts, true);\n"
461 + "log(safeTagName(tw.lastChild()));\n"
462 + "log(safeTagName(tw.previousSibling()));\n"
463 + "log(safeTagName(tw.previousSibling()));\n"
464 + "log(safeTagName(tw.previousSibling()));\n"
465 + "log(safeTagName(tw.previousSibling()));";
466
467 test2(script);
468 }
469 }