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