1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html.xpath;
16
17 import org.htmlunit.WebDriverTestCase;
18 import org.htmlunit.junit.BrowserRunner;
19 import org.htmlunit.junit.annotation.Alerts;
20 import org.junit.Test;
21 import org.junit.runner.RunWith;
22
23
24
25
26
27
28
29
30 @RunWith(BrowserRunner.class)
31 public class HtmlUnitXPath2Test extends WebDriverTestCase {
32
33
34
35
36 @Override
37 protected boolean isWebClientCached() {
38 return true;
39 }
40
41
42
43
44 @Test
45 @Alerts({"4", "null"})
46 public void xPathNull() throws Exception {
47 final String content = DOCTYPE_HTML
48 + "<html><head>\n"
49 + "<script>\n"
50 + LOG_TITLE_FUNCTION
51 + "function test() {\n"
52 + " try {\n"
53 + " var node = '';"
54 + " var expr = null;\n"
55 + " var result = document.evaluate(expr, document.documentElement, null, XPathResult.ANY_TYPE, null);\n"
56 + " node = result.iterateNext();\n"
57 + " log(result.resultType);\n"
58 + " log(node);\n"
59 + " } catch(e) { logEx(e) }\n"
60 + "}\n"
61 + "</script></head>\n"
62 + "<body onload='test()'>\n"
63 + " <select name='test'><option value='1'>foo and foo</option></select>\n"
64 + "</body></html>";
65
66 loadPageVerifyTitle2(content);
67 }
68
69
70
71
72 @Test
73 @Alerts({"4", "null"})
74 public void xPathUndefined() throws Exception {
75 final String content = DOCTYPE_HTML
76 + "<html><head>\n"
77 + "<script>\n"
78 + LOG_TITLE_FUNCTION
79 + "function test() {\n"
80 + " try {\n"
81 + " var node = '';"
82 + " var expr = undefined;\n"
83 + " var result = document.evaluate(expr, document.documentElement, null, XPathResult.ANY_TYPE, null);\n"
84 + " node = result.iterateNext();\n"
85 + " log(result.resultType);\n"
86 + " log(node);\n"
87 + " } catch(e) { logEx(e) }\n"
88 + "}\n"
89 + "</script></head>\n"
90 + "<body onload='test()'>\n"
91 + " <select name='test'><option value='1'>foo and foo</option></select>\n"
92 + "</body></html>";
93
94 loadPageVerifyTitle2(content);
95 }
96
97
98
99
100 @Test
101 @Alerts({"102", "111", "111", "160", "97", "110", "100", "160", "102", "111", "111"})
102 public void optionText() throws Exception {
103 final String content = DOCTYPE_HTML
104 + "<html><head>\n"
105 + "<script>\n"
106 + LOG_TITLE_FUNCTION
107 + "function test() {\n"
108 + " try {\n"
109 + " var expr = 'string(//option)';\n"
110 + " var result = document.evaluate(expr, document.documentElement, null, XPathResult.ANY_TYPE, null);\n"
111 + " var value = result.stringValue;\n"
112 + " for (var i = 0; i < value.length; i++) {\n"
113 + " log(value.charCodeAt(i));\n"
114 + " }\n"
115 + " } catch(e) { logEx(e) }\n"
116 + "}\n"
117 + "</script></head>\n"
118 + "<body onload='test()'>\n"
119 + " <select name='test'><option value='1'>foo and foo</option></select>\n"
120 + "</body></html>";
121
122 loadPageVerifyTitle2(content);
123 }
124
125
126
127
128 @Test
129 @Alerts("[object HTMLParagraphElement][object HTMLDivElement]")
130 public void pipe() throws Exception {
131 final String content = DOCTYPE_HTML
132 + "<html>\n"
133 + "<head>\n"
134 + "<script>\n"
135 + LOG_TITLE_FUNCTION
136 + "function test() {\n"
137 + " try {\n"
138 + " var res = '';"
139 + " var expr = '//p | //div';\n"
140 + " var result = document.evaluate(expr, document.documentElement, null, XPathResult.ANY_TYPE, null);\n"
141 + " while (node = result.iterateNext()) {\n"
142 + " res += node;\n"
143 + " }\n"
144 + " log(res);\n"
145 + " } catch(e) { logEx(e) }\n"
146 + "}\n"
147 + "</script></head>\n"
148 + "<body onload='test()'>\n"
149 + " <p></p>\n"
150 + " <div></div>\n"
151 + "</body></html>";
152
153 loadPageVerifyTitle2(content);
154 }
155
156
157
158
159 @Test
160 @Alerts("a")
161 public void math() throws Exception {
162 final String content = DOCTYPE_HTML
163 + "<html>\n"
164 + "<head>\n"
165 + "<script>\n"
166 + LOG_TITLE_FUNCTION
167 + "function test() {\n"
168 + " try {\n"
169 + " var res = '';"
170 + " var expr = '//p[position()=(1+5-(2*2))div 2]';\n"
171 + " var result = document.evaluate(expr, document.documentElement, null, XPathResult.ANY_TYPE, null);\n"
172 + " while (node = result.iterateNext()) {\n"
173 + " res += node.id;\n"
174 + " }\n"
175 + " log(res);\n"
176 + " } catch(e) { logEx(e) }\n"
177 + "}\n"
178 + "</script></head>\n"
179 + "<body onload='test()'>\n"
180 + " <div>\n"
181 + " <p id='a'></p>\n"
182 + " <p id='b'></p>\n"
183 + " </div>\n"
184 + "</body></html>";
185
186 loadPageVerifyTitle2(content);
187 }
188
189
190
191
192 @Test
193 @Alerts("b")
194 public void gt() throws Exception {
195 compare("//p[position()>1]");
196 }
197
198
199
200
201 @Test
202 @Alerts("ab")
203 public void gte() throws Exception {
204 compare("//p[position()>=1]");
205 }
206
207
208
209
210 @Test
211 @Alerts("a")
212 public void lt() throws Exception {
213 compare("//p[position()<2]");
214 }
215
216
217
218
219 @Test
220 @Alerts("ab")
221 public void lte() throws Exception {
222 compare("//p[position()<=2]");
223 }
224
225
226
227
228 @Test
229 @Alerts("b")
230 public void eq() throws Exception {
231 compare("//p[position()=2]");
232 }
233
234
235
236
237 @Test
238 @Alerts("b")
239 public void neq() throws Exception {
240 compare("//p[position()!=1]");
241 }
242
243
244
245
246 @Test
247 @Alerts("a")
248 public void and() throws Exception {
249 compare("//p[@x>= 0 and @y=7]");
250 }
251
252
253
254
255 @Test
256 @Alerts("ab")
257 public void or() throws Exception {
258 compare("//p[@x>= 0 or @y>4]");
259 }
260
261
262
263
264 @Test
265 @Alerts("ab")
266 public void mod() throws Exception {
267 compare("//p[@y mod 6 = 1]");
268 }
269
270
271
272
273 @Test
274 @Alerts("'adc'")
275 public void translate() throws Exception {
276 compareStringValue("translate(\"abc\", \"b\", \"d\")");
277 }
278
279
280
281
282 @Test
283 @Alerts("true")
284 public void trueTest() throws Exception {
285 compareBooleanValue("true()");
286 }
287
288
289
290
291 @Test
292 @Alerts("false")
293 public void falseTest() throws Exception {
294 compareBooleanValue("false()");
295 }
296
297
298
299
300 @Test
301 @Alerts("true")
302 public void booleanTest() throws Exception {
303 compareBooleanValue("boolean(7)");
304 }
305
306
307
308
309 @Test
310 @Alerts("false")
311 public void booleanTestFalse() throws Exception {
312 compareBooleanValue("boolean(0)");
313 }
314
315
316
317
318 @Test
319 @Alerts("b")
320 public void number() throws Exception {
321 compare("//p[@y=number(\" 13\t \")]");
322 }
323
324
325
326
327 @Test
328 @Alerts("false")
329 public void startsWith() throws Exception {
330 compareBooleanValue("starts-with(\"haystack\", \"needle\")");
331 }
332
333
334
335
336 @Test
337 @Alerts("true")
338 public void startsWithFound() throws Exception {
339 compareBooleanValue("starts-with(\"haystack\", \"hay\")");
340 }
341
342
343
344
345 @Test
346 @Alerts("true")
347 public void startsWithWhole() throws Exception {
348 compareBooleanValue("starts-with(\"haystack\", \"haystack\")");
349 }
350
351
352
353
354 @Test
355 @Alerts("true")
356 public void startsWithEmpty() throws Exception {
357 compareBooleanValue("starts-with(\"haystack\", \"\")");
358 }
359
360
361
362
363 @Test
364 @Alerts("true")
365 public void startsWithEmptyEmpty() throws Exception {
366 compareBooleanValue("starts-with(\"\", \"\")");
367 }
368
369
370
371
372 @Test
373 @Alerts("'tml'")
374 public void substring() throws Exception {
375 compareStringValue("substring(\"HtmlUnit\", 2, 3)");
376 }
377
378
379
380
381 @Test
382 @Alerts("''")
383 public void substringWithNegativeLength() throws Exception {
384 compareStringValue("substring(\"HtmlUnit\", 2, -1)");
385 }
386
387
388
389
390 @Test
391 @Alerts("''")
392 public void substringNegativeStartWithLength() throws Exception {
393 compareStringValue("substring(\"HtmlUnit\", -50, 20)");
394 }
395
396
397
398
399 @Test
400 @Alerts("'Unit'")
401 public void substringAfter() throws Exception {
402 compareStringValue("substring-after(\"HtmlUnit\", \"tml\")");
403 }
404
405
406
407
408 @Test
409 @Alerts("'Html'")
410 public void substringBefore() throws Exception {
411 compareStringValue("substring-before(\"HtmlUnit\", \"Uni\")");
412 }
413
414
415
416
417 @Test
418 @Alerts("false")
419 public void not() throws Exception {
420 compareBooleanValue("not(\"HtmlUnit\")");
421 }
422
423
424
425
426 @Test
427 @Alerts("a")
428 public void attrib() throws Exception {
429 compare("//p[@x=1]");
430 }
431
432
433
434
435 @Test
436 @Alerts("SyntaxError/DOMException")
437 public void lowerCaseNotSupported() throws Exception {
438 compareError("//*[lower-case(@id) = \"a\"]");
439 }
440
441
442
443
444 @Test
445 @Alerts("SyntaxError/DOMException")
446 public void upperCaseNotSupported() throws Exception {
447 compareError("//*[upper-case(@id) = \"A\"]");
448 }
449
450
451
452
453 @Test
454 @Alerts("SyntaxError/DOMException")
455 public void endsWithNotSupported() throws Exception {
456 compareError("ends-with(\"haystack\", \"haystack\")");
457 }
458
459 private void compare(final String xpath) throws Exception {
460 final String content = DOCTYPE_HTML
461 + "<html>\n"
462 + "<head>\n"
463 + "<script>\n"
464 + LOG_TITLE_FUNCTION
465 + "function test() {\n"
466 + " try {\n"
467 + " var res = '';\n"
468 + " var expr = '" + xpath + "';\n"
469 + " var result = document.evaluate(expr, document.documentElement, null, XPathResult.ANY_TYPE, null);\n"
470 + " while (node = result.iterateNext()) {\n"
471 + " res += node.id;\n"
472 + " }\n"
473 + " log(res);\n"
474 + " } catch(e) { logEx(e) }\n"
475 + "}\n"
476 + "</script></head>\n"
477 + "<body onload='test()'>\n"
478 + " <div>\n"
479 + " <p id='a' x='1' y='7'></p>\n"
480 + " <p id='b' y='13'></p>\n"
481 + " </div>\n"
482 + "</body></html>";
483
484 loadPageVerifyTitle2(content);
485 }
486
487 private void compareStringValue(final String xpath) throws Exception {
488 final String content = DOCTYPE_HTML
489 + "<html>\n"
490 + "<head>\n"
491 + "<script>\n"
492 + LOG_TITLE_FUNCTION
493 + "function test() {\n"
494 + " try {\n"
495 + " var res = '';\n"
496 + " var expr = '" + xpath + "';\n"
497 + " var result = document.evaluate(expr, document.documentElement, null, XPathResult.ANY_TYPE, null);\n"
498 + " log(\"'\" + result.stringValue + \"'\");\n"
499 + " } catch(e) { logEx(e) }\n"
500 + "}\n"
501 + "</script></head>\n"
502 + "<body onload='test()'>\n"
503 + " <div>\n"
504 + " <p id='a' x='1' y='7'></p>\n"
505 + " <p id='b' y='13'></p>\n"
506 + " </div>\n"
507 + "</body></html>";
508
509 loadPageVerifyTitle2(content);
510 }
511
512 private void compareBooleanValue(final String xpath) throws Exception {
513 final String content = DOCTYPE_HTML
514 + "<html>\n"
515 + "<head>\n"
516 + "<script>\n"
517 + LOG_TITLE_FUNCTION
518 + "function test() {\n"
519 + " try {\n"
520 + " var res = '';\n"
521 + " var expr = '" + xpath + "';\n"
522 + " var result = document.evaluate(expr, document.documentElement, null, XPathResult.ANY_TYPE, null);\n"
523 + " log(result.booleanValue);\n"
524 + " } catch(e) { logEx(e) }\n"
525 + "}\n"
526 + "</script></head>\n"
527 + "<body onload='test()'>\n"
528 + " <div>\n"
529 + " <p id='a' x='1' y='7'></p>\n"
530 + " <p id='b' y='13'></p>\n"
531 + " </div>\n"
532 + "</body></html>";
533
534 loadPageVerifyTitle2(content);
535 }
536
537 private void compareError(final String xpath) throws Exception {
538 final String content = DOCTYPE_HTML
539 + "<html>\n"
540 + "<head>\n"
541 + "<script>\n"
542 + LOG_TITLE_FUNCTION
543 + "function test() {\n"
544 + " try {\n"
545 + " var expr = '" + xpath + "';\n"
546 + " var result = document.evaluate(expr, document.documentElement, null, XPathResult.ANY_TYPE, null);\n"
547 + " log('error expected');\n"
548 + " } catch(e) { logEx(e) }\n"
549 + "}\n"
550 + "</script></head>\n"
551 + "<body onload='test()'>\n"
552 + "</body></html>";
553
554 loadPageVerifyTitle2(content);
555 }
556
557
558
559
560 @Test
561 @Alerts("mySpan")
562 public void minimalParameters() throws Exception {
563 final String content = DOCTYPE_HTML
564 + "<html>\n"
565 + "<head>\n"
566 + "<script>\n"
567 + LOG_TITLE_FUNCTION
568 + "function test() {\n"
569 + " try {\n"
570 + " var res = '';\n"
571 + " var result = document.evaluate('//span', document.documentElement);\n"
572 + " while (node = result.iterateNext()) {\n"
573 + " res += node.id;\n"
574 + " }\n"
575 + " log(res);\n"
576 + " } catch(e) { logEx(e) }\n"
577 + "}\n"
578 + "</script></head>\n"
579 + "<body onload='test()'>\n"
580 + " <div id='myDiv' attr='false'>false</span>\n"
581 + " <span id='mySpan' attr='true'>true</span>\n"
582 + "</body></html>";
583
584 loadPageVerifyTitle2(content);
585 }
586
587
588
589
590 @Test
591 @Alerts("mySpan")
592 public void undefinedResult() throws Exception {
593 final String content = DOCTYPE_HTML
594 + "<html>\n"
595 + "<head>\n"
596 + "<script>\n"
597 + LOG_TITLE_FUNCTION
598 + "function test() {\n"
599 + " try {\n"
600 + " var res = '';\n"
601 + " var result = document.evaluate('//span', "
602 + "document.documentElement, null, XPathResult.ANY_TYPE, undefined);\n"
603 + " while (node = result.iterateNext()) {\n"
604 + " res += node.id;\n"
605 + " }\n"
606 + " log(res);\n"
607 + " } catch(e) { logEx(e) }\n"
608 + "}\n"
609 + "</script></head>\n"
610 + "<body onload='test()'>\n"
611 + " <div id='myDiv' attr='false'>false</span>\n"
612 + " <span id='mySpan' attr='true'>true</span>\n"
613 + "</body></html>";
614
615 loadPageVerifyTitle2(content);
616 }
617
618
619
620
621 @Test
622 @Alerts("TypeError")
623 public void stringResult() throws Exception {
624 final String content = DOCTYPE_HTML
625 + "<html>\n"
626 + "<head>\n"
627 + "<script>\n"
628 + LOG_TITLE_FUNCTION
629 + "function test() {\n"
630 + " try {\n"
631 + " var res = '';\n"
632 + " var result = document.evaluate('//span', "
633 + "document.documentElement, null, XPathResult.ANY_TYPE, 'abcd');\n"
634 + " while (node = result.iterateNext()) {\n"
635 + " res += node.id;\n"
636 + " }\n"
637 + " log(res);\n"
638 + " } catch(e) { logEx(e) }\n"
639 + "}\n"
640 + "</script></head>\n"
641 + "<body onload='test()'>\n"
642 + " <div id='myDiv' attr='false'>false</span>\n"
643 + " <span id='mySpan' attr='true'>true</span>\n"
644 + "</body></html>";
645
646 loadPageVerifyTitle2(content);
647 }
648
649
650
651
652 @Test
653 @Alerts("mySpan")
654 public void objectResult() throws Exception {
655 final String content = DOCTYPE_HTML
656 + "<html>\n"
657 + "<head>\n"
658 + "<script>\n"
659 + LOG_TITLE_FUNCTION
660 + "function test() {\n"
661 + " try {\n"
662 + " var res = '';\n"
663 + " var result = document.evaluate('//span', "
664 + "document.documentElement, null, XPathResult.ANY_TYPE, {});\n"
665 + " while (node = result.iterateNext()) {\n"
666 + " res += node.id;\n"
667 + " }\n"
668 + " log(res);\n"
669 + " } catch(e) { logEx(e) }\n"
670 + "}\n"
671 + "</script></head>\n"
672 + "<body onload='test()'>\n"
673 + " <div id='myDiv' attr='false'>false</span>\n"
674 + " <span id='mySpan' attr='true'>true</span>\n"
675 + "</body></html>";
676
677 loadPageVerifyTitle2(content);
678 }
679
680
681
682
683 @Test
684 @Alerts(DEFAULT = "mySpan - - myDiv",
685 FF = "mySpan - myDiv - ",
686 FF_ESR = "mySpan - myDiv - ")
687 public void reuseResult() throws Exception {
688 final String content = DOCTYPE_HTML
689 + "<html>\n"
690 + "<head>\n"
691 + "<script>\n"
692 + LOG_TITLE_FUNCTION
693 + "function test() {\n"
694 + " try {\n"
695 + " var res = '';\n"
696 + " var result = document.evaluate('//span', "
697 + "document.documentElement, null, XPathResult.ANY_TYPE);\n"
698 + " while (node = result.iterateNext()) {\n"
699 + " res += node.id;\n"
700 + " }\n"
701 + " res += ' - ';\n"
702
703 + " var result2 = document.evaluate('//div', "
704 + "document.documentElement, null, XPathResult.ANY_TYPE, result);\n"
705 + " while (node = result.iterateNext()) {\n"
706 + " res += node.id;\n"
707 + " }\n"
708 + " res += ' - ';\n"
709
710 + " while (node = result2.iterateNext()) {\n"
711 + " res += node.id;\n"
712 + " }\n"
713
714 + " log(res);\n"
715 + " } catch(e) { logEx(e) }\n"
716 + "}\n"
717 + "</script></head>\n"
718 + "<body onload='test()'>\n"
719 + " <div id='myDiv' attr='false'>false</span>\n"
720 + " <span id='mySpan' attr='true'>true</span>\n"
721 + "</body></html>";
722
723 loadPageVerifyTitle2(content);
724 }
725
726
727
728
729 @Test
730 @Alerts("myDiv1")
731 public void documentEvaluateFirst() throws Exception {
732 final String content = DOCTYPE_HTML
733 + "<html>\n"
734 + "<head>\n"
735 + "<script>\n"
736 + LOG_TITLE_FUNCTION
737 + "function test() {\n"
738 + " try {\n"
739 + " var res = '';\n"
740 + " var result = document.evaluate('//div', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE);\n"
741 + " log(result.singleNodeValue.id);\n"
742 + " } catch(e) { logEx(e) }\n"
743 + "}\n"
744 + "</script></head>\n"
745 + "<body onload='test()'>\n"
746 + " <div id='myDiv1'>div1</div>\n"
747 + " <div id='myDiv2'>div1</div>\n"
748 + "</body></html>";
749
750 loadPageVerifyTitle2(content);
751 }
752 }