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.html;
16  
17  import java.nio.charset.StandardCharsets;
18  import java.util.Collections;
19  
20  import org.htmlunit.WebDriverTestCase;
21  import org.htmlunit.junit.annotation.Alerts;
22  import org.htmlunit.junit.annotation.HtmlUnitNYI;
23  import org.htmlunit.util.MimeType;
24  import org.htmlunit.util.NameValuePair;
25  import org.junit.jupiter.api.Test;
26  import org.openqa.selenium.WebDriver;
27  
28  /**
29   * Tests for {@link HtmlPage}.
30   *
31   * @author Ahmed Ashour
32   * @author Marc Guillemot
33   * @author Ronald Brill
34   * @author Frank Danek
35   * @author Joerg Werner
36   */
37  public class HtmlPage6Test extends WebDriverTestCase {
38  
39      /**
40       * Test auto-refresh from a meta tag.
41       * @throws Exception if the test fails
42       */
43      @Test
44      @Alerts({"second", "2", "§§URL§§second/"})
45      public void refresh_MetaTag_DefaultRefreshHandler() throws Exception {
46          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;URL=§§URL§§\">");
47          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=§§URL§§\">");
48      }
49  
50      /**
51       * @throws Exception if the test fails
52       */
53      @Test
54      @Alerts({"second", "2", "§§URL§§second/"})
55      public void refresh_MetaTag_caseSensitivity() throws Exception {
56          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; Url=§§URL§§\">");
57      }
58  
59      /**
60       * Regression test for bug #954.
61       * @throws Exception if the test fails
62       */
63      @Test
64      @Alerts({"second", "2", "§§URL§§second/"})
65      public void refresh_MetaTag_spaceSeparator() throws Exception {
66          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0 Url=§§URL§§\">");
67          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\nUrl=§§URL§§\">");
68          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\tUrl=§§URL§§\">");
69      }
70  
71      /**
72       * Regression test for bug #954.
73       * @throws Exception if the test fails
74       */
75      @Test
76      @Alerts({"second", "2", "§§URL§§second/"})
77      public void refresh_MetaTag_commaSeparator() throws Exception {
78          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0,Url=§§URL§§\">");
79          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0, Url=§§URL§§\">");
80      }
81  
82      /**
83       * @throws Exception if the test fails
84       */
85      @Test
86      @Alerts({"first", "1"})
87      public void refresh_MetaTag_noSeparator() throws Exception {
88          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0Url=§§URL§§\">");
89          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0§§URL§§\">");
90          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0abc=§§URL§§\">");
91          testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0abc§§URL§§\">");
92      }
93  
94      /**
95       * Test for bug #1002.
96       * @throws Exception if the test fails
97       */
98      @Test
99      @Alerts({"second", "2", "§§URL§§second/"})
100     public void refresh_MetaTag_no_url_label() throws Exception {
101         testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;§§URL§§\">");
102         testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; §§URL§§\">");
103         testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0 §§URL§§\">");
104         testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\n§§URL§§\">");
105     }
106 
107     /**
108      * @throws Exception if the test fails
109      */
110     @Test
111     @Alerts({"wrong", "2", "§§URL§§abcd=§§URL§§second/"})
112     @HtmlUnitNYI(CHROME = {"wrong", "2", "§§URL§§abcd=§§URL1§§second/"},
113             EDGE = {"wrong", "2", "§§URL§§abcd=§§URL1§§second/"},
114             FF = {"wrong", "2", "§§URL§§abcd=§§URL1§§second/"},
115             FF_ESR = {"wrong", "2", "§§URL§§abcd=§§URL1§§second/"})
116     public void refresh_MetaTag_wrong_url_label() throws Exception {
117         testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0;abcd=§§URL§§\">");
118         testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; abcd=§§URL§§\">");
119         testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0 abcd=§§URL§§\">");
120         testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\nabcd=§§URL§§\">");
121     }
122 
123     /**
124      * Test auto-refresh from a meta tag with no URL.
125      * @throws Exception if the test fails
126      */
127     @Test
128     @Alerts({"first", "3", "§§URL§§"})
129     public void refresh_MetaTag_NoUrl() throws Exception {
130         // currently an endless loop
131         // todo testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"1\">");
132         // todo testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"1;\">");
133         // todo testRefresh_MetaTag("<META HTTP-EQUIV=\"Refresh\" CONTENT=\"1 \">");
134     }
135 
136     /**
137      * Test auto-refresh from a meta tag with URL quoted.
138      * @throws Exception if the test fails
139      */
140     @Test
141     @Alerts({"second", "2", "§§URL§§second/"})
142     public void refresh_MetaTag_Quoted() throws Exception {
143         testRefresh_MetaTag("<META HTTP-EQUIV='Refresh' CONTENT='0;URL=\"§§URL§§\"'>");
144     }
145 
146     /**
147      * Test auto-refresh from a meta tag with URL partly quoted.
148      * @throws Exception if the test fails
149      */
150     @Test
151     @Alerts({"second", "2", "§§URL§§second/"})
152     public void refresh_MetaTag_PartlyQuoted() throws Exception {
153         testRefresh_MetaTag("<META HTTP-EQUIV='Refresh' CONTENT=\"0;URL='§§URL§§\">");
154     }
155 
156     /**
157      * Test that whitespace before and after ';' is permitted.
158      *
159      * @throws Exception if the test fails
160      */
161     @Test
162     @Alerts({"second", "2", "§§URL§§second/"})
163     public void refresh_MetaTag_Whitespace() throws Exception {
164         testRefresh_MetaTag("<META HTTP-EQUIV='Refresh' CONTENT='0  ;  URL=§§URL§§'>");
165     }
166 
167     /**
168      * Test that the refresh time can be a double ("3.4", for example), not just an integer.
169      *
170      * @throws Exception if an error occurs
171      */
172     @Test
173     @Alerts({"second", "2", "§§URL§§second/"})
174     public void refresh_MetaTag_Double() throws Exception {
175         testRefresh_MetaTag("<META HTTP-EQUIV='Refresh' CONTENT='1.2  ;  URL=§§URL§§'>");
176     }
177 
178     /**
179      * @throws Exception if an error occurs
180      */
181     @Test
182     @Alerts({"wrong", "2", "§§URL§§2;URL=§§URL§§second/"})
183     @HtmlUnitNYI(CHROME = {"wrong", "2", "§§URL§§2;URL=§§URL1§§second/"},
184             EDGE = {"wrong", "2", "§§URL§§2;URL=§§URL1§§second/"},
185             FF = {"wrong", "2", "§§URL§§2;URL=§§URL1§§second/"},
186             FF_ESR = {"wrong", "2", "§§URL§§2;URL=§§URL1§§second/"})
187     public void refresh_MetaTag_DoubleComma() throws Exception {
188         testRefresh_MetaTag("<META HTTP-EQUIV='Refresh' CONTENT='1,2;URL=§§URL§§'>");
189     }
190 
191     private void testRefresh_MetaTag(final String metaTag) throws Exception {
192         final String firstContent = DOCTYPE_HTML
193             + "<html><head><title>first§</title>\n"
194             + metaTag.replace("§§URL§§", URL_SECOND.toString()) + "\n"
195             + "</head><body></body></html>";
196 
197         final String secondContent = DOCTYPE_HTML
198                 + "<html><head><title>second§</title></head><body></body></html>";
199         final String wrongContent = DOCTYPE_HTML
200                 + "<html><head><title>wrong§</title></head><body></body></html>";
201 
202         getMockWebConnection().setResponse(URL_SECOND, secondContent);
203         getMockWebConnection().setDefaultResponse(wrongContent);
204 
205         expandExpectedAlertsVariables(URL_FIRST);
206         final String[] expectedAlerts = getExpectedAlerts();
207         for (int i = 0; i < expectedAlerts.length; i++) {
208             expectedAlerts[i] = expectedAlerts[i]
209                                 .replaceAll("§§URL1§§", URL_FIRST.toExternalForm().replace("http://", "http:/"));
210         }
211 
212         final int count = getMockWebConnection().getRequestCount();
213         final WebDriver driver = loadPage2(firstContent);
214         if (useRealBrowser()) {
215             Thread.sleep(DEFAULT_WAIT_TIME.multipliedBy(3).toMillis());
216         }
217         verifyTitle2(DEFAULT_WAIT_TIME, driver, expectedAlerts[0]);
218         assertEquals(Integer.parseInt(expectedAlerts[1]), getMockWebConnection().getRequestCount() - count);
219         if (expectedAlerts.length > 2) {
220             assertEquals(expectedAlerts[2], getMockWebConnection().getLastWebRequest().getUrl().toString());
221         }
222     }
223 
224     /**
225      * @throws Exception if the test fails
226      */
227     @Test
228     @Alerts({"second", "2", "§§URL§§second/"})
229     public void refresh_HttpResponseHeader_DefaultRefreshHandler() throws Exception {
230         testRefresh_HttpResponseHeader("0;URL=§§URL§§");
231         testRefresh_HttpResponseHeader("0; URL=§§URL§§");
232     }
233 
234     /**
235      * @throws Exception if the test fails
236      */
237     @Test
238     @Alerts({"second", "2", "§§URL§§second/"})
239     public void refresh_HttpResponseHeader_caseSensitivity() throws Exception {
240         testRefresh_HttpResponseHeader("0; Url=§§URL§§");
241     }
242 
243     /**
244      * @throws Exception if the test fails
245      */
246     @Test
247     @Alerts({"second", "2", "§§URL§§second/"})
248     public void refresh_HttpResponseHeader_spaceSeparator() throws Exception {
249         testRefresh_HttpResponseHeader("0 Url=§§URL§§");
250         testRefresh_HttpResponseHeader("0\nUrl=§§URL§§");
251         testRefresh_HttpResponseHeader("0\tUrl=§§URL§§");
252     }
253 
254     /**
255      * Regression test for bug #954.
256      * @throws Exception if the test fails
257      */
258     @Test
259     @Alerts({"second", "2", "§§URL§§second/"})
260     public void refresh_HttpResponseHeader_commaSeparator() throws Exception {
261         testRefresh_HttpResponseHeader("0,Url=§§URL§§");
262         testRefresh_HttpResponseHeader("0, Url=§§URL§§");
263     }
264 
265     /**
266      * @throws Exception if the test fails
267      */
268     @Test
269     @Alerts({"first", "1"})
270     public void refresh_HttpResponseHeader_noSeparator() throws Exception {
271         testRefresh_HttpResponseHeader("0Url=§§URL§§");
272         testRefresh_HttpResponseHeader("0§§URL§§");
273         testRefresh_HttpResponseHeader("0abc=§§URL§§");
274         testRefresh_HttpResponseHeader("0abc§§URL§§");
275     }
276 
277     /**
278      * Test for bug #1002.
279      * @throws Exception if the test fails
280      */
281     @Test
282     @Alerts({"second", "2", "§§URL§§second/"})
283     public void refresh_HttpResponseHeader_no_url_label() throws Exception {
284         testRefresh_HttpResponseHeader("0;§§URL§§");
285         testRefresh_HttpResponseHeader("0; §§URL§§");
286         testRefresh_HttpResponseHeader("0 §§URL§§");
287         testRefresh_HttpResponseHeader("0\n§§URL§§");
288     }
289 
290     /**
291      * @throws Exception if the test fails
292      */
293     @Test
294     @Alerts({"wrong", "2", "§§URL§§abcd=§§URL§§second/"})
295     @HtmlUnitNYI(CHROME = {"wrong", "2", "§§URL§§abcd=§§URL1§§second/"},
296             EDGE = {"wrong", "2", "§§URL§§abcd=§§URL1§§second/"},
297             FF = {"wrong", "2", "§§URL§§abcd=§§URL1§§second/"},
298             FF_ESR = {"wrong", "2", "§§URL§§abcd=§§URL1§§second/"})
299     public void refresh_HttpResponseHeader_wrong_url_label() throws Exception {
300         testRefresh_HttpResponseHeader("0;abcd=§§URL§§");
301         testRefresh_HttpResponseHeader("0; abcd=§§URL§§");
302         testRefresh_HttpResponseHeader("0 abcd=§§URL§§");
303         testRefresh_HttpResponseHeader("0\nabcd=§§URL§§");
304     }
305 
306     /**
307      * Test auto-refresh from a meta tag with no URL.
308      * @throws Exception if the test fails
309      */
310     @Test
311     @Alerts({"first", "3", "§§URL§§"})
312     public void refresh_HttpResponseHeader_NoUrl() throws Exception {
313         // currently an endless loop
314         // todo testRefresh_HttpResponseHeader("1");
315         // todo testRefresh_HttpResponseHeader("1;");
316         // todo testRefresh_HttpResponseHeader("1 ");
317     }
318 
319     /**
320      * Test auto-refresh from a meta tag with URL quoted.
321      * @throws Exception if the test fails
322      */
323     @Test
324     @Alerts({"second", "2", "§§URL§§second/"})
325     public void refresh_HttpResponseHeader_Quoted() throws Exception {
326         testRefresh_HttpResponseHeader("0;URL=\"§§URL§§\"");
327     }
328 
329     /**
330      * Test auto-refresh from a meta tag with URL partly quoted.
331      * @throws Exception if the test fails
332      */
333     @Test
334     @Alerts({"second", "2", "§§URL§§second/"})
335     public void refresh_HttpResponseHeader_PartlyQuoted() throws Exception {
336         testRefresh_HttpResponseHeader("0;URL='§§URL§§");
337     }
338 
339     /**
340      * Test that whitespace before and after ';' is permitted.
341      *
342      * @throws Exception if the test fails
343      */
344     @Test
345     @Alerts({"second", "2", "§§URL§§second/"})
346     public void refresh_HttpResponseHeader_Whitespace() throws Exception {
347         testRefresh_HttpResponseHeader("0  ;  URL=§§URL§§");
348     }
349 
350     /**
351      * @throws Exception if an error occurs
352      */
353     @Test
354     @Alerts({"second", "2", "§§URL§§second/"})
355     public void refresh_HttpResponseHeader_Double() throws Exception {
356         testRefresh_HttpResponseHeader("1.2  ;  URL=§§URL§§");
357     }
358 
359     /**
360      * @throws Exception if an error occurs
361      */
362     @Test
363     @Alerts({"wrong", "2", "§§URL§§2;URL=§§URL§§second/"})
364     @HtmlUnitNYI(CHROME = {"wrong", "2", "§§URL§§2;URL=§§URL1§§second/"},
365             EDGE = {"wrong", "2", "§§URL§§2;URL=§§URL1§§second/"},
366             FF = {"wrong", "2", "§§URL§§2;URL=§§URL1§§second/"},
367             FF_ESR = {"wrong", "2", "§§URL§§2;URL=§§URL1§§second/"})
368     public void refresh_HttpResponseHeader_DoubleComma() throws Exception {
369         testRefresh_HttpResponseHeader("1,2;URL=§§URL§§");
370     }
371 
372     private void testRefresh_HttpResponseHeader(final String refreshHeader) throws Exception {
373         final String firstContent = DOCTYPE_HTML
374                 + "<html><head><title>first§</title>\n"
375                 + "</head><body></body></html>";
376         final String secondContent = DOCTYPE_HTML
377                 + "<html><head><title>second§</title></head><body></body></html>";
378         final String wrongContent = DOCTYPE_HTML
379                 + "<html><head><title>wrong§</title></head><body></body></html>";
380 
381         final String header = refreshHeader.replace("§§URL§§", URL_SECOND.toString());
382         getMockWebConnection().setResponse(URL_FIRST, firstContent, 200, "OK", MimeType.TEXT_HTML, Collections
383                 .singletonList(new NameValuePair("Refresh", header)));
384         getMockWebConnection().setResponse(URL_SECOND, secondContent);
385         getMockWebConnection().setDefaultResponse(wrongContent);
386 
387         expandExpectedAlertsVariables(URL_FIRST);
388         final String[] expectedAlerts = getExpectedAlerts();
389         for (int i = 0; i < expectedAlerts.length; i++) {
390             expectedAlerts[i] = expectedAlerts[i]
391                                 .replaceAll("§§URL1§§", URL_FIRST.toExternalForm().replace("http://", "http:/"));
392         }
393 
394         final int count = getMockWebConnection().getRequestCount();
395         final WebDriver driver = loadPage2(URL_FIRST, StandardCharsets.ISO_8859_1);
396         if (useRealBrowser()) {
397             Thread.sleep(DEFAULT_WAIT_TIME.multipliedBy(3).toMillis());
398         }
399         verifyTitle2(DEFAULT_WAIT_TIME, driver, expectedAlerts[0]);
400         assertEquals(Integer.parseInt(expectedAlerts[1]), getMockWebConnection().getRequestCount() - count);
401         if (expectedAlerts.length > 2) {
402             assertEquals(expectedAlerts[2], getMockWebConnection().getLastWebRequest().getUrl().toString());
403         }
404     }
405 }