View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.html.parser;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.html.HtmlPageTest;
19  import org.htmlunit.junit.BrowserRunner;
20  import org.htmlunit.junit.annotation.Alerts;
21  import org.htmlunit.junit.annotation.HtmlUnitNYI;
22  import org.junit.Test;
23  import org.junit.runner.RunWith;
24  
25  /**
26   * Test class for {@link HTMLParser}.
27   *
28   * @author Ahmed Ashour
29   * @author Ronald Brill
30   * @author Marc Guillemot
31   * @author Frank Danek
32   */
33  @RunWith(BrowserRunner.class)
34  public class HTMLParser2Test extends WebDriverTestCase {
35  
36      /**
37       * @throws Exception failure
38       */
39      @Test
40      public void qualified_body() throws Exception {
41          final String html = "<html><body>\n"
42              + "<wicket:body>whatever</wicket:body>\n"
43              + "</body></html>";
44          loadPage2(html);
45      }
46  
47      /**
48       * Malformed HTML:
49       * &lt;/td&gt;some text&lt;/tr&gt; =&gt; text comes before the table.
50       *
51       * @throws Exception on test failure
52       */
53      @Test
54      @Alerts({"\\nbeforeafter", "undefined", "undefined"})
55      public void htmlTableTextAroundTD() throws Exception {
56          final String html = "<html><head>\n"
57              + "<script>\n"
58              + LOG_TITLE_FUNCTION_NORMALIZE
59              + "function test() {\n"
60              + "  var tmp = document.getElementById('testDiv');\n"
61              + "  tmp = tmp.firstChild;\n"
62              + "  log(tmp.data);\n"
63              + "  tmp = tmp.nextSibling;\n"
64              + "  log(tmp.data);\n"
65              + "  tmp = tmp.nextSibling;\n"
66              + "  log(tmp.tagName);\n"
67              + "}\n"
68              + "</script>\n"
69              + "</head>\n"
70              + "<body onload='test()'><div id='testDiv'>\n"
71              + "<table><tr>before<td></td>after</tr></table>\n"
72              + "</div></body></html>";
73  
74          loadPageVerifyTitle2(html);
75      }
76  
77      /**
78       * Malformed HTML:
79       * &lt;/td&gt;some text&lt;/tr&gt; =&gt; text comes before the table.
80       *
81       * @throws Exception on test failure
82       */
83      @Test
84      @Alerts({"\\nabcbeforeafter", "undefined", "undefined"})
85      public void htmlTableTextAroundTD2() throws Exception {
86          final String html = "<html><head>\n"
87              + "<script>\n"
88              + LOG_TITLE_FUNCTION_NORMALIZE
89              + "function test() {\n"
90              + "  var tmp = document.getElementById('testDiv');\n"
91              + "  tmp = tmp.firstChild;\n"
92              + "  log(tmp.data);\n"
93              + "  tmp = tmp.nextSibling;\n"
94              + "  log(tmp.data);\n"
95              + "  tmp = tmp.nextSibling;\n"
96              + "  log(tmp.tagName);\n"
97              + "}\n"
98              + "</script>\n"
99              + "</head>\n"
100             + "<body onload='test()'><div id='testDiv'>\n"
101             + "abc<table><tr>before<td></td>after</tr></table>\n"
102             + "</div></body></html>";
103 
104         loadPageVerifyTitle2(html);
105     }
106 
107     /**
108      * Malformed HTML:
109      * &lt;/td&gt;some text&lt;/tr&gt; =&gt; text comes before the table.
110      *
111      * @throws Exception on test failure
112      */
113     @Test
114     @Alerts({"\\nbe", "B-for", "e", "STRONG-aft", "er", "[object\\sHTMLTableElement]"})
115     public void htmlTableTagsAroundTD() throws Exception {
116         final String html = "<html><head>\n"
117             + "<script>\n"
118             + LOG_TITLE_FUNCTION_NORMALIZE
119             + "function test() {\n"
120             + "  var tmp = document.getElementById('testDiv');\n"
121             + "  tmp = tmp.firstChild;\n"
122             + "  log(tmp.data);\n"
123 
124             + "  tmp = tmp.nextSibling;\n"
125             + "  log(tmp.nodeName + '-' + tmp.firstChild.data);\n"
126 
127             + "  tmp = tmp.nextSibling;\n"
128             + "  log(tmp.data);\n"
129 
130             + "  tmp = tmp.nextSibling;\n"
131             + "  log(tmp.nodeName + '-' + tmp.firstChild.data);\n"
132 
133             + "  tmp = tmp.nextSibling;\n"
134             + "  log(tmp.data);\n"
135 
136             + "  log(tmp.nextSibling);\n"
137             + "}\n"
138             + "</script>\n"
139             + "</head>\n"
140             + "<body onload='test()'><div id='testDiv'>\n"
141             + "<table><tr>be<b>for</b>e<td></td><strong>aft</strong>er</tr></table>\n"
142             + "</div></body></html>";
143 
144         loadPageVerifyTitle2(html);
145     }
146 
147     /**
148      * @throws Exception on test failure
149      */
150     @Test
151     @Alerts("TABLE")
152     public void htmlTableWhitespaceAroundTD() throws Exception {
153         final String html = "<html><head>\n"
154             + "<script>\n"
155             + LOG_TITLE_FUNCTION
156             + "function test() {\n"
157             + "  var tmp = document.getElementById('testDiv');\n"
158             + "  tmp = tmp.firstChild;\n"
159             + "  log(tmp.tagName);\n"
160             + "}\n"
161             + "</script>\n"
162             + "</head>\n"
163             + "<body onload='test()'><div id='testDiv'><table><tr> <td></td> </tr></table>\n"
164             + "</div></body></html>";
165 
166         loadPageVerifyTitle2(html);
167     }
168 
169     /**
170      * @throws Exception on test failure
171      */
172     @Test
173     @Alerts({"H2", "TABLE"})
174     public void htmlTableMisplacedElementInside() throws Exception {
175         final String html = "<html><head>\n"
176             + "<script>\n"
177             + LOG_TITLE_FUNCTION
178             + "function test() {\n"
179             + "  var tmp = document.body.firstChild;\n"
180             + "  log(tmp.tagName);\n"
181             + "  tmp = document.body.firstChild.nextSibling;\n"
182             + "  log(tmp.tagName);\n"
183             + "}\n"
184             + "</script>\n"
185             + "</head>\n"
186             + "<body onload='test()'><table><tr><td></td><h2>Wrong Place</h2></tr></table>\n"
187             + "</body></html>";
188 
189         loadPageVerifyTitle2(html);
190     }
191 
192     /**
193      * @throws Exception on test failure
194      */
195     @Test
196     @Alerts({"H2", "TABLE"})
197     public void htmlTableMisplacedElementInside2() throws Exception {
198         final String html = "<html><head>\n"
199             + "<script>\n"
200             + LOG_TITLE_FUNCTION
201             + "function test() {\n"
202             + "  var tmp = document.body.firstChild;\n"
203             + "  log(tmp.tagName);\n"
204             + "  tmp = document.body.firstChild.nextSibling;\n"
205             + "  log(tmp.tagName);\n"
206             + "}\n"
207             + "</script>\n"
208             + "</head>\n"
209             + "<body onload='test()'><table><tr><td></td><h2>Wrong Place</h2><td></td></tr></table>\n"
210             + "</body></html>";
211 
212         loadPageVerifyTitle2(html);
213     }
214 
215     /**
216      * @throws Exception on test failure
217      */
218     @Test
219     @Alerts({"H2", "TABLE"})
220     public void htmlTableMisplacedElementInside3() throws Exception {
221         final String html = "<html><head>\n"
222             + "<script>\n"
223             + LOG_TITLE_FUNCTION
224             + "function test() {\n"
225             + "  var tmp = document.body.firstChild;\n"
226             + "  log(tmp.tagName);\n"
227             + "  tmp = document.body.firstChild.nextSibling;\n"
228             + "  log(tmp.tagName);\n"
229             + "}\n"
230             + "</script>\n"
231             + "</head>\n"
232             + "<body onload='test()'><table><tr><td></td></tr><h2>Wrong Place</h2></table>\n"
233             + "</body></html>";
234 
235         loadPageVerifyTitle2(html);
236     }
237 
238     /**
239      * @throws Exception on test failure
240      */
241     @Test
242     @Alerts({"H2", "TABLE"})
243     public void htmlTableMisplacedElementInside4() throws Exception {
244         final String html = "<html><head>\n"
245             + "<script>\n"
246             + LOG_TITLE_FUNCTION
247             + "function test() {\n"
248             + "  var tmp = document.body.firstChild;\n"
249             + "  log(tmp.tagName);\n"
250             + "  tmp = document.body.firstChild.nextSibling;\n"
251             + "  log(tmp.tagName);\n"
252             + "}\n"
253             + "</script>\n"
254             + "</head>\n"
255             + "<body onload='test()'><table><tr><td></td></tr><h2>Wrong Place</h2><tr><td></td></tr></table>\n"
256             + "</body></html>";
257 
258         loadPageVerifyTitle2(html);
259     }
260 
261     /**
262      * @throws Exception if the test fails
263      */
264     @Test
265     @Alerts({"H2", "TABLE", "H2", "TABLE", "SCRIPT"})
266     public void htmlTableMisplacedElementInside5() throws Exception {
267         final String html = "<html><head>\n"
268                 + "</head>\n"
269                 + "<body>"
270                 +   "<table>"
271                 +     "<tr>"
272                 +       "<h2>X</h2>"
273                 +       "<td>1st</td>"
274                 +     "</tr>\n"
275 
276                 +       "<table>"
277                 +         "<tr>"
278                 +           "<h2>Y</h2>"
279                 +           "<td>1st</td>"
280                 +         "</tr>"
281                 +       "</table>\n"
282                 +   "</table>\n"
283 
284                 + "<script>\n"
285                 + LOG_TITLE_FUNCTION
286                 + "   var tmp = document.body.firstChild;\n"
287                 + "   while (tmp != null) {if (tmp.tagName) log(tmp.tagName); tmp = tmp.nextSibling;}\n"
288                 + "</script>\n"
289                 + "</body></html>";
290         loadPageVerifyTitle2(html);
291     }
292 
293     /**
294      * @throws Exception if the test fails
295      */
296     @Test
297     @Alerts({"H2#x", "TABLE", "H2#y", "TABLE", "H2#z", "TABLE", "H2#a", "TABLE", "SCRIPT"})
298     public void htmlTableMisplacedElementInside6() throws Exception {
299         final String html = "<html><head>\n"
300                 + "</head>\n"
301                 + "<body>"
302                 +   "<table>"
303                 +     "<tr>"
304                 +       "<h2 id='x'>X</h2>"
305                 +       "<td>x</td>"
306                 +     "</tr>\n"
307 
308                 +       "<table>"
309                 +         "<tr>"
310                 +           "<h2 id='y'>Y</h2>"
311                 +           "<td>y</td>"
312                 +         "</tr>"
313                 +       "</table>\n"
314 
315                 +     "<h2 id='z'>Z</h2>"
316                 +     "<table><tr><td>z</td></table>\n"
317                 +   "</table>\n"
318 
319                 +   "<h2 id='a'>A</h2>"
320                 +   "<table><tr><td>a</td></table>\n"
321                 +   "</table>\n"
322 
323                 + "<script>\n"
324                 + LOG_TITLE_FUNCTION
325                 + "   var tmp = document.body.firstChild;\n"
326                 + "   while (tmp != null) {\n"
327                 + "     if (tmp.tagName) {\n"
328                 + "       log(tmp.tagName + (tmp.id ? '#' + tmp.id : ''));\n"
329                 + "     }\n"
330                 + "     tmp = tmp.nextSibling;\n"
331                 + "   }\n"
332                 + "</script>\n"
333                 + "</body></html>";
334         loadPageVerifyTitle2(html);
335     }
336 
337     /**
338      * @throws Exception if the test fails
339      */
340     @Test
341     @Alerts({"4", "TABLE", "TABLE", "SPAN", "SCRIPT"})
342     public void tableInsideTable() throws Exception {
343         final String html = "<html><head>\n"
344                 + "</head>\n"
345                 + "<body>"
346                 +   "<table>"
347                 +     "<tr>"
348                 +       "<td>x</td>"
349                 +     "</tr>\n"
350 
351                 +       "<table>"
352                 +         "<tr>"
353                 +           "<td>y</td>"
354                 +         "</tr>"
355                 +       "</table>\n"
356 
357                       // the second table has closed the first one
358                 +     "<tr>"
359                 +       "<td><span>z</span></td>"
360                 +     "</tr>\n"
361                 +   "</table>\n"
362 
363                 + "<script>\n"
364                 + LOG_TITLE_FUNCTION
365                 + "  log(document.body.children.length);\n"
366                 + "  log(document.body.children[0].tagName);\n"
367                 + "  log(document.body.children[1].tagName);\n"
368                 + "  log(document.body.children[2].tagName);\n"
369                 + "  log(document.body.children[3].tagName);\n"
370                 + "</script>\n"
371                 + "</body></html>";
372         loadPageVerifyTitle2(html);
373     }
374 
375     /**
376      * @throws Exception if the test fails
377      */
378     @Test
379     @Alerts({"4", "TABLE", "TABLE", "SPAN", "SCRIPT"})
380     public void tableInsideTableTr() throws Exception {
381         final String html = "<html><head>\n"
382                 + "</head>\n"
383                 + "<body>"
384                 +   "<table>"
385                 +     "<tr>"
386                 +       "<td>x</td>"
387                 +     "</tr>\n"
388 
389                 +     "<tr>"
390                 +       "<table>"
391                 +         "<tr>"
392                 +           "<td>y</td>"
393                 +         "</tr>"
394                 +       "</table>\n"
395                 +     "</tr>\n"
396 
397                       // the second table has closed the first one
398                 +     "<tr>"
399                 +       "<td><span>z</span></td>"
400                 +     "</tr>\n"
401                 +   "</table>\n"
402 
403                 + "<script>\n"
404                 + LOG_TITLE_FUNCTION
405                 + "  log(document.body.children.length);\n"
406                 + "  log(document.body.children[0].tagName);\n"
407                 + "  log(document.body.children[1].tagName);\n"
408                 + "  log(document.body.children[2].tagName);\n"
409                 + "  log(document.body.children[3].tagName);\n"
410                 + "</script>\n"
411                 + "</body></html>";
412         loadPageVerifyTitle2(html);
413     }
414 
415     /**
416      * @throws Exception if the test fails
417      */
418     @Test
419     @Alerts({"2", "TABLE", "SCRIPT"})
420     public void tableInsideTableTd() throws Exception {
421         final String html = "<html><head>\n"
422                 + "</head>\n"
423                 + "<body>"
424                 +   "<table>"
425                 +     "<tr>"
426                 +       "<td>x</td>"
427                 +     "</tr>\n"
428 
429                 +     "<tr><td>"
430                 +       "<table>"
431                 +         "<tr>"
432                 +           "<td>y</td>"
433                 +         "</tr>"
434                 +       "</table>\n"
435                 +     "</td></tr>\n"
436 
437                       // the second table has closed the first one
438                 +     "<tr>"
439                 +       "<td><span>z</span></td>"
440                 +     "</tr>\n"
441                 +   "</table>\n"
442 
443                 + "<script>\n"
444                 + LOG_TITLE_FUNCTION
445                 + "  log(document.body.children.length);\n"
446                 + "  log(document.body.children[0].tagName);\n"
447                 + "  log(document.body.children[1].tagName);\n"
448                 + "</script>\n"
449                 + "</body></html>";
450         loadPageVerifyTitle2(html);
451     }
452 
453     /**
454      * @throws Exception if the test fails
455      */
456     @Test
457     @Alerts({"1", "TABLE"})
458     public void scriptInsideTable() throws Exception {
459         final String html = "<html><head>\n"
460                 + "</head>\n"
461                 + "<body>"
462                 +   "<table>"
463                 +     "<tr>"
464                 +       "<td>1st</td>"
465                 +     "</tr>\n"
466 
467                 + "<script>\n"
468                 + LOG_TITLE_FUNCTION
469                 + "  log(document.body.childNodes.length);\n"
470                 + "  var tmp = document.body.firstChild;\n"
471                 + "  while (tmp != null) {if (tmp.tagName) log(tmp.tagName); tmp = tmp.nextSibling;}\n"
472                 + "</script>\n"
473                 + "</body></html>";
474         loadPageVerifyTitle2(html);
475     }
476 
477     /**
478      * @throws Exception if the test fails
479      */
480     @Test
481     @Alerts({"1", "TABLE"})
482     public void scriptInsideTableRows() throws Exception {
483         final String html = "<html><head>\n"
484                 + "</head>\n"
485                 + "<body>"
486                 +   "<table>"
487                 +     "<tr>"
488                 +       "<td>1st</td>"
489                 +     "</tr>\n"
490                 +     "<tr>"
491 
492                 + "<script>\n"
493                 + LOG_TITLE_FUNCTION
494                 + "  log(document.body.childNodes.length);\n"
495                 + "  var tmp = document.body.firstChild;\n"
496                 + "  while (tmp != null) {if (tmp.tagName) log(tmp.tagName); tmp = tmp.nextSibling;}\n"
497                 + "</script>\n"
498 
499                 +     "</tr>\n"
500                 + "</body></html>";
501         loadPageVerifyTitle2(html);
502     }
503 
504     /**
505      * @throws Exception if the test fails
506      */
507     @Test
508     @Alerts({"1", "TABLE"})
509     public void scriptInsideTableData() throws Exception {
510         final String html = "<html><head>\n"
511                 + "</head>\n"
512                 + "<body>"
513                 +   "<table>"
514                 +     "<tr>"
515                 +       "<td>1st</td>"
516                 +     "</tr>\n"
517                 +     "<tr>"
518                 +       "<td>"
519 
520                 + "<script>\n"
521                 + LOG_TITLE_FUNCTION
522                 + "  log(document.body.childNodes.length);\n"
523                 + "  var tmp = document.body.firstChild;\n"
524                 + "  while (tmp != null) {if (tmp.tagName) log(tmp.tagName); tmp = tmp.nextSibling;}\n"
525                 + "</script>\n"
526 
527                 +       "</td>"
528                 +     "</tr>\n"
529                 + "</body></html>";
530         loadPageVerifyTitle2(html);
531     }
532 
533     /**
534      * @throws Exception on test failure
535      */
536     @Test
537     @Alerts({"TABLE", "TABLE"})
538     public void htmlTableClosesAnother() throws Exception {
539         final String html = "<html><head>\n"
540             + "<script>\n"
541             + "function test() {\n"
542             + LOG_TITLE_FUNCTION
543             + "  var tmp = document.body.firstChild;\n"
544             + "  log(tmp.tagName);\n"
545             + "  tmp = document.body.firstChild.nextSibling;\n"
546             + "  log(tmp.tagName);\n"
547             + "}\n"
548             + "</script>\n"
549             + "</head>\n"
550 
551             + "<body onload='test()'>"
552             + "<table>"
553             +   "<tr>"
554             +     "<td>a</td>"
555             +   "</tr>"
556 
557             +   "<table>"
558             +     "<tr>"
559             +       "<td>o</td>"
560             +     "</tr>"
561             +   "</table>\n"
562 
563             + "</table>\n"
564             + "</body></html>";
565 
566         loadPageVerifyTitle2(html);
567     }
568 
569     /**
570      * @throws Exception on test failure
571      */
572     @Test
573     @Alerts({"TABLE", "TABLE"})
574     public void htmlTableClosesAnotherInsideTr() throws Exception {
575         final String html = "<html><head>\n"
576             + "<script>\n"
577             + LOG_TITLE_FUNCTION
578             + "function test() {\n"
579             + "  var tmp = document.body.firstChild;\n"
580             + "  log(tmp.tagName);\n"
581             + "  tmp = document.body.firstChild.nextSibling;\n"
582             + "  log(tmp.tagName);\n"
583             + "}\n"
584             + "</script>\n"
585             + "</head>\n"
586 
587             + "<body onload='test()'>"
588             + "<table>"
589             +   "<tr>"
590 
591             +   "<table>"
592             +     "<tr>"
593             +       "<td>o</td>"
594             +     "</tr>"
595             +   "</table>\n"
596 
597             +   "</tr>"
598             + "</table>\n"
599             + "</body></html>";
600 
601         loadPageVerifyTitle2(html);
602     }
603 
604 
605     /**
606      * @throws Exception on test failure
607      */
608     @Test
609     @Alerts({"TABLE", "null"})
610     public void htmlTableNotClosesOnotherInsideTd() throws Exception {
611         final String html = "<html><head>\n"
612             + "<script>\n"
613             + LOG_TITLE_FUNCTION
614             + "function test() {\n"
615             + "  var tmp = document.body.firstChild;\n"
616             + "  log(tmp.tagName);\n"
617             + "  tmp = document.body.firstChild.nextSibling;\n"
618             + "  log(tmp);\n"
619             + "}\n"
620             + "</script>\n"
621             + "</head>\n"
622 
623             + "<body onload='test()'>"
624             + "<table>"
625             +   "<tr>"
626             +     "<td><span>"
627 
628             +   "<table>"
629             +     "<tr>"
630             +       "<td>o</td>"
631             +     "</tr>"
632             +   "</table>\n"
633 
634             +     "</span></td>"
635             +   "</tr>"
636             + "</table>"
637             + "</body></html>";
638 
639         loadPageVerifyTitle2(html);
640     }
641 
642     /**
643      * @throws Exception on test failure
644      */
645     @Test
646     @Alerts("Hi!")
647     public void unclosedCommentsInScript() throws Exception {
648         final String html = "<html><body>\n"
649             + "<script><!--\n"
650             + "window.document.title = 'Hi!§';\n"
651             + "</script>\n"
652             + "<h1>Ho!§</h1>\n"
653             + "<!-- some comment -->\n"
654             + "<h1>Hu!</h1>\n"
655             + "</body></html>";
656 
657         loadPageVerifyTitle2(html);
658     }
659 
660     /**
661      * This tests for a bug in NekoHTML.
662      * @throws Exception on test failure
663      */
664     @Test
665     @Alerts({"P", "BUTTON", "DIV"})
666     public void divInsideButton() throws Exception {
667         final String html = "<html><head>\n"
668             + "<script>\n"
669             + LOG_TITLE_FUNCTION
670             + "function test() {\n"
671             + "try {\n"
672             + "  var tmp = document.getElementById('myP');\n"
673             + "  log(tmp.tagName);\n"
674             + "  tmp = tmp.firstChild;\n"
675             + "  log(tmp.tagName);\n"
676             + "  tmp = tmp.firstChild.tagName;\n"
677             + "  log(tmp);\n"
678             + "} catch(e) { logEx(e); }\n"
679             + "}\n"
680             + "</script>\n"
681             + "</head>\n"
682             + "<body onload='test()'>\n"
683             + "<p id='myP'><button><div>Test</div></button></p>\n"
684             + "</body></html>";
685 
686         loadPageVerifyTitle2(html);
687     }
688 
689     /**
690      * This tests for a bug in NekoHTML.
691      * @throws Exception on test failure
692      */
693     @Test
694     @Alerts({"P", "LABEL", "OBJECT"})
695     public void objectInsideLabel() throws Exception {
696         final String html = "<html><head>\n"
697             + "<script>\n"
698             + LOG_TITLE_FUNCTION
699             + "function test() {\n"
700             + "try {\n"
701             + "  var tmp = document.getElementById('myP');\n"
702             + "  log(tmp.tagName);\n"
703             + "  tmp = tmp.firstChild;\n"
704             + "  log(tmp.tagName);\n"
705             + "  tmp = tmp.firstChild.tagName;\n"
706             + "  log(tmp);\n"
707             + "} catch(e) { logEx(e); }\n"
708             + "}\n"
709             + "</script>\n"
710             + "</head>\n"
711             + "<body onload='test()'>\n"
712             + "<p id='myP'><label><object></object></label></p>\n"
713             + "</body></html>";
714 
715         loadPageVerifyTitle2(html);
716     }
717 
718     /**
719      * This tests for a bug in NekoHTML.
720      * Without setting a property NekoHTML closes all inline tags
721      * when a table start tag is detected. This is ok from the spec
722      * but different with real browsers.
723      *
724      * @throws Exception on test failure
725      */
726     @Test
727     public void tableClosesInlineTags() throws Exception {
728         final String html = "<html><head>\n"
729                 + "<script>\n"
730                 + "  function test() {\n"
731                 + "    var myP = document.getElementById('myP');\n"
732                 + "    for(var i = 0; i < myP.childNodes.length; i++) {\n"
733                 + "      var myNode = myP.childNodes[i];\n"
734                 + "      if (myNode.nodeType == 1 && myNode.nodeName != 'TABLE') {\n"
735                 + "        var hasTable = false;\n"
736                 + "        for(var j = 0; j<myNode.childNodes.length; j++) {\n"
737                 + "          if (myNode.childNodes[j].nodeName == 'TABLE') {\n"
738                 + "            hasTable = true;\n"
739                 + "          }\n"
740                 + "        }\n"
741                 + "        if (!hasTable) {\n"
742                 + "          log('<' + myNode.nodeName + '>');\n"
743                 + "        }\n"
744                 + "      }\n"
745                 + "    }\n"
746                 + "  }\n"
747                 + "</script>\n"
748                 + "</head>\n"
749                 + "\n"
750                 + "<body onload='test()'>\n"
751                 + "\n"
752                 + "<p id='myP'>\n"
753                 + "  <a><table></table></a>\n"
754                 + "  <abbr><table></table></abbr>\n"
755                 + "  <acronym><table></table></acronym>\n"
756                 + "  <b><table></table></b>\n"
757                 + "  <bdo><table></table></bdo>\n"
758                 + "  <big><table></table></big>\n"
759                 + "  <button><table></table></button>\n"
760                 + "  <cite><table></table></cite>\n"
761                 + "  <code><table></table></code>\n"
762                 + "  <del><table></table></del>\n"
763                 + "  <dfn><table></table></dfn>\n"
764                 + "  <em><table></table></em>\n"
765                 + "  <font><table></table></font>\n"
766                 + "  <i><table></table></i>\n"
767                 + "  <ins><table></table></ins>\n"
768                 + "  <kbd><table></table></kbd>\n"
769                 + "  <label><table></table></label>\n"
770                 + "  <map><table></table></map>\n"
771                 + "  <q><table></table></q>\n"
772                 + "  <samp><table></table></samp>\n"
773                 + "  <small><table></table></small>\n"
774                 + "  <span><table></table></span>\n"
775                 + "  <strong><table></table></strong>\n"
776                 + "  <sub><table></table></sub>\n"
777                 + "  <sup><table></table></sup>\n"
778                 + "  <tt><table></table></tt>\n"
779                 + "  <var><table></table></var>\n"
780                 + "</p>\n"
781                 + "\n"
782                 + "</body>\n"
783                 + "</html>";
784 
785         loadPageVerifyTitle2(html);
786     }
787 
788     /**
789      * @throws Exception on test failure
790      */
791     @Test
792     @Alerts({"2", "2", "3", "3", "2", "2", "3", "2", "2", "3", "2", "2"})
793     public void childNodes_p_parent() throws Exception {
794         final String html = "<html><head>\n"
795             + "<script>\n"
796             + LOG_TITLE_FUNCTION
797             + "function test() {\n"
798             + "  for (var i = 1; i <= 12; i++) {\n"
799             + "    log(document.getElementById('p' + i).childNodes.length);\n"
800             + "  }\n"
801             + "}\n"
802             + "</script>\n"
803             + "</head><body onload='test()'>\n"
804             + "<p id='p1'><input> </p>\n"
805             + "<p id='p2'> <input></p>\n"
806             + "<p id='p3'> <input> </p>\n"
807             + "<p id='p4'> <a></a> </p>\n"
808             + "<p id='p5'><a></a> </p>\n"
809             + "<p id='p6'> <a></a></p>\n"
810             + "<p id='p7'> <a href='hi'>there</a> </p>\n"
811             + "<p id='p8'><a href='hi'>there</a> </p>\n"
812             + "<p id='p9'> <a href='hi'>there</a></p>\n"
813             + "<p id='p10'> <a href='hi'></a> </p>\n"
814             + "<p id='p11'><a href='hi'></a> </p>\n"
815             + "<p id='p12'> <a href='hi'></a></p>\n"
816             + "</body></html>";
817 
818         loadPageVerifyTitle2(html);
819     }
820 
821     /**
822      * @throws Exception on test failure
823      */
824     @Test
825     @Alerts({"2", "2", "3", "3", "2", "2", "3", "2", "2", "3", "2", "2", "3"})
826     public void childNodes_f() throws Exception {
827         final String html = "<html><head>\n"
828             + "<script>\n"
829             + LOG_TITLE_FUNCTION
830             + "function test() {\n"
831             + "  for (var i = 1; i <= 13; i++) {\n"
832             + "    log(document.getElementById('f' + i).childNodes.length);\n"
833             + "  }\n"
834             + "}\n"
835             + "</script>\n"
836             + "</head><body onload='test()'>\n"
837             + "<form id='f1'><input> </form>\n"
838             + "<form id='f2'> <input></form>\n"
839             + "<form id='f3'> <input> </form>\n"
840             + "<form id='f4'> <a></a> </form>\n"
841             + "<form id='f5'><a></a> </form>\n"
842             + "<form id='f6'> <a></a></form>\n"
843             + "<form id='f7'> <a href='hi'>there</a> </form>\n"
844             + "<form id='f8'><a href='hi'>there</a> </form>\n"
845             + "<form id='f9'> <a href='hi'>there</a></form>\n"
846             + "<form id='f10'> <a href='hi'></a> </form>\n"
847             + "<form id='f11'><a href='hi'></a> </form>\n"
848             + "<form id='f12'> <a href='hi'></a></form>\n"
849             + "<form id='f13'> <div> </div> </form>\n"
850             + "</body></html>";
851         loadPageVerifyTitle2(html);
852     }
853 
854     /**
855      * Conditional comments are removed from the dom.
856      * @throws Exception on test failure
857      */
858     @Test
859     @Alerts({"<!--[if gt IE 11]><br><![endif]-->", "<!--[if lt IE 11]><br><![endif]-->"})
860     public void ieConditionalCommentsNotInDom() throws Exception {
861         final String html = "<html><head>\n"
862             + "<script>\n"
863             + LOG_TITLE_FUNCTION
864             + "function test() {\n"
865             + "try {\n"
866             + "  var tmp = document.getElementById('my1');\n"
867             + "  log(tmp.innerHTML);\n"
868             + "  tmp = document.getElementById('my2');\n"
869             + "  log(tmp.innerHTML);\n"
870             + "} catch(e) { logEx(e); }\n"
871             + "}\n"
872             + "</script>\n"
873             + "</head>\n"
874             + "<body onload='test()'>\n"
875             + "  <div id='my1'><!--[if gt IE 11]><br><![endif]--></div>\n"
876             + "  <div id='my2'><!--[if lt IE 11]><br><![endif]--></div>\n"
877             + "</body></html>";
878 
879         loadPageVerifyTitle2(html);
880     }
881 
882     /**
883      * Test incorrect parsing of LABEL within A tag. Fixed in NekoHTML 1.9.19.
884      * @see <a href="http://sf.net/p/htmlunit/bugs/1547/">Bug #1547</a>
885      * @throws Exception on test failure
886      */
887     @Test
888     @Alerts("1")
889     public void acceptLabelWithinAnchor() throws Exception {
890         final String html = "<html><body>\n"
891             + "<a href='foo'>\n"
892             + "<label>XL</label>\n"
893             + "</a>\n"
894             + "<script>\n"
895             + LOG_TITLE_FUNCTION
896             + "log(document.links.length)\n"
897             + "</script>\n"
898             + "</body></html>";
899 
900         loadPageVerifyTitle2(html);
901     }
902 
903     /**
904      * @see <a href="http://sf.net/p/htmlunit/bugs/1423/">Bug #1423</a>
905      * @throws Exception on test failure
906      */
907     @Test
908     @Alerts({"<var data=\"f\"> <a href=\"#\">a</a> <div>d</div> <li>l</li> </var> ", "3"})
909     public void varInsideUl() throws Exception {
910         final String html =
911             HtmlPageTest.STANDARDS_MODE_PREFIX_
912             + "<html>\n"
913             + "<head></head>\n"
914             + "<body>\n"
915             + "<ul id='myUl'>\n"
916             +   "<var data='f'>\n"
917             +     "<a href='#'>a</a>\n"
918             +     "<div>d</div>\n"
919             +     "<li>l</li>\n"
920             +   "</var>\n"
921             + "</ul>\n"
922             + "<script>\n"
923             + LOG_TITLE_FUNCTION
924             + "  var tmp = document.getElementById('myUl');\n"
925             + "  log(tmp.innerHTML);\n"
926             + "  log(tmp.childNodes.length);\n"
927             + "</script>\n"
928             + "</body></html>";
929 
930         loadPageVerifyTitle2(html);
931     }
932 
933     /**
934      * @see <a href="http://sf.net/p/htmlunit/bugs/1046/">Bug #1046</a>
935      * @throws Exception on test failure
936      */
937     @Test
938     @Alerts({"<table> <tbody><tr> <td>data</td> </tr> </tbody></table> ", "3"})
939     public void tableInsideAnchor() throws Exception {
940         final String html =
941             HtmlPageTest.STANDARDS_MODE_PREFIX_
942             + "<html>\n"
943             + "<head></head>\n"
944             + "<body>\n"
945             +  "<a id='myA' href='#'>\n"
946             +   "<table>\n"
947             +     "<tr>\n"
948             +       "<td>data</td>\n"
949             +     "</tr>\n"
950             +   "</table>\n"
951             +  "</a>\n"
952             + "<script>\n"
953             + LOG_TITLE_FUNCTION
954             + "  var tmp = document.getElementById('myA');\n"
955             + "  log(tmp.innerHTML);\n"
956             + "  log(tmp.childNodes.length);\n"
957             + "</script>\n"
958             + "</body></html>";
959 
960         loadPageVerifyTitle2(html);
961     }
962 
963     /**
964      * Issue #1825.
965      * @throws Exception on test failure
966      */
967     @Test
968     @Alerts({"<iframe></div></body></html></iframe>", "1",
969              "1", "IFRAME", "null", "1",
970              "3", "#text", "</div></body></html>"})
971     @HtmlUnitNYI(CHROME = {"<iframe>&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</iframe>", "1",
972                            "1", "IFRAME", "null", "1",
973                            "3", "#text", "</div></body></html>"},
974             EDGE = {"<iframe>&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</iframe>", "1",
975                     "1", "IFRAME", "null", "1",
976                     "3", "#text", "</div></body></html>"},
977             FF = {"<iframe>&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</iframe>", "1",
978                   "1", "IFRAME", "null", "1",
979                   "3", "#text", "</div></body></html>"},
980             FF_ESR = {"<iframe>&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</iframe>", "1",
981                       "1", "IFRAME", "null", "1",
982                       "3", "#text", "</div></body></html>"})
983     public void selfClosingIframe() throws Exception {
984         final String html = "<html><head>\n"
985             + "<script>\n"
986             + LOG_TITLE_FUNCTION
987             + "function test() {\n"
988             + "try {\n"
989             + "  var tmp = document.getElementById('myDiv');\n"
990             + "  log(tmp.innerHTML);\n"
991             + "  log(tmp.childNodes.length);\n"
992 
993             + "  var child = tmp.childNodes[0];\n"
994             + "  log(child.nodeType);\n"
995             + "  log(child.nodeName);\n"
996             + "  log(child.nodeValue);\n"
997 
998             + "  log(child.childNodes.length);\n"
999             + "  var child2 = child.childNodes[0];\n"
1000             + "  log(child2.nodeType);\n"
1001             + "  log(child2.nodeName);\n"
1002             + "  log(child2.nodeValue);\n"
1003 
1004             + "} catch(e) { logEx(e); }\n"
1005             + "}\n"
1006             + "</script>\n"
1007             + "</head>\n"
1008             + "<body onload='test()'>\n"
1009             + "  <div id='myDiv'><iframe/></div>"
1010             + "</body></html>";
1011 
1012         loadPageVerifyTitle2(html);
1013     }
1014 
1015     /**
1016      * Issue #1842.
1017      * @throws Exception on test failure
1018      */
1019     @Test
1020     @Alerts({"2", "1-1#DL", "0-1#DT", "1-1#DL", "0-1#DT"})
1021     public void dlShouldCloseDt() throws Exception {
1022         final String html = "<html><head>\n"
1023             + "<script>\n"
1024             + LOG_TITLE_FUNCTION
1025             + "function test() {\n"
1026             + "try {\n"
1027             + "  var tmp = document.getElementById('myBody');\n"
1028             + "  log(tmp.childNodes.length);\n"
1029 
1030             + "  var child = tmp.childNodes[0];\n"
1031             + "  log(child.childNodes.length + '-' + child.nodeType + '#' +child.nodeName);\n"
1032 
1033             + "  var child2 = child.childNodes[0];\n"
1034             + "  log(child2.childNodes.length + '-' + child2.nodeType + '#' +child2.nodeName);\n"
1035 
1036             + "  var child = tmp.childNodes[1];\n"
1037             + "  log(child.childNodes.length + '-' + child.nodeType + '#' +child.nodeName);\n"
1038 
1039             + "  var child2 = child.childNodes[0];\n"
1040             + "  log(child2.childNodes.length + '-' + child2.nodeType + '#' +child2.nodeName);\n"
1041 
1042             + "} catch(e) { logEx(e); }\n"
1043             + "}\n"
1044             + "</script>\n"
1045             + "</head>\n"
1046             + "<body id='myBody' onload='test()'>"
1047             + "<DL><DT></DL>"
1048             + "<DL><DT></DL>"
1049             + "</body></html>";
1050 
1051         loadPageVerifyTitle2(html);
1052     }
1053 
1054     /**
1055      * As of version 2.43.0 this fails with a stack overflow.
1056      *
1057      * @throws Exception on test failure
1058      */
1059     @Test
1060     @Alerts({"1", "1-1#P"})
1061     public void innerHtmlParagraph() throws Exception {
1062         final String html = "<html><head>\n"
1063             + "<script>\n"
1064             + LOG_TITLE_FUNCTION
1065             + "function test() {\n"
1066             + "try {\n"
1067             + "  var tmp = document.getElementById('myP');\n"
1068             + "  tmp.innerHTML = '<p>HtmlUnit</p>';\n"
1069             + "  log(tmp.childNodes.length);\n"
1070 
1071             + "  var child = tmp.childNodes[0];\n"
1072             + "  log(child.childNodes.length + '-' + child.nodeType + '#' + child.nodeName);\n"
1073 
1074             + "} catch(e) { logEx(e); }\n"
1075             + "}\n"
1076             + "</script>\n"
1077             + "</head>\n"
1078             + "<body onload='test()'>"
1079             + "  <p id='myP'>Test</p>"
1080             + "</body></html>";
1081 
1082         loadPageVerifyTitle2(html);
1083     }
1084 
1085     /**
1086      * @throws Exception on test failure
1087      */
1088     @Test
1089     @Alerts({"P", "A para", "STYLE", "graph."})
1090     public void styleInsideP() throws Exception {
1091         final String html = "<html><head>\n"
1092             + "<script>\n"
1093             + LOG_TITLE_FUNCTION
1094             + "function test() {\n"
1095             + "try {\n"
1096             + "  var tmp = document.getElementById('myP');\n"
1097             + "  log(tmp.tagName);\n"
1098 
1099             + "  tmp = tmp.firstChild;\n"
1100             + "  log(tmp.textContent);\n"
1101 
1102             + "  tmp = tmp.nextSibling;\n"
1103             + "  log(tmp.tagName);\n"
1104 
1105             + "  tmp = tmp.nextSibling;\n"
1106             + "  log(tmp.textContent);\n"
1107             + "} catch(e) { logEx(e); }\n"
1108             + "}\n"
1109             + "</script>\n"
1110             + "</head>\n"
1111             + "<body onload='test()'>\n"
1112             + "  <p id='myP'>A para<style>h1 {color:red;} p {color:blue;}</style>graph.</p>\n"
1113             + "</body></html>";
1114 
1115         loadPageVerifyTitle2(html);
1116     }
1117 
1118     /**
1119      * @throws Exception on test failure
1120      */
1121     @Test
1122     @Alerts({"TABLE", "STYLE"})
1123     public void styleInsideTable() throws Exception {
1124         final String html = "<html><head>\n"
1125             + "<script>\n"
1126             + LOG_TITLE_FUNCTION
1127             + "function test() {\n"
1128             + "try {\n"
1129             + "  var tmp = document.getElementById('myP');\n"
1130             + "  log(tmp.tagName);\n"
1131 
1132             + "  tmp = tmp.firstChild;\n"
1133             + "  log(tmp.tagName);\n"
1134             + "} catch(e) { logEx(e); }\n"
1135             + "}\n"
1136             + "</script>\n"
1137             + "</head>\n"
1138             + "<body onload='test()'>\n"
1139             + "  <table id='myP'><style>h1 {color:red;} p {color:blue;}</style></table>\n"
1140             + "</body></html>";
1141 
1142         loadPageVerifyTitle2(html);
1143     }
1144 
1145     /**
1146      * @throws Exception if the test fails
1147      */
1148     @Test
1149     @Alerts({"2", "8"})
1150     public void childNodesDynamicUpdateDuringParsing() throws Exception {
1151         final String html =
1152                 "<html><head>\n"
1153                 + "<script>\n"
1154                 + LOG_TITLE_FUNCTION
1155                 + "</script>\n"
1156                 + "</head>\n"
1157                 + "<body id='id1'>\n"
1158                 + "<script>\n"
1159                 + "  var childNodes = document.getElementById('id1').childNodes;\n"
1160                 + "  log(childNodes.length);\n"
1161                 + "</script>\n"
1162                 + "<h1>My First Heading</h1>\n"
1163                 + "<p>My first paragraph.</p>\n"
1164                 + "<script>\n"
1165                 + "  log(childNodes.length);\n"
1166                 + "</script>\n"
1167                 + "</body></html>";
1168 
1169         loadPageVerifyTitle2(html);
1170     }
1171 }