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 java.net.URL;
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import org.htmlunit.CollectingAlertHandler;
22  import org.htmlunit.MockWebConnection;
23  import org.htmlunit.SimpleWebTestCase;
24  import org.htmlunit.WebClient;
25  import org.htmlunit.html.HtmlAnchor;
26  import org.htmlunit.html.HtmlPage;
27  import org.htmlunit.junit.BrowserRunner;
28  import org.htmlunit.junit.annotation.Alerts;
29  import org.junit.Test;
30  import org.junit.runner.RunWith;
31  
32  /**
33   * Tests for {@link Location}.
34   *
35   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
36   * @author Michael Ottati
37   * @author Marc Guillemot
38   * @author Daniel Gredler
39   * @author Ahmed Ashour
40   * @author Ronald Brill
41   * @author Lai Quang Duong
42   */
43  @RunWith(BrowserRunner.class)
44  public class LocationTest extends SimpleWebTestCase {
45  
46      /**
47       * @throws Exception if the test fails
48       */
49      @Test
50      public void href() throws Exception {
51          final WebClient webClient = getWebClient();
52          final MockWebConnection webConnection = new MockWebConnection();
53  
54          final String content = DOCTYPE_HTML
55              + "<html><head><title>First</title><script>\n"
56              + "function test() {\n"
57              + "  alert(window.location.href);\n"
58              + "}\n"
59              + "</script></head><body onload='test()'>\n"
60              + "</body></html>";
61  
62          webConnection.setResponse(new URL("http://myHostName/"), content);
63          webClient.setWebConnection(webConnection);
64  
65          final List<String> collectedAlerts = new ArrayList<>();
66          webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
67  
68          webClient.getPage("http://myHostName");
69          final String[] expectedAlerts = {"http://myHostName/" };
70          assertEquals(expectedAlerts, collectedAlerts);
71      }
72  
73      /**
74       * @throws Exception if the test fails
75       */
76      @Test
77      public void getVariousAttributes() throws Exception {
78          String[] expectedAlerts = {
79              "",               // hash
80              "first",          // host
81              "first",          // hostname
82              "http://first/",  // href
83              "/",              // pathname
84              "",               // port
85              "http:",          // protocol
86              ""                // search
87          };
88          testGetVariousAttributes("http://first", expectedAlerts);
89  
90          // Try page with all the appropriate parts
91          expectedAlerts = new String[] {
92              "#wahoo",                            // hash
93              "www.first:77",                      // host
94              "www.first",                         // hostname
95              "http://www.first:77/foo?bar#wahoo", // href
96              "/foo",                              // pathname
97              "77",                                // port
98              "http:",                             // protocol
99              "?bar"                               // search
100         };
101         testGetVariousAttributes("http://www.first:77/foo?bar#wahoo", expectedAlerts);
102     }
103 
104     private void testGetVariousAttributes(final String url, final String[] expectedAlerts) throws Exception {
105         final WebClient client = getWebClient();
106         final MockWebConnection webConnection = new MockWebConnection();
107 
108         final String content = DOCTYPE_HTML
109             + "<html><head><title>First</title><script>\n"
110             + "function doTest() {\n"
111             + "  var location = document.location;\n"
112             + "  alert(location.hash);\n"
113             + "  alert(location.host);\n"
114             + "  alert(location.hostname);\n"
115             + "  alert(location.href);\n"
116             + "  alert(location.pathname);\n"
117             + "  alert(location.port);\n"
118             + "  alert(location.protocol);\n"
119             + "  alert(location.search);\n"
120             + "}\n</script></head>\n"
121             + "<body onload='doTest()'></body></html>";
122 
123         webConnection.setDefaultResponse(content);
124         client.setWebConnection(webConnection);
125 
126         final List<String> collectedAlerts = new ArrayList<>();
127         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
128 
129         // Try page with only a server name
130         client.getPage(url);
131         assertEquals(expectedAlerts, collectedAlerts);
132     }
133 
134     /**
135      * @throws Exception if the test fails
136      */
137     @Test
138     public void setHostname() throws Exception {
139         final WebClient webClient = getWebClient();
140         final MockWebConnection webConnection = new MockWebConnection();
141         final URL url = new URL("http://abc.com/index.html#bottom");
142         final URL url2 = new URL("http://xyz.com/index.html#bottom");
143         final String html = DOCTYPE_HTML
144             + "<html><head><title>Test 1</title></head>\n"
145             + "<body onload='location.hostname=\"xyz.com\"'>...</body></html>";
146         final String html2 = DOCTYPE_HTML
147                 + "<html><head><title>Test 2</title></head><body>...</body></html>";
148         webConnection.setResponse(url, html);
149         webConnection.setResponse(url2, html2);
150         webClient.setWebConnection(webConnection);
151 
152         final HtmlPage page = webClient.getPage(url);
153         assertEquals("Test 2", page.getTitleText());
154         assertEquals(url2.toExternalForm(), page.getUrl().toExternalForm());
155     }
156 
157     /**
158      * @throws Exception if the test fails
159      */
160     @Test
161     public void setHostWithoutPort() throws Exception {
162         final WebClient webClient = getWebClient();
163         final MockWebConnection webConnection = new MockWebConnection();
164         final URL url = new URL("http://abc.com/index.html#bottom");
165         final URL url2 = new URL("http://xyz.com/index.html#bottom");
166         final String html = DOCTYPE_HTML
167             + "<html><head><title>Test 1</title></head>\n"
168             + "<body onload='location.host=\"xyz.com\"'>...</body></html>";
169         final String html2 = DOCTYPE_HTML
170                 + "<html><head><title>Test 2</title></head><body>...</body></html>";
171         webConnection.setResponse(url, html);
172         webConnection.setResponse(url2, html2);
173         webClient.setWebConnection(webConnection);
174 
175         final HtmlPage page = webClient.getPage(url);
176         assertEquals("Test 2", page.getTitleText());
177         assertEquals(url2.toExternalForm(), page.getUrl().toExternalForm());
178     }
179 
180     /**
181      * @throws Exception if the test fails
182      */
183     @Test
184     public void setHostWithPort() throws Exception {
185         final WebClient webClient = getWebClient();
186         final MockWebConnection webConnection = new MockWebConnection();
187         final URL url = new URL("http://abc.com/index.html#bottom");
188         final URL url2 = new URL("http://xyz.com:8080/index.html#bottom");
189         final String html = DOCTYPE_HTML
190             + "<html><head><title>Test 1</title></head>\n"
191             + "<body onload='location.host=\"xyz.com:8080\"'>...</body></html>";
192         final String html2 = DOCTYPE_HTML
193                 + "<html><head><title>Test 2</title></head><body>...</body></html>";
194         webConnection.setResponse(url, html);
195         webConnection.setResponse(url2, html2);
196         webClient.setWebConnection(webConnection);
197 
198         final HtmlPage page = webClient.getPage(url);
199         assertEquals("Test 2", page.getTitleText());
200         assertEquals(url2.toExternalForm(), page.getUrl().toExternalForm());
201     }
202 
203     /**
204      * @throws Exception if the test fails
205      */
206     @Test
207     public void setPathname() throws Exception {
208         final URL url = new URL("http://abc.com/index.html?blah=bleh");
209         final URL url2 = new URL("http://abc.com/en/index.html?blah=bleh");
210         final String html = DOCTYPE_HTML
211             + "<html><head><title>Test 1</title></head>\n"
212             + "<body onload='location.pathname=\"/en/index.html\"'>...</body></html>";
213         final String html2 = DOCTYPE_HTML
214                 + "<html><head><title>Test 2</title></head><body>...</body></html>";
215 
216         getMockWebConnection().setResponse(url, html);
217         getMockWebConnection().setResponse(url2, html2);
218 
219         final HtmlPage page = getWebClientWithMockWebConnection().getPage(url);
220         assertEquals("Test 2", page.getTitleText());
221         assertEquals(url2.toExternalForm(), page.getUrl().toExternalForm());
222     }
223 
224     /**
225      * @throws Exception if the test fails
226      */
227     @Test
228     public void setPort() throws Exception {
229         final WebClient webClient = getWebClient();
230         final MockWebConnection webConnection = new MockWebConnection();
231         final URL url = new URL("http://abc.com/index.html#bottom");
232         final URL url2 = new URL("http://abc.com:88/index.html#bottom");
233         final String html = DOCTYPE_HTML
234             + "<html><head><title>Test 1</title></head>\n"
235             + "<body onload='location.port=\"88\"'>...</body></html>";
236         final String html2 = DOCTYPE_HTML
237                 + "<html><head><title>Test 2</title></head><body>...</body></html>";
238         webConnection.setResponse(url, html);
239         webConnection.setResponse(url2, html2);
240         webClient.setWebConnection(webConnection);
241 
242         final HtmlPage page = webClient.getPage(url);
243         assertEquals("Test 2", page.getTitleText());
244         assertEquals(url2.toExternalForm(), page.getUrl().toExternalForm());
245     }
246 
247     /**
248      * @throws Exception if the test fails
249      */
250     @Test
251     public void setProtocol() throws Exception {
252         final URL url = new URL("http://abc.com/index.html?blah=bleh");
253         final URL url2 = new URL("ftp://abc.com/index.html?blah=bleh");
254         final String html = DOCTYPE_HTML
255             + "<html><head><title>Test 1</title></head>\n"
256             + "<body onload='location.protocol=\"ftp\"'>...</body></html>";
257         final String html2 = DOCTYPE_HTML
258                 + "<html><head><title>Test 2</title></head><body>...</body></html>";
259 
260         getMockWebConnection().setResponse(url, html);
261         getMockWebConnection().setResponse(url2, html2);
262 
263         final HtmlPage page = getWebClientWithMockWebConnection().getPage(url);
264         assertEquals("Test 2", page.getTitleText());
265         assertEquals(url2.toExternalForm(), page.getUrl().toExternalForm());
266     }
267 
268     /**
269      * Verifies that modifying <tt>window.location.hash</tt> works, but that it doesn't
270      * force the page to reload from the server. This is very important for the Dojo
271      * unit tests, which will keep reloading themselves if the page gets reloaded.
272      *
273      * @throws Exception if the test fails
274      */
275     @Test
276     public void setHash() throws Exception {
277         final WebClient webClient = getWebClient();
278         final MockWebConnection conn = new MockWebConnection();
279 
280         final String html = DOCTYPE_HTML
281             + "<html><head><title>Test</title></head><body>\n"
282             + "<a id='a' onclick='alert(location.hash);location.hash=\"b\";alert(location.hash);'>go</a>\n"
283             + "<h2 id='b'>...</h2></body></html>";
284 
285         conn.setResponse(URL_FIRST, html);
286         webClient.setWebConnection(conn);
287 
288         final List<String> actual = new ArrayList<>();
289         webClient.setAlertHandler(new CollectingAlertHandler(actual));
290 
291         final HtmlPage page = webClient.getPage(URL_FIRST);
292         final HtmlAnchor anchor = page.getHtmlElementById("a");
293         final HtmlPage page2 = anchor.click();
294 
295         // Verify that it worked.
296         final String[] expected = new String[] {"", "#b"};
297         assertEquals(expected, actual);
298 
299         // Verify that we didn't reload the page.
300         assertTrue(page == page2);
301         assertEquals(URL_FIRST, conn.getLastWebRequest().getUrl());
302     }
303 
304     /**
305      * Regression test for http://sourceforge.net/p/htmlunit/bugs/307/.
306      * @throws Exception if the test fails
307      */
308     @Test
309     public void replaceWithFrame() throws Exception {
310         final WebClient webClient = getWebClient();
311         final MockWebConnection webConnection = new MockWebConnection();
312 
313         final String mainContent = DOCTYPE_HTML
314             + "<html>\n"
315             + "  <frameset rows='100,*'>\n"
316             + "    <frame name='menu' src='menu.html'/>\n"
317             + "    <frame name='content' src='content.html'/>\n"
318             + "  </frameset>\n"
319             + "</html>";
320         final String frameMenu = DOCTYPE_HTML
321             + "<html><body>\n"
322             + "<a href='#' id='myLink' target='content' "
323             + "onclick='parent.frames.content.location.replace(\"test.html\");return false;'>Test2</a>\n"
324             + "</body></html>";
325         final String frameContent = DOCTYPE_HTML
326                 + "<html><head><title>Start content</title></head><body></body></html>";
327         final String frameTest = DOCTYPE_HTML
328                 + "<html><head><title>Test</title></head><body></body></html>";
329 
330         webConnection.setResponse(URL_FIRST, mainContent);
331         webConnection.setResponse(new URL(URL_FIRST, "menu.html"), frameMenu);
332         webConnection.setResponse(new URL(URL_FIRST, "content.html"), frameContent);
333         webConnection.setResponse(new URL(URL_FIRST, "test.html"), frameTest);
334 
335         webClient.setWebConnection(webConnection);
336 
337         final HtmlPage page = webClient.getPage(URL_FIRST);
338         assertEquals(3, webClient.getWebWindows().size());
339         assertEquals("Start content", ((HtmlPage) page.getFrameByName("content").getEnclosedPage()).getTitleText());
340 
341         final HtmlPage menuPage = (HtmlPage) page.getFrameByName("menu").getEnclosedPage();
342         menuPage.getHtmlElementById("myLink").click();
343         assertEquals(3, webClient.getWebWindows().size());
344         assertEquals("Test", ((HtmlPage) page.getFrameByName("content").getEnclosedPage()).getTitleText());
345     }
346 
347     /**
348      * Tests that location.reload() works correctly.
349      * @throws Exception if the test fails
350      */
351     @Test
352     public void reload() throws Exception {
353         final String content = DOCTYPE_HTML
354             + "<html>\n"
355             + "  <head><title>test</title></head>\n"
356             + "  <body>\n"
357             + "    <a href='javascript:window.location.reload();' id='link1'>reload</a>\n"
358             + "  </body>\n"
359             + "</html>";
360 
361         final HtmlPage page1 = loadPage(content);
362         final HtmlAnchor link = page1.getHtmlElementById("link1");
363         final HtmlPage page2 = link.click();
364 
365         assertEquals(page1.getTitleText(), page2.getTitleText());
366         assertNotSame(page1, page2);
367     }
368 
369     /**
370      * @throws Exception if the test fails
371      */
372     @Test
373     @Alerts("c")
374     public void locationWithTarget() throws Exception {
375         final WebClient client = getWebClient();
376         final List<String> alerts = new ArrayList<>();
377         client.setAlertHandler(new CollectingAlertHandler(alerts));
378 
379         final URL url = getClass().getResource("LocationTest_locationWithTarget_a.html");
380         assertNotNull(url);
381 
382         final HtmlPage a = client.getPage(url);
383         final HtmlPage c = (HtmlPage) a.getFrameByName("c").getEnclosedPage();
384         c.getHtmlElementById("anchor").click();
385         assertEquals(getExpectedAlerts(), alerts);
386     }
387 
388     /**
389      * @throws Exception if an error occurs
390      */
391     @Test
392     public void fileUrlFormat() throws Exception {
393         final URL url = getClass().getResource("LocationTest_fileUrlFormat.html");
394         assertNotNull(url);
395 
396         final WebClient client = getWebClient();
397         final List<String> alerts = new ArrayList<>();
398         client.setAlertHandler(new CollectingAlertHandler(alerts));
399         client.getPage(url);
400 
401         assertEquals(1, alerts.size());
402         assertTrue(alerts.get(0).startsWith("file:///"));
403     }
404 }