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.xml;
16  
17  import java.io.File;
18  import java.net.URL;
19  
20  import org.htmlunit.SimpleWebTestCase;
21  import org.htmlunit.WebClient;
22  import org.htmlunit.WebWindow;
23  import org.htmlunit.html.HtmlPage;
24  import org.htmlunit.junit.annotation.Alerts;
25  import org.junit.jupiter.api.Test;
26  
27  /**
28   * Tests for {@link XMLHttpRequest}.
29   *
30   * @author Daniel Gredler
31   * @author Marc Guillemot
32   * @author Ahmed Ashour
33   * @author Stuart Begg
34   * @author Sudhan Moghe
35   * @author Thorsten Wendelmuth
36   * @author Atsushi Nakagawa
37   */
38  public class XMLHttpRequest4Test extends SimpleWebTestCase {
39  
40      /**
41       * @throws Exception if the test fails
42       */
43      @Test
44      public void setLocation_onreadystatechange() throws Exception {
45          final String content = DOCTYPE_HTML
46              + "<html>\n"
47              + "  <head>\n"
48              + "    <title>Page1</title>\n"
49              + "    <script>\n"
50              + "      var request;\n"
51              + "      function testAsync() {\n"
52              + "        request = new XMLHttpRequest();\n"
53              + "        request.onreadystatechange = onReadyStateChange;\n"
54              + "        request.open('GET', 'foo.xml', true);\n"
55              + "        request.send('');\n"
56              + "      }\n"
57              + "      function onReadyStateChange() {\n"
58              + "        if (request.readyState == 4) {\n"
59              + "          window.location.href = 'about:blank';\n"
60              + "        }\n"
61              + "      }\n"
62              + "    </script>\n"
63              + "  </head>\n"
64              + "  <body onload='testAsync()'>\n"
65              + "  </body>\n"
66              + "</html>";
67  
68          getMockWebConnection().setDefaultResponse("");
69          final WebWindow window = loadPage(content).getEnclosingWindow();
70          assertEquals(0, window.getWebClient().waitForBackgroundJavaScriptStartingBefore(1000));
71          assertEquals("about:blank", window.getEnclosedPage().getUrl());
72      }
73  
74      /**
75       * @throws Exception if the test fails
76       */
77      @Test
78      public void setLocation_addEventListener() throws Exception {
79          final String content = DOCTYPE_HTML
80              + "<html>\n"
81              + "  <head>\n"
82              + "    <title>Page1</title>\n"
83              + "    <script>\n"
84              + "      var request;\n"
85              + "      function testAsync() {\n"
86              + "        request = new XMLHttpRequest();\n"
87              + "        request.addEventListener('readystatechange', onReadyStateChange);\n"
88              + "        request.open('GET', 'foo.xml', true);\n"
89              + "        request.send('');\n"
90              + "      }\n"
91              + "      function onReadyStateChange() {\n"
92              + "        if (request.readyState == 4) {\n"
93              + "          window.location.href = 'about:blank';\n"
94              + "        }\n"
95              + "      }\n"
96              + "    </script>\n"
97              + "  </head>\n"
98              + "  <body onload='testAsync()'>\n"
99              + "  </body>\n"
100             + "</html>";
101 
102         getMockWebConnection().setDefaultResponse("");
103         final WebWindow window = loadPage(content).getEnclosingWindow();
104         assertEquals(0, window.getWebClient().waitForBackgroundJavaScriptStartingBefore(1000));
105         assertEquals("about:blank", window.getEnclosedPage().getUrl());
106     }
107 
108     /**
109      * Testing event invocation order.
110      * @throws Exception if the test fails
111      */
112     @Test
113     @Alerts({"onreadystatechange_1: readyState=1",
114              "onreadystatechange_2: readyState=1",
115              "onreadystatechange_p: readyState=1",
116              "onreadystatechange_3: readyState=1",
117              "onreadystatechange_4: readyState=1",
118              "onreadystatechange_1: readyState=2",
119              "onreadystatechange_2: readyState=2",
120              "onreadystatechange_p: readyState=2",
121              "onreadystatechange_3: readyState=2",
122              "onreadystatechange_4: readyState=2",
123              "onreadystatechange_1: readyState=3",
124              "onreadystatechange_2: readyState=3",
125              "onreadystatechange_p: readyState=3",
126              "onreadystatechange_3: readyState=3",
127              "onreadystatechange_4: readyState=3",
128              "onreadystatechange_1: readyState=4",
129              "onreadystatechange_2: readyState=4",
130              "onreadystatechange_p: readyState=4",
131              "onreadystatechange_3: readyState=4",
132              "onreadystatechange_4: readyState=4"})
133     public void eventInvocationOrder() throws Exception {
134         final String html = DOCTYPE_HTML
135             + "<html>\n"
136             + "<head>\n"
137             + "<script>\n"
138             + "function test() {\n"
139             + "  var xhr = new XMLHttpRequest();\n"
140             + "\n"
141             + "  var onreadystatechange_1 = function (e) {\n"
142             + "    alert('onreadystatechange_1: readyState=' + xhr.readyState);\n"
143             + "  }\n"
144             + "  var onreadystatechange_2 = function (e) {\n"
145             + "    alert('onreadystatechange_2: readyState=' + xhr.readyState);\n"
146             + "    e.stopPropagation();\n"
147             + "  }\n"
148             + "  var onreadystatechange_3 = function (e) {\n"
149             + "    alert('onreadystatechange_3: readyState=' + xhr.readyState);\n"
150             + "    e.stopPropagation();\n"
151             + "  }\n"
152             + "  var onreadystatechange_4 = function (e) {\n"
153             + "    alert('onreadystatechange_4: readyState=' + xhr.readyState);\n"
154             + "  }\n"
155             + "\n"
156             + "  var onreadystatechange_p = function (e) {\n"
157             + "    alert('onreadystatechange_p: readyState=' + xhr.readyState);\n"
158             + "  }\n"
159             + "\n"
160             + "  xhr.addEventListener('readystatechange', onreadystatechange_1, false);\n"
161             + "  xhr.addEventListener('readystatechange', onreadystatechange_2, true);\n"
162             + "  xhr.onreadystatechange = onreadystatechange_p;\n"
163             + "  xhr.addEventListener('readystatechange', onreadystatechange_3, false);\n"
164             + "  xhr.addEventListener('readystatechange', onreadystatechange_4, true);\n"
165             + "  xhr.open('GET', 'foo.xml');\n"
166             + "  xhr.send();\n"
167             + "}\n"
168             + "</script>\n"
169             + "</head>\n"
170             + "<body onload='test()'>\n"
171             + "</body>\n"
172             + "</html>\n";
173 
174         getMockWebConnection().setDefaultResponse("");
175         loadPageWithAlerts(html, URL_FIRST, DEFAULT_WAIT_TIME);
176     }
177 
178     /**
179      * @throws Exception if the test fails
180      */
181     @Test
182     @Alerts("onreadystatechange [object Event]§readystatechange§1§"
183             + "onreadystatechange [object Event]§readystatechange§4§")
184     public void sendLocalFileAllowed() throws Exception {
185         // see org.htmlunit.javascript.host.xml.XMLHttpRequest5Test.sendLocalFile()
186         final URL fileURL = getClass().getClassLoader().getResource("testfiles/localxmlhttprequest/index.html");
187         final File file = new File(fileURL.toURI());
188         assertTrue("File '" + file.getAbsolutePath() + "' does not exist", file.exists());
189 
190         final WebClient client = getWebClient();
191         client.getOptions().setFileProtocolForXMLHttpRequestsAllowed(true);
192 
193         final HtmlPage page = client.getPage(fileURL);
194 
195         assertEquals(0, client.waitForBackgroundJavaScriptStartingBefore(1000));
196         assertEquals(getExpectedAlerts()[0], page.getTitleText());
197     }
198 
199     /**
200      * @throws Exception if the test fails
201      */
202     @Test
203     @Alerts("onreadystatechange [object Event]§readystatechange§1§"
204             + "onreadystatechange [object Event]§readystatechange§4§")
205     public void sendLocalSubFileAllowed() throws Exception {
206         // see org.htmlunit.javascript.host.xml.XMLHttpRequest5Test.sendLocalFile()
207         final URL fileURL = getClass().getClassLoader().getResource("testfiles/localxmlhttprequest/index_sub.html");
208         final File file = new File(fileURL.toURI());
209         assertTrue("File '" + file.getAbsolutePath() + "' does not exist", file.exists());
210 
211         final WebClient client = getWebClient();
212         client.getOptions().setFileProtocolForXMLHttpRequestsAllowed(true);
213 
214         final HtmlPage page = client.getPage(fileURL);
215 
216         assertEquals(0, client.waitForBackgroundJavaScriptStartingBefore(1000));
217         assertEquals(getExpectedAlerts()[0], page.getTitleText());
218     }
219 }