1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.css;
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 public class CSSSelector3Test extends WebDriverTestCase {
28
29
30
31
32 @Test
33 @Alerts({"6", "[object HTMLBodyElement]", "[object HTMLLIElement]", "[object HTMLScriptElement]",
34 "5", "[object HTMLBodyElement]", "[object HTMLScriptElement]",
35 "5", "[object HTMLBodyElement]", "[object HTMLScriptElement]"})
36 public void notElement() throws Exception {
37 final String html = DOCTYPE_HTML
38 + "<html>\n"
39 + "<head><title></title></head>\n"
40 + "<body>\n"
41 + "<ul>\n"
42 + " <li>ul - item 0</li>\n"
43 + "</ul>\n"
44
45 + "<script>\n"
46 + LOG_TITLE_FUNCTION
47 + " try {\n"
48 + " let items = document.querySelectorAll(':not(ul)');"
49 + " log(items.length);\n"
50 + " log(items[3]);\n"
51 + " log(items[4]);\n"
52 + " log(items[5]);\n"
53
54 + " items = document.querySelectorAll(':not(ul, li)');"
55 + " log(items.length);\n"
56 + " log(items[3]);\n"
57 + " log(items[4]);\n"
58
59 + " items = document.querySelectorAll(':not(ul):not(li)');"
60 + " log(items.length);\n"
61 + " log(items[3]);\n"
62 + " log(items[4]);\n"
63 + " } catch (e) { logEx(e); }\n"
64 + "</script>\n"
65
66 + "</body></html>";
67
68 loadPageVerifyTitle2(html);
69 }
70
71
72
73
74 @Test
75 @Alerts("0")
76 public void notStar() throws Exception {
77 final String html = DOCTYPE_HTML
78 + "<html>\n"
79 + "<head><title></title></head>\n"
80 + "<body>\n"
81 + "<ul>\n"
82 + " <li>ul - item 0</li>\n"
83 + "</ul>\n"
84
85 + "<script>\n"
86 + LOG_TITLE_FUNCTION
87 + " try {\n"
88 + " let items = document.querySelectorAll(':not(*)');"
89 + " log(items.length);\n"
90 + " } catch (e) { logEx(e); }\n"
91 + "</script>\n"
92
93 + "</body></html>";
94
95 loadPageVerifyTitle2(html);
96 }
97
98
99
100
101 @Test
102 @Alerts({"1", "[object HTMLUListElement]"})
103 public void notId() throws Exception {
104 final String html = DOCTYPE_HTML
105 + "<html>\n"
106 + "<head><title></title></head>\n"
107 + "<body>\n"
108 + "<ul id='foo'>\n"
109 + " <li>ul - item 0</li>\n"
110 + "</ul>\n"
111
112 + "<script>\n"
113 + LOG_TITLE_FUNCTION
114 + " try {\n"
115 + " let items = document.querySelectorAll('#foo:not(#bar)');"
116 + " log(items.length);\n"
117 + " log(items[0]);\n"
118 + " } catch (e) { logEx(e); }\n"
119 + "</script>\n"
120
121 + "</body></html>";
122
123 loadPageVerifyTitle2(html);
124 }
125
126
127
128
129 @Test
130 @Alerts({"1", "<a>my</a>", "0"})
131 public void notTable() throws Exception {
132 final String html = DOCTYPE_HTML
133 + "<html>\n"
134 + "<head><title></title></head>\n"
135 + "<body>\n"
136 + "<table>\n"
137 + " <tr><td><a>my</a></td></tr>\n"
138 + "</table>\n"
139
140 + "<script>\n"
141 + LOG_TITLE_FUNCTION
142 + " try {\n"
143 + " let items = document.querySelectorAll('body :not(table) a');"
144 + " log(items.length);\n"
145 + " log(items[0].outerHTML);\n"
146
147 + " items = document.querySelectorAll('body a:not(table a)');"
148 + " log(items.length);\n"
149 + " } catch (e) { logEx(e); }\n"
150 + "</script>\n"
151
152 + "</body></html>";
153
154 loadPageVerifyTitle2(html);
155 }
156
157
158
159
160 @Test
161 @Alerts("SyntaxError/DOMException")
162 public void notDoubleColon() throws Exception {
163 final String html = DOCTYPE_HTML
164 + "<html>\n"
165 + "<head><title></title></head>\n"
166 + "<body>\n"
167 + "<ul>\n"
168 + " <li>ul - item 0</li>\n"
169 + "</ul>\n"
170
171 + "<script>\n"
172 + LOG_TITLE_FUNCTION
173 + " try {\n"
174 + " let items = document.querySelectorAll('::not(ul)');"
175 + " } catch (e) { logEx(e); }\n"
176 + "</script>\n"
177
178 + "</body></html>";
179
180 loadPageVerifyTitle2(html);
181 }
182
183
184
185
186 @Test
187 @Alerts({"1", "[object HTMLUListElement]",
188 "2", "[object HTMLUListElement]", "[object HTMLOListElement]"})
189 public void isElement() throws Exception {
190 final String html = DOCTYPE_HTML
191 + "<html>\n"
192 + "<head></head>\n"
193 + "<body>\n"
194 + "<ul>\n"
195 + " <li>ul - item 0</li>\n"
196 + " <li>ul - item 1</li>\n"
197 + "</ul>\n"
198 + "<ol>\n"
199 + " <li>ol - item 0</li>\n"
200 + " <li>ol - item 1</li>\n"
201 + "</ol>\n"
202
203 + "<script>\n"
204 + LOG_TITLE_FUNCTION
205 + " try {\n"
206 + " let items = document.querySelectorAll(':is(ul)');"
207 + " log(items.length);\n"
208 + " log(items[0]);\n"
209
210 + " items = document.querySelectorAll(':is(ul, ol)');"
211 + " log(items.length);\n"
212 + " log(items[0]);\n"
213 + " log(items[1]);\n"
214 + " } catch (e) { logEx(e); }\n"
215 + "</script>\n"
216
217 + "</body></html>";
218
219 loadPageVerifyTitle2(html);
220 }
221
222
223
224
225 @Test
226 @Alerts({"2", "ul - item 1", "ol - item 1"})
227 public void isAttribute() throws Exception {
228 final String html = DOCTYPE_HTML
229 + "<html>\n"
230 + "<head></head>\n"
231 + "<body>\n"
232 + "<ul>\n"
233 + " <li name='i0'>ul - item 0</li>\n"
234 + " <li name='i1'>ul - item 1</li>\n"
235 + "</ul>\n"
236 + "<ol>\n"
237 + " <li name='i7'>ol - item 0</li>\n"
238 + " <li name='i2'>ol - item 1</li>\n"
239 + "</ol>\n"
240
241 + "<script>\n"
242 + LOG_TITLE_FUNCTION
243 + " try {\n"
244 + " let items = document.querySelectorAll(\":is([name='i1'], [name='i2'])\");"
245 + " log(items.length);\n"
246 + " log(items[0].innerText);\n"
247 + " log(items[1].innerText);\n"
248 + " } catch (e) { logEx(e); }\n"
249 + "</script>\n"
250
251 + "</body></html>";
252
253 loadPageVerifyTitle2(html);
254 }
255
256
257
258
259 @Test
260 @Alerts({"4", "ul - item 0 ul - item 1", "ul - item 1",
261 "ol - item 0 ol - item 1", "ol - item 1"})
262 public void isDuplicates() throws Exception {
263 final String html = DOCTYPE_HTML
264 + "<html>\n"
265 + "<head></head>\n"
266 + "<body>\n"
267 + "<ul>\n"
268 + " <li name='i0'>ul - item 0</li>\n"
269 + " <li name='i1'>ul - item 1</li>\n"
270 + "</ul>\n"
271 + "<ol name='i1'>\n"
272 + " <li name='i7'>ol - item 0</li>\n"
273 + " <li name='i2'>ol - item 1</li>\n"
274 + "</ol>\n"
275
276 + "<script>\n"
277 + LOG_TITLE_FUNCTION
278 + " try {\n"
279 + " let items = document.querySelectorAll(\":is(ul, [name='i1'], [name='i2'])\");"
280 + " log(items.length);\n"
281 + " log(items[0].innerText);\n"
282 + " log(items[1].innerText);\n"
283 + " log(items[2].innerText);\n"
284 + " log(items[3].innerText);\n"
285 + " } catch (e) { logEx(e); }\n"
286 + "</script>\n"
287
288 + "</body></html>";
289
290 loadPageVerifyTitle2(html);
291 }
292
293
294
295
296 @Test
297 @Alerts("SyntaxError/DOMException")
298 public void isDoubleColon() throws Exception {
299 final String html = DOCTYPE_HTML
300 + "<html>\n"
301 + "<head><title></title></head>\n"
302 + "<body>\n"
303 + "<ul>\n"
304 + " <li>ul - item 0</li>\n"
305 + "</ul>\n"
306
307 + "<script>\n"
308 + LOG_TITLE_FUNCTION
309 + " try {\n"
310 + " let items = document.querySelectorAll('::is(ul)');"
311 + " } catch (e) { logEx(e); }\n"
312 + "</script>\n"
313
314 + "</body></html>";
315
316 loadPageVerifyTitle2(html);
317 }
318
319
320
321
322 @Test
323 @Alerts({"1", "[object HTMLUListElement]",
324 "2", "[object HTMLUListElement]", "[object HTMLOListElement]"})
325 public void whereElement() throws Exception {
326 final String html = DOCTYPE_HTML
327 + "<html>\n"
328 + "<head></head>\n"
329 + "<body>\n"
330 + "<ul>\n"
331 + " <li>ul - item 0</li>\n"
332 + " <li>ul - item 1</li>\n"
333 + "</ul>\n"
334 + "<ol>\n"
335 + " <li>ol - item 0</li>\n"
336 + " <li>ol - item 1</li>\n"
337 + "</ol>\n"
338
339 + "<script>\n"
340 + LOG_TITLE_FUNCTION
341 + " try {\n"
342 + " let items = document.querySelectorAll(':where(ul)');"
343 + " log(items.length);\n"
344 + " log(items[0]);\n"
345
346 + " items = document.querySelectorAll(':where(ul, ol)');"
347 + " log(items.length);\n"
348 + " log(items[0]);\n"
349 + " log(items[1]);\n"
350 + " } catch (e) { logEx(e); }\n"
351 + "</script>\n"
352
353 + "</body></html>";
354
355 loadPageVerifyTitle2(html);
356 }
357
358
359
360
361 @Test
362 @Alerts({"2", "ul - item 1", "ol - item 1"})
363 public void whereAttribute() throws Exception {
364 final String html = DOCTYPE_HTML
365 + "<html>\n"
366 + "<head></head>\n"
367 + "<body>\n"
368 + "<ul>\n"
369 + " <li name='i0'>ul - item 0</li>\n"
370 + " <li name='i1'>ul - item 1</li>\n"
371 + "</ul>\n"
372 + "<ol>\n"
373 + " <li name='i7'>ol - item 0</li>\n"
374 + " <li name='i2'>ol - item 1</li>\n"
375 + "</ol>\n"
376
377 + "<script>\n"
378 + LOG_TITLE_FUNCTION
379 + " try {\n"
380 + " let items = document.querySelectorAll(\":where([name='i1'], [name='i2'])\");"
381 + " log(items.length);\n"
382 + " log(items[0].innerText);\n"
383 + " log(items[1].innerText);\n"
384 + " } catch (e) { logEx(e); }\n"
385 + "</script>\n"
386
387 + "</body></html>";
388
389 loadPageVerifyTitle2(html);
390 }
391
392
393
394
395 @Test
396 @Alerts({"4", "ul - item 0 ul - item 1", "ul - item 1",
397 "ol - item 0 ol - item 1", "ol - item 1"})
398 public void whereDuplicates() throws Exception {
399 final String html = DOCTYPE_HTML
400 + "<html>\n"
401 + "<head></head>\n"
402 + "<body>\n"
403 + "<ul>\n"
404 + " <li name='i0'>ul - item 0</li>\n"
405 + " <li name='i1'>ul - item 1</li>\n"
406 + "</ul>\n"
407 + "<ol name='i1'>\n"
408 + " <li name='i7'>ol - item 0</li>\n"
409 + " <li name='i2'>ol - item 1</li>\n"
410 + "</ol>\n"
411
412 + "<script>\n"
413 + LOG_TITLE_FUNCTION
414 + " try {\n"
415 + " let items = document.querySelectorAll(\":where(ul, [name='i1'], [name='i2'])\");"
416 + " log(items.length);\n"
417 + " log(items[0].innerText);\n"
418 + " log(items[1].innerText);\n"
419 + " log(items[2].innerText);\n"
420 + " log(items[3].innerText);\n"
421 + " } catch (e) { logEx(e); }\n"
422 + "</script>\n"
423
424 + "</body></html>";
425
426 loadPageVerifyTitle2(html);
427 }
428
429
430
431
432 @Test
433 @Alerts("SyntaxError/DOMException")
434 public void whereDoubleColon() throws Exception {
435 final String html = DOCTYPE_HTML
436 + "<html>\n"
437 + "<head><title></title></head>\n"
438 + "<body>\n"
439 + "<ul>\n"
440 + " <li>ul - item 0</li>\n"
441 + "</ul>\n"
442
443 + "<script>\n"
444 + LOG_TITLE_FUNCTION
445 + " try {\n"
446 + " let items = document.querySelectorAll('::where(ul)');"
447 + " } catch (e) { logEx(e); }\n"
448 + "</script>\n"
449
450 + "</body></html>";
451
452 loadPageVerifyTitle2(html);
453 }
454
455
456
457
458 @Test
459 @Alerts({"1", "SECTION / a0 a1"})
460 public void hasDescandant() throws Exception {
461 final String html = DOCTYPE_HTML
462 + "<html>\n"
463 + "<head></head>\n"
464 + "<body>\n"
465 + "<section>\n"
466 + " <article class='featured'>a0</article>\n"
467 + " <article>a1</article>\n"
468 + "</section>\n"
469 + "<section>\n"
470 + " <article>a2</article>\r\n"
471 + "</section>\n"
472
473 + "<script>\n"
474 + LOG_TITLE_FUNCTION
475 + " try {\n"
476 + " let items = document.querySelectorAll(\"section:has(.featured)\");"
477 + " log(items.length);\n"
478 + " log(items[0].tagName + ' / ' + items[0].innerText);\n"
479 + " } catch (e) { logEx(e); }\n"
480 + "</script>\n"
481
482 + "</body></html>";
483
484 loadPageVerifyTitle2(html);
485 }
486
487
488
489
490 @Test
491 @Alerts({"1", "SECTION / a0 a1"})
492 public void hasDescandantDeep() throws Exception {
493 final String html = DOCTYPE_HTML
494 + "<html>\n"
495 + "<head></head>\n"
496 + "<body>\n"
497 + "<section>\n"
498 + " <div>\n"
499 + " <article class='featured'>a0</article>\n"
500 + " <article>a1</article>\n"
501 + " </div>\n"
502 + "</section>\n"
503
504 + "<script>\n"
505 + LOG_TITLE_FUNCTION
506 + " try {\n"
507 + " let items = document.querySelectorAll(\"section:has(.featured)\");"
508 + " log(items.length);\n"
509 + " log(items[0].tagName + ' / ' + items[0].innerText);\n"
510 + " } catch (e) { logEx(e); }\n"
511 + "</script>\n"
512
513 + "</body></html>";
514
515 loadPageVerifyTitle2(html);
516 }
517
518
519
520
521 @Test
522 @Alerts({"1", "SECTION / a0 a1"})
523 public void hasChild() throws Exception {
524 final String html = DOCTYPE_HTML
525 + "<html>\n"
526 + "<head></head>\n"
527 + "<body>\n"
528 + "<section>\n"
529 + " <article class='featured'>a0</article>\n"
530 + " <article>a1</article>\n"
531 + "</section>\n"
532 + "<section>\n"
533 + " <article>a2</article>\r\n"
534 + "</section>\n"
535
536 + "<script>\n"
537 + LOG_TITLE_FUNCTION
538 + " try {\n"
539 + " let items = document.querySelectorAll(\"section:has(> .featured)\");"
540 + " log(items.length);\n"
541 + " log(items[0].tagName + ' / ' + items[0].innerText);\n"
542 + " } catch (e) { logEx(e); }\n"
543 + "</script>\n"
544
545 + "</body></html>";
546
547 loadPageVerifyTitle2(html);
548 }
549
550
551
552
553 @Test
554 @Alerts("0")
555 public void hasChildDeep() throws Exception {
556 final String html = DOCTYPE_HTML
557 + "<html>\n"
558 + "<head></head>\n"
559 + "<body>\n"
560 + "<section>\n"
561 + " <div>\n"
562 + " <article class='featured'>a0</article>\n"
563 + " <article>a1</article>\n"
564 + " </div>\n"
565 + "</section>\n"
566
567 + "<script>\n"
568 + LOG_TITLE_FUNCTION
569 + " try {\n"
570 + " let items = document.querySelectorAll(\"section:has(> .featured)\");"
571 + " log(items.length);\n"
572 + " } catch (e) { logEx(e); }\n"
573 + "</script>\n"
574
575 + "</body></html>";
576
577 loadPageVerifyTitle2(html);
578 }
579
580
581
582
583 @Test
584 @Alerts({"1", "H1 / h1 1"})
585 public void hasNextSiblingCombinator() throws Exception {
586 final String html = DOCTYPE_HTML
587 + "<html>\n"
588 + "<head></head>\n"
589 + "<body>\n"
590 + "<section>\n"
591 + " <article>\n"
592 + " <h1>h1 0</h1>\n"
593 + " <p>p0</p>\n"
594 + " </article>\n"
595 + " <article>\n"
596 + " <h1>h1 1</h1>\n"
597 + " <h2>h2 0</h2>\n"
598 + " <p>p1</p>\n"
599 + " </article>\n"
600 + " <article>\n"
601 + " <h1>h1 2</h1>\n"
602 + " <p>p2</p>\n"
603 + " <h2>h2 1</h2>\n"
604 + " </article>\n"
605 + "</section>\n"
606 + "<section>\n"
607 + " <article>a2</article>\r\n"
608 + "</section>\n"
609
610 + "<script>\n"
611 + LOG_TITLE_FUNCTION
612 + " try {\n"
613 + " let items = document.querySelectorAll(\"h1:has(+ h2)\");"
614 + " log(items.length);\n"
615 + " log(items[0].tagName + ' / ' + items[0].innerText);\n"
616 + " } catch (e) { logEx(e); }\n"
617 + "</script>\n"
618
619 + "</body></html>";
620
621 loadPageVerifyTitle2(html);
622 }
623
624
625
626
627 @Test
628 @Alerts({"2", "H1 / h1 1", "H1 / h1 2"})
629 public void hasSubsequentSiblingCombinator() throws Exception {
630 final String html = DOCTYPE_HTML
631 + "<html>\n"
632 + "<head></head>\n"
633 + "<body>\n"
634 + "<section>\n"
635 + " <article>\n"
636 + " <h1>h1 0</h1>\n"
637 + " <p>p0</p>\n"
638 + " </article>\n"
639 + " <article>\n"
640 + " <h1>h1 1</h1>\n"
641 + " <h2>h2 0</h2>\n"
642 + " <p>p1</p>\n"
643 + " </article>\n"
644 + " <article>\n"
645 + " <h1>h1 2</h1>\n"
646 + " <p>p2</p>\n"
647 + " <h2>h2 1</h2>\n"
648 + " </article>\n"
649 + "</section>\n"
650 + "<section>\n"
651 + " <article>a2</article>\r\n"
652 + "</section>\n"
653
654 + "<script>\n"
655 + LOG_TITLE_FUNCTION
656 + " try {\n"
657 + " let items = document.querySelectorAll(\"h1:has(~ h2)\");"
658 + " log(items.length);\n"
659 + " log(items[0].tagName + ' / ' + items[0].innerText);\n"
660 + " log(items[1].tagName + ' / ' + items[1].innerText);\n"
661 + " } catch (e) { logEx(e); }\n"
662 + "</script>\n"
663
664 + "</body></html>";
665
666 loadPageVerifyTitle2(html);
667 }
668
669
670
671
672 @Test
673 @Alerts({"2", "H1 / h1 1", "H2 / h2 0",
674 "2", "H1 / h1 1", "H2 / h2 0"})
675 public void hasIs() throws Exception {
676 final String html = DOCTYPE_HTML
677 + "<html>\n"
678 + "<head></head>\n"
679 + "<body>\n"
680 + "<section>\n"
681 + " <article>\n"
682 + " <h1>h1 0</h1>\n"
683 + " <p>p0</p>\n"
684 + " </article>\n"
685 + " <article>\n"
686 + " <h1>h1 1</h1>\n"
687 + " <h2>h2 0</h2>\n"
688 + " <h3>h3 0</h3>\n"
689 + " <p>p1</p>\n"
690 + " </article>\n"
691 + "</section>\n"
692 + "<section>\n"
693 + " <article>a2</article>\r\n"
694 + "</section>\n"
695
696 + "<script>\n"
697 + LOG_TITLE_FUNCTION
698 + " try {\n"
699 + " let items = document.querySelectorAll(\":is(h1, h2, h3):has(+ :is(h2, h3, h4))\");"
700 + " log(items.length);\n"
701 + " log(items[0].tagName + ' / ' + items[0].innerText);\n"
702 + " log(items[1].tagName + ' / ' + items[1].innerText);\n"
703
704 + " items = document.querySelectorAll(\":is(h1, h2, h3):has(+ h2, + h3, + h4)\");"
705 + " log(items.length);\n"
706 + " log(items[0].tagName + ' / ' + items[0].innerText);\n"
707 + " log(items[1].tagName + ' / ' + items[1].innerText);\n"
708 + " } catch (e) { logEx(e); }\n"
709 + "</script>\n"
710
711 + "</body></html>";
712
713 loadPageVerifyTitle2(html);
714 }
715
716
717
718
719 @Test
720 @Alerts({"2", "ARTICLE / h1 0", "ARTICLE / p0"})
721 public void hasOr() throws Exception {
722 final String html = DOCTYPE_HTML
723 + "<html>\n"
724 + "<head></head>\n"
725 + "<body>\n"
726 + "<section>\n"
727 + " <article>\n"
728 + " <h1>h1 0</h1>\n"
729 + " </article>\n"
730 + " <article>\n"
731 + " <p>p0</p>\n"
732 + " </article>\n"
733 + " <article>\n"
734 + " <div>div0</div>\n"
735 + " </article>\n"
736 + "</section>\n"
737
738 + "<script>\n"
739 + LOG_TITLE_FUNCTION
740 + " try {\n"
741 + " let items = document.querySelectorAll(\"article:has(h1, p)\");"
742 + " log(items.length);\n"
743 + " log(items[0].tagName + ' / ' + items[0].innerText);\n"
744 + " log(items[1].tagName + ' / ' + items[1].innerText);\n"
745 + " } catch (e) { logEx(e); }\n"
746 + "</script>\n"
747
748 + "</body></html>";
749
750 loadPageVerifyTitle2(html);
751 }
752
753
754
755
756 @Test
757 @Alerts({"1", "ARTICLE / h1 1 p1"})
758 public void hasAnd() throws Exception {
759 final String html = DOCTYPE_HTML
760 + "<html>\n"
761 + "<head></head>\n"
762 + "<body>\n"
763 + "<section>\n"
764 + " <article>\n"
765 + " <h1>h1 0</h1>\n"
766 + " </article>\n"
767 + " <article>\n"
768 + " <p>p0</p>\n"
769 + " </article>\n"
770 + " <article>\n"
771 + " <h1>h1 1</h1>\n"
772 + " <p>p1</p>\n"
773 + " </article>\n"
774 + " <article>\n"
775 + " <div>div0</div>\n"
776 + " </article>\n"
777 + "</section>\n"
778
779 + "<script>\n"
780 + LOG_TITLE_FUNCTION
781 + " try {\n"
782 + " let items = document.querySelectorAll(\"article:has(h1):has(p)\");"
783 + " log(items.length);\n"
784 + " log(items[0].tagName + ' / ' + items[0].innerText);\n"
785 + " } catch (e) { logEx(e); }\n"
786 + "</script>\n"
787
788 + "</body></html>";
789
790 loadPageVerifyTitle2(html);
791 }
792
793
794
795
796
797 @Test
798 @Alerts({"0", "SyntaxError/DOMException"})
799 public void hasSizzleJQuery182InvalidContains() throws Exception {
800 final String html = DOCTYPE_HTML
801 + "<html>\n"
802 + "<head></head>\n"
803 + "<body>\n"
804
805 + "<script>\n"
806 + LOG_TITLE_FUNCTION
807 + " try {\n"
808 + " items = document.querySelectorAll(\"#form select:has(option:first-child)\");"
809 + " log(items.length);\n"
810
811 + " items = document.querySelectorAll(\"#form select:has(option:first-child:contains('o'))\");"
812 + " log(items.length);\n"
813 + " } catch (e) { logEx(e); }\n"
814 + "</script>\n"
815
816 + "</body></html>";
817
818 loadPageVerifyTitle2(html);
819 }
820
821
822
823
824 @Test
825 @Alerts("SyntaxError/DOMException")
826 public void hasDoubleColon() throws Exception {
827 final String html = DOCTYPE_HTML
828 + "<html>\n"
829 + "<head><title></title></head>\n"
830 + "<body>\n"
831 + "<ul>\n"
832 + " <li>ul - item 0</li>\n"
833 + "</ul>\n"
834
835 + "<script>\n"
836 + LOG_TITLE_FUNCTION
837 + " try {\n"
838 + " let items = document.querySelectorAll('::has(ul)');"
839 + " } catch (e) { logEx(e); }\n"
840 + "</script>\n"
841
842 + "</body></html>";
843
844 loadPageVerifyTitle2(html);
845 }
846 }