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;
16  
17  import static org.junit.Assert.fail;
18  
19  import java.net.URL;
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.Collections;
23  import java.util.LinkedList;
24  import java.util.List;
25  
26  import org.htmlunit.CollectingAlertHandler;
27  import org.htmlunit.ConfirmHandler;
28  import org.htmlunit.DialogWindow;
29  import org.htmlunit.MockWebConnection;
30  import org.htmlunit.OnbeforeunloadHandler;
31  import org.htmlunit.Page;
32  import org.htmlunit.PrintHandler;
33  import org.htmlunit.SimpleWebTestCase;
34  import org.htmlunit.StatusHandler;
35  import org.htmlunit.WebClient;
36  import org.htmlunit.WebConsole;
37  import org.htmlunit.WebConsole.Logger;
38  import org.htmlunit.WebWindow;
39  import org.htmlunit.WebWindowEvent;
40  import org.htmlunit.WebWindowListener;
41  import org.htmlunit.WebWindowNotFoundException;
42  import org.htmlunit.html.HtmlAnchor;
43  import org.htmlunit.html.HtmlButton;
44  import org.htmlunit.html.HtmlButtonInput;
45  import org.htmlunit.html.HtmlElement;
46  import org.htmlunit.html.HtmlInlineFrame;
47  import org.htmlunit.html.HtmlInput;
48  import org.htmlunit.html.HtmlPage;
49  import org.htmlunit.junit.BrowserRunner;
50  import org.htmlunit.junit.annotation.Alerts;
51  import org.htmlunit.junit.annotation.HtmlUnitNYI;
52  import org.htmlunit.util.MimeType;
53  import org.junit.Test;
54  import org.junit.runner.RunWith;
55  
56  /**
57   * Tests for {@link Window}.
58   *
59   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
60   * @author <a href="mailto:chen_jun@users.sourceforge.net">Chen Jun</a>
61   * @author David K. Taylor
62   * @author Darrell DeBoer
63   * @author Marc Guillemot
64   * @author Dierk Koenig
65   * @author Chris Erskine
66   * @author David D. Kilzer
67   * @author Ahmed Ashour
68   * @author Daniel Gredler
69   * @author Frank Danek
70   * @author Ronald Brill
71   */
72  @RunWith(BrowserRunner.class)
73  public class WindowTest extends SimpleWebTestCase {
74  
75      /**
76       * @throws Exception if the test fails
77       */
78      @Test
79      public void openWindow() throws Exception {
80          final WebClient webClient = getWebClient();
81          final MockWebConnection webConnection = new MockWebConnection();
82  
83          final List<String> collectedAlerts = new ArrayList<>();
84          webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
85  
86          final String firstContent = DOCTYPE_HTML
87              + "<html><head><title>First</title></head><body>\n"
88              + "<form name='form1'>\n"
89              + "  <a id='link' onClick='window.open(\"" + URL_SECOND + "\", \"MyNewWindow\").focus(); "
90              + "return false;'>Click me</a>\n"
91              + "</form>\n"
92              + "</body></html>";
93          final String secondContent = DOCTYPE_HTML
94              + "<html><head><title>Second</title></head><body>\n"
95              + "<script>alert(self.name)</script>\n"
96              + "</body></html>";
97  
98          final List<WebWindowEvent> events = new LinkedList<>();
99          webClient.addWebWindowListener(new WebWindowListener() {
100             @Override
101             public void webWindowOpened(final WebWindowEvent event) {
102                 events.add(event);
103             }
104 
105             @Override
106             public void webWindowContentChanged(final WebWindowEvent event) {
107                 events.add(event);
108             }
109 
110             @Override
111             public void webWindowClosed(final WebWindowEvent event) {
112                 events.add(event);
113             }
114         });
115 
116         webConnection.setResponse(URL_FIRST, firstContent);
117         webConnection.setResponse(URL_SECOND, secondContent);
118         webClient.setWebConnection(webConnection);
119 
120         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
121         assertEquals("First", firstPage.getTitleText());
122 
123         final HtmlAnchor anchor = firstPage.getHtmlElementById("link");
124         final HtmlPage secondPage = anchor.click();
125         assertNotSame(firstPage, secondPage);
126 
127         // Expecting contentChanged, opened, contentChanged
128         assertEquals(3, events.size());
129 
130         final WebWindow firstWebWindow = (WebWindow) events.get(0).getSource();
131         final WebWindow secondWebWindow = (WebWindow) events.get(2).getSource();
132         assertSame(webClient.getCurrentWindow(), secondWebWindow);
133         assertEquals("MyNewWindow", secondWebWindow.getName());
134 
135         assertEquals("First", ((HtmlPage) firstWebWindow.getEnclosedPage()).getTitleText());
136         assertEquals("Second", ((HtmlPage) secondWebWindow.getEnclosedPage()).getTitleText());
137 
138         final WebWindowEvent changedEvent = events.get(2);
139         assertNull(changedEvent.getOldPage());
140         assertEquals("Second", ((HtmlPage) changedEvent.getNewPage()).getTitleText());
141 
142         assertEquals(new String[] {"MyNewWindow"}, collectedAlerts);
143     }
144 
145     /**
146      * @throws Exception if the test fails
147      */
148     @Test
149     public void openWindow_base() throws Exception {
150         final WebClient webClient = getWebClient();
151         final MockWebConnection webConnection = new MockWebConnection();
152 
153         final List<String> collectedAlerts = new ArrayList<>();
154         webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
155 
156         final String firstContent = DOCTYPE_HTML
157             + "<html><head><title>First</title><base target='MyNewWindow'></head><body>\n"
158             + "<form name='form1'>\n"
159             + "  <a id='link' href='" + URL_SECOND + "'>Click me</a>\n"
160             + "</form>\n"
161             + "</body></html>";
162         final String secondContent = DOCTYPE_HTML
163             + "<html><head><title>Second</title></head><body>\n"
164             + "<script>alert(self.name)</script>\n"
165             + "</body></html>";
166 
167         webConnection.setResponse(URL_FIRST, firstContent);
168         webConnection.setResponse(URL_SECOND, secondContent);
169         webClient.setWebConnection(webConnection);
170 
171         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
172         assertEquals("First", firstPage.getTitleText());
173         final WebWindow firstWebWindow = firstPage.getEnclosingWindow();
174         assertEquals(firstWebWindow, firstWebWindow.getTopWindow());
175 
176         final HtmlAnchor anchor = firstPage.getHtmlElementById("link");
177         final HtmlPage secondPage = anchor.click();
178         assertEquals("Second", secondPage.getTitleText());
179         assertNotSame(firstPage, secondPage);
180 
181         final WebWindow secondWebWindow = secondPage.getEnclosingWindow();
182         assertNotSame(firstWebWindow, secondWebWindow);
183         assertEquals("MyNewWindow", secondWebWindow.getName());
184         assertEquals(secondWebWindow, secondWebWindow.getTopWindow());
185 
186         assertEquals(new String[] {"MyNewWindow"}, collectedAlerts);
187     }
188 
189     /**
190      * _blank is a magic name. If we call open(url, '_blank') then a new
191      * window must be loaded.
192      * @throws Exception if the test fails
193      */
194     @Test
195     public void openWindow_blank() throws Exception {
196         final WebClient webClient = getWebClient();
197         final MockWebConnection webConnection = new MockWebConnection();
198 
199         final List<String> collectedAlerts = new ArrayList<>();
200         webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
201 
202         final String firstContent = DOCTYPE_HTML
203             + "<html><head><title>First</title></head><body>\n"
204             + "  <iframe name='secondFrame' id='secondFrame' src='" + URL_SECOND + "'></iframe>\n"
205             + "</body></html>";
206         final String secondContent = DOCTYPE_HTML
207             + "<html><head><title>Second</title></head><body>\n"
208             + "  <a id='link' "
209             + "onClick='window.open(\"" + URL_THIRD + "\", \"_blank\").focus(); '>\n"
210             + "Click me</a>\n"
211             + "</body></html>";
212         final String thirdContent = DOCTYPE_HTML
213             + "<html><head><title>Third</title></head><body>\n"
214             + "</body></html>";
215 
216         webConnection.setResponse(URL_FIRST, firstContent);
217         webConnection.setResponse(URL_SECOND, secondContent);
218         webConnection.setResponse(URL_THIRD, thirdContent);
219         webClient.setWebConnection(webConnection);
220 
221         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
222         assertEquals("First", firstPage.getTitleText());
223         final WebWindow firstWindow = firstPage.getEnclosingWindow();
224 
225         final HtmlInlineFrame secondFrame = firstPage.getHtmlElementById("secondFrame");
226         final HtmlPage secondPage = (HtmlPage) secondFrame.getEnclosedPage();
227         assertEquals("Second", secondPage.getTitleText());
228         try {
229             assertEquals(secondFrame.getEnclosedWindow(), webClient.getWebWindowByName("secondFrame"));
230             // Expected path
231         }
232         catch (final WebWindowNotFoundException e) {
233             fail("Expected secondFrame would be found before click.");
234         }
235         final HtmlAnchor anchor = secondPage.getHtmlElementById("link");
236         final HtmlPage thirdPage = anchor.click();
237         assertEquals("Third", thirdPage.getTitleText());
238         final WebWindow thirdWindow = thirdPage.getEnclosingWindow();
239         assertNotSame(firstWindow, thirdWindow);
240 
241         assertEquals("", thirdWindow.getName());
242 
243         assertEquals(thirdWindow, thirdWindow.getTopWindow());
244         try {
245             assertEquals(secondFrame.getEnclosedWindow(), webClient.getWebWindowByName("secondFrame"));
246             // Expected path
247         }
248         catch (final WebWindowNotFoundException e) {
249             fail("Expected secondFrame would be found after click.");
250         }
251 
252         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
253     }
254 
255     /**
256      * _self is a magic name. If we call open(url, '_self') then the current window must be
257      * reloaded.
258      * @throws Exception if the test fails
259      */
260     @Test
261     public void openWindow_self() throws Exception {
262         final WebClient webClient = getWebClient();
263         final MockWebConnection webConnection = new MockWebConnection();
264 
265         final String firstContent = DOCTYPE_HTML
266             + "<html><head><title>First</title></head><body>\n"
267             + "<form name='form1'>\n"
268             + "  <a id='link' onClick='window.open(\"" + URL_SECOND + "\", \"_self\"); "
269             + "return false;'>Click me</a>\n"
270             + "</form>\n"
271             + "</body></html>";
272         final String secondContent = DOCTYPE_HTML
273                 + "<html><head><title>Second</title></head><body></body></html>";
274 
275         webConnection.setResponse(URL_FIRST, firstContent);
276         webConnection.setResponse(URL_SECOND, secondContent);
277         webClient.setWebConnection(webConnection);
278 
279         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
280         assertEquals("First", firstPage.getTitleText());
281 
282         final List<WebWindowEvent> events = new LinkedList<>();
283         webClient.addWebWindowListener(new WebWindowListener() {
284             @Override
285             public void webWindowOpened(final WebWindowEvent event) {
286                 events.add(event);
287             }
288 
289             @Override
290             public void webWindowContentChanged(final WebWindowEvent event) {
291                 events.add(event);
292             }
293 
294             @Override
295             public void webWindowClosed(final WebWindowEvent event) {
296                 events.add(event);
297             }
298         });
299 
300         final WebWindow firstWebWindow = firstPage.getEnclosingWindow();
301 
302         final HtmlAnchor anchor = firstPage.getHtmlElementById("link");
303         final HtmlPage secondPage = anchor.click();
304         assertEquals("First", firstPage.getTitleText());
305         assertEquals("Second", secondPage.getTitleText());
306 
307         assertEquals(1, events.size());
308 
309         final WebWindow secondWebWindow = (WebWindow) events.get(0).getSource();
310         assertSame(webClient.getCurrentWindow(), firstWebWindow);
311         assertSame(firstWebWindow, secondWebWindow);
312     }
313 
314     /**
315      * _top is a magic name. If we call open(url, '_top') then the top level
316      * window must be reloaded.
317      * @throws Exception if the test fails
318      */
319     @Test
320     public void openWindow_top() throws Exception {
321         final WebClient webClient = getWebClient();
322         final MockWebConnection webConnection = new MockWebConnection();
323 
324         final String firstContent = DOCTYPE_HTML
325             + "<html><head><title>First</title></head><body>\n"
326             + "  <iframe name='secondFrame' id='secondFrame' src='" + URL_SECOND + "'></iframe>\n"
327             + "</body></html>";
328         final String secondContent = DOCTYPE_HTML
329             + "<html><head><title>Second</title></head><body>\n"
330             + "  <iframe name='thirdFrame' id='thirdFrame' src='" + URL_THIRD + "'></iframe>\n"
331             + "</body></html>";
332         final String thirdContent = DOCTYPE_HTML
333             + "<html><head><title>Third</title></head><body>\n"
334             + "  <a id='link' onClick='window.open(\"http://fourth\", \"_top\"); "
335             + "return false;'>Click me</a>\n"
336             + "</body></html>";
337         final String fourthContent = DOCTYPE_HTML
338             + "<html><head><title>Fourth</title></head><body></body></html>";
339 
340         webConnection.setResponse(URL_FIRST, firstContent);
341         webConnection.setResponse(URL_SECOND, secondContent);
342         webConnection.setResponse(URL_THIRD, thirdContent);
343         webConnection.setResponse(new URL("http://fourth/"), fourthContent);
344         webClient.setWebConnection(webConnection);
345 
346         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
347         assertEquals("First", firstPage.getTitleText());
348 
349         final WebWindow firstWebWindow = firstPage.getEnclosingWindow();
350         assertEquals("First", firstPage.getTitleText());
351         final HtmlInlineFrame secondFrame = firstPage.getHtmlElementById("secondFrame");
352         final HtmlPage secondPage = (HtmlPage) secondFrame.getEnclosedPage();
353         assertEquals("Second", secondPage.getTitleText());
354         final HtmlInlineFrame thirdFrame = secondPage.getHtmlElementById("thirdFrame");
355         final HtmlPage thirdPage = (HtmlPage) thirdFrame.getEnclosedPage();
356         assertEquals("Third", thirdPage.getTitleText());
357 
358         assertSame(webClient.getCurrentWindow(), firstWebWindow);
359         assertNotSame(firstWebWindow, secondPage);
360 
361         final HtmlAnchor anchor = thirdPage.getHtmlElementById("link");
362         final HtmlPage fourthPage = anchor.click();
363         final WebWindow fourthWebWindow = fourthPage.getEnclosingWindow();
364         assertSame(firstWebWindow, fourthWebWindow);
365         assertSame(fourthWebWindow, fourthWebWindow.getTopWindow());
366         try {
367             webClient.getWebWindowByName("secondFrame");
368             fail("Did not expect secondFrame to still exist after click.");
369         }
370         catch (final WebWindowNotFoundException e) {
371             // Expected path
372         }
373         try {
374             webClient.getWebWindowByName("thirdFrame");
375             fail("Did not expect thirdFrame to still exist after click.");
376         }
377         catch (final WebWindowNotFoundException e) {
378             // Expected path
379         }
380     }
381 
382     /**
383      * {@code _parent} is a magic name. If we call open(url, '_parent') then the parent window must be reloaded.
384      *
385      * @throws Exception if the test fails
386      */
387     @Test
388     public void openWindow_parent() throws Exception {
389         final WebClient webClient = getWebClient();
390         final MockWebConnection webConnection = new MockWebConnection();
391 
392         final String firstContent = DOCTYPE_HTML
393             + "<html><head><title>First</title></head><body>\n"
394             + "  <iframe name='secondFrame' id='secondFrame' src='" + URL_SECOND + "'></iframe>\n"
395             + "</body></html>";
396         final String secondContent = DOCTYPE_HTML
397             + "<html><head><title>Second</title></head><body>\n"
398             + "  <iframe name='thirdFrame' id='thirdFrame' src='" + URL_THIRD + "'></iframe>\n"
399             + "</body></html>";
400         final String thirdContent = DOCTYPE_HTML
401             + "<html><head><title>Third</title></head><body>\n"
402             + "  <a id='link' onClick='window.open(\"http://fourth\", \"_parent\"); "
403             + "return false;'>Click me</a>\n"
404             + "</body></html>";
405         final String fourthContent = DOCTYPE_HTML
406             + "<html><head><title>Fourth</title></head><body></body></html>";
407 
408         webConnection.setResponse(URL_FIRST, firstContent);
409         webConnection.setResponse(URL_SECOND, secondContent);
410         webConnection.setResponse(URL_THIRD, thirdContent);
411         webConnection.setResponse(new URL("http://fourth/"), fourthContent);
412         webClient.setWebConnection(webConnection);
413 
414         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
415         assertEquals("First", firstPage.getTitleText());
416 
417         final WebWindow firstWebWindow = firstPage.getEnclosingWindow();
418         assertEquals("First", firstPage.getTitleText());
419         final HtmlInlineFrame secondFrame = firstPage.getHtmlElementById("secondFrame");
420         final HtmlPage secondPage = (HtmlPage) secondFrame.getEnclosedPage();
421         assertEquals("Second", secondPage.getTitleText());
422         final HtmlInlineFrame thirdFrame = secondPage.getHtmlElementById("thirdFrame");
423         final HtmlPage thirdPage = (HtmlPage) thirdFrame.getEnclosedPage();
424         assertEquals("Third", thirdPage.getTitleText());
425 
426         assertSame(webClient.getCurrentWindow(), firstWebWindow);
427         assertNotSame(firstWebWindow, secondFrame);
428 
429         final HtmlAnchor anchor = thirdPage.getHtmlElementById("link");
430         final HtmlPage fourthPage = anchor.click();
431         final WebWindow fourthWebWindow = fourthPage.getEnclosingWindow();
432         assertSame(secondFrame.getEnclosedWindow(), fourthWebWindow);
433         try {
434             final WebWindow namedWindow = webClient.getWebWindowByName("secondFrame");
435             assertSame(namedWindow.getEnclosedPage(), fourthPage);
436             // Expected path
437         }
438         catch (final WebWindowNotFoundException e) {
439             fail("Expected secondFrame would be found after click.");
440         }
441         try {
442             webClient.getWebWindowByName("thirdFrame");
443             fail("Did not expect thirdFrame to still exist after click.");
444         }
445         catch (final WebWindowNotFoundException e) {
446             // Expected path
447         }
448     }
449 
450     /**
451      * Regression test for 1592723: window.open('', 'someName') should
452      * retrieve existing window named 'someName' rather than opening a new window
453      * if such a window exists.
454      * @throws Exception if the test fails
455      */
456     @Test
457     @Alerts({"true", "true", "true"})
458     public void openWindow_existingWindow() throws Exception {
459         final String html = DOCTYPE_HTML
460             + "<html><head><script>\n"
461             + "function test() {\n"
462             + "  var w1 = window.open('about:blank', 'foo');\n"
463             + "  alert(w1 != null);\n"
464             + "  var w2 = window.open('', 'foo');\n"
465             + "  alert(w1 == w2);\n"
466             + "  var w3 = window.open('', 'myFrame');\n"
467             + "  alert(w3 == window.frames.myFrame);\n"
468             + "}\n"
469             + "</script></head><body onload='test()'>\n"
470             + "<iframe name='myFrame' id='myFrame'></iframe>\n"
471             + "</body></html>";
472 
473         loadPageWithAlerts(html);
474     }
475 
476     /**
477      * Verifies that <tt>window.open</tt> behaves correctly when popups are blocked.
478      * @throws Exception if an error occurs
479      */
480     @Test
481     public void openWindow_blocked() throws Exception {
482         final String html = DOCTYPE_HTML
483             + "<html>\n"
484             + "<head>\n"
485             + "<script>\n"
486             + "  var w;\n"
487             + "  function test() {\n"
488             + "    w = window.open('', 'foo');\n"
489             + "  }\n"
490             + "</script>\n"
491             + "</head>\n"
492             + "<body onload='test()'>\n"
493             + "<div id='d' onclick='alert(w)'>test</div>\n"
494             + "</body></html>";
495 
496         final List<String> actual = new ArrayList<>();
497         final WebClient client = getWebClient();
498         client.getOptions().setPopupBlockerEnabled(true);
499         client.setAlertHandler(new CollectingAlertHandler(actual));
500 
501         final MockWebConnection webConnection = new MockWebConnection();
502         webConnection.setDefaultResponse(html);
503         client.setWebConnection(webConnection);
504 
505         final HtmlPage page = client.getPage("http://foo");
506         page.getHtmlElementById("d").click();
507         final String[] expected = {"null"};
508         assertEquals(expected, actual);
509     }
510 
511     /**
512      * @throws Exception if the test fails
513      */
514     @Test
515     public void alert_NoAlertHandler() throws Exception {
516         final String firstContent = DOCTYPE_HTML
517             + "<html><head><title>First</title><script>function doTest() {alert('foo')}</script></head>\n"
518             + "<body onload='doTest()'></body></html>";
519 
520         final HtmlPage firstPage = loadPage(firstContent);
521         assertEquals("First", firstPage.getTitleText());
522     }
523 
524     /**
525      * @throws Exception if the test fails
526      */
527     @Test
528     public void parentAndTop() throws Exception {
529         final String firstContent = DOCTYPE_HTML
530             + "<html><head><title>First</title></head><body>\n"
531             + "  <iframe name='left' src='" + URL_SECOND + "'></iframe>\n"
532             + "</body></html>";
533         final String secondContent = DOCTYPE_HTML
534             + "<html><head><title>Second</title></head><body>\n"
535             + "  <iframe name='innermost' src='" + URL_THIRD + "'></iframe>\n"
536             + "</body></html>";
537         final String thirdContent = DOCTYPE_HTML
538             + "<html><head><title>Third</title><script>\n"
539             + "function doAlert() {\n"
540             + "  alert(parent != this);\n"
541             + "  alert(top != this);\n"
542             + "  alert(parent != top);\n"
543             + "  alert(parent.parent == top);\n"
544             + "  alert(parent.frames[0] == this);\n"
545             + "  alert(top.frames[0] == parent);\n"
546             + "}\n"
547             + "</script></head>\n"
548             + "<body><a id='clickme' onClick='doAlert()'>foo</a></body></html>";
549 
550         final WebClient webClient = getWebClient();
551         final List<String> collectedAlerts = new ArrayList<>();
552         webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
553 
554         final MockWebConnection webConnection = new MockWebConnection();
555         webConnection.setResponse(URL_FIRST, firstContent);
556         webConnection.setResponse(URL_SECOND, secondContent);
557         webConnection.setResponse(URL_THIRD, thirdContent);
558 
559         webClient.setWebConnection(webConnection);
560 
561         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
562         assertEquals("First", firstPage.getTitleText());
563 
564         final WebWindow innermostWebWindow = webClient.getWebWindowByName("innermost");
565         final HtmlPage innermostPage = (HtmlPage) innermostWebWindow.getEnclosedPage();
566         innermostPage.getHtmlElementById("clickme").click();
567 
568         assertNotSame(innermostWebWindow.getParentWindow(), innermostWebWindow);
569         assertNotSame(innermostWebWindow.getTopWindow(), innermostWebWindow);
570         assertNotSame(innermostWebWindow.getParentWindow(), innermostWebWindow.getTopWindow());
571         assertSame(innermostWebWindow.getParentWindow().getParentWindow(), innermostWebWindow.getTopWindow());
572 
573         assertEquals(new String[] {"true", "true", "true", "true", "true", "true"}, collectedAlerts);
574     }
575 
576     /**
577      * @throws Exception if the test fails
578      */
579     @Test
580     public void confirm() throws Exception {
581         final WebClient webClient = getWebClient();
582         final MockWebConnection webConnection = new MockWebConnection();
583         final List<String> collectedAlerts = new ArrayList<>();
584         final List<String> collectedConfirms = new ArrayList<>();
585 
586         webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
587         webClient.setConfirmHandler(new ConfirmHandler() {
588             @Override
589             public boolean handleConfirm(final Page page, final String message) {
590                 collectedConfirms.add(message);
591                 return true;
592             }
593         });
594 
595         final String firstContent
596             = "<html><head><title>First</title><script>function doTest() {alert(confirm('foo'))}</script>\n"
597             + "</head><body onload='doTest()'></body></html>";
598 
599         webConnection.setResponse(URL_FIRST, firstContent);
600         webClient.setWebConnection(webConnection);
601 
602         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
603         assertEquals("First", firstPage.getTitleText());
604 
605         assertEquals(new String[] {"foo"}, collectedConfirms);
606         assertEquals(new String[] {"true"}, collectedAlerts);
607     }
608 
609     /**
610      * @throws Exception if the test fails
611      */
612     @Test
613     public void confirm_noConfirmHandler() throws Exception {
614         final String html = DOCTYPE_HTML
615             + "<html><head><title>First</title><script>function doTest() {alert(confirm('foo'))}</script>\n"
616             + "</head><body onload='doTest()'></body></html>";
617 
618         final List<String> collectedAlerts = new ArrayList<>();
619         loadPage(html, collectedAlerts);
620 
621         assertEquals(new String[] {"true"}, collectedAlerts);
622     }
623 
624     /**
625      * @throws Exception if the test fails
626      */
627     @Test
628     public void prompt() throws Exception {
629         try (WebClient webClient = getWebClient()) {
630             try (MockWebConnection webConnection = new MockWebConnection()) {
631                 final List<String> collectedAlerts = new ArrayList<>();
632                 final List<String> collectedPrompts = new ArrayList<>();
633 
634                 webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
635                 webClient.setPromptHandler((page, message, defaultValue) -> {
636                     collectedPrompts.add(message);
637                     return "Flintstone";
638                 });
639 
640                 final String html = DOCTYPE_HTML
641                         + "<html><head><title>First</title>\n"
642                         + "<script>function doTest() {alert(prompt('foo'))}</script>\n"
643                         + "</head><body onload='doTest()'></body></html>";
644 
645                 webConnection.setResponse(URL_FIRST, html);
646                 webClient.setWebConnection(webConnection);
647 
648                 final HtmlPage firstPage = webClient.getPage(URL_FIRST);
649                 assertEquals("First", firstPage.getTitleText());
650 
651                 assertEquals(new String[] {"foo"}, collectedPrompts);
652                 assertEquals(new String[] {"Flintstone"}, collectedAlerts);
653             }
654         }
655     }
656 
657     /**
658      * @throws Exception if the test fails
659      */
660     @Test
661     public void promptWithDefault() throws Exception {
662         try (WebClient webClient = getWebClient()) {
663             try (MockWebConnection webConnection = new MockWebConnection()) {
664                 final List<String> collectedAlerts = new ArrayList<>();
665                 final List<String> collectedPrompts = new ArrayList<>();
666 
667                 webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
668                 webClient.setPromptHandler((page, message, defaultValue) -> {
669                     collectedPrompts.add(message);
670                     collectedPrompts.add(defaultValue);
671                     return defaultValue;
672                 });
673 
674                 final String html = DOCTYPE_HTML
675                         + "<html><head><title>First</title>\n"
676                         + "<script>function doTest() {alert(prompt('foo', 'some default'))}</script>\n"
677                         + "</head><body onload='doTest()'></body></html>";
678 
679                 webConnection.setResponse(URL_FIRST, html);
680                 webClient.setWebConnection(webConnection);
681 
682                 final HtmlPage firstPage = webClient.getPage(URL_FIRST);
683                 assertEquals("First", firstPage.getTitleText());
684 
685                 assertEquals(new String[] {"foo", "some default"}, collectedPrompts);
686                 assertEquals(new String[] {"some default"}, collectedAlerts);
687             }
688         }
689     }
690 
691     /**
692      * @throws Exception if the test fails
693      */
694     @Test
695     public void prompt_noPromptHandler() throws Exception {
696         final WebClient webClient = getWebClient();
697         final MockWebConnection webConnection = new MockWebConnection();
698         final List<String> collectedAlerts = new ArrayList<>();
699         final List<String> collectedPrompts = new ArrayList<>();
700 
701         webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
702 
703         final String firstContent = DOCTYPE_HTML
704             + "<html><head><title>First</title><script>function doTest() {alert(prompt('foo'))}</script>\n"
705             + "</head><body onload='doTest()'></body></html>";
706 
707         webConnection.setResponse(URL_FIRST, firstContent);
708         webClient.setWebConnection(webConnection);
709 
710         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
711         assertEquals("First", firstPage.getTitleText());
712 
713         assertEquals(Collections.EMPTY_LIST, collectedPrompts);
714         assertEquals(new String[] {"null"}, collectedAlerts);
715     }
716 
717     /**
718      * @throws Exception if the test fails
719      */
720     @Test
721     public void setOpenerLocationHrefRelative() throws Exception {
722         final WebClient webClient = getWebClient();
723         final MockWebConnection webConnection = new MockWebConnection();
724 
725         final String aContent = DOCTYPE_HTML
726             + "<html><head><title>A</title></head><body>\n"
727             + "<button id='clickme' onClick='window.open(\"b/b.html\");'>Click me</a>\n"
728             + "</body></html>";
729         final String bContent = DOCTYPE_HTML
730             + "<html><head><title>B</title></head><body>\n"
731             + "<button id='clickme' onClick='opener.location.href=\"../c.html\";'>Click me</a>\n"
732             + "</body></html>";
733         final String cContent = DOCTYPE_HTML
734             + "<html><head><title>C</title></head><body></body></html>";
735         final String failContent = DOCTYPE_HTML
736             + "<html><head><title>FAILURE!!!</title></head><body></body></html>";
737 
738         webConnection.setResponse(new URL("http://opener/test/a.html"), aContent);
739         webConnection.setResponse(new URL("http://opener/test/b/b.html"), bContent);
740         webConnection.setResponse(new URL("http://opener/test/c.html"), cContent);
741         webConnection.setResponse(new URL("http://opener/c.html"), failContent);
742 
743         webClient.setWebConnection(webConnection);
744 
745         final HtmlPage firstPage = webClient.getPage("http://opener/test/a.html");
746         assertEquals("A", firstPage.getTitleText());
747 
748         final HtmlButton buttonA = firstPage.getHtmlElementById("clickme");
749         final HtmlPage pageB = buttonA.click();
750         assertNotNull("B", pageB);
751         assertEquals("B", pageB.getTitleText());
752 
753         final HtmlButton buttonB = pageB.getHtmlElementById("clickme");
754         final HtmlPage thirdPage = buttonB.click();
755         assertSame("Page B has lost focus", pageB, thirdPage);
756         assertEquals("C", ((HtmlPage) firstPage.getEnclosingWindow().getEnclosedPage()).getTitleText());
757     }
758 
759     /**
760      * Test closing using JavaScript.
761      * @throws Exception if the test fails
762      */
763     @Test
764     public void close() throws Exception {
765         final WebClient webClient = getWebClient();
766         final MockWebConnection webConnection = new MockWebConnection();
767 
768         final List<String> collectedAlerts = new ArrayList<>();
769         webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
770 
771         final String firstContent = DOCTYPE_HTML
772             + "<html><head><title>First</title></head><body>\n"
773             + "<a href='" + URL_SECOND + "' id='link' target='_blank'>Link</a>\n"
774             + "</body></html>";
775         final String secondContent = DOCTYPE_HTML
776             + "<html><head><title>Second</title></head><body>\n"
777             + "<h1>Second</h1><form>\n"
778             + "<input type='submit' name='action' value='Close' id='button' "
779             + "onclick='window.close(); return false;'>\n"
780             + "</form></body></html>";
781 
782         webConnection.setResponse(URL_FIRST, firstContent);
783         webConnection.setResponse(URL_SECOND, secondContent);
784         webClient.setWebConnection(webConnection);
785 
786         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
787         assertEquals("First", firstPage.getTitleText());
788         assertEquals(1, webClient.getWebWindows().size());
789         final WebWindow firstWindow = firstPage.getEnclosingWindow();
790 
791         final HtmlPage secondPage = firstPage.getHtmlElementById("link").click();
792         assertEquals("Second", secondPage.getTitleText());
793         assertEquals(2, webClient.getWebWindows().size());
794         final WebWindow secondWindow = secondPage.getEnclosingWindow();
795 
796         assertNotSame(firstWindow, secondWindow);
797 
798         final List<WebWindowEvent> events = new LinkedList<>();
799         webClient.addWebWindowListener(new WebWindowListener() {
800             @Override
801             public void webWindowOpened(final WebWindowEvent event) {
802                 events.add(event);
803             }
804 
805             @Override
806             public void webWindowContentChanged(final WebWindowEvent event) {
807                 events.add(event);
808             }
809 
810             @Override
811             public void webWindowClosed(final WebWindowEvent event) {
812                 events.add(event);
813             }
814         });
815 
816         secondPage.getHtmlElementById("button").click();
817 
818         final List<WebWindowEvent> expectedEvents = Arrays.asList(new WebWindowEvent[]{
819             new WebWindowEvent(secondWindow, WebWindowEvent.CLOSE, secondPage, null)
820         });
821         assertEquals(expectedEvents, events);
822 
823         assertEquals(1, webClient.getWebWindows().size());
824         assertEquals(firstWindow, webClient.getCurrentWindow());
825 
826         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
827     }
828 
829     /**
830      * @throws Exception if the test fails
831      */
832     @Test
833     public void status() throws Exception {
834         final WebClient webClient = getWebClient();
835         final MockWebConnection webConnection = new MockWebConnection();
836 
837         final String firstContent = DOCTYPE_HTML
838             +  "<html><head><title>First</title><script>\n"
839             + "function doTest() {\n"
840             + "  alert(window.status);\n"
841             + "  window.status = 'newStatus';\n"
842             + "  alert(window.status);\n"
843             + "}\n"
844             + "</script></head><body onload='doTest()'>\n"
845             + "</body></html>";
846 
847         final URL url = URL_FIRST;
848         webConnection.setResponse(url, firstContent);
849         webClient.setWebConnection(webConnection);
850 
851         final List<String> collectedAlerts = new ArrayList<>();
852         webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
853 
854         final List<String> collectedStatus = new ArrayList<>();
855         webClient.setStatusHandler(new StatusHandler() {
856             @Override
857             public void statusMessageChanged(final Page page, final String message) {
858                 collectedStatus.add(message);
859             }
860         });
861         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
862         assertEquals("First", firstPage.getTitleText());
863 
864         final String[] expectedAlerts = {"", "newStatus"};
865         assertEquals("alerts", expectedAlerts, collectedAlerts);
866 
867         final String[] expectedStatus = {"newStatus"};
868         assertEquals("status", expectedStatus, collectedStatus);
869     }
870 
871     /**
872      * @throws Exception if the test fails
873      */
874     @Test
875     public void print() throws Exception {
876         final String html = DOCTYPE_HTML
877             + "<html>\n"
878             + "<head></head>\n"
879             + "<body>\n"
880             + "<script>\n"
881             + "  window.print();\n"
882             + "</script>\n"
883             + "</body>\n"
884             + "</html>";
885 
886         loadPageWithAlerts(html);
887     }
888 
889     /**
890      * Open a window with only an image for content, then try to set focus to it.
891      *
892      * @throws Exception if the test fails
893      */
894     @Test
895     public void openWindow_image() throws Exception {
896         final WebClient webClient = getWebClient();
897         final MockWebConnection webConnection = new MockWebConnection();
898 
899         final String firstContent = DOCTYPE_HTML
900             + "<html><head><title>First</title></head><body>\n"
901             + "<form name='form1'>\n"
902             + "  <a id='link' onClick='window.open(\"" + URL_SECOND + "\", \"_blank\").focus(); return false;'"
903             + "return false;'>Click me</a>\n"
904             + "</form>\n"
905             + "</body></html>";
906         final String secondContent = new String(new char[]{
907             'G', 'I', 'F', '8', '9', 'a', 0x01, 0x00,
908             0x01, 0x00, 0x80, 0x00, 0x00, 0xfe, 0xd4, 0xaf,
909             0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x00,
910             0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00,
911             0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44,
912             0x01, 0x00, 0x3b});
913 
914         webConnection.setResponse(URL_FIRST, firstContent, 200, "OK", MimeType.TEXT_HTML, Collections.emptyList());
915         webConnection.setResponse(URL_SECOND, secondContent, 200, "OK", MimeType.IMAGE_GIF, Collections.emptyList());
916         webClient.setWebConnection(webConnection);
917 
918         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
919         assertEquals("First", firstPage.getTitleText());
920 
921         final List<WebWindowEvent> events = new LinkedList<>();
922         webClient.addWebWindowListener(new WebWindowListener() {
923             @Override
924             public void webWindowOpened(final WebWindowEvent event) {
925                 events.add(event);
926             }
927 
928             @Override
929             public void webWindowContentChanged(final WebWindowEvent event) {
930                 events.add(event);
931             }
932 
933             @Override
934             public void webWindowClosed(final WebWindowEvent event) {
935                 events.add(event);
936             }
937         });
938 
939         final WebWindow firstWebWindow = firstPage.getEnclosingWindow();
940 
941         final HtmlAnchor anchor = firstPage.getHtmlElementById("link");
942         final Page secondPage = anchor.click();
943         assertEquals("First", firstPage.getTitleText());
944         assertEquals(MimeType.IMAGE_GIF, secondPage.getWebResponse().getContentType());
945 
946         assertEquals(2, events.size());
947 
948         final WebWindow secondWebWindow = (WebWindow) events.get(0).getSource();
949 
950         assertSame(webClient.getCurrentWindow(), secondWebWindow);
951         assertNotSame(firstWebWindow, secondWebWindow);
952     }
953 
954     /**
955      * Open a window with only text for content, then try to set focus to it.
956      *
957      * @throws Exception if the test fails
958      */
959     @Test
960     public void openWindow_text() throws Exception {
961         final WebClient webClient = getWebClient();
962         final MockWebConnection webConnection = new MockWebConnection();
963 
964         final String firstContent = DOCTYPE_HTML
965             + "<html><head><title>First</title></head><body>\n"
966             + "<form name='form1'>\n"
967             + "  <a id='link' onClick='window.open(\"" + URL_SECOND + "\", \"_blank\").focus(); return false;'"
968             + "return false;'>Click me</a>\n"
969             + "</form>\n"
970             + "</body></html>";
971         final String secondContent = "Hello World";
972 
973         webConnection.setResponse(URL_FIRST, firstContent, 200, "OK", MimeType.TEXT_HTML, Collections.emptyList());
974         webConnection.setResponse(URL_SECOND, secondContent, 200, "OK", MimeType.TEXT_PLAIN, Collections.emptyList());
975         webClient.setWebConnection(webConnection);
976 
977         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
978         assertEquals("First", firstPage.getTitleText());
979 
980         final List<WebWindowEvent> events = new LinkedList<>();
981         webClient.addWebWindowListener(new WebWindowListener() {
982             @Override
983             public void webWindowOpened(final WebWindowEvent event) {
984                 events.add(event);
985             }
986 
987             @Override
988             public void webWindowContentChanged(final WebWindowEvent event) {
989                 events.add(event);
990             }
991 
992             @Override
993             public void webWindowClosed(final WebWindowEvent event) {
994                 events.add(event);
995             }
996         });
997 
998         final WebWindow firstWebWindow = firstPage.getEnclosingWindow();
999 
1000         final HtmlAnchor anchor = firstPage.getHtmlElementById("link");
1001         final Page secondPage = anchor.click();
1002         assertEquals("First", firstPage.getTitleText());
1003         assertEquals(MimeType.TEXT_PLAIN, secondPage.getWebResponse().getContentType());
1004 
1005         assertEquals(2, events.size());
1006 
1007         final WebWindow secondWebWindow = (WebWindow) events.get(0).getSource();
1008 
1009         assertSame(webClient.getCurrentWindow(), secondWebWindow);
1010         assertNotSame(firstWebWindow, secondWebWindow);
1011     }
1012 
1013     /**
1014      * Open a window with only XML for content, then try to set focus to it.
1015      *
1016      * @throws Exception if the test fails
1017      */
1018     @Test
1019     public void openWindow_xml() throws Exception {
1020         final WebClient webClient = getWebClient();
1021         final MockWebConnection webConnection = new MockWebConnection();
1022 
1023         final String firstContent = DOCTYPE_HTML
1024             + "<html><head><title>First</title></head><body>\n"
1025             + "<form name='form1'>\n"
1026             + "  <a id='link' onClick='window.open(\"" + URL_SECOND + "\", \"_blank\").focus(); return false;'"
1027             + "return false;'>Click me</a>\n"
1028             + "</form>\n"
1029             + "</body></html>";
1030         final String secondContent = "<junk></junk>\n";
1031 
1032         webConnection.setResponse(URL_FIRST, firstContent, 200, "OK", MimeType.TEXT_HTML, Collections.emptyList());
1033         webConnection.setResponse(URL_SECOND, secondContent, 200, "OK", MimeType.TEXT_XML, Collections.emptyList());
1034         webClient.setWebConnection(webConnection);
1035 
1036         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
1037         assertEquals("First", firstPage.getTitleText());
1038 
1039         final List<WebWindowEvent> events = new LinkedList<>();
1040         webClient.addWebWindowListener(new WebWindowListener() {
1041             @Override
1042             public void webWindowOpened(final WebWindowEvent event) {
1043                 events.add(event);
1044             }
1045 
1046             @Override
1047             public void webWindowContentChanged(final WebWindowEvent event) {
1048                 events.add(event);
1049             }
1050 
1051             @Override
1052             public void webWindowClosed(final WebWindowEvent event) {
1053                 events.add(event);
1054             }
1055         });
1056 
1057         final WebWindow firstWebWindow = firstPage.getEnclosingWindow();
1058 
1059         final HtmlAnchor anchor = firstPage.getHtmlElementById("link");
1060         final Page secondPage = anchor.click();
1061         assertEquals("First", firstPage.getTitleText());
1062         assertEquals(MimeType.TEXT_XML, secondPage.getWebResponse().getContentType());
1063 
1064         assertEquals(2, events.size());
1065 
1066         final WebWindow secondWebWindow = (WebWindow) events.get(0).getSource();
1067 
1068         assertSame(webClient.getCurrentWindow(), secondWebWindow);
1069         assertNotSame(firstWebWindow, secondWebWindow);
1070     }
1071 
1072     /**
1073      * Open a window with only JavaScript for content, then try to set focus to it.
1074      *
1075      * @throws Exception if the test fails
1076      */
1077     @Test
1078     public void openWindow_javascript() throws Exception {
1079         final WebClient webClient = getWebClient();
1080         final MockWebConnection webConnection = new MockWebConnection();
1081 
1082         final String firstContent = DOCTYPE_HTML
1083             + "<html><head><title>First</title></head><body>\n"
1084             + "<form name='form1'>\n"
1085             + "  <a id='link' onClick='window.open(\"" + URL_SECOND + "\", \"_blank\").focus(); return false;'"
1086             + "return false;'>Click me</a>\n"
1087             + "</form>\n"
1088             + "</body></html>";
1089         final String secondContent = "var x=1;\n";
1090 
1091         webConnection.setResponse(URL_FIRST, firstContent, 200, "OK", MimeType.TEXT_HTML, Collections.emptyList());
1092         webConnection.setResponse(URL_SECOND, secondContent, 200, "OK", "text/javascript", Collections.emptyList());
1093         webClient.setWebConnection(webConnection);
1094 
1095         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
1096         assertEquals("First", firstPage.getTitleText());
1097 
1098         final List<WebWindowEvent> events = new LinkedList<>();
1099         webClient.addWebWindowListener(new WebWindowListener() {
1100             @Override
1101             public void webWindowOpened(final WebWindowEvent event) {
1102                 events.add(event);
1103             }
1104 
1105             @Override
1106             public void webWindowContentChanged(final WebWindowEvent event) {
1107                 events.add(event);
1108             }
1109 
1110             @Override
1111             public void webWindowClosed(final WebWindowEvent event) {
1112                 events.add(event);
1113             }
1114         });
1115 
1116         final WebWindow firstWebWindow = firstPage.getEnclosingWindow();
1117 
1118         final HtmlAnchor anchor = firstPage.getHtmlElementById("link");
1119         final Page secondPage = anchor.click();
1120         assertEquals("First", firstPage.getTitleText());
1121         assertEquals("text/javascript", secondPage.getWebResponse().getContentType());
1122 
1123         assertEquals(2, events.size());
1124 
1125         final WebWindow secondWebWindow = (WebWindow) events.get(0).getSource();
1126 
1127         assertSame(webClient.getCurrentWindow(), secondWebWindow);
1128         assertNotSame(firstWebWindow, secondWebWindow);
1129     }
1130 
1131     /**
1132      * Open a window with only text for content, then try to set focus to it.
1133      *
1134      * @throws Exception if the test fails
1135      */
1136     @Test
1137     public void openWindow_html() throws Exception {
1138         final WebClient webClient = getWebClient();
1139         final MockWebConnection webConnection = new MockWebConnection();
1140 
1141         final String firstContent = DOCTYPE_HTML
1142             + "<html><head><title>First</title></head><body>\n"
1143             + "<form name='form1'>\n"
1144             + "  <a id='link' onClick='window.open(\"" + URL_SECOND + "\", \"_blank\").focus(); return false;'"
1145             + "return false;'>Click me</a>\n"
1146             + "</form>\n"
1147             + "</body></html>";
1148         final String secondContent = DOCTYPE_HTML
1149             + "<html><head><title>Second</title></head><body>\n"
1150             + "<p>Hello World</p>\n"
1151             + "</body></html>";
1152 
1153         webConnection.setResponse(URL_FIRST, firstContent);
1154         webConnection.setResponse(URL_SECOND, secondContent);
1155         webClient.setWebConnection(webConnection);
1156 
1157         final HtmlPage firstPage = webClient.getPage(URL_FIRST);
1158         assertEquals("First", firstPage.getTitleText());
1159 
1160         final List<WebWindowEvent> events = new LinkedList<>();
1161         webClient.addWebWindowListener(new WebWindowListener() {
1162             @Override
1163             public void webWindowOpened(final WebWindowEvent event) {
1164                 events.add(event);
1165             }
1166 
1167             @Override
1168             public void webWindowContentChanged(final WebWindowEvent event) {
1169                 events.add(event);
1170             }
1171 
1172             @Override
1173             public void webWindowClosed(final WebWindowEvent event) {
1174                 events.add(event);
1175             }
1176         });
1177 
1178         final WebWindow firstWebWindow = firstPage.getEnclosingWindow();
1179 
1180         final HtmlAnchor anchor = firstPage.getHtmlElementById("link");
1181         final Page secondPage = anchor.click();
1182         assertEquals("First", firstPage.getTitleText());
1183         assertEquals(MimeType.TEXT_HTML, secondPage.getWebResponse().getContentType());
1184 
1185         assertEquals(2, events.size());
1186 
1187         final WebWindow secondWebWindow = (WebWindow) events.get(0).getSource();
1188 
1189         assertSame(webClient.getCurrentWindow(), secondWebWindow);
1190         assertNotSame(firstWebWindow, secondWebWindow);
1191     }
1192 
1193     /**
1194      * Basic test for the <tt>showModalDialog</tt> method. See bug #703.
1195      * @throws Exception if an error occurs
1196      */
1197     @Test
1198     @Alerts("not available")
1199     public void showModalDialog() throws Exception {
1200         final String html1 = DOCTYPE_HTML
1201             + "<html><head><script>\n"
1202             + "  function test() {\n"
1203             + "    if (!window.showModalDialog) {alert('not available'); return; }\n"
1204             + "    alert(window.returnValue);\n"
1205             + "    var o = new Object();\n"
1206             + "    o.firstName = 'Jane';\n"
1207             + "    o.lastName = 'Smith';\n"
1208             + "    var ret = showModalDialog('myDialog.html', o, 'dialogHeight:300px; dialogLeft:200px;');\n"
1209             + "    alert(ret);\n"
1210             + "    alert('finished');\n"
1211             + "  }\n"
1212             + "</script></head><body>\n"
1213             + "  <button onclick='test()' id='b'>Test</button>\n"
1214             + "</body></html>";
1215 
1216         final String html2 = DOCTYPE_HTML
1217             + "<html><head><script>\n"
1218             + "  var o = window.dialogArguments;\n"
1219             + "  alert(o.firstName);\n"
1220             + "  alert(o.lastName);\n"
1221             + "  window.returnValue = 'sdg';\n"
1222             + "</script></head>\n"
1223             + "<body>foo</body></html>";
1224 
1225         final WebClient client = getWebClient();
1226         final List<String> actual = new ArrayList<>();
1227         client.setAlertHandler(new CollectingAlertHandler(actual));
1228 
1229         final MockWebConnection conn = new MockWebConnection();
1230         conn.setResponse(URL_FIRST, html1);
1231         conn.setResponse(new URL(URL_FIRST, "myDialog.html"), html2);
1232         client.setWebConnection(conn);
1233 
1234         final HtmlPage page = client.getPage(URL_FIRST);
1235         final HtmlElement button = page.getHtmlElementById("b");
1236         final HtmlPage dialogPage = button.click();
1237 
1238         if (getExpectedAlerts().length > 1) {
1239             final DialogWindow dialog = (DialogWindow) dialogPage.getEnclosingWindow();
1240             dialog.close();
1241         }
1242 
1243         assertEquals(getExpectedAlerts(), actual);
1244     }
1245 
1246     /**
1247      * Test for the <tt>showModalDialog</tt> method.
1248      * This tests blocking until the window gets closed.
1249      * Can not currently be tested with WebDriver
1250      * https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/284
1251      *
1252      * To fix this, we need to allow user to interact with the opened dialog before showModalDialog() returns
1253      * @throws Exception if an error occurs
1254      */
1255     @Test
1256     @Alerts({"undefined", "not available"})
1257     public void showModalDialogWithButton() throws Exception {
1258         final String html1 = DOCTYPE_HTML
1259             + "<html><head>\n"
1260             + "  <script>\n"
1261             + "    function test() {\n"
1262             + "      alert(window.returnValue);\n"
1263             + "      if (!window.showModalDialog) {alert('not available'); return; }\n"
1264             + "      var res = showModalDialog('myDialog.html', null, 'dialogHeight:300px; dialogLeft:200px;');\n"
1265             + "      alert(res);\n"
1266             + "      alert('finished');\n"
1267             + "    }\n"
1268             + "  </script>\n"
1269             + "</head>\n"
1270             + "<body>\n"
1271             + "  <button onclick='test()' id='openDlg'>Test</button>\n"
1272             + "</body></html>";
1273 
1274         final String html2 = DOCTYPE_HTML
1275             + "<html><head>\n"
1276             + "</head>\n"
1277             + "<body>\n"
1278             + "  <button id='closeDlg' onclick='window.returnValue = \"result\"; window.close();'></button>\n"
1279             + "</body>\n"
1280             + "</html>";
1281 
1282         final WebClient client = getWebClient();
1283         final List<String> actual = new ArrayList<>();
1284         client.setAlertHandler(new CollectingAlertHandler(actual));
1285 
1286         final MockWebConnection conn = new MockWebConnection();
1287         conn.setResponse(URL_FIRST, html1);
1288         conn.setResponse(new URL(URL_FIRST, "myDialog.html"), html2);
1289         client.setWebConnection(conn);
1290 
1291         final HtmlPage page = getWebClient().getPage(URL_FIRST);
1292         final HtmlElement button = page.getHtmlElementById("openDlg");
1293         button.click();
1294 
1295         // TODO: <button id='closeDlg'> should be clicked
1296         assertEquals(getExpectedAlerts(), actual);
1297     }
1298 
1299     /**
1300      * Basic test for the <tt>showModelessDialog</tt> method. See bug #703.
1301      * @throws Exception if an error occurs
1302      */
1303     @Test
1304     @Alerts("")
1305     public void showModelessDialog() throws Exception {
1306         final String html1 = DOCTYPE_HTML
1307             + "<html><head><script>\n"
1308             + "  var userName = '';\n"
1309             + "  function test() {\n"
1310             + "    if (window.showModelessDialog) {\n"
1311             + "      var newWindow = showModelessDialog('myDialog.html', window, 'status:false');\n"
1312             + "      alert(newWindow);\n"
1313             + "    }\n"
1314             + "  }\n"
1315             + "  function update() { alert(userName); }\n"
1316             + "</script></head><body>\n"
1317             + "  <input type='button' id='b' value='Test' onclick='test()'>\n"
1318             + "</body></html>";
1319 
1320         final String html2 = DOCTYPE_HTML
1321             + "<html><head><script>\n"
1322             + "function update() {\n"
1323             + "  var w = dialogArguments;\n"
1324             + "  w.userName = document.getElementById('name').value;\n"
1325             + "  w.update();\n"
1326             + "}\n"
1327             + "</script></head><body>\n"
1328             + "  Name: <input id='name'><input value='OK' id='b' type='button' onclick='update()'>\n"
1329             + "</body></html>";
1330 
1331         final WebClient client = getWebClient();
1332         final List<String> actual = new ArrayList<>();
1333         client.setAlertHandler(new CollectingAlertHandler(actual));
1334 
1335         final MockWebConnection conn = new MockWebConnection();
1336         conn.setResponse(URL_FIRST, html1);
1337         conn.setResponse(new URL(URL_FIRST, "myDialog.html"), html2);
1338         client.setWebConnection(conn);
1339 
1340         final HtmlPage page = client.getPage(URL_FIRST);
1341         final HtmlElement button = page.getHtmlElementById("b");
1342         final HtmlPage dialogPage = button.click();
1343 
1344         if (!dialogPage.getUrl().equals(URL_FIRST)) {
1345             final HtmlInput input = dialogPage.getHtmlElementById("name");
1346             input.setValue("a");
1347 
1348             final HtmlButtonInput button2 = (HtmlButtonInput) dialogPage.getHtmlElementById("b");
1349             button2.click();
1350 
1351             assertEquals(getExpectedAlerts(), actual);
1352         }
1353     }
1354 
1355     /**
1356      * @throws Exception if an error occurs
1357      */
1358     @Test
1359     @Alerts({"true", "[object Window]", "[object Window]"})
1360     public void overwriteProperty_top() throws Exception {
1361         final String html = DOCTYPE_HTML
1362             + "<html><body><script>\n"
1363             + "  alert(window.top == this);\n"
1364             + "  var top = 123;\n"
1365             + "  alert(top);\n"
1366             + "  alert(window.top);\n"
1367             + "</script></body></html>";
1368         // this can't be tested using WebDriver currently (i.e. using loadPageWithAlerts2)
1369         // because the hack currently used to capture alerts needs reference to property "top".
1370         loadPageWithAlerts(html);
1371     }
1372 
1373     /**
1374      * @throws Exception if an error occurs
1375      */
1376     @Test
1377     @Alerts({"true", "[object Window]", "[object Window]"})
1378     public void overwriteProperty_top2() throws Exception {
1379         final String html = DOCTYPE_HTML
1380             + "<html><body><script>\n"
1381             + "  alert(window.top == this);\n"
1382             + "  window.top = 123;\n"
1383             + "  alert(top);\n"
1384             + "  alert(window.top);\n"
1385             + "</script></body></html>";
1386         // this can't be tested using WebDriver currently (i.e. using loadPageWithAlerts2)
1387         // because the hack currently used to capture alerts needs reference to property "top".
1388         loadPageWithAlerts(html);
1389     }
1390 
1391     /**
1392      * Download of next page is done first after onbeforeunload is done.
1393      * @throws Exception if an error occurs
1394      */
1395     @Test
1396     @Alerts("x")
1397     public void onbeforeunload_calledBeforeDownload() throws Exception {
1398         final String html = DOCTYPE_HTML
1399             + "<html><body><script>\n"
1400             + "  window.onbeforeunload = function() { alert('x'); return 'hello'; };\n"
1401             + "  window.location = 'foo.html';\n"
1402             + "</script></body></html>";
1403 
1404         final WebClient webClient = getWebClientWithMockWebConnection();
1405         getMockWebConnection().setDefaultResponse("");
1406 
1407         final OnbeforeunloadHandler handler = new OnbeforeunloadHandler() {
1408             @Override
1409             public boolean handleEvent(final Page page, final String returnValue) {
1410                 final String[] expectedRequests = {""};
1411                 assertEquals(expectedRequests, getMockWebConnection().getRequestedUrls(URL_FIRST));
1412                 return true;
1413             }
1414         };
1415         webClient.setOnbeforeunloadHandler(handler);
1416         loadPageWithAlerts(html);
1417 
1418         final String[] expectedRequests = {"", "foo.html"};
1419         assertEquals(expectedRequests, getMockWebConnection().getRequestedUrls(URL_FIRST));
1420     }
1421 
1422     /**
1423      * @throws Exception if an error occurs
1424      */
1425     @Test
1426     public void serialization() throws Exception {
1427         final String html = DOCTYPE_HTML
1428             + "<html><head></head><body><iframe></iframe><script>window.frames</script></body></html>";
1429         final HtmlPage page = loadPageWithAlerts(html);
1430         clone(page.getEnclosingWindow());
1431     }
1432 
1433     /**
1434      * Regression test for bug #844.
1435      * @throws Exception if an error occurs
1436      */
1437     @Test
1438     @Alerts("x")
1439     public void onbeforeunload_setToFunction() throws Exception {
1440         final String html = DOCTYPE_HTML
1441             + "<html><body><script>\n"
1442             + "  window.onbeforeunload = function() { alert('x'); return 'x'; };\n"
1443             + "  window.location = 'about:blank';\n"
1444             + "</script></body></html>";
1445         loadPageWithAlerts(html);
1446     }
1447 
1448     /**
1449      * @throws Exception if an error occurs
1450      */
1451     @Test
1452     @Alerts({"10", "20", "30", "40"})
1453     public void viewportSetters() throws Exception {
1454         final String html = DOCTYPE_HTML
1455                 + "<html>\n"
1456                 + "<head></head>\n"
1457                 + "<body>\n"
1458                 + "<script>\n"
1459                 + "alert(window.innerWidth);\n"
1460                 + "alert(window.innerHeight);\n"
1461                 + "alert(window.outerWidth);\n"
1462                 + "alert(window.outerHeight);\n"
1463                 + "</script>\n"
1464                 + "</body>\n"
1465                 + "</html>";
1466 
1467         final List<String> collectedAlerts = new ArrayList<>();
1468         final WebClient client = getWebClient();
1469         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
1470 
1471         final MockWebConnection webConnection = new MockWebConnection();
1472         webConnection.setDefaultResponse(html);
1473         client.setWebConnection(webConnection);
1474 
1475         final WebWindow topLevelWindow = client.getTopLevelWindows().get(0);
1476         topLevelWindow.setInnerWidth(10);
1477         topLevelWindow.setInnerHeight(20);
1478         topLevelWindow.setOuterWidth(30);
1479         topLevelWindow.setOuterHeight(40);
1480         client.getPage(URL_FIRST);
1481         assertEquals(getExpectedAlerts(), collectedAlerts);
1482     }
1483 
1484     /**
1485      * @throws Exception if the test fails
1486      */
1487     @Test
1488     @Alerts(DEFAULT = "",
1489             FF = "info: Dumper",
1490             FF_ESR = "info: Dumper")
1491     public void dump() throws Exception {
1492         final WebConsole console = getWebClient().getWebConsole();
1493         final List<String> messages = new ArrayList<>();
1494         console.setLogger(new Logger() {
1495 
1496             @Override
1497             public void warn(final Object message) {
1498             }
1499 
1500             @Override
1501             public void trace(final Object message) {
1502             }
1503 
1504             @Override
1505             public void info(final Object message) {
1506                 messages.add("info: " + message);
1507             }
1508 
1509             @Override
1510             public void error(final Object message) {
1511             }
1512 
1513             @Override
1514             public void debug(final Object message) {
1515             }
1516 
1517             @Override
1518             public boolean isTraceEnabled() {
1519                 return false;
1520             }
1521 
1522             @Override
1523             public boolean isDebugEnabled() {
1524                 return false;
1525             }
1526 
1527             @Override
1528             public boolean isInfoEnabled() {
1529                 return true;
1530             }
1531 
1532             @Override
1533             public boolean isWarnEnabled() {
1534                 return true;
1535             }
1536 
1537             @Override
1538             public boolean isErrorEnabled() {
1539                 return true;
1540             }
1541         });
1542 
1543         final String html = DOCTYPE_HTML
1544             + "<html><head><title>foo</title><script>\n"
1545             + "function test() {\n"
1546             + "  if (window.dump) {\n"
1547             + "    window.dump('Dumper');\n"
1548             + "  }\n"
1549             + "}\n"
1550             + "</script></head><body onload='test()'></body></html>";
1551 
1552         loadPage(html);
1553         assertEquals(getExpectedAlerts(), messages);
1554     }
1555 
1556     /**
1557      * Regression test for http://sourceforge.net/p/htmlunit/bugs/234/
1558      * and https://bugzilla.mozilla.org/show_bug.cgi?id=443491.
1559      * @throws Exception if the test fails
1560      */
1561     @Test
1562     public void overwriteFunctions_alert() throws Exception {
1563         final String html = DOCTYPE_HTML
1564             + "<html>\n"
1565             + "<head>\n"
1566             + "  <script language='JavaScript'>\n"
1567             + "    function alert(x) {\n"
1568             + "      document.title = x;\n"
1569             + "    }\n"
1570             + "    alert('hello');\n"
1571             + "  </script>\n"
1572             + "</head>\n"
1573             + "<body>\n"
1574             + "</body>\n"
1575             + "</html>";
1576 
1577         final HtmlPage page = loadPageWithAlerts(html);
1578         assertEquals("hello", page.getTitleText());
1579     }
1580 
1581     /**
1582      * @throws Exception if the test fails
1583      */
1584     @Test
1585     @Alerts({"before print§printed§from timeout§", "before print§print handled§printed§from timeout§"})
1586     public void printHandler() throws Exception {
1587         // we have to test this manually
1588 
1589         final WebClient webClient = getWebClient();
1590         final MockWebConnection webConnection = new MockWebConnection();
1591 
1592         final String firstContent = DOCTYPE_HTML
1593             + "<html><head>\n"
1594             + "<script>\n"
1595             + "  function log(msg) { window.document.title += msg + '§'; }\n"
1596 
1597             + "  function doTest() {\n"
1598             + "    setTimeout(() => { log('from timeout'); }, 100)\n"
1599             + "    log('before print');\n"
1600             + "    window.print();\n"
1601             + "    log('printed');\n"
1602             + "  }\n"
1603             + "</script>\n"
1604             + "</head>\n"
1605             + "<body>\n"
1606             + "  <button id='click' onclick='doTest()'>Print</button>\n"
1607             + "</body></html>";
1608 
1609         final URL url = URL_FIRST;
1610         webConnection.setResponse(url, firstContent);
1611         webClient.setWebConnection(webConnection);
1612 
1613         HtmlPage page = webClient.getPage(URL_FIRST);
1614         page.getElementById("click").click();
1615         webClient.waitForBackgroundJavaScript(DEFAULT_WAIT_TIME.toMillis());
1616 
1617         assertEquals(getExpectedAlerts()[0], page.getTitleText());
1618 
1619         webClient.setPrintHandler(new PrintHandler() {
1620             @Override
1621             public void handlePrint(final HtmlPage pageToPrint) {
1622                 try {
1623                     Thread.sleep(DEFAULT_WAIT_TIME.toMillis());
1624                 }
1625                 catch (final InterruptedException e) {
1626                     pageToPrint.executeJavaScript("log('" + e.getMessage() + "');");
1627                 }
1628                 pageToPrint.executeJavaScript("log('print handled');");
1629             }
1630         });
1631 
1632         page = webClient.getPage(URL_FIRST);
1633         page.getElementById("click").click();
1634         webClient.waitForBackgroundJavaScript(200000 * DEFAULT_WAIT_TIME.toMillis());
1635 
1636         assertEquals(getExpectedAlerts()[1], page.getTitleText());
1637     }
1638 
1639     /**
1640      * @throws Exception if the test fails
1641      */
1642     @Test
1643     @Alerts("before print"
1644                     + "§event beforeprint"
1645                     + "§[object Event]beforeprint-false-false-false-[object Window]"
1646                         + "-false-2-true-true-[object Window]-[object Window]-beforeprint"
1647                     + "§event afterprint"
1648                     + "§[object Event]afterprint-false-false-false-[object Window]"
1649                         + "-false-2-true-true-[object Window]-[object Window]-afterprint"
1650                     + "§printed§")
1651     @HtmlUnitNYI(CHROME = "before print"
1652                     + "§event beforeprint"
1653                     + "§[object Event]beforeprint-false-false-false-[object Window]"
1654                         + "-false-2-undefined-true-[object Window]-[object Window]-beforeprint"
1655                     + "§event afterprint"
1656                     + "§[object Event]afterprint-false-false-false-[object Window]"
1657                         + "-false-2-undefined-true-[object Window]-[object Window]-afterprint"
1658                     + "§printed§",
1659             EDGE = "before print"
1660                     + "§event beforeprint"
1661                     + "§[object Event]beforeprint-false-false-false-[object Window]"
1662                         + "-false-2-undefined-true-[object Window]-[object Window]-beforeprint"
1663                     + "§event afterprint"
1664                     + "§[object Event]afterprint-false-false-false-[object Window]"
1665                         + "-false-2-undefined-true-[object Window]-[object Window]-afterprint"
1666                     + "§printed§",
1667             FF = "before print"
1668                     + "§event beforeprint"
1669                     + "§[object Event]beforeprint-false-false-false-[object Window]"
1670                         + "-false-2-undefined-true-[object Window]-[object Window]-beforeprint"
1671                     + "§event afterprint"
1672                     + "§[object Event]afterprint-false-false-false-[object Window]"
1673                         + "-false-2-undefined-true-[object Window]-[object Window]-afterprint"
1674                     + "§printed§",
1675             FF_ESR = "before print"
1676                     + "§event beforeprint"
1677                     + "§[object Event]beforeprint-false-false-false-[object Window]"
1678                         + "-false-2-undefined-true-[object Window]-[object Window]-beforeprint"
1679                     + "§event afterprint"
1680                     + "§[object Event]afterprint-false-false-false-[object Window]"
1681                         + "-false-2-undefined-true-[object Window]-[object Window]-afterprint"
1682                     + "§printed§")
1683     public void printEvent() throws Exception {
1684         // we have to test this manually
1685 
1686         final WebClient webClient = getWebClient();
1687         final MockWebConnection webConnection = new MockWebConnection();
1688 
1689         // without an print handler set the print method is a noop
1690         webClient.setPrintHandler(new PrintHandler() {
1691             @Override
1692             public void handlePrint(final HtmlPage page) {
1693             }
1694         });
1695 
1696 
1697         final String firstContent = DOCTYPE_HTML
1698             + "<html><head>\n"
1699             + "<script>\n"
1700             + "  function log(msg) { window.document.title += msg + '§'; }\n"
1701 
1702             + "  function dumpEvent(event) {\n"
1703             + "    var msg = event;\n"
1704             + "    msg = msg + event.type;\n"
1705             + "    msg = msg + '-' + event.bubbles;\n"
1706             + "    msg = msg + '-' + event.cancelable;\n"
1707             + "    msg = msg + '-' + event.composed;\n"
1708             + "    msg = msg + '-' + event.currentTarget;\n"
1709             + "    msg = msg + '-' + event.defaultPrevented;\n"
1710             + "    msg = msg + '-' + event.eventPhase;\n"
1711             + "    msg = msg + '-' + event.isTrusted;\n"
1712             + "    msg = msg + '-' + event.returnValue;\n"
1713             + "    msg = msg + '-' + event.srcElement;\n"
1714             + "    msg = msg + '-' + event.target;\n"
1715             // + "    msg = msg + '-' + event.timeStamp;\n"
1716             + "    msg = msg + '-' + event.type;\n"
1717             + "    log(msg);\n"
1718             + "  }\n"
1719 
1720             + "  function doTest() {\n"
1721             + "    addEventListener('beforeprint', function(e) { log('event beforeprint'); dumpEvent(e); })\n"
1722             + "    addEventListener('afterprint', function(e) { log('event afterprint'); dumpEvent(e); })\n"
1723 
1724             + "    log('before print');\n"
1725             + "    window.print();\n"
1726             + "    log('printed');\n"
1727             + "  }\n"
1728             + "</script>\n"
1729             + "</head>\n"
1730             + "<body>\n"
1731             + "  <button id='click' onclick='doTest()'>Print</button>\n"
1732             + "</body></html>";
1733 
1734         final URL url = URL_FIRST;
1735         webConnection.setResponse(url, firstContent);
1736         webClient.setWebConnection(webConnection);
1737 
1738         final HtmlPage page = webClient.getPage(URL_FIRST);
1739         page.getElementById("click").click();
1740         webClient.waitForBackgroundJavaScript(DEFAULT_WAIT_TIME.toMillis());
1741 
1742         assertEquals(getExpectedAlerts()[0], page.getTitleText());
1743     }
1744 
1745     /**
1746      * @throws Exception if the test fails
1747      */
1748     @Test
1749     @Alerts("block§none§block§")
1750     public void printCssMediaRule() throws Exception {
1751         // we have to test this manually
1752 
1753         final WebClient webClient = getWebClient();
1754         final MockWebConnection webConnection = new MockWebConnection();
1755 
1756         // without an print handler set the print method is a noop
1757         webClient.setPrintHandler(new PrintHandler() {
1758             @Override
1759             public void handlePrint(final HtmlPage page) {
1760                 page.executeJavaScript(
1761                         "log(window.getComputedStyle(document.getElementById('tester') ,null)"
1762                                 + ".getPropertyValue('display'))");
1763             }
1764         });
1765 
1766 
1767         final String firstContent = DOCTYPE_HTML
1768             + "<html><head>\n"
1769             + "<script>\n"
1770             + "  function log(msg) { window.document.title += msg + '§'; }\n"
1771 
1772             + "  function doTest() {\n"
1773             + "    log(window.getComputedStyle(document.getElementById('tester') ,null)"
1774                         + ".getPropertyValue('display'));\n"
1775             + "    window.print();\n"
1776             + "    log(window.getComputedStyle(document.getElementById('tester') ,null)"
1777                         + ".getPropertyValue('display'));\n"
1778             + "  }\n"
1779             + "</script>\n"
1780             + "<style type='text/css'>\n"
1781             + "  @media print { p { display: none }}\n"
1782             + "</style>"
1783             + "</head>\n"
1784             + "<body>\n"
1785             + "  <p id='tester'>HtmlUnit</p>\n"
1786             + "  <button id='click' onclick='doTest()'>Print</button>\n"
1787             + "</body></html>";
1788 
1789         final URL url = URL_FIRST;
1790         webConnection.setResponse(url, firstContent);
1791         webClient.setWebConnection(webConnection);
1792 
1793         final HtmlPage page = webClient.getPage(URL_FIRST);
1794         page.getElementById("click").click();
1795         webClient.waitForBackgroundJavaScript(DEFAULT_WAIT_TIME.toMillis());
1796 
1797         assertEquals(getExpectedAlerts()[0], page.getTitleText());
1798     }
1799 }