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.html;
16  
17  import static java.nio.charset.StandardCharsets.ISO_8859_1;
18  import static java.nio.charset.StandardCharsets.UTF_8;
19  
20  import java.net.URL;
21  import java.nio.charset.StandardCharsets;
22  import java.util.List;
23  
24  import org.htmlunit.MockWebConnection;
25  import org.htmlunit.WebDriverTestCase;
26  import org.htmlunit.junit.BrowserRunner;
27  import org.htmlunit.junit.annotation.Alerts;
28  import org.htmlunit.junit.annotation.HtmlUnitNYI;
29  import org.htmlunit.util.MimeType;
30  import org.junit.Test;
31  import org.junit.runner.RunWith;
32  import org.openqa.selenium.By;
33  import org.openqa.selenium.WebDriver;
34  import org.openqa.selenium.WebElement;
35  
36  /**
37   * Tests for {@link HTMLDocument}'s write(ln) function.
38   *
39   * @author Ahmed Ashour
40   * @author Marc Guillemot
41   * @author Frank Danek
42   * @author Ronald Brill
43   */
44  @RunWith(BrowserRunner.class)
45  public class HTMLDocumentWrite2Test extends WebDriverTestCase {
46  
47      /**
48       * @throws Exception if the test fails
49       */
50      @Test
51      @Alerts("[object HTMLDocument]")
52      public void openResult() throws Exception {
53          final String html = DOCTYPE_HTML
54              + "<html>\n"
55              + "<head>\n"
56              + "<script>\n"
57              + LOG_WINDOW_NAME_FUNCTION
58              + "function test() {\n"
59              + "  var res = document.open();\n"
60              + "  log(res);\n"
61              + "  document.close();\n"
62              + "}\n"
63              + "</script>\n"
64              + "</head>\n"
65              + "<body onload='setTimeout(test, 4);'>\n"
66              + "</body>\n"
67              + "</html>";
68  
69          loadPage2(html);
70          verifyWindowName2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
71      }
72  
73      /**
74       * @throws Exception if the test fails
75       */
76      @Test
77      @Alerts("Hello There")
78      public void write() throws Exception {
79          final String html = DOCTYPE_HTML
80              + "<html>\n"
81              + "<head>\n"
82              + "<title>Test</title>\n"
83              + "<script>\n"
84              + LOG_WINDOW_NAME_FUNCTION
85              + "function test() {\n"
86              + "  document.write('<html><body><scr'+'ipt>log(\"Hello There\")</scr'+'ipt></body></html>');\n"
87              + "}\n"
88              + "</script>\n"
89              + "</head>\n"
90              + "<body onload='setTimeout(test, 4);'>\n"
91              + "</body>\n"
92              + "</html>";
93  
94          loadPage2(html);
95          verifyWindowName2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
96      }
97  
98      /**
99       * @throws Exception if the test fails
100      */
101     @Test
102     public void writeSomeTags() throws Exception {
103         final String html = DOCTYPE_HTML
104             + "<html><head></head>\n"
105             + "<body>\n"
106             + "<script>\n"
107             + "document.write(\"<div id='div1'></div>\");\n"
108             + "document.write('<div', \" id='div2'>\", '</div>');\n"
109             + "document.writeln('<p', \" id='p3'>\", '</p>');\n"
110             + "</script>\n"
111             + "</form></body></html>";
112 
113         final WebDriver driver = loadPage2(html);
114 
115         assertEquals("div", driver.findElement(By.id("div1")).getTagName());
116         assertEquals("div", driver.findElement(By.id("div2")).getTagName());
117         assertEquals("p", driver.findElement(By.id("p3")).getTagName());
118     }
119 
120     /**
121      * <a href="https://sourceforge.net/tracker/?func=detail&aid=2855731&group_id=47038&atid=448266">Bug 2855731</a>.
122      * @throws Exception if an error occurs
123      */
124     @Test
125     @Alerts("1")
126     public void write_nested() throws Exception {
127         final String html = DOCTYPE_HTML
128             + "<html><body><script>\n"
129             + LOG_WINDOW_NAME_FUNCTION
130             + "var s = '\"<script>log(1);<\\/scr\" + \"ipt>\"';\n"
131             + "document.write('<script><!--\\ndocument.write(' + s + ');\\n--><\\/script>');\n"
132             + "</script></body></html>";
133 
134         loadPage2(html);
135         verifyWindowName2(getWebDriver(), getExpectedAlerts());
136     }
137 
138     /**
139      * Caused infinite loop at some point of 2.6 snapshot.
140      * See <a href="http://sourceforge.net/support/tracker.php?aid=2824922">Bug 2824922</a>
141      * @throws Exception if the test fails
142      */
143     @Test
144     public void write2_html_endhtml_in_head() throws Exception {
145         final String html = DOCTYPE_HTML
146             + "<html><head>\n"
147             + "<script>\n"
148             + "document.write('<HTML></HTML>');\n"
149             + "</script>\n"
150             + "</head><body>\n"
151             + "</body></html>\n";
152 
153         loadPage2(html);
154     }
155 
156     /**
157      * We couldn't document.write() script elements that contained the '&lt;' character...
158      * @exception Exception if the test fails
159      */
160     @Test
161     @Alerts("true")
162     public void writeScript() throws Exception {
163         final String html = DOCTYPE_HTML
164             + "<html><body><script>\n"
165             + LOG_WINDOW_NAME_FUNCTION
166             + "  document.write('<scr'+'ipt>log(1<2)</sc'+'ript>');\n"
167             + "</script></body></html>";
168 
169         loadPage2(html);
170         verifyWindowName2(getWebDriver(), getExpectedAlerts());
171     }
172 
173     /**
174      * @throws Exception if the test fails
175      */
176     @Test
177     public void writeUnicode() throws Exception {
178         final String html = DOCTYPE_HTML
179             + "<html><body><script>\n"
180             + "document.open();\n"
181             + "document.write('<div id=\"assert\">Hello worl\u0414</div>');\n"
182             + "document.close();\n"
183             + "</script>\n"
184             + "</body></html>";
185 
186         final WebDriver driver = loadPage2(html, URL_FIRST, "text/html; charset=UTF-8", UTF_8);
187         final String result = driver.findElement(By.id("assert")).getText();
188         assertEquals("Hello worl\u0414", result);
189     }
190 
191     /**
192      * @throws Exception if the test fails
193      */
194     @Test
195     public void writeISO_8859_1() throws Exception {
196         final String html = DOCTYPE_HTML
197             + "<html><body><script>\n"
198             + "document.open();\n"
199             + "document.write('<div id=\"assert\">\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc</div>');\n"
200             + "document.close();\n"
201             + "</script>\n"
202             + "</body></html>";
203 
204         final WebDriver driver = loadPage2(html, URL_FIRST, "text/html; charset=ISO-8859-1", ISO_8859_1);
205         final String result = driver.findElement(By.id("assert")).getText();
206         assertEquals("\u00e4\u00f6\u00fc\u00c4\u00d6\u00dc", result);
207     }
208 
209     /**
210      * @throws Exception if the test fails
211      */
212     @Test
213     public void open_FF() throws Exception {
214         final String html = DOCTYPE_HTML
215             + "<html><head><title>foo</title><script>\n"
216             + "  function performAction() {\n"
217             + "    actionwindow = window.open('', '1205399746518', "
218             + "'location=no,scrollbars=no,resizable=no,width=200,height=275');\n"
219             + "    actionwindow.document.writeln('Please wait while connecting to server...');\n"
220             + "    actionwindow.focus();\n"
221             + "    actionwindow.close();\n"
222             + "  }\n"
223             + "</script></head><body>\n"
224             + "  <input value='Click Me' type=button onclick='performAction()'>\n"
225             + "</body></html>";
226 
227         final WebDriver driver = loadPageWithAlerts2(html);
228         driver.findElement(By.xpath("//input")).click();
229     }
230 
231     /**
232      * Regression test for bug 2884585.
233      * As of HtmlUnit-2.7-SNAPSHOT 17.01.2010 &lt;script src="..."... written
234      * by document.write was not loaded and executed after the &lt;/script&gt;
235      * when the page was loaded as result of a click.
236      * @throws Exception if the test fails
237      */
238     @Test
239     @Alerts({" after-write Hello", " after-write Hello after-write Hello"})
240     public void writeExternalScriptAfterClick() throws Exception {
241         shutDownAll();
242 
243         final String html = DOCTYPE_HTML
244             + "<html><head>\n"
245             + "<script>\n"
246             + "document.write('<scr'+'ipt src=\"script.js\"></scr'+'ipt>');\n"
247             + "window.name += ' after-write ';\n"
248             + "</script>\n"
249             + "<script>\n"
250             + "window.name += window.foo;\n"
251             + "</script>\n"
252             + "</head>\n"
253             + "<body>\n"
254             + "<a href='?again'>a link</a>\n"
255             + "</body>\n"
256             + "</html>";
257 
258         getMockWebConnection().setDefaultResponse("window.foo = 'Hello'", MimeType.TEXT_JAVASCRIPT);
259         final WebDriver driver = loadPage2(html);
260         verifyJsVariable(driver, "window.top.name", getExpectedAlerts()[0]);
261 
262         driver.findElement(By.linkText("a link")).click();
263         verifyJsVariable(driver, "window.top.name", getExpectedAlerts()[1]);
264     }
265 
266     /**
267      * Regression test for bug 2921851.
268      * @throws Exception if the test fails
269      */
270     @Test
271     @Alerts("#1")
272     @HtmlUnitNYI(CHROME = "#0",
273             EDGE = "#0",
274             FF = "#0",
275             FF_ESR = "#0")
276     public void writeInNewWindowAndReadFormCollection() throws Exception {
277         final String html = DOCTYPE_HTML
278             + "<html><head>\n"
279             + "<script>\n"
280             + "function test() {\n"
281             + "  var newWin = window.open('', 'myPopup', '');\n"
282             + "  var newDoc = newWin.document;\n"
283             + "  newDoc.write('<html><body><form name=newForm></form></body></html>');\n"
284             + "  document.title = '#' + newDoc.forms.length;\n"
285             + "}\n"
286             + "</script></head>\n"
287             + "<body onload='test()'>\n"
288             + "</body></html>";
289 
290         final WebDriver driver = loadPage2(html);
291         assertTitle(driver, getExpectedAlerts()[0]);
292     }
293 
294     /**
295      * Partial regression test for bug 2921851: use opener URL as base URL
296      * for resolution of relative URLs in document.write.
297      * @throws Exception if the test fails
298      */
299     @Test
300     @Alerts({"2", "§§URL§§foo"})
301     public void urlResolutionInWriteForm() throws Exception {
302         final String html = DOCTYPE_HTML
303             + "<html><head>\n"
304             + "<script>\n"
305             + "function test() {\n"
306             + "  var newWin = window.open('', 'myPopup', '');\n"
307             + "  var d = newWin.document;\n"
308             + "  d.write('<html><body><form action=foo method=post><input type=submit id=it></form></body></html>');\n"
309             + "  d.close();\n"
310             + "}\n"
311             + "</script></head>\n"
312             + "<body onload='test()'>\n"
313             + "</body></html>";
314 
315         final int startCount = getMockWebConnection().getRequestCount();
316         expandExpectedAlertsVariables(URL_FIRST);
317 
318         getMockWebConnection().setDefaultResponse("");
319         final WebDriver driver = loadPage2(html);
320         driver.switchTo().window("myPopup");
321         driver.findElement(By.id("it")).click();
322         if (useRealBrowser()) {
323             Thread.sleep(400);
324         }
325 
326         assertEquals(Integer.parseInt(getExpectedAlerts()[0]),
327                 getMockWebConnection().getRequestCount() - startCount);
328         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest().getUrl());
329     }
330 
331     /**
332      * Partial regression test for bug 2921851: the window returned by <tt>window.open()</tt> should
333      * be proxied (i.e. "live").
334      * @throws Exception if an error occurs
335      */
336     @Test
337     @Alerts("<form></form>#[object HTMLFormElement]")
338     public void writeOnOpenedWindow_WindowIsProxied() throws Exception {
339         final String html = DOCTYPE_HTML
340             + "<html><head><script>\n"
341             + "function test() {\n"
342             + "  var w = window.open('','blah','width=460,height=420');\n"
343             + "  w.document.write('<html><body><form></form></body></html>');\n"
344             + "  w.document.close();\n"
345             + "  document.title = w.document.body.innerHTML;\n"
346             + "  document.title += '#' + w.document.forms[0];\n"
347             + "}\n"
348             + "</script></head>\n"
349             + "<body onload='test()'>\n"
350             + "</body></html>";
351 
352         final WebDriver driver = loadPage2(html);
353         assertTitle(driver, getExpectedAlerts()[0]);
354     }
355 
356     /**
357      * Partial regression test for bug 2921851: the document returned by <tt>window.document</tt> should
358      * be proxied (i.e. "live").
359      * @throws Exception if an error occurs
360      */
361     @Test
362     @Alerts("<form></form>#[object HTMLFormElement]")
363     public void writeOnOpenedWindow_DocumentIsProxied() throws Exception {
364         final String html = DOCTYPE_HTML
365             + "<html><head><script>\n"
366             + "function test() {\n"
367             + "  var w = window.open('','blah','width=460,height=420');\n"
368             + "  var d = w.document;\n"
369             + "  d.write('<html><body><form></form></body></html>');\n"
370             + "  d.close();\n"
371             + "  document.title = d.body.innerHTML;\n"
372             + "  document.title += '#' + d.forms[0];\n"
373             + "}\n"
374             + "</script></head><body onload='test()'>foo</body></html>";
375 
376         try {
377             final WebDriver driver = loadPage2(html);
378             assertTitle(driver, getExpectedAlerts()[0]);
379         }
380         finally {
381             shutDownAll();
382         }
383     }
384 
385     /**
386      * This was causing a StackOverflowError.
387      *
388      * @throws Exception if an error occurs
389      */
390     @Test
391     public void writeInFrameWithOnload() throws Exception {
392         final String html = DOCTYPE_HTML
393             + "<html><head></head>\n"
394             + "<body>\n"
395             + "<iframe id='theIframe' src='about:blank'></iframe>\n"
396             + "<script>\n"
397             + "var doc = document.getElementById('theIframe').contentWindow.document;\n"
398             + "doc.open();\n"
399             + "doc.write('<html>');\n"
400             + "doc.write('<body onload=\"document.getElementById(\\'foo\\')\">');\n"
401             + "doc.write('</body></html>');\n"
402             + "doc.close();\n"
403             + "</script>\n"
404             + "</body>\n"
405             + "</html>";
406         loadPageWithAlerts2(html);
407     }
408 
409     /**
410      * Regression test for bug 743241.
411      * @throws Exception if the test fails
412      */
413     @Test
414     public void write_loadScript() throws Exception {
415         final String html = DOCTYPE_HTML
416             + "<html><head><title>First</title></head><body>\n"
417             + "<script src='script.js'></script>\n"
418             + "</form></body></html>";
419 
420         final String script = "document.write(\"<div id='div1'>hello</div>\");\n";
421         getMockWebConnection().setDefaultResponse(script, MimeType.TEXT_JAVASCRIPT);
422 
423         final WebDriver driver = loadPage2(html);
424         assertTitle(driver, "First");
425 
426         assertEquals("hello", driver.findElement(By.id("div1")).getText());
427     }
428 
429     /**
430      * @throws Exception if an error occurs
431      */
432     @Test
433     public void write_fromScriptAddedWithAppendChild_inline() throws Exception {
434         final String html = DOCTYPE_HTML
435             + "<html><head></head><body>\n"
436             + "<div id='it'><script>\n"
437             + LOG_WINDOW_NAME_FUNCTION
438             + "try {\n"
439             + "  var s = document.createElement('script');\n"
440             + "  var t = document.createTextNode(\"document.write('in inline script'); document.title = 'done';\");\n"
441             + "  s.appendChild(t);\n"
442             + "  document.body.appendChild(s);\n"
443             + "} catch(e) { logEx(e); }\n"
444             + "</script></div></body></html>";
445 
446         final WebDriver driver = loadPage2(html);
447         verifyWindowName2(getWebDriver(), getExpectedAlerts());
448 
449         assertTitle(driver, "done");
450         assertEquals("in inline script", driver.findElement(By.id("it")).getText());
451     }
452 
453     /**
454      * @throws Exception if an error occurs
455      */
456     @Test
457     public void write_fromScriptAddedWithAppendChild_external() throws Exception {
458         final String html = DOCTYPE_HTML
459                 + "<html><head></head><body>\n"
460                 + "<div id='it'>here</div><script>\n"
461                 + "  var s = document.createElement('script');\n"
462                 + "  s.src = 'foo.js';\n"
463                 + "  document.body.appendChild(s);\n"
464                 + "</script></body></html>";
465 
466         final String js = "document.write('from external script');\n"
467                     + "document.title = 'done';";
468 
469         getMockWebConnection().setDefaultResponse(js, MimeType.TEXT_JAVASCRIPT);
470         final WebDriver driver = loadPage2(html);
471 
472         assertTitle(driver, "done");
473         assertEquals("here", driver.findElement(By.id("it")).getText());
474         assertEquals("here", driver.findElement(By.tagName("body")).getText());
475     }
476 
477     /**
478      * Verifies that document.write() sends content to the correct destination (always somewhere in the body).
479      * @throws Exception if an error occurs
480      */
481     @Test
482     @Alerts({"null", "[object HTMLBodyElement]", "s1 s2 s3 s4 s5"})
483     public void write_Destination() throws Exception {
484         final String html = DOCTYPE_HTML
485             + "<html>\n"
486             + "  <head>\n"
487             + "    <script>" + LOG_WINDOW_NAME_FUNCTION + "</script>\n"
488             + "    <script>log(document.body);</script>\n"
489             + "    <script>document.write('<span id=\"s1\">1</span>');</script>\n"
490             + "    <script>log(document.body);</script>\n"
491             + "    <title>test</title>\n"
492             + "    <script>document.write('<span id=\"s2\">2</span>');</script>\n"
493             + "  </head>\n"
494             + "  <body id='foo'>\n"
495             + "    <script>document.write('<span id=\"s3\">3</span>');</script>\n"
496             + "    <span id='s4'>4</span>\n"
497             + "    <script>document.write('<span id=\"s5\">5</span>');</script>\n"
498             + "    <script>\n"
499             + "      var s = '';\n"
500             + "      for(var n = document.body.firstChild; n; n = n.nextSibling) {\n"
501             + "        if(n.id) {\n"
502             + "          if(s.length > 0) s+= ' ';\n"
503             + "            s += n.id;\n"
504             + "        }\n"
505             + "      }\n"
506             + "      log(s);\n"
507             + "    </script>\n"
508             + "  </body>\n"
509             + "</html>";
510 
511         loadPage2(html);
512         verifyWindowName2(getWebDriver(), getExpectedAlerts());
513     }
514 
515     /**
516      * Verifies that document.write() sends content to the correct destination (always somewhere in the body),
517      * and that if a synthetic temporary body needs to be created, the attributes of the real body are eventually
518      * used once the body is parsed.
519      * @throws Exception if an error occurs
520      */
521     @Test
522     @Alerts({"null", "[object HTMLBodyElement]", "", "foo"})
523     public void write_BodyAttributesKept() throws Exception {
524         final String html = DOCTYPE_HTML
525             + "<html>\n"
526             + "  <head>\n"
527             + "    <script>" + LOG_WINDOW_NAME_FUNCTION + "</script>\n"
528             + "    <script>log(document.body);</script>\n"
529             + "    <script>document.write('<span id=\"s1\">1</span>');</script>\n"
530             + "    <script>log(document.body);</script>\n"
531             + "    <script>log(document.body.id);</script>\n"
532             + "    <title>test</title>\n"
533             + "  </head>\n"
534             + "  <body id='foo'>\n"
535             + "    <script>log(document.body.id);</script>\n"
536             + "  </body>\n"
537             + "</html>";
538 
539         loadPage2(html);
540         verifyWindowName2(getWebDriver(), getExpectedAlerts());
541     }
542 
543     /**
544      * Verifies that document.write() sends content to the correct destination (always somewhere in the body),
545      * and that script elements written to the document are executed in the correct order.
546      * @throws Exception if an error occurs
547      */
548     @Test
549     @Alerts({"1", "2", "3"})
550     public void write_ScriptExecutionOrder() throws Exception {
551         final String html = DOCTYPE_HTML
552             + "<html>\n"
553             + "  <head>\n"
554             + "    <title>test</title>\n"
555             + "    <script>" + LOG_WINDOW_NAME_FUNCTION + "</script>\n"
556             + "    <script>log('1');</script>\n"
557             + "    <script>document.write('<scrip'+'t>log(\"2\")</s'+'cript>');</script>\n"
558             + "  </head>\n"
559             + "  <body>\n"
560             + "    <script>document.write('<scrip'+'t>log(\"3\")</s'+'cript>');</script>\n"
561             + "  </body>\n"
562             + "</html>";
563 
564         loadPage2(html);
565         verifyWindowName2(getWebDriver(), getExpectedAlerts());
566     }
567 
568     /**
569      * @throws Exception if the test fails
570      */
571     @Test
572     @Alerts("outer")
573     public void writeInManyTimes() throws Exception {
574         final String html = DOCTYPE_HTML
575             + "<html><head><title>foo</title><script>\n"
576             + LOG_WINDOW_NAME_FUNCTION
577             + "function doTest() {\n"
578             + "  log(document.getElementById('inner').parentNode.id);\n"
579             + "}\n"
580             + "</script></head>\n"
581             + "<body onload='doTest()'>\n"
582             + "<script>\n"
583             + "document.write('<div id=\"outer\">');\n"
584             + "document.write('<div id=\"inner\"/>');\n"
585             + "document.write('</div>');\n"
586             + "</script>\n"
587             + "</body></html>";
588 
589         loadPage2(html);
590         verifyWindowName2(getWebDriver(), getExpectedAlerts());
591     }
592 
593     /**
594      * Test for bug 1185389.
595      * @throws Exception if the test fails
596      */
597     @Test
598     @Alerts({"theBody", "theBody", "theBody"})
599     public void writeAddNodesToCorrectParent() throws Exception {
600         final String html = DOCTYPE_HTML
601              + "<html><head><title>foo</title></head>\n"
602              + "<body id=\"theBody\">\n"
603              + "<script>\n"
604              + LOG_WINDOW_NAME_FUNCTION
605              + "document.write('<p id=\"para1\">Paragraph #1</p>');\n"
606              + "document.write('<p id=\"para2\">Paragraph #2</p>');\n"
607              + "document.write('<p id=\"para3\">Paragraph #3</p>');\n"
608              + "log(document.getElementById('para1').parentNode.id);\n"
609              + "log(document.getElementById('para2').parentNode.id);\n"
610              + "log(document.getElementById('para3').parentNode.id);\n"
611              + "</script>\n"
612              + "</body></html>";
613 
614         loadPage2(html);
615         verifyWindowName2(getWebDriver(), getExpectedAlerts());
616     }
617 
618     /**
619      * Test for bug 436.
620      * http://sourceforge.net/p/htmlunit/bugs/436/
621      * @throws Exception if the test fails
622      */
623     @Test
624     @Alerts({"outer", "inner1"})
625     public void writeAddNodesToCorrectParent_Bug1678826() throws Exception {
626         final String html = DOCTYPE_HTML
627              + "<html><head><title>foo</title><script>\n"
628              + LOG_WINDOW_NAME_FUNCTION
629              + "function doTest() {\n"
630              + "  log(document.getElementById('inner1').parentNode.id);\n"
631              + "  log(document.getElementById('inner2').parentNode.id);\n"
632              + "}\n"
633              + "</script></head>\n"
634              + "<body onload='doTest()'>\n"
635              + "<script>\n"
636              + "document.write('<div id=\"outer\">');\n"
637              + "document.write('<br id=\"br1\">');\n"
638              + "document.write('<div id=\"inner1\"/>');\n"
639              + "document.write('<hr id=\"hr1\"/>');\n"
640              + "document.write('<div id=\"inner2\"/>');\n"
641              + "document.write('</div>');\n"
642              + "</script>\n"
643              + "</body></html>";
644 
645         loadPage2(html);
646         verifyWindowName2(getWebDriver(), getExpectedAlerts());
647 
648         releaseResources();
649         shutDownAll();
650     }
651 
652      /**
653       * @throws Exception if the test fails
654       */
655     @Test
656     @Alerts({"STYLE", "SCRIPT"})
657     public void writeStyle() throws Exception {
658         final String html = DOCTYPE_HTML
659              + "<html><head><title>foo</title></head><body>\n"
660              + "<script>\n"
661              + LOG_WINDOW_NAME_FUNCTION
662              + "  document.write('<style type=\"text/css\" id=\"myStyle\">');\n"
663              + "  document.write('  .nwr {white-space: nowrap;}');\n"
664              + "  document.write('</style>');\n"
665              + "  document.write('<div id=\"myDiv\">');\n"
666              + "  document.write('</div>');\n"
667              + "  log(document.getElementById('myDiv').previousSibling.nodeName);\n"
668              + "  log(document.getElementById('myStyle').previousSibling.nodeName);\n"
669              + "</script>\n"
670              + "</body></html>";
671 
672         loadPage2(html);
673         verifyWindowName2(getWebDriver(), getExpectedAlerts());
674     }
675 
676     /**
677      * @throws Exception if the test fails
678      */
679     @Test
680     public void openReplace() throws Exception {
681         final String html = DOCTYPE_HTML
682             + "<html>\n"
683             + "<head>\n"
684             + "  <title>Test</title>\n"
685             + "<script>\n"
686             + "function test() {\n"
687             + "  var htmlDocument = '<html><head>"
688                     + "<script>document.title = \"parsed script executed\";</' + 'script>"
689                     + "</head><body>After</body</head>';\n"
690             + "  var newHTML = document.open('text/html', 'replace');\n"
691             + "  newHTML.write(htmlDocument);\n"
692             + "  newHTML.close();\n"
693             + "}\n"
694             + "</script>\n"
695             + "</head>\n"
696             + "<body onload='setTimeout(test, 4);'>\n"
697             + " Before\n"
698             + "</body>\n"
699             + "</html>";
700 
701         final WebDriver driver = loadPageWithAlerts2(html);
702         assertTitle(driver, "parsed script executed");
703         assertEquals("After", driver.findElement(By.tagName("body")).getText());
704     }
705 
706     /**
707      * Verifies that scripts added to the document via document.write(...) don't execute until the current script
708      * finishes executing; bug found at <a href="http://code.google.com/apis/maps/">the Google Maps API site</a>.
709      * @throws Exception if an error occurs
710      */
711     @Test
712     public void write_scriptExecutionPostponed() throws Exception {
713         final String html = DOCTYPE_HTML
714             + "<html><body>\n"
715             + "<div id='d'></div>\n"
716             + "<script>function log(s) { document.getElementById('d').innerHTML += s + ' '; }</script>\n"
717             + "<script src='a.js'></script>\n"
718             + "<script>log(2);document.write('<scr'+'ipt src=\"b.js\"></scr'+'ipt>');log(3);</script>\n"
719             + "<script src='c.js'></script>\n"
720             + "<script>\n"
721             + "  log(6);document.write('<scr'+'ipt src=\"d.js\"></scr'+'ipt>');log(7);\n"
722             + "  log(8);document.write('<scr'+'ipt src=\"e.js\"></scr'+'ipt>');log(9);\n"
723             + "</script>\n"
724             + "<script src='f.js'></script>\n"
725             + "</body></html>";
726         final MockWebConnection conn = getMockWebConnection();
727         conn.setResponse(URL_FIRST, html);
728         conn.setResponse(new URL(URL_FIRST, "a.js"), "log(1)", MimeType.TEXT_JAVASCRIPT);
729         conn.setResponse(new URL(URL_FIRST, "b.js"), "log(4)", MimeType.TEXT_JAVASCRIPT);
730         conn.setResponse(new URL(URL_FIRST, "c.js"), "log(5)", MimeType.TEXT_JAVASCRIPT);
731         conn.setResponse(new URL(URL_FIRST, "d.js"), "log(10)", MimeType.TEXT_JAVASCRIPT);
732         conn.setResponse(new URL(URL_FIRST, "e.js"), "log(11)", MimeType.TEXT_JAVASCRIPT);
733         conn.setResponse(new URL(URL_FIRST, "f.js"), "log(12)", MimeType.TEXT_JAVASCRIPT);
734 
735         final WebDriver driver = loadPage2(html);
736         assertEquals("1 2 3 4 5 6 7 8 9 10 11 12", driver.findElement(By.tagName("body")).getText());
737     }
738 
739     /**
740      * Regression test for Bug #71.
741      * @throws Exception if the test fails
742      */
743     @Test
744     public void write_script() throws Exception {
745         final URL mainUrl = new URL(URL_FIRST, "main.html");
746         final URL firstUrl = new URL(URL_FIRST, "first.html");
747         final URL secondUrl = new URL(URL_FIRST, "second.html");
748         final URL scriptUrl = new URL(URL_FIRST, "script.js");
749 
750         final String mainHtml = DOCTYPE_HTML
751             + "<html>\n"
752             + "<head><title>Main</title></head>\n"
753             + "<body>\n"
754             + "  <iframe name='iframe' id='iframe' src='" + firstUrl + "'></iframe>\n"
755             + "  <script type='text/javascript'>\n"
756             + "    document.write('<script type=\"text/javascript\" src=\"" + scriptUrl + "\"></' + 'script>');\n"
757             + "  </script>"
758             + "</body></html>";
759 
760         getMockWebConnection().setResponse(mainUrl, mainHtml);
761 
762         final String firstHtml = DOCTYPE_HTML + "<html><body><h1 id='first'>First</h1></body></html>";
763         getMockWebConnection().setResponse(firstUrl, firstHtml);
764 
765         final String secondHtml = DOCTYPE_HTML + "<html><body><h1 id='second'>Second</h1></body></html>";
766         getMockWebConnection().setResponse(secondUrl, secondHtml);
767 
768         final String script = "document.getElementById('iframe').src = '" + secondUrl + "';\n";
769         getMockWebConnection().setResponse(new URL(URL_FIRST, "script.js"), script, MimeType.TEXT_JAVASCRIPT);
770 
771         final WebDriver driver = loadPage2(mainUrl, StandardCharsets.UTF_8);
772         assertEquals("Main", driver.getTitle());
773 
774         final WebElement iframe = driver.findElement(By.id("iframe"));
775         assertEquals(secondUrl.toExternalForm(), iframe.getAttribute("src"));
776 
777         driver.switchTo().frame(iframe);
778         assertEquals("Second", driver.findElement(By.id("second")).getText());
779     }
780 
781     /**
782      * @throws Exception if the test fails
783      */
784     @Test
785     @Alerts({"A", "A"})
786     public void write_InDOM() throws Exception {
787         final String html = DOCTYPE_HTML
788             + "<html>\n"
789             + "<head></head>\n"
790             + "<body>\n"
791             + "  <script type='text/javascript'>\n"
792             + LOG_TITLE_FUNCTION
793             + "    document.write('<a id=\"blah\">Hello World</a>');\n"
794             + "    document.write('<a id=\"blah2\">Hello World 2</a>');\n"
795             + "    log(document.getElementById('blah').tagName);\n"
796             + "    log(document.getElementById('blah2').tagName);\n"
797             + "  </script>\n"
798             + "  <a id='blah3'>Hello World 3</a>\n"
799             + "</body></html>";
800 
801         final WebDriver driver = loadPage2(html);
802         verifyTitle2(driver, getExpectedAlerts());
803 
804         final List<WebElement> anchors = driver.findElements(By.tagName("a"));
805         assertEquals(3, anchors.size());
806         assertEquals("Hello World", anchors.get(0).getText());
807         assertEquals("Hello World 2", anchors.get(1).getText());
808         assertEquals("Hello World 3", anchors.get(2).getText());
809     }
810 
811     /**
812      * Test for bug 1950462: calling document.write inside a function (after assigning
813      * document.write to a local variable) tries to invoke document.write on the prototype
814      * document instance, rather than the actual document host object. This leads to an
815      * {@link IllegalStateException} (DomNode has not been set for this SimpleScriptable).
816      * @throws Exception if an error occurs
817      */
818     @Test
819     @Alerts({"foo called", "exception occurred"})
820     public void write_AssignedToVar2() throws Exception {
821         final String html = DOCTYPE_HTML
822             + "<html>\n"
823             + "<head></head>\n"
824             + "<body>\n"
825             + "<script>\n"
826             + LOG_TITLE_FUNCTION
827             + "  function foo() { log('foo called'); var d = document.write; d(4); }\n"
828             + "  try {\n"
829             + "    foo();\n"
830             + "  } catch(e) { log('exception occurred'); document.write(7); }\n"
831             + "</script>\n"
832             + "</body></html>";
833 
834         final WebDriver driver = loadPage2(html);
835         verifyTitle2(driver, getExpectedAlerts());
836 
837         assertEquals("7", driver.findElement(By.tagName("body")).getText());
838     }
839 
840     /**
841      * Verifies that calling document.write() after document parsing has finished results in a whole
842      * new page being loaded.
843      * @throws Exception if an error occurs
844      */
845     @Test
846     public void write_WhenParsingFinished() throws Exception {
847         final String html = DOCTYPE_HTML
848             + "<html>\n"
849             + "<head>\n"
850             + "<script>\n"
851             + "  function test() { document.write(1); document.write(2); document.close(); }\n"
852             + "</script></head>\n"
853             + "<body>\n"
854             + "  <span id='s' onclick='test()'>click</span>\n"
855             + "</body></html>";
856 
857         final WebDriver driver = loadPage2(html);
858         assertEquals("click", driver.findElement(By.tagName("body")).getText());
859 
860         driver.findElement(By.id("s")).click();
861         assertEquals("12", driver.findElement(By.tagName("body")).getText());
862     }
863 
864     /**
865      * @throws Exception if the test fails
866      */
867     @Test
868     public void writeWithSplitAnchorTag() throws Exception {
869         final String html = DOCTYPE_HTML
870             + "<html>\n"
871             + "<body><script>\n"
872             + "document.write(\"<a href=\'start.html\");\n"
873             + "document.write(\"\'>\");\n"
874             + "document.write('click here</a>');\n"
875             + "</script>\n"
876             + "</body></html>";
877 
878         final WebDriver driver = loadPage2(html);
879 
880         final List<WebElement> anchors = driver.findElements(By.tagName("a"));
881         assertEquals(1, anchors.size());
882         assertEquals("http://localhost:22222/start.html", anchors.get(0).getAttribute("href"));
883         assertEquals("click here", anchors.get(0).getText());
884     }
885 
886     /**
887      * Verifies that calls to document.open() are ignored while the page's HTML is being parsed.
888      * @throws Exception if an error occurs
889      */
890     @Test
891     public void open_IgnoredDuringParsing() throws Exception {
892         final String html = DOCTYPE_HTML
893                 + "<html><body>1<script>document.open();document.write('2');</script>3</body></html>";
894 
895         final WebDriver driver = loadPage2(html);
896         assertEquals("123", driver.findElement(By.tagName("body")).getText());
897     }
898 
899     /**
900      * @throws Exception if the test fails
901      */
902     @Test
903     public void writeWithSpace() throws Exception {
904         final String html = DOCTYPE_HTML
905             + "<html>\n"
906             + "<body>\n"
907             + "  <script>\n"
908             + "    document.write('Hello ');\n"
909             + "    document.write('World');\n"
910             + "  </script>\n"
911             + "</body></html>";
912 
913         final WebDriver driver = loadPage2(html);
914         assertEquals("Hello World", driver.findElement(By.tagName("body")).getText());
915     }
916 
917     /**
918      * @throws Exception if the test fails
919      */
920     @Test
921     @Alerts({"0", "foo1", "1", "2", "3", "4", "5", "A", "B", "foo3"})
922     public void writeScriptInManyTimes() throws Exception {
923         final String html = DOCTYPE_HTML
924             + "<html>\n"
925             + "<head>\n"
926             + "<script>\n"
927             + LOG_TITLE_FUNCTION
928             + "  log('0');\n"
929             + "  document.write('<script>log(\"foo1\");</' + 'script>');\n"
930 
931             + "  log('1');\n"
932             + "  document.write('<script src=\"scriptA.js\"></' + 'script>');\n"
933             + "  log('2');\n"
934 
935             + "  document.write('<script src=\"scriptB.js\">');\n"
936             + "  log('3');\n"
937             + "  document.write('<' + '/script>');\n"
938             + "  log('4');\n"
939             + "  document.write('<script>log(\"foo3\");</' + 'script>');\n"
940             + "  log('5');\n"
941             + "</script>\n"
942             + "</head>\n"
943             + "<body>\n"
944             + "</body></html>";
945 
946         final URL scriptUrlA = new URL(URL_FIRST, "scriptA.js");
947         final URL scriptUrlB = new URL(URL_FIRST, "scriptB.js");
948 
949         getMockWebConnection().setDefaultResponse(html);
950         getMockWebConnection().setResponse(scriptUrlA, "log('A');\n", MimeType.TEXT_JAVASCRIPT);
951         getMockWebConnection().setResponse(scriptUrlB, "log('B');\n", MimeType.TEXT_JAVASCRIPT);
952 
953         loadPageVerifyTitle2(html);
954     }
955 
956     /**
957      * @throws Exception if the test fails
958      */
959     @Test
960     @Alerts({"0", "foo1", "1", "foo2", "2", "3", "4", "A", "foo3"})
961     public void writeScriptPostponed() throws Exception {
962         final String html = DOCTYPE_HTML
963             + "<html>\n"
964             + "<head>\n"
965             + "<script>\n"
966             + LOG_TITLE_FUNCTION
967             + "  log('0');\n"
968             + "</script>\n"
969 
970             + "<script>log(\"foo1\");</script>'\n"
971 
972             + "<script>\n"
973             + "  log('1');\n"
974             + "  document.write('<script>log(\"foo2\");</' + 'script>');\n"
975             + "  log('2');\n"
976             + "  document.write('<script src=\"scriptA.js\"></' + 'script>');\n"
977             + "  log('3');\n"
978             + "  document.write('<script>log(\"foo3\");</' + 'script>');\n"
979             + "  log('4');\n"
980             + "</script>\n"
981 
982             + "</head>\n"
983             + "<body>\n"
984             + "</body></html>";
985 
986         final URL scriptUrlA = new URL(URL_FIRST, "scriptA.js");
987 
988         getMockWebConnection().setDefaultResponse(html);
989         getMockWebConnection().setResponse(scriptUrlA, "log('A');\n", MimeType.TEXT_JAVASCRIPT);
990 
991         loadPageVerifyTitle2(html);
992     }
993 
994     /**
995      * @throws Exception if the test fails
996      */
997     @Test
998     @Alerts({"0", "A", "1", "foo2", "2", "3", "4", "B", "foo3"})
999     public void writeScriptPostponedBeforeWrite() throws Exception {
1000         final String html = DOCTYPE_HTML
1001             + "<html>\n"
1002             + "<head>\n"
1003             + "<script>\n"
1004             + LOG_TITLE_FUNCTION
1005             + "  log('0');\n"
1006             + "</script>\n"
1007 
1008             + "<script src='scriptA.js'></script>'\n"
1009 
1010             + "<script>\n"
1011             + "  log('1');\n"
1012             + "  document.write('<script>log(\"foo2\");</' + 'script>');\n"
1013             + "  log('2');\n"
1014             + "  document.write('<script src=\"scriptB.js\"></' + 'script>');\n"
1015             + "  log('3');\n"
1016             + "  document.write('<script>log(\"foo3\");</' + 'script>');\n"
1017             + "  log('4');\n"
1018             + "</script>\n"
1019 
1020             + "</head>\n"
1021             + "<body>\n"
1022             + "</body></html>";
1023 
1024         final URL scriptUrlA = new URL(URL_FIRST, "scriptA.js");
1025         final URL scriptUrlB = new URL(URL_FIRST, "scriptB.js");
1026 
1027         getMockWebConnection().setDefaultResponse(html);
1028         getMockWebConnection().setResponse(scriptUrlA, "log('A');\n", MimeType.TEXT_JAVASCRIPT);
1029         getMockWebConnection().setResponse(scriptUrlB, "log('B');\n", MimeType.TEXT_JAVASCRIPT);
1030 
1031         loadPageVerifyTitle2(html);
1032     }
1033 
1034     /**
1035      * Test for bug 1613119.
1036      * @throws Exception if the test fails
1037      */
1038     @Test
1039     @Alerts({"scr1", "scr2", "null", "null", "[object HTMLScriptElement]", "[object HTMLScriptElement]"})
1040     public void writeAddNodesInCorrectPositions() throws Exception {
1041         final String html = DOCTYPE_HTML
1042             + "<html>\n"
1043             + "<head></head>\n"
1044             + "<body id=\"theBody\">\n"
1045             + "<div id='target1'></div>\n"
1046             + "<script>\n"
1047             + LOG_TITLE_FUNCTION
1048             + "document.write(\""
1049             + "<div>"
1050             + "  <sc\"+\"ript id='scr1'>document.write('<div id=\\\"div1\\\" />');</s\"+\"cript>"
1051             + "  <sc\"+\"ript id='scr2'>document.write('<div id=\\\"div2\\\" />');</s\"+\"cript>"
1052             + "</div>"
1053             + "\");\n"
1054             + "let html = \""
1055             + "<div>"
1056             + "  <sc\"+\"ript id='scr3'>document.write('<div id=\\\"div3\\\" />');</s\"+\"cript>"
1057             + "  <sc\"+\"ript id='scr4'>document.write('<div id=\\\"div4\\\" />');</s\"+\"cript>"
1058             + "</div>"
1059             + "\";"
1060             + "document.getElementById('target1').innerHTML = html;\n"
1061             + "</script>\n"
1062             + "<script>\n"
1063             + "function logId(obj) { log(obj != null ? obj.id : 'null'); }\n"
1064             + "logId(document.getElementById('div1').previousSibling);\n"
1065             + "logId(document.getElementById('div2').previousSibling);\n"
1066             + "log(document.getElementById('div3'));\n"
1067             + "log(document.getElementById('div4'));\n"
1068             + "log(document.getElementById('scr3'));\n"
1069             + "log(document.getElementById('scr4'));\n"
1070 
1071             + "</script>\n"
1072             + "</body></html>";
1073 
1074         loadPageVerifyTitle2(html);
1075     }
1076 
1077     /**
1078      * @throws Exception if the test fails
1079      */
1080     @Test
1081     public void aboutURL() throws Exception {
1082         final String html = DOCTYPE_HTML
1083             + "<html><body><script language='JavaScript'>\n"
1084             + "w2 = window.open('about:blank', 'AboutBlank');\n"
1085             + "w2.document.open();\n"
1086             + "w2.document.write('<html><head><title>hello</title></head><body></body></html>');\n"
1087             + "w2.document.close();\n"
1088             + "</script></body></html>";
1089 
1090         final WebDriver driver = loadPage2(html);
1091         driver.switchTo().window("AboutBlank");
1092         assertEquals("hello", driver.getTitle());
1093     }
1094 
1095     /**
1096      * @throws Exception if an error occurs
1097      */
1098     @Test
1099     @Alerts("§§URL§§")
1100     public void locationAfterWrite() throws Exception {
1101         final String html = DOCTYPE_HTML
1102             + "<html>\n"
1103             + "<head><script>\n"
1104             + "function test() {\n"
1105             + "  window.document.title += 'abcd';\n"
1106             + "  document.open();\n"
1107             + "  document.write("
1108                     + "'<html><body onload=\"window.document.title += document.location + \\'§\\'\"></body></html>');\n"
1109             + "  document.close();\n"
1110             + "}\n"
1111             + "</script></head>\n"
1112             + "<body onload='setTimeout(test, 4);'></body></html>";
1113 
1114         loadPage2(html);
1115         expandExpectedAlertsVariables(URL_FIRST);
1116         verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
1117     }
1118 
1119     /**
1120      * @throws Exception if an error occurs
1121      */
1122     @Test
1123     @Alerts(DEFAULT = {"", "First", "First", "FORM", "true", "true"},
1124             FF = {"", "First", "FORM", "true", "true", "First"},
1125             FF_ESR = {"", "First", "FORM", "true", "true", "First"})
1126     @HtmlUnitNYI(FF = {"", "First", "First", "FORM", "true", "true"},
1127             FF_ESR = {"", "First", "First", "FORM", "true", "true"})
1128     public void newElementsAfterWrite() throws Exception {
1129         final String html = DOCTYPE_HTML
1130             + "<html>"
1131             + "<head><script>\n"
1132             + LOG_WINDOW_NAME_FUNCTION
1133             + "function test() {\n"
1134             + "  log(document.title);\n"
1135             + "  document.open();\n"
1136             + "  document.write('<html><head><title>First</title></head>');\n"
1137             + "  document.write('<body onload=\"log(document.title)\">');\n"
1138             + "  document.write('<form name=\"submitForm\" method=\"post\">');\n"
1139             + "  document.write('</form></body></html>');\n"
1140             + "  document.close();\n"
1141             + "  log(document.title);\n"
1142             + "  log(document.submitForm.tagName);\n"
1143             + "  log(window.document == document);\n"
1144             + "  log(document.submitForm == document.getElementsByTagName('form')[0]);\n"
1145             + "}\n"
1146             + "</script></head>\n"
1147             + "<body onload='setTimeout(test, 4);'></body></html>";
1148 
1149         loadPage2(html);
1150         verifyWindowName2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts());
1151     }
1152 }