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.javascript.host.dom;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.annotation.Alerts;
19  import org.htmlunit.junit.annotation.HtmlUnitNYI;
20  import org.junit.jupiter.api.Test;
21  
22  /**
23   * Tests for {@link DocumentFragment}.
24   *
25   * @author Marc Guillemot
26   * @author Ahmed Ashour
27   * @author Ronald Brill
28   * @author Frank Danek
29   */
30  public class DocumentFragmentTest extends WebDriverTestCase {
31  
32      /**
33       * Regression test for bug 3191431 on computation from child selector
34       * in a document fragment.
35       * @throws Exception if the test fails
36       */
37      @Test
38      @Alerts(DEFAULT = "[object CSSStyleDeclaration]",
39              FF = "[object CSSStyleProperties]",
40              FF_ESR = "[object CSS2Properties]")
41      public void getComputedStyleOnChild() throws Exception {
42          final String html = DOCTYPE_HTML
43              + "<html><head><style>\n"
44              + "  body > div { background-color: green#FF0000; }\n"
45              + "</style></head>\n"
46              + "<body>\n"
47              + "<script>\n"
48              + LOG_TITLE_FUNCTION
49              + "  try {\n"
50              + "    var frag = document.createDocumentFragment();\n"
51              + "    var d = document.createElement('div');\n"
52              + "    frag.appendChild(d);\n"
53              + "    log(window.getComputedStyle(d, null));\n"
54              + "  } catch(e) { logEx(e); }\n"
55              + "</script>\n"
56              + "</body>\n"
57              + "</html>";
58  
59          loadPageVerifyTitle2(html);
60      }
61  
62      /**
63       * @throws Exception if the test fails
64       */
65      @Test
66      public void createElement() throws Exception {
67          final String html = DOCTYPE_HTML
68              + "<html>\n"
69              + "  <head>\n"
70              + "    <script>\n"
71              + LOG_TITLE_FUNCTION
72              + "      function test() {\n"
73              + "        var frag = document.createDocumentFragment();\n"
74              + "        if (frag.createElement) {\n"
75              + "          var d = frag.createElement('div');\n"
76              + "          log(d.tagName);\n"
77              + "        }\n"
78              + "      }\n"
79              + "    </script>\n"
80              + "  </head>\n"
81              + "  <body onload='test()'>\n"
82              + "  </body>\n"
83              + "</html>";
84  
85          loadPageVerifyTitle2(html);
86      }
87  
88      /**
89       * @throws Exception if an error occurs
90       */
91      @Test
92      @Alerts({"1", "DIV", "DIV"})
93      public void querySelector() throws Exception {
94          final String html = DOCTYPE_HTML
95              + "<html><head>\n"
96              + "<script>\n"
97              + LOG_TITLE_FUNCTION
98              + "function test() {\n"
99              + "  var frag = document.createDocumentFragment();\n"
100             + "  var d = document.createElement('div');\n"
101             + "  frag.appendChild(d);\n"
102 
103             + "  log(frag.querySelectorAll('div').length);\n"
104             + "  log(frag.querySelectorAll('div')[0].tagName);\n"
105             + "  log(frag.querySelector('div').tagName);\n"
106             + "}\n"
107             + "</script></head>\n"
108             + "<body onload='test()'>\n"
109             + "<div id='root'>\n"
110             + "</div>\n"
111             + "</body></html>";
112 
113         loadPageVerifyTitle2(html);
114     }
115 
116     /**
117      * @throws Exception if an error occurs
118      */
119     @Test
120     @Alerts("0")
121     public void children() throws Exception {
122         final String html = DOCTYPE_HTML
123             + "<html><head>\n"
124             + "<script>\n"
125             + LOG_TITLE_FUNCTION
126             + "function test() {\n"
127             + "  var fragment = document.createDocumentFragment();\n"
128             + "  fragment.textContent = '';\n"
129             + "  log(fragment.childNodes.length);\n"
130             + "}\n"
131             + "</script></head>\n"
132             + "<body onload='test()'>\n"
133             + "</body></html>";
134 
135         loadPageVerifyTitle2(html);
136     }
137 
138     /**
139      * @throws Exception if an error occurs
140      */
141     @Test
142     @Alerts({"[object DocumentFragment]", "undefined"})
143     public void url() throws Exception {
144         final String html = "<!DOCTYPE><html><head>\n"
145             + "<script>\n"
146             + LOG_TITLE_FUNCTION
147             + "function test() {\n"
148             + "  var fragment = document.createDocumentFragment();\n"
149             + "  log(fragment);\n"
150             + "  log(fragment.URL);\n"
151             + "}\n"
152             + "</script></head>\n"
153             + "<body onload='test()'>\n"
154             + "</body></html>";
155 
156         loadPageVerifyTitle2(html);
157     }
158 
159     /**
160      * @throws Exception if the test fails
161      */
162     @Test
163     @Alerts({"0", "null", "null", "1", "myDiv", "myDiv"})
164     public void firstElementChild() throws Exception {
165         final String html = DOCTYPE_HTML
166             + "<html><head>\n"
167             + "<script>\n"
168             + LOG_TITLE_FUNCTION
169             + "  function test() {\n"
170             + "    var fragment = document.createDocumentFragment();\n"
171 
172             + "    log(fragment.childElementCount);\n"
173             + "    log(fragment.firstElementChild);\n"
174             + "    log(fragment.lastElementChild);\n"
175 
176             + "    if (fragment.childElementCount === undefined) { return; };\n"
177 
178             + "    var d = document.createElement('div');\n"
179             + "    d.id = 'myDiv';\n"
180             + "    fragment.appendChild(d);\n"
181             + "    var e = document.createElement('input');\n"
182             + "    e.id = 'first';\n"
183             + "    d.appendChild(e);\n"
184 
185             + "    log(fragment.childElementCount);\n"
186             + "    log(fragment.firstElementChild.id);\n"
187             + "    log(fragment.lastElementChild.id);\n"
188             + "  }\n"
189             + "</script>\n"
190             + "</head>\n"
191             + "<body onload='test()'>\n"
192             + "</body></html>";
193 
194         loadPageVerifyTitle2(html);
195     }
196 
197     /**
198      * @throws Exception if the test fails
199      */
200     @Test
201     @Alerts({"0", "null", "null", "0", "null", "null", "1", "myDiv", "myDiv"})
202     public void firstElementChildTextNode() throws Exception {
203         final String html = DOCTYPE_HTML
204             + "<html><head>\n"
205             + "<script>\n"
206             + LOG_TITLE_FUNCTION
207             + "  function test() {\n"
208             + "    var fragment = document.createDocumentFragment();\n"
209 
210             + "    log(fragment.childElementCount);\n"
211             + "    log(fragment.firstElementChild);\n"
212             + "    log(fragment.lastElementChild);\n"
213 
214             + "    if (fragment.childElementCount === undefined) { return; };\n"
215 
216             + "    var txt = document.createTextNode('HtmlUnit');\n"
217             + "    fragment.appendChild(txt);\n"
218 
219             + "    log(fragment.childElementCount);\n"
220             + "    log(fragment.firstElementChild);\n"
221             + "    log(fragment.lastElementChild);\n"
222 
223             + "    var d = document.createElement('div');\n"
224             + "    d.id = 'myDiv';\n"
225             + "    fragment.appendChild(d);\n"
226 
227             + "    log(fragment.childElementCount);\n"
228             + "    log(fragment.firstElementChild.id);\n"
229             + "    log(fragment.lastElementChild.id);\n"
230             + "  }\n"
231             + "</script>\n"
232             + "</head>\n"
233             + "<body onload='test()'>\n"
234             + "</body></html>";
235 
236         loadPageVerifyTitle2(html);
237     }
238 
239     /**
240      * @throws Exception if the test fails
241      */
242     @Test
243     @Alerts({"null", "null", "null", "null", "[object HTMLDivElement]", "null", "null"})
244     public void getElementById() throws Exception {
245         final String html = DOCTYPE_HTML
246             + "<html>\n"
247             + "<head>\n"
248             + "  <script>\n"
249             + LOG_TITLE_FUNCTION
250             + "  function test() {\n"
251             + "    var fragment = document.createDocumentFragment();\n"
252             + "    var d = document.createElement('div');\n"
253             + "    d.id = 'myDiv';\n"
254             + "    fragment.appendChild(d);\n"
255             + "    var e = document.createElement('input');\n"
256             + "    e.id = 'first';\n"
257             + "    d.appendChild(e);\n"
258 
259             + "    log(document.getElementById(''));\n"
260             + "    log(document.getElementById(undefined));\n"
261             + "    log(document.getElementById(null));\n"
262             + "    log(document.getElementById('unknown'));\n"
263             + "    log(document.getElementById('myDiv'));\n"
264             + "    log(document.getElementById('mydiv'));\n"
265             + "    log(document.getElementById('first'));\n"
266             + "  }\n"
267             + "  </script>\n"
268             + "</head>\n"
269             + "<body onload='test()'>\n"
270             + "<div id='myDiv'>\n"
271             + "  <div></div>\n"
272             + "</div>\n"
273             + "</body>\n"
274             + "</html>";
275 
276         loadPageVerifyTitle2(html);
277     }
278 
279     /**
280      * @throws Exception on test failure
281      */
282     @Test
283     @Alerts({"true", "true"})
284     public void ownerDocument() throws Exception {
285         final String content = DOCTYPE_HTML
286             + "<html>\n"
287             + "<head>\n"
288             + "  <script>\n"
289             + LOG_TITLE_FUNCTION
290             + "    function test() {\n"
291             + "      var fragment = document.createDocumentFragment();\n"
292             + "      log(document === fragment.ownerDocument);\n"
293 
294             + "      var div = document.createElement('div');\n"
295             + "      fragment.appendChild(div);\n"
296             + "      log(div.ownerDocument === document);\n"
297             + "    }\n"
298             + "  </script>\n"
299             + "</head>\n"
300             + "<body onload='test()'>bla\n"
301             + "</body>\n"
302             + "</html>";
303 
304         loadPageVerifyTitle2(content);
305     }
306 
307     /**
308      * @throws Exception on test failure
309      */
310     @Test
311     @Alerts({"false", "true", "false", "true", "false", "true", "true", "false"})
312     public void getRootNode() throws Exception {
313         final String content = DOCTYPE_HTML
314             + "<html>\n"
315             + "<head>\n"
316             + "  <script>\n"
317             + LOG_TITLE_FUNCTION
318             + "    function test() {\n"
319             + "      if (!document.body.getRootNode) {\n"
320             + "        log('-'); return;\n"
321             + "      }\n"
322             + "      var fragment = document.createDocumentFragment();\n"
323             + "      log(document === fragment.getRootNode());\n"
324             + "      log(fragment === fragment.getRootNode());\n"
325 
326             + "      var div = document.createElement('div');\n"
327             + "      fragment.appendChild(div);\n"
328             + "      log(document === div.getRootNode());\n"
329             + "      log(fragment === div.getRootNode());\n"
330 
331             + "      document.body.appendChild(fragment);\n"
332             + "      log(document === fragment.getRootNode());\n"
333             + "      log(fragment === fragment.getRootNode());\n"
334             + "      log(document === div.getRootNode());\n"
335             + "      log(fragment === div.getRootNode());\n"
336             + "    }\n"
337             + "  </script>\n"
338             + "</head>\n"
339             + "<body onload='test()'>bla\n"
340             + "</body>\n"
341             + "</html>";
342 
343         loadPageVerifyTitle2(content);
344     }
345 
346     /**
347      * @throws Exception on test failure
348      */
349     @Test
350     @Alerts("0")
351     public void ctor() throws Exception {
352         final String content = DOCTYPE_HTML
353             + "<html>\n"
354             + "<head>\n"
355             + "  <script>\n"
356             + LOG_TITLE_FUNCTION
357             + "    function test() {\n"
358             + "      var fragment = new DocumentFragment();\n"
359             + "      log(fragment.querySelectorAll('p').length);\n"
360             + "    }\n"
361             + "  </script>\n"
362             + "</head>\n"
363             + "<body onload='test()'>bla\n"
364             + "</body>\n"
365             + "</html>";
366 
367         loadPageVerifyTitle2(content);
368     }
369 
370     /**
371      * @throws Exception on test failure
372      */
373     @Test
374     @Alerts({"1", "[object HTMLDivElement]"})
375     public void append() throws Exception {
376         final String content = DOCTYPE_HTML
377             + "<html>\n"
378             + "<head>\n"
379             + "  <script>\n"
380             + LOG_TITLE_FUNCTION
381             + "    function test() {\n"
382             + "      let fragment = new DocumentFragment();\n"
383             + "      let div = document.createElement('div');\n"
384             + "      fragment.append(div);"
385             + "      log(fragment.children.length);\n"
386             + "      log(fragment.children[0]);\n"
387             + "    }\n"
388             + "  </script>\n"
389             + "</head>\n"
390             + "<body onload='test()'>bla\n"
391             + "</body>\n"
392             + "</html>";
393 
394         loadPageVerifyTitle2(content);
395     }
396 
397     /**
398      * @throws Exception on test failure
399      */
400     @Test
401     @Alerts("0")
402     public void appendNoParam() throws Exception {
403         final String content = DOCTYPE_HTML
404             + "<html>\n"
405             + "<head>\n"
406             + "  <script>\n"
407             + LOG_TITLE_FUNCTION
408             + "    function test() {\n"
409             + "      let fragment = new DocumentFragment();\n"
410             + "      fragment.append();"
411             + "      log(fragment.children.length);\n"
412             + "    }\n"
413             + "  </script>\n"
414             + "</head>\n"
415             + "<body onload='test()'>bla\n"
416             + "</body>\n"
417             + "</html>";
418 
419         loadPageVerifyTitle2(content);
420     }
421 
422     /**
423      * @throws Exception on test failure
424      */
425     @Test
426     @Alerts({"1", "[object Text]", "abcd",
427              "2", "[object Text]", "1234"})
428     public void appendText() throws Exception {
429         final String content = DOCTYPE_HTML
430             + "<html>\n"
431             + "<head>\n"
432             + "  <script>\n"
433             + LOG_TITLE_FUNCTION
434             + "    function test() {\n"
435             + "      let fragment = new DocumentFragment();\n"
436             + "      fragment.append('abcd');"
437             + "      log(fragment.childNodes.length);\n"
438             + "      log(fragment.childNodes[0]);\n"
439             + "      log(fragment.childNodes[0].textContent);\n"
440 
441             + "      let txt = document.createTextNode('1234');\n"
442             + "      fragment.append(txt);"
443             + "      log(fragment.childNodes.length);\n"
444             + "      log(fragment.childNodes[1]);\n"
445             + "      log(fragment.childNodes[1].textContent);\n"
446             + "    }\n"
447             + "  </script>\n"
448             + "</head>\n"
449             + "<body onload='test()'>bla\n"
450             + "</body>\n"
451             + "</html>";
452 
453         loadPageVerifyTitle2(content);
454     }
455 
456     /**
457      * @throws Exception on test failure
458      */
459     @Test
460     @Alerts({"1", "[object HTMLDivElement]",
461              "2", "[object Text]", "abcd",
462              "3", "[object HTMLDivElement]",
463              "4", "[object Text]", "1234",
464              "5", "[object HTMLDivElement]"})
465     public void appendMixed() throws Exception {
466         final String content = DOCTYPE_HTML
467             + "<html>\n"
468             + "<head>\n"
469             + "  <script>\n"
470             + LOG_TITLE_FUNCTION
471             + "    function test() {\n"
472             + "      let fragment = new DocumentFragment();\n"
473 
474             + "      let div = document.createElement('div');\n"
475             + "      fragment.append(div);"
476             + "      log(fragment.childNodes.length);\n"
477             + "      log(fragment.childNodes[0]);\n"
478 
479             + "      fragment.append('abcd');"
480             + "      log(fragment.childNodes.length);\n"
481             + "      log(fragment.childNodes[1]);\n"
482             + "      log(fragment.childNodes[1].textContent);\n"
483 
484             + "      div = document.createElement('div');\n"
485             + "      fragment.append(div);"
486             + "      log(fragment.childNodes.length);\n"
487             + "      log(fragment.childNodes[2]);\n"
488 
489             + "      let txt = document.createTextNode('1234');\n"
490             + "      fragment.append(txt);"
491             + "      log(fragment.childNodes.length);\n"
492             + "      log(fragment.childNodes[3]);\n"
493             + "      log(fragment.childNodes[3].textContent);\n"
494 
495             + "      div = document.createElement('div');\n"
496             + "      fragment.append(div);"
497             + "      log(fragment.childNodes.length);\n"
498             + "      log(fragment.childNodes[4]);\n"
499             + "    }\n"
500             + "  </script>\n"
501             + "</head>\n"
502             + "<body onload='test()'>bla\n"
503             + "</body>\n"
504             + "</html>";
505 
506         loadPageVerifyTitle2(content);
507     }
508 
509     /**
510      * @throws Exception on test failure
511      */
512     @Test
513     @Alerts({"1", "[object HTMLDivElement]"})
514     public void prepend() throws Exception {
515         final String content = DOCTYPE_HTML
516             + "<html>\n"
517             + "<head>\n"
518             + "  <script>\n"
519             + LOG_TITLE_FUNCTION
520             + "    function test() {\n"
521             + "      let fragment = new DocumentFragment();\n"
522             + "      let div = document.createElement('div');\n"
523             + "      fragment.prepend(div);"
524             + "      log(fragment.children.length);\n"
525             + "      log(fragment.children[0]);\n"
526             + "    }\n"
527             + "  </script>\n"
528             + "</head>\n"
529             + "<body onload='test()'>bla\n"
530             + "</body>\n"
531             + "</html>";
532 
533         loadPageVerifyTitle2(content);
534     }
535 
536     /**
537      * @throws Exception on test failure
538      */
539     @Test
540     @Alerts("0")
541     public void prependNoParam() throws Exception {
542         final String content = DOCTYPE_HTML
543             + "<html>\n"
544             + "<head>\n"
545             + "  <script>\n"
546             + LOG_TITLE_FUNCTION
547             + "    function test() {\n"
548             + "      let fragment = new DocumentFragment();\n"
549             + "      fragment.prepend();"
550             + "      log(fragment.children.length);\n"
551             + "    }\n"
552             + "  </script>\n"
553             + "</head>\n"
554             + "<body onload='test()'>bla\n"
555             + "</body>\n"
556             + "</html>";
557 
558         loadPageVerifyTitle2(content);
559     }
560 
561     /**
562      * @throws Exception on test failure
563      */
564     @Test
565     @Alerts({"1", "[object Text]", "abcd",
566              "2", "[object Text]", "1234"})
567     public void prependText() throws Exception {
568         final String content = DOCTYPE_HTML
569             + "<html>\n"
570             + "<head>\n"
571             + "  <script>\n"
572             + LOG_TITLE_FUNCTION
573             + "    function test() {\n"
574             + "      let fragment = new DocumentFragment();\n"
575             + "      fragment.prepend('abcd');"
576             + "      log(fragment.childNodes.length);\n"
577             + "      log(fragment.childNodes[0]);\n"
578             + "      log(fragment.childNodes[0].textContent);\n"
579 
580             + "      let txt = document.createTextNode('1234');\n"
581             + "      fragment.prepend(txt);"
582             + "      log(fragment.childNodes.length);\n"
583             + "      log(fragment.childNodes[0]);\n"
584             + "      log(fragment.childNodes[0].textContent);\n"
585             + "    }\n"
586             + "  </script>\n"
587             + "</head>\n"
588             + "<body onload='test()'>bla\n"
589             + "</body>\n"
590             + "</html>";
591 
592         loadPageVerifyTitle2(content);
593     }
594 
595     /**
596      * @throws Exception on test failure
597      */
598     @Test
599     @Alerts({"1", "[object HTMLDivElement]",
600              "2", "[object Text]", "abcd",
601              "3", "[object HTMLDivElement]",
602              "4", "[object Text]", "1234",
603              "5", "[object HTMLDivElement]"})
604     public void prependMixed() throws Exception {
605         final String content = DOCTYPE_HTML
606             + "<html>\n"
607             + "<head>\n"
608             + "  <script>\n"
609             + LOG_TITLE_FUNCTION
610             + "    function test() {\n"
611             + "      let fragment = new DocumentFragment();\n"
612 
613             + "      let div = document.createElement('div');\n"
614             + "      fragment.prepend(div);"
615             + "      log(fragment.childNodes.length);\n"
616             + "      log(fragment.childNodes[0]);\n"
617 
618             + "      fragment.prepend('abcd');"
619             + "      log(fragment.childNodes.length);\n"
620             + "      log(fragment.childNodes[0]);\n"
621             + "      log(fragment.childNodes[0].textContent);\n"
622 
623             + "      div = document.createElement('div');\n"
624             + "      fragment.prepend(div);"
625             + "      log(fragment.childNodes.length);\n"
626             + "      log(fragment.childNodes[0]);\n"
627 
628             + "      let txt = document.createTextNode('1234');\n"
629             + "      fragment.prepend(txt);"
630             + "      log(fragment.childNodes.length);\n"
631             + "      log(fragment.childNodes[0]);\n"
632             + "      log(fragment.childNodes[0].textContent);\n"
633 
634             + "      div = document.createElement('div');\n"
635             + "      fragment.prepend(div);"
636             + "      log(fragment.childNodes.length);\n"
637             + "      log(fragment.childNodes[0]);\n"
638             + "    }\n"
639             + "  </script>\n"
640             + "</head>\n"
641             + "<body onload='test()'>bla\n"
642             + "</body>\n"
643             + "</html>";
644 
645         loadPageVerifyTitle2(content);
646     }
647 
648     /**
649      * @throws Exception on test failure
650      */
651     @Test
652     @Alerts({"1", "[object HTMLDivElement]"})
653     public void replaceChildren() throws Exception {
654         final String content = DOCTYPE_HTML
655             + "<html>\n"
656             + "<head>\n"
657             + "  <script>\n"
658             + LOG_TITLE_FUNCTION
659             + "    function test() {\n"
660             + "      let fragment = new DocumentFragment();\n"
661             + "      let div = document.createElement('div');\n"
662             + "      fragment.replaceChildren(div);"
663             + "      log(fragment.children.length);\n"
664             + "      log(fragment.children[0]);\n"
665             + "    }\n"
666             + "  </script>\n"
667             + "</head>\n"
668             + "<body onload='test()'>bla\n"
669             + "</body>\n"
670             + "</html>";
671 
672         loadPageVerifyTitle2(content);
673     }
674 
675     /**
676      * @throws Exception on test failure
677      */
678     @Test
679     @Alerts("0")
680     public void replaceChildrenNoParam() throws Exception {
681         final String content = DOCTYPE_HTML
682             + "<html>\n"
683             + "<head>\n"
684             + "  <script>\n"
685             + LOG_TITLE_FUNCTION
686             + "    function test() {\n"
687             + "      let fragment = new DocumentFragment();\n"
688             + "      fragment.replaceChildren();"
689             + "      log(fragment.children.length);\n"
690             + "    }\n"
691             + "  </script>\n"
692             + "</head>\n"
693             + "<body onload='test()'>bla\n"
694             + "</body>\n"
695             + "</html>";
696 
697         loadPageVerifyTitle2(content);
698     }
699 
700     /**
701      * @throws Exception on test failure
702      */
703     @Test
704     @Alerts({"1", "[object Text]", "abcd",
705              "1", "[object Text]", "1234"})
706     public void replaceChildrenText() throws Exception {
707         final String content = DOCTYPE_HTML
708             + "<html>\n"
709             + "<head>\n"
710             + "  <script>\n"
711             + LOG_TITLE_FUNCTION
712             + "    function test() {\n"
713             + "      let fragment = new DocumentFragment();\n"
714             + "      fragment.replaceChildren('abcd');"
715             + "      log(fragment.childNodes.length);\n"
716             + "      log(fragment.childNodes[0]);\n"
717             + "      log(fragment.childNodes[0].textContent);\n"
718 
719             + "      let txt = document.createTextNode('1234');\n"
720             + "      fragment.replaceChildren(txt);"
721             + "      log(fragment.childNodes.length);\n"
722             + "      log(fragment.childNodes[0]);\n"
723             + "      log(fragment.childNodes[0].textContent);\n"
724             + "    }\n"
725             + "  </script>\n"
726             + "</head>\n"
727             + "<body onload='test()'>bla\n"
728             + "</body>\n"
729             + "</html>";
730 
731         loadPageVerifyTitle2(content);
732     }
733 
734     /**
735      * @throws Exception on test failure
736      */
737     @Test
738     @Alerts({"1", "[object HTMLDivElement]",
739              "1", "[object Text]", "abcd",
740              "1", "[object HTMLDivElement]",
741              "1", "[object Text]", "1234",
742              "1", "[object HTMLDivElement]"})
743     public void replaceChildrenMixed() throws Exception {
744         final String content = DOCTYPE_HTML
745             + "<html>\n"
746             + "<head>\n"
747             + "  <script>\n"
748             + LOG_TITLE_FUNCTION
749             + "    function test() {\n"
750             + "      let fragment = new DocumentFragment();\n"
751 
752             + "      let div = document.createElement('div');\n"
753             + "      fragment.replaceChildren(div);"
754             + "      log(fragment.childNodes.length);\n"
755             + "      log(fragment.childNodes[0]);\n"
756 
757             + "      fragment.replaceChildren('abcd');"
758             + "      log(fragment.childNodes.length);\n"
759             + "      log(fragment.childNodes[0]);\n"
760             + "      log(fragment.childNodes[0].textContent);\n"
761 
762             + "      div = document.createElement('div');\n"
763             + "      fragment.replaceChildren(div);"
764             + "      log(fragment.childNodes.length);\n"
765             + "      log(fragment.childNodes[0]);\n"
766 
767             + "      let txt = document.createTextNode('1234');\n"
768             + "      fragment.replaceChildren(txt);"
769             + "      log(fragment.childNodes.length);\n"
770             + "      log(fragment.childNodes[0]);\n"
771             + "      log(fragment.childNodes[0].textContent);\n"
772 
773             + "      div = document.createElement('div');\n"
774             + "      fragment.replaceChildren(div);"
775             + "      log(fragment.childNodes.length);\n"
776             + "      log(fragment.childNodes[0]);\n"
777             + "    }\n"
778             + "  </script>\n"
779             + "</head>\n"
780             + "<body onload='test()'>bla\n"
781             + "</body>\n"
782             + "</html>";
783 
784         loadPageVerifyTitle2(content);
785     }
786 
787     /**
788      * @throws Exception if the test fails
789      */
790     @Test
791     @Alerts(DEFAULT = {"DIV", "SPAN", "P", "DIV", "P", "SPAN"},
792             FF_ESR = {"DIV", "SPAN", "P", "no moveBefore()"})
793     public void moveBefore_basic() throws Exception {
794         final String html = DOCTYPE_HTML
795             + "<html><head><script>\n"
796             + LOG_TITLE_FUNCTION
797             + "  function test() {\n"
798             + "    var fragment = document.createDocumentFragment();\n"
799             + "    var div = document.createElement('div');\n"
800             + "    div.id = 'div1';\n"
801             + "    var span = document.createElement('span');\n"
802             + "    span.id = 'span1';\n"
803             + "    var p = document.createElement('p');\n"
804             + "    p.id = 'p1';\n"
805             + "    fragment.appendChild(div);\n"
806             + "    fragment.appendChild(span);\n"
807             + "    fragment.appendChild(p);\n"
808 
809             + "    log(fragment.childNodes[0].tagName);\n"
810             + "    log(fragment.childNodes[1].tagName);\n"
811             + "    log(fragment.childNodes[2].tagName);\n"
812 
813             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
814 
815             + "    fragment.moveBefore(p, span);\n"
816             + "    log(fragment.childNodes[0].tagName);\n"
817             + "    log(fragment.childNodes[1].tagName);\n"
818             + "    log(fragment.childNodes[2].tagName);\n"
819             + "  }\n"
820             + "</script></head>\n"
821             + "<body onload='test()'>\n"
822             + "</body></html>";
823         loadPageVerifyTitle2(html);
824     }
825 
826     /**
827      * @throws Exception if the test fails
828      */
829     @Test
830     @Alerts(DEFAULT = {"DIV", "SPAN", "P", "P", "DIV", "SPAN"},
831             FF_ESR = {"DIV", "SPAN", "P", "no moveBefore()"})
832     public void moveBefore_moveToFirst() throws Exception {
833         final String html = DOCTYPE_HTML
834             + "<html><head><script>\n"
835             + LOG_TITLE_FUNCTION
836             + "  function test() {\n"
837             + "    var fragment = document.createDocumentFragment();\n"
838             + "    var div = document.createElement('div');\n"
839             + "    div.id = 'div1';\n"
840             + "    var span = document.createElement('span');\n"
841             + "    span.id = 'span1';\n"
842             + "    var p = document.createElement('p');\n"
843             + "    p.id = 'p1';\n"
844             + "    fragment.appendChild(div);\n"
845             + "    fragment.appendChild(span);\n"
846             + "    fragment.appendChild(p);\n"
847 
848             + "    log(fragment.childNodes[0].tagName);\n"
849             + "    log(fragment.childNodes[1].tagName);\n"
850             + "    log(fragment.childNodes[2].tagName);\n"
851 
852             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
853 
854             + "    fragment.moveBefore(p, div);\n"
855             + "    log(fragment.childNodes[0].tagName);\n"
856             + "    log(fragment.childNodes[1].tagName);\n"
857             + "    log(fragment.childNodes[2].tagName);\n"
858             + "  }\n"
859             + "</script></head>\n"
860             + "<body onload='test()'>\n"
861             + "</body></html>";
862         loadPageVerifyTitle2(html);
863     }
864 
865     /**
866      * @throws Exception if the test fails
867      */
868     @Test
869     @Alerts(DEFAULT = {"DIV", "SPAN", "P", "DIV", "SPAN", "P"},
870             FF_ESR = {"DIV", "SPAN", "P", "no moveBefore()"})
871     public void moveBefore_samePosition() throws Exception {
872         final String html = DOCTYPE_HTML
873             + "<html><head><script>\n"
874             + LOG_TITLE_FUNCTION
875             + "  function test() {\n"
876             + "    var fragment = document.createDocumentFragment();\n"
877             + "    var div = document.createElement('div');\n"
878             + "    div.id = 'div1';\n"
879             + "    var span = document.createElement('span');\n"
880             + "    span.id = 'span1';\n"
881             + "    var p = document.createElement('p');\n"
882             + "    p.id = 'p1';\n"
883             + "    fragment.appendChild(div);\n"
884             + "    fragment.appendChild(span);\n"
885             + "    fragment.appendChild(p);\n"
886 
887             + "    log(fragment.childNodes[0].tagName);\n"
888             + "    log(fragment.childNodes[1].tagName);\n"
889             + "    log(fragment.childNodes[2].tagName);\n"
890 
891             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
892 
893             + "    fragment.moveBefore(span, p);\n"
894             + "    log(fragment.childNodes[0].tagName);\n"
895             + "    log(fragment.childNodes[1].tagName);\n"
896             + "    log(fragment.childNodes[2].tagName);\n"
897             + "  }\n"
898             + "</script></head>\n"
899             + "<body onload='test()'>\n"
900             + "</body></html>";
901         loadPageVerifyTitle2(html);
902     }
903 
904     /**
905      * @throws Exception if the test fails
906      */
907     @Test
908     @Alerts(DEFAULT = {"DIV", "SPAN", "P", "DIV", "SPAN", "P"},
909             FF_ESR = {"DIV", "SPAN", "P", "no moveBefore()"})
910     public void moveBefore_samePositionFirst() throws Exception {
911         final String html = DOCTYPE_HTML
912             + "<html><head><script>\n"
913             + LOG_TITLE_FUNCTION
914             + "  function test() {\n"
915             + "    var fragment = document.createDocumentFragment();\n"
916             + "    var div = document.createElement('div');\n"
917             + "    div.id = 'div1';\n"
918             + "    var span = document.createElement('span');\n"
919             + "    span.id = 'span1';\n"
920             + "    var p = document.createElement('p');\n"
921             + "    p.id = 'p1';\n"
922             + "    fragment.appendChild(div);\n"
923             + "    fragment.appendChild(span);\n"
924             + "    fragment.appendChild(p);\n"
925 
926             + "    log(fragment.childNodes[0].tagName);\n"
927             + "    log(fragment.childNodes[1].tagName);\n"
928             + "    log(fragment.childNodes[2].tagName);\n"
929 
930             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
931 
932             + "    fragment.moveBefore(div, span);\n"
933             + "    log(fragment.childNodes[0].tagName);\n"
934             + "    log(fragment.childNodes[1].tagName);\n"
935             + "    log(fragment.childNodes[2].tagName);\n"
936             + "  }\n"
937             + "</script></head>\n"
938             + "<body onload='test()'>\n"
939             + "</body></html>";
940         loadPageVerifyTitle2(html);
941     }
942 
943     /**
944      * @throws Exception if the test fails
945      */
946     @Test
947     @Alerts(DEFAULT = {"DIV", "SPAN", "P", "DIV", "SPAN", "P"},
948             FF_ESR = {"DIV", "SPAN", "P", "no moveBefore()"})
949     public void moveBefore_itself() throws Exception {
950         final String html = DOCTYPE_HTML
951             + "<html><head><script>\n"
952             + LOG_TITLE_FUNCTION
953             + "  function test() {\n"
954             + "    var fragment = document.createDocumentFragment();\n"
955             + "    var div = document.createElement('div');\n"
956             + "    div.id = 'div1';\n"
957             + "    var span = document.createElement('span');\n"
958             + "    span.id = 'span1';\n"
959             + "    var p = document.createElement('p');\n"
960             + "    p.id = 'p1';\n"
961             + "    fragment.appendChild(div);\n"
962             + "    fragment.appendChild(span);\n"
963             + "    fragment.appendChild(p);\n"
964 
965             + "    log(fragment.childNodes[0].tagName);\n"
966             + "    log(fragment.childNodes[1].tagName);\n"
967             + "    log(fragment.childNodes[2].tagName);\n"
968 
969             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
970 
971             + "    fragment.moveBefore(span, span);\n"
972             + "    log(fragment.childNodes[0].tagName);\n"
973             + "    log(fragment.childNodes[1].tagName);\n"
974             + "    log(fragment.childNodes[2].tagName);\n"
975             + "  }\n"
976             + "</script></head>\n"
977             + "<body onload='test()'>\n"
978             + "</body></html>";
979         loadPageVerifyTitle2(html);
980     }
981 
982     /**
983      * @throws Exception if the test fails
984      */
985     @Test
986     @Alerts(DEFAULT = "HierarchyRequestError/DOMException",
987             FF_ESR = "no moveBefore()")
988     public void moveBefore_ancestor() throws Exception {
989         final String html = DOCTYPE_HTML
990             + "<html><head><script>\n"
991             + LOG_TITLE_FUNCTION
992             + "  function test() {\n"
993             + "    var fragment = document.createDocumentFragment();\n"
994             + "    var div = document.createElement('div');\n"
995             + "    div.id = 'div1';\n"
996             + "    var span = document.createElement('span');\n"
997             + "    span.id = 'span1';\n"
998             + "    fragment.appendChild(div);\n"
999             + "    div.appendChild(span);\n"
1000 
1001             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1002 
1003             + "    try {\n"
1004             + "      span.moveBefore(div, null);\n"
1005             + "      log('success');\n"
1006             + "    } catch(e) {\n"
1007             + "      logEx(e);\n"
1008             + "    }\n"
1009             + "  }\n"
1010             + "</script></head>\n"
1011             + "<body onload='test()'>\n"
1012             + "</body></html>";
1013         loadPageVerifyTitle2(html);
1014     }
1015 
1016     /**
1017      * @throws Exception if the test fails
1018      */
1019     @Test
1020     @Alerts(DEFAULT = "NotFoundError/DOMException",
1021             FF_ESR = "no moveBefore()")
1022     public void moveBefore_differentParents() throws Exception {
1023         final String html = DOCTYPE_HTML
1024             + "<html><head><script>\n"
1025             + LOG_TITLE_FUNCTION
1026             + "  function test() {\n"
1027             + "    var fragment1 = document.createDocumentFragment();\n"
1028             + "    var fragment2 = document.createDocumentFragment();\n"
1029             + "    var div = document.createElement('div');\n"
1030             + "    div.id = 'div1';\n"
1031             + "    var p = document.createElement('p');\n"
1032             + "    p.id = 'p1';\n"
1033             + "    fragment1.appendChild(div);\n"
1034             + "    fragment2.appendChild(p);\n"
1035 
1036             + "    if (!fragment1.moveBefore) { log('no moveBefore()'); return; }\n"
1037 
1038             + "    try {\n"
1039             + "      fragment1.moveBefore(div, p);\n"
1040             + "      log('success');\n"
1041             + "    } catch(e) {\n"
1042             + "      logEx(e);\n"
1043             + "    }\n"
1044             + "  }\n"
1045             + "</script></head>\n"
1046             + "<body onload='test()'>\n"
1047             + "</body></html>";
1048         loadPageVerifyTitle2(html);
1049     }
1050 
1051     /**
1052      * @throws Exception if the test fails
1053      */
1054     @Test
1055     @Alerts(DEFAULT = "NotFoundError/DOMException",
1056             FF_ESR = "no moveBefore()")
1057     public void moveBefore_descendant() throws Exception {
1058         final String html = DOCTYPE_HTML
1059             + "<html><head><script>\n"
1060             + LOG_TITLE_FUNCTION
1061             + "  function test() {\n"
1062             + "    var fragment = document.createDocumentFragment();\n"
1063             + "    var div = document.createElement('div');\n"
1064             + "    div.id = 'div1';\n"
1065             + "    var span = document.createElement('span');\n"
1066             + "    span.id = 'span1';\n"
1067             + "    var p = document.createElement('p');\n"
1068             + "    p.id = 'p1';\n"
1069             + "    fragment.appendChild(div);\n"
1070             + "    div.appendChild(span);\n"
1071             + "    fragment.appendChild(p);\n"
1072 
1073             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1074 
1075             + "    try {\n"
1076             + "      div.moveBefore(span, fragment);\n"
1077             + "      log('success');\n"
1078             + "    } catch(e) {\n"
1079             + "      logEx(e);\n"
1080             + "    }\n"
1081             + "  }\n"
1082             + "</script></head>\n"
1083             + "<body onload='test()'>\n"
1084             + "</body></html>";
1085         loadPageVerifyTitle2(html);
1086     }
1087 
1088     /**
1089      * @throws Exception if the test fails
1090      */
1091     @Test
1092     @Alerts(DEFAULT = "NotFoundError/DOMException",
1093             FF_ESR = "no moveBefore()")
1094     public void moveBefore_movedNotChild() throws Exception {
1095         final String html = DOCTYPE_HTML
1096             + "<html><head><script>\n"
1097             + LOG_TITLE_FUNCTION
1098             + "  function test() {\n"
1099             + "    var fragment1 = document.createDocumentFragment();\n"
1100             + "    var fragment2 = document.createDocumentFragment();\n"
1101             + "    var span = document.createElement('span');\n"
1102             + "    span.id = 'span1';\n"
1103             + "    var p = document.createElement('p');\n"
1104             + "    p.id = 'p1';\n"
1105             + "    fragment1.appendChild(span);\n"
1106             + "    fragment2.appendChild(p);\n"
1107 
1108             + "    if (!fragment1.moveBefore) { log('no moveBefore()'); return; }\n"
1109 
1110             + "    try {\n"
1111             + "      fragment1.moveBefore(span, p);\n"
1112             + "      log('success');\n"
1113             + "    } catch(e) {\n"
1114             + "      logEx(e);\n"
1115             + "    }\n"
1116             + "  }\n"
1117             + "</script></head>\n"
1118             + "<body onload='test()'>\n"
1119             + "</body></html>";
1120         loadPageVerifyTitle2(html);
1121     }
1122 
1123     /**
1124      * @throws Exception if the test fails
1125      */
1126     @Test
1127     @Alerts(DEFAULT = "NotFoundError/DOMException",
1128             FF_ESR = "no moveBefore()")
1129     public void moveBefore_referenceNotChild() throws Exception {
1130         final String html = DOCTYPE_HTML
1131             + "<html><head><script>\n"
1132             + LOG_TITLE_FUNCTION
1133             + "  function test() {\n"
1134             + "    var fragment1 = document.createDocumentFragment();\n"
1135             + "    var fragment2 = document.createDocumentFragment();\n"
1136             + "    var span = document.createElement('span');\n"
1137             + "    span.id = 'span1';\n"
1138             + "    var p = document.createElement('p');\n"
1139             + "    p.id = 'p1';\n"
1140             + "    fragment1.appendChild(span);\n"
1141             + "    fragment2.appendChild(p);\n"
1142 
1143             + "    if (!fragment1.moveBefore) { log('no moveBefore()'); return; }\n"
1144 
1145             + "    try {\n"
1146             + "      fragment1.moveBefore(span, p);\n"
1147             + "      log('success');\n"
1148             + "    } catch(e) {\n"
1149             + "      logEx(e);\n"
1150             + "    }\n"
1151             + "  }\n"
1152             + "</script></head>\n"
1153             + "<body onload='test()'>\n"
1154             + "</body></html>";
1155         loadPageVerifyTitle2(html);
1156     }
1157 
1158     /**
1159      * @throws Exception if the test fails
1160      */
1161     @Test
1162     @Alerts(DEFAULT = {"SPAN", "DIV", "P", "3", "A"},
1163             FF_ESR = "no moveBefore()")
1164     public void moveBefore_preservesChildren() throws Exception {
1165         final String html = DOCTYPE_HTML
1166             + "<html><head><script>\n"
1167             + LOG_TITLE_FUNCTION
1168             + "  function test() {\n"
1169             + "    var fragment = document.createDocumentFragment();\n"
1170             + "    var div = document.createElement('div');\n"
1171             + "    div.id = 'div1';\n"
1172             + "    var spanA = document.createElement('span');\n"
1173             + "    spanA.textContent = 'A';\n"
1174             + "    var spanB = document.createElement('span');\n"
1175             + "    spanB.textContent = 'B';\n"
1176             + "    var spanC = document.createElement('span');\n"
1177             + "    spanC.textContent = 'C';\n"
1178             + "    div.appendChild(spanA);\n"
1179             + "    div.appendChild(spanB);\n"
1180             + "    div.appendChild(spanC);\n"
1181             + "    var span = document.createElement('span');\n"
1182             + "    span.id = 'span1';\n"
1183             + "    var p = document.createElement('p');\n"
1184             + "    p.id = 'p1';\n"
1185             + "    fragment.appendChild(span);\n"
1186             + "    fragment.appendChild(p);\n"
1187             + "    fragment.appendChild(div);\n"
1188 
1189             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1190 
1191             + "    fragment.moveBefore(div, p);\n"
1192             + "    log(fragment.childNodes[0].tagName);\n"
1193             + "    log(fragment.childNodes[1].tagName);\n"
1194             + "    log(fragment.childNodes[2].tagName);\n"
1195             + "    log(div.children.length);\n"
1196             + "    log(div.children[0].textContent);\n"
1197             + "  }\n"
1198             + "</script></head>\n"
1199             + "<body onload='test()'>\n"
1200             + "</body></html>";
1201         loadPageVerifyTitle2(html);
1202     }
1203 
1204     /**
1205      * @throws Exception if the test fails
1206      */
1207     @Test
1208     @Alerts(DEFAULT = {"text1", "myClass"},
1209             FF_ESR = "no moveBefore()")
1210     public void moveBefore_preservesAttributes() throws Exception {
1211         final String html = DOCTYPE_HTML
1212             + "<html><head><script>\n"
1213             + LOG_TITLE_FUNCTION
1214             + "  function test() {\n"
1215             + "    var fragment = document.createDocumentFragment();\n"
1216             + "    var div = document.createElement('div');\n"
1217             + "    div.id = 'div1';\n"
1218             + "    div.setAttribute('data-test', 'text1');\n"
1219             + "    div.className = 'myClass';\n"
1220             + "    var span = document.createElement('span');\n"
1221             + "    span.id = 'span1';\n"
1222             + "    fragment.appendChild(span);\n"
1223             + "    fragment.appendChild(div);\n"
1224 
1225             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1226 
1227             + "    fragment.moveBefore(div, span);\n"
1228             + "    log(div.getAttribute('data-test'));\n"
1229             + "    log(div.className);\n"
1230             + "  }\n"
1231             + "</script></head>\n"
1232             + "<body onload='test()'>\n"
1233             + "</body></html>";
1234         loadPageVerifyTitle2(html);
1235     }
1236 
1237     /**
1238      * @throws Exception if the test fails
1239      */
1240     @Test
1241     @Alerts(DEFAULT = "true",
1242             FF_ESR = "no moveBefore()")
1243     public void moveBefore_returnValue() throws Exception {
1244         final String html = DOCTYPE_HTML
1245             + "<html><head><script>\n"
1246             + LOG_TITLE_FUNCTION
1247             + "  function test() {\n"
1248             + "    var fragment = document.createDocumentFragment();\n"
1249             + "    var div = document.createElement('div');\n"
1250             + "    div.id = 'div1';\n"
1251             + "    var span = document.createElement('span');\n"
1252             + "    span.id = 'span1';\n"
1253             + "    fragment.appendChild(span);\n"
1254             + "    fragment.appendChild(div);\n"
1255 
1256             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1257 
1258             + "    var result = fragment.moveBefore(div, span);\n"
1259             + "    log(result === undefined);\n"
1260             + "  }\n"
1261             + "</script></head>\n"
1262             + "<body onload='test()'>\n"
1263             + "</body></html>";
1264         loadPageVerifyTitle2(html);
1265     }
1266 
1267     /**
1268      * @throws Exception if the test fails
1269      */
1270     @Test
1271     @Alerts(DEFAULT = {"DIV", "P", "SPAN", "SECTION"},
1272             FF_ESR = "no moveBefore()")
1273     public void moveBefore_multipleOperations() throws Exception {
1274         final String html = DOCTYPE_HTML
1275             + "<html><head><script>\n"
1276             + LOG_TITLE_FUNCTION
1277             + "  function test() {\n"
1278             + "    var fragment = document.createDocumentFragment();\n"
1279             + "    var div = document.createElement('div');\n"
1280             + "    div.id = 'div1';\n"
1281             + "    var span = document.createElement('span');\n"
1282             + "    span.id = 'span1';\n"
1283             + "    var p = document.createElement('p');\n"
1284             + "    p.id = 'p1';\n"
1285             + "    var section = document.createElement('section');\n"
1286             + "    section.id = 'section1';\n"
1287             + "    fragment.appendChild(div);\n"
1288             + "    fragment.appendChild(span);\n"
1289             + "    fragment.appendChild(p);\n"
1290             + "    fragment.appendChild(section);\n"
1291 
1292             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1293 
1294             + "    fragment.moveBefore(section, span);\n"
1295             + "    fragment.moveBefore(p, section);\n"
1296             + "    fragment.moveBefore(span, section);\n"
1297 
1298             + "    log(fragment.childNodes[0].tagName);\n"
1299             + "    log(fragment.childNodes[1].tagName);\n"
1300             + "    log(fragment.childNodes[2].tagName);\n"
1301             + "    log(fragment.childNodes[3].tagName);\n"
1302             + "  }\n"
1303             + "</script></head>\n"
1304             + "<body onload='test()'>\n"
1305             + "</body></html>";
1306         loadPageVerifyTitle2(html);
1307     }
1308 
1309     /**
1310      * @throws Exception if the test fails
1311      */
1312     @Test
1313     @Alerts(DEFAULT = {"2", "DIV", "SPAN"},
1314             FF_ESR = "no moveBefore()")
1315     public void moveBefore_nullReferenceNode() throws Exception {
1316         final String html = DOCTYPE_HTML
1317             + "<html><head><script>\n"
1318             + LOG_TITLE_FUNCTION
1319             + "  function test() {\n"
1320             + "    var fragment = document.createDocumentFragment();\n"
1321             + "    var div = document.createElement('div');\n"
1322             + "    div.id = 'div1';\n"
1323             + "    var span = document.createElement('span');\n"
1324             + "    span.id = 'span1';\n"
1325             + "    fragment.appendChild(span);\n"
1326             + "    fragment.appendChild(div);\n"
1327 
1328             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1329 
1330             + "    fragment.moveBefore(span, null);\n"
1331 
1332             + "    log(fragment.childNodes.length);\n"
1333             + "    log(fragment.childNodes[0].tagName);\n"
1334             + "    log(fragment.childNodes[1].tagName);\n"
1335             + "  }\n"
1336             + "</script></head>\n"
1337             + "<body onload='test()'>\n"
1338             + "</body></html>";
1339         loadPageVerifyTitle2(html);
1340     }
1341 
1342     /**
1343      * @throws Exception if the test fails
1344      */
1345     @Test
1346     @Alerts(DEFAULT = "NotFoundError/DOMException",
1347             FF_ESR = "no moveBefore()")
1348     public void moveBefore_detachedReferenceNode() throws Exception {
1349         final String html = DOCTYPE_HTML
1350             + "<html><head><script>\n"
1351             + LOG_TITLE_FUNCTION
1352             + "  function test() {\n"
1353             + "    var fragment = document.createDocumentFragment();\n"
1354             + "    var div = document.createElement('div');\n"
1355             + "    div.id = 'div1';\n"
1356             + "    var divDetached = document.createElement('div');\n"
1357             + "    fragment.appendChild(div);\n"
1358 
1359             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1360 
1361             + "    try {\n"
1362             + "      fragment.moveBefore(div, divDetached);\n"
1363             + "      log('success');\n"
1364             + "    } catch(e) {\n"
1365             + "      logEx(e);\n"
1366             + "    }\n"
1367             + "  }\n"
1368             + "</script></head>\n"
1369             + "<body onload='test()'>\n"
1370             + "</body></html>";
1371         loadPageVerifyTitle2(html);
1372     }
1373 
1374     /**
1375      * @throws Exception if the test fails
1376      */
1377     @Test
1378     @Alerts(DEFAULT = "HierarchyRequestError/DOMException",
1379             FF_ESR = "no moveBefore()")
1380     @HtmlUnitNYI(CHROME = "success", EDGE = "success", FF = "success")
1381     public void moveBefore_detachedMovedNode() throws Exception {
1382         final String html = DOCTYPE_HTML
1383             + "<html><head><script>\n"
1384             + LOG_TITLE_FUNCTION
1385             + "  function test() {\n"
1386             + "    var fragment = document.createDocumentFragment();\n"
1387             + "    var div = document.createElement('div');\n"
1388             + "    div.id = 'div1';\n"
1389             + "    var divDetached = document.createElement('div');\n"
1390             + "    fragment.appendChild(div);\n"
1391 
1392             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1393 
1394             + "    try {\n"
1395             + "      fragment.moveBefore(divDetached, div);\n"
1396             + "      log('success');\n"
1397             + "    } catch(e) {\n"
1398             + "      logEx(e);\n"
1399             + "    }\n"
1400             + "  }\n"
1401             + "</script></head>\n"
1402             + "<body onload='test()'>\n"
1403             + "</body></html>";
1404         loadPageVerifyTitle2(html);
1405     }
1406 
1407     /**
1408      * @throws Exception if the test fails
1409      */
1410     @Test
1411     @Alerts(DEFAULT = "TypeError",
1412             FF_ESR = "no moveBefore()")
1413     public void moveBefore_missingArgs() throws Exception {
1414         final String html = DOCTYPE_HTML
1415             + "<html><head><script>\n"
1416             + LOG_TITLE_FUNCTION
1417             + "  function test() {\n"
1418             + "    var fragment = document.createDocumentFragment();\n"
1419 
1420             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1421 
1422             + "    try {\n"
1423             + "      fragment.moveBefore();\n"
1424             + "      log('success');\n"
1425             + "    } catch(e) {\n"
1426             + "      logEx(e);\n"
1427             + "    }\n"
1428             + "  }\n"
1429             + "</script></head>\n"
1430             + "<body onload='test()'>\n"
1431             + "</body></html>";
1432         loadPageVerifyTitle2(html);
1433     }
1434 
1435     /**
1436      * @throws Exception if the test fails
1437      */
1438     @Test
1439     @Alerts(DEFAULT = "TypeError",
1440             FF_ESR = "no moveBefore()")
1441     public void moveBefore_missingReferenceNode() throws Exception {
1442         final String html = DOCTYPE_HTML
1443             + "<html><head><script>\n"
1444             + LOG_TITLE_FUNCTION
1445             + "  function test() {\n"
1446             + "    var fragment = document.createDocumentFragment();\n"
1447             + "    var div = document.createElement('div');\n"
1448             + "    fragment.appendChild(div);\n"
1449 
1450             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1451 
1452             + "    try {\n"
1453             + "      fragment.moveBefore(div);\n"
1454             + "      log('success');\n"
1455             + "    } catch(e) {\n"
1456             + "      logEx(e);\n"
1457             + "    }\n"
1458             + "  }\n"
1459             + "</script></head>\n"
1460             + "<body onload='test()'>\n"
1461             + "</body></html>";
1462         loadPageVerifyTitle2(html);
1463     }
1464 
1465     /**
1466      * @throws Exception if the test fails
1467      */
1468     @Test
1469     @Alerts(DEFAULT = "true",
1470             FF_ESR = "no moveBefore()")
1471     @HtmlUnitNYI(CHROME = "false", EDGE = "false", FF = "false")
1472     public void moveBefore_staysInDocument() throws Exception {
1473         final String html = DOCTYPE_HTML
1474             + "<html><head><script>\n"
1475             + LOG_TITLE_FUNCTION
1476             + "  function test() {\n"
1477             + "    var fragment = document.createDocumentFragment();\n"
1478             + "    var div = document.createElement('div');\n"
1479             + "    div.id = 'div1';\n"
1480             + "    var span = document.createElement('span');\n"
1481             + "    span.id = 'span1';\n"
1482             + "    fragment.appendChild(span);\n"
1483             + "    fragment.appendChild(div);\n"
1484 
1485             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1486 
1487             + "    fragment.moveBefore(div, span);\n"
1488             + "    log(fragment.contains(div));\n"
1489             + "  }\n"
1490             + "</script></head>\n"
1491             + "<body onload='test()'>\n"
1492             + "</body></html>";
1493         loadPageVerifyTitle2(html);
1494     }
1495 
1496     /**
1497      * @throws Exception if the test fails
1498      */
1499     @Test
1500     @Alerts(DEFAULT = {"2", "SPAN", "DIV", "1", "SPAN", "3", "SPAN", "DIV", "DIV", "0", "1", "SPAN"},
1501             FF_ESR = "no moveBefore()")
1502     public void moveBefore_nullLevelUp() throws Exception {
1503         final String html = DOCTYPE_HTML
1504             + "<html><head><script>\n"
1505             + LOG_TITLE_FUNCTION
1506             + "  function test() {\n"
1507             + "    var fragment = document.createDocumentFragment();\n"
1508             + "    var span = document.createElement('span');\n"
1509             + "    span.id = 'span1';\n"
1510             + "    fragment.appendChild(span);\n"
1511             + "    var div1 = document.createElement('div');\n"
1512             + "    div1.id = 'div1';\n"
1513             + "    fragment.appendChild(div1);\n"
1514             + "    var div2 = document.createElement('div');\n"
1515             + "    div2.id = 'div2';\n"
1516             + "    div1.appendChild(div2);\n"
1517             + "    span = document.createElement('span');\n"
1518             + "    div2.appendChild(span);\n"
1519 
1520             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1521 
1522             + "    log(fragment.children.length);\n"
1523             + "    log(fragment.children[0].tagName);\n"
1524             + "    log(fragment.children[1].tagName);\n"
1525 
1526             + "    log(div2.children.length);\n"
1527             + "    log(div2.children[0].tagName);\n"
1528 
1529             + "    fragment.moveBefore(div2, null);\n"
1530 
1531             + "    log(fragment.children.length);\n"
1532             + "    log(fragment.children[0].tagName);\n"
1533             + "    log(fragment.children[1].tagName);\n"
1534             + "    log(fragment.children[2].tagName);\n"
1535 
1536             + "    log(div1.children.length);\n"
1537             + "    log(div2.children.length);\n"
1538             + "    log(div2.children[0].tagName);\n"
1539             + "  }\n"
1540             + "</script></head>\n"
1541             + "<body onload='test()'>\n"
1542             + "</body></html>";
1543         loadPageVerifyTitle2(html);
1544     }
1545 
1546     /**
1547      * @throws Exception if the test fails
1548      */
1549     @Test
1550     @Alerts(DEFAULT = "TypeError",
1551             FF_ESR = "no moveBefore()")
1552     public void moveBefore_wrongMovedNode() throws Exception {
1553         final String html = DOCTYPE_HTML
1554             + "<html><head><script>\n"
1555             + LOG_TITLE_FUNCTION
1556             + "  function test() {\n"
1557             + "    var fragment = document.createDocumentFragment();\n"
1558             + "    var span = document.createElement('span');\n"
1559             + "    span.id = 'span1';\n"
1560             + "    fragment.appendChild(span);\n"
1561 
1562             + "    var parent = document.getElementById('parent');\n"
1563             + "    var div = document.getElementById('div');\n"
1564             + "    var divDetached = document.createElement('div');\n"
1565 
1566             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1567 
1568             + "    try {\n"
1569             + "      fragment.moveBefore('HtmlUnit', null);\n"
1570             + "      log('success');\n"
1571             + "    } catch(e) {\n"
1572             + "      logEx(e);\n"
1573             + "    }\n"
1574             + "  }\n"
1575             + "</script></head>\n"
1576             + "<body onload='test()'>\n"
1577             + "</body></html>";
1578         loadPageVerifyTitle2(html);
1579     }
1580 
1581     /**
1582      * @throws Exception if the test fails
1583      */
1584     @Test
1585     @Alerts(DEFAULT = "TypeError",
1586             FF_ESR = "no moveBefore()")
1587     public void moveBefore_wrongReferenceNodeNode() throws Exception {
1588         final String html = DOCTYPE_HTML
1589             + "<html><head><script>\n"
1590             + LOG_TITLE_FUNCTION
1591             + "  function test() {\n"
1592             + "    var fragment = document.createDocumentFragment();\n"
1593             + "    var span = document.createElement('span');\n"
1594             + "    span.id = 'span1';\n"
1595             + "    fragment.appendChild(span);\n"
1596 
1597             + "    if (!fragment.moveBefore) { log('no moveBefore()'); return; }\n"
1598 
1599             + "    try {\n"
1600             + "      fragment.moveBefore(span, 'HtmlUnit');\n"
1601             + "      log('success');\n"
1602             + "    } catch(e) {\n"
1603             + "      logEx(e);\n"
1604             + "    }\n"
1605             + "  }\n"
1606             + "</script></head>\n"
1607             + "<body onload='test()'>\n"
1608             + "</body></html>";
1609         loadPageVerifyTitle2(html);
1610     }
1611 }