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 java.nio.charset.StandardCharsets.ISO_8859_1;
18  
19  import java.io.File;
20  
21  import org.apache.commons.io.FileUtils;
22  import org.htmlunit.WebDriverTestCase;
23  import org.htmlunit.junit.annotation.Alerts;
24  import org.htmlunit.junit.annotation.HtmlUnitNYI;
25  import org.junit.jupiter.api.Test;
26  import org.openqa.selenium.By;
27  import org.openqa.selenium.WebDriver;
28  
29  /**
30   * Tests for {@link URL}.
31   *
32   * @author Ronald Brill
33   */
34  public class URLTest extends WebDriverTestCase {
35  
36      /**
37       * @throws Exception if an error occurs
38       */
39      @Test
40      @Alerts("function URL() { [native code] }")
41      public void windowURL() throws Exception {
42          final String html = DOCTYPE_HTML
43              + "<html>\n"
44              + "<head>\n"
45              + "  <script>\n"
46              + LOG_TITLE_FUNCTION
47              + "    function test() {\n"
48              + "      log(window.URL);\n"
49              + "    }\n"
50              + "  </script>\n"
51              + "</head>\n"
52              + "<body onload='test()'>\n"
53              + "</body>\n"
54              + "</html>";
55          loadPageVerifyTitle2(html);
56      }
57  
58      /**
59       * @throws Exception if an error occurs
60       */
61      @Test
62      @Alerts({"https://developer.mozilla.org/", "https://developer.mozilla.org/",
63               "https://developer.mozilla.org/en-US/docs", "https://developer.mozilla.org/en-US/docs",
64               "https://developer.mozilla.org/en-US/docs", "https://developer.mozilla.org/en-US/docs",
65               "http://www.example.com/"})
66      public void ctor() throws Exception {
67          final String html = DOCTYPE_HTML
68              + "<html>\n"
69              + "<head>\n"
70              + "  <script>\n"
71              + LOG_TITLE_FUNCTION
72              + "    function test() {\n"
73              + "      if (typeof window.URL === 'function') {\n"
74              + "        log(new URL('/', 'https://developer.mozilla.org'));\n"
75              + "        var b = new URL('https://developer.mozilla.org');\n"
76              + "        log(b);\n"
77              + "        log(new URL('en-US/docs', b));\n"
78              + "        var d = new URL('/en-US/docs', b);\n"
79              + "        log(d);\n"
80              + "        log(new URL('/en-US/docs', d));\n"
81              + "        log(new URL('/en-US/docs', 'https://developer.mozilla.org/fr-FR/toto'));\n"
82              + "        log(new URL('http://www.example.com', 'https://developers.mozilla.com'));\n"
83              + "      }\n"
84              + "    }\n"
85              + "  </script>\n"
86              + "</head>\n"
87              + "<body onload='test()'>\n"
88              + "</body>\n"
89              + "</html>";
90  
91          loadPageVerifyTitle2(html);
92      }
93  
94      /**
95       * @throws Exception if an error occurs
96       */
97      @Test
98      @Alerts({"data:,foo", "data:,foo"})
99      public void ctorDataUrl() throws Exception {
100         final String html = DOCTYPE_HTML
101             + "<html>\n"
102             + "<head>\n"
103             + "  <script>\n"
104             + LOG_TITLE_FUNCTION
105             + "    function test() {\n"
106             + "      if (typeof window.URL === 'function') {\n"
107             + "        log(new URL('data:,foo'));\n"
108             + "        log(new URL('data:,foo', 'http://localhost:22222/test/index.html'));\n"
109             + "      }\n"
110             + "    }\n"
111             + "  </script>\n"
112             + "</head>\n"
113             + "<body onload='test()'>\n"
114             + "</body>\n"
115             + "</html>";
116 
117         loadPageVerifyTitle2(html);
118     }
119 
120     /**
121      * @throws Exception if an error occurs
122      */
123     @Test
124     @Alerts({"TypeError", "TypeError"})
125     public void ctorInvalid() throws Exception {
126         final String html = DOCTYPE_HTML
127             + "<html>\n"
128             + "<head>\n"
129             + "  <script>\n"
130             + LOG_TITLE_FUNCTION
131             + "    function test() {\n"
132             + "      if (typeof window.URL === 'function') {\n"
133             + "        try {\n"
134             + "          new URL('/en-US/docs', '');\n"
135             + "        } catch(e) { logEx(e); }\n"
136             + "        try {\n"
137             + "          new URL('/en-US/docs');\n"
138             + "        } catch(e) { logEx(e); }\n"
139             + "      }\n"
140             + "    }\n"
141             + "  </script>\n"
142             + "</head>\n"
143             + "<body onload='test()'>\n"
144             + "</body>\n"
145             + "</html>";
146 
147         loadPageVerifyTitle2(html);
148     }
149 
150     /**
151      * @throws Exception if an error occurs
152      */
153     @Test
154     @Alerts("http://developer.mozilla.org")
155     public void origin() throws Exception {
156         final String html = DOCTYPE_HTML
157             + "<html>\n"
158             + "<head>\n"
159             + "  <script>\n"
160             + LOG_TITLE_FUNCTION
161             + "    function test() {\n"
162             + "      if (typeof window.URL === 'function') {\n"
163             + "        var u = new URL('http://developer.mozilla.org/en-US/docs');\n"
164             + "        log(u.origin);\n"
165             + "      }\n"
166             + "    }\n"
167             + "  </script>\n"
168             + "</head>\n"
169             + "<body onload='test()'>\n"
170             + "</body>\n"
171             + "</html>";
172         loadPageVerifyTitle2(html);
173     }
174 
175     /**
176      * @throws Exception if an error occurs
177      */
178     @Test
179     @Alerts("http://developer.mozilla.org")
180     public void originDefaultPort() throws Exception {
181         final String html = DOCTYPE_HTML
182             + "<html>\n"
183             + "<head>\n"
184             + "  <script>\n"
185             + LOG_TITLE_FUNCTION
186             + "    function test() {\n"
187             + "      if (typeof window.URL === 'function') {\n"
188             + "        var u = new URL('http://developer.mozilla.org:80/en-US/docs');\n"
189             + "        log(u.origin);\n"
190             + "      }\n"
191             + "    }\n"
192             + "  </script>\n"
193             + "</head>\n"
194             + "<body onload='test()'>\n"
195             + "</body>\n"
196             + "</html>";
197         loadPageVerifyTitle2(html);
198     }
199 
200     /**
201      * @throws Exception if an error occurs
202      */
203     @Test
204     @Alerts("http://developer.mozilla.org:1234")
205     public void originPort() throws Exception {
206         final String html = DOCTYPE_HTML
207             + "<html>\n"
208             + "<head>\n"
209             + "  <script>\n"
210             + LOG_TITLE_FUNCTION
211             + "    function test() {\n"
212             + "      if (typeof window.URL === 'function') {\n"
213             + "        var u = new URL('http://developer.mozilla.org:1234/en-US/docs');\n"
214             + "        log(u.origin);\n"
215             + "      }\n"
216             + "    }\n"
217             + "  </script>\n"
218             + "</head>\n"
219             + "<body onload='test()'>\n"
220             + "</body>\n"
221             + "</html>";
222         loadPageVerifyTitle2(html);
223     }
224 
225     /**
226      * @throws Exception if the test fails
227      */
228     @Test
229     public void createObjectURL() throws Exception {
230         final String html = DOCTYPE_HTML
231             + "<html>\n"
232             + "<head>\n"
233             + "<script>\n"
234             + "function test() {\n"
235             + "  if (document.testForm.fileupload.files) {\n"
236             + "    var files = document.testForm.fileupload.files;\n"
237 
238             + "    var url = window.URL.createObjectURL(files[0]);\n"
239             + "    alert(url);\n"
240             + "    window.URL.revokeObjectURL(url);\n"
241             + "  }\n"
242             + "}\n"
243             + "</script>\n"
244             + "</head>\n"
245             + "<body>\n"
246             + "  <form name='testForm'>\n"
247             + "    <input type='file' id='fileupload' name='fileupload'>\n"
248             + "  </form>\n"
249             + "  <button id='testBtn' onclick='test()'>Tester</button>\n"
250             + "</body>\n"
251             + "</html>";
252 
253         final WebDriver driver = loadPage2(html);
254 
255         final File tstFile = File.createTempFile("HtmlUnitUploadTest", ".txt");
256         try {
257             FileUtils.writeStringToFile(tstFile, "Hello HtmlUnit", ISO_8859_1);
258 
259             final String path = tstFile.getCanonicalPath();
260             driver.findElement(By.name("fileupload")).sendKeys(path);
261 
262             driver.findElement(By.id("testBtn")).click();
263 
264             final String url = getCollectedAlerts(driver, 1).get(0);
265             assertTrue(url, url.startsWith("blob:"));
266         }
267         finally {
268             FileUtils.deleteQuietly(tstFile);
269         }
270     }
271 
272     /**
273      * @throws Exception if an error occurs
274      */
275     @Test
276     @Alerts({"", "a=u&x="})
277     public void searchParams() throws Exception {
278         final String html = DOCTYPE_HTML
279             + "<html>\n"
280             + "<head>\n"
281             + "  <script>\n"
282             + LOG_TITLE_FUNCTION
283             + "    function test() {\n"
284             + "      if (typeof window.URL === 'function') {\n"
285             + "        var u = new URL('http://developer.mozilla.org/en-US/docs');\n"
286             + "        log(u.searchParams);\n"
287             + "        u = new URL('http://developer.mozilla.org/en-US/docs?a=u&x');\n"
288             + "        log(u.searchParams);\n"
289             + "      }\n"
290             + "    }\n"
291             + "  </script>\n"
292             + "</head>\n"
293             + "<body onload='test()'>\n"
294             + "</body>\n"
295             + "</html>";
296         loadPageVerifyTitle2(html);
297     }
298 
299     /**
300      * @throws Exception if an error occurs
301      */
302     @Test
303     @Alerts({"", "a=u&x=", "x=22", "x=22"})
304     public void searchParamsSyncedWithUrlChanges() throws Exception {
305         final String html = DOCTYPE_HTML
306             + "<html>\n"
307             + "<head>\n"
308             + "  <script>\n"
309             + LOG_TITLE_FUNCTION
310             + "    function test() {\n"
311             + "      if (typeof window.URL === 'function') {\n"
312             + "        var u = new URL('http://developer.mozilla.org/en-US/docs');\n"
313             + "        log(u.searchParams);\n"
314             + "        u = new URL('http://developer.mozilla.org/en-US/docs?a=u&x');\n"
315 
316             + "        var param = u.searchParams;\n"
317             + "        log(param);\n"
318 
319             + "        u.search = 'x=22';\n"
320             + "        log(u.searchParams);\n"
321             + "        log(param);\n"
322             + "      }\n"
323             + "    }\n"
324             + "  </script>\n"
325             + "</head>\n"
326             + "<body onload='test()'>\n"
327             + "</body>\n"
328             + "</html>";
329         loadPageVerifyTitle2(html);
330     }
331 
332     /**
333      * @throws Exception if the test fails
334      */
335     @Test
336     @Alerts({"/", "/en-US/docs", "/en-US/docs"})
337     public void getPathName() throws Exception {
338         final String html = DOCTYPE_HTML
339                         + "<html>\n"
340                         + "<head>\n"
341                         + "  <script>\n"
342                         + LOG_TITLE_FUNCTION
343                         + "    function test() {\n"
344                         + "      if (typeof window.URL === 'function') {\n"
345                         + "        var u = new URL('http://developer.mozilla.org');\n"
346                         + "        log(u.pathname);\n"
347                         + "        u = new URL('http://developer.mozilla.org/en-US/docs');\n"
348                         + "        log(u.pathname);\n"
349                         + "        u = new URL('http://developer.mozilla.org/en-US/docs?a=u&x');\n"
350                         + "        log(u.pathname);\n"
351                         + "      }\n"
352                         + "    }\n"
353                         + "  </script>\n"
354                         + "</head>\n"
355                         + "<body onload='test()'>\n"
356                         + "</body>\n"
357                         + "</html>";
358         loadPageVerifyTitle2(html);
359     }
360 
361     /**
362      * @throws Exception if the test fails
363      */
364     @Test
365     @Alerts({"/path", "/path",
366              "http://developer.mozilla.org/new/path?a=u&x",
367              "http://developer.mozilla.org/?a=u&x"})
368     public void setPathName() throws Exception {
369         final String html = DOCTYPE_HTML
370                         + "<html>\n"
371                         + "<head>\n"
372                         + "  <script>\n"
373                         + LOG_TITLE_FUNCTION
374                         + "    function test() {\n"
375                         + "      if (typeof window.URL === 'function') {\n"
376                         + "        var u = new URL('http://developer.mozilla.org');\n"
377                         + "        u.pathname = 'path';\n"
378                         + "        log(u.pathname);\n"
379                         + "        u.pathname = '/path';\n"
380                         + "        log(u.pathname);\n"
381                         + "        u = new URL('http://developer.mozilla.org/en-US/docs?a=u&x');\n"
382                         + "        u.pathname = 'new/path';"
383                         + "        log(u.toString());\n"
384                         + "        u.pathname='';\n"
385                         + "        log(u.toString());\n"
386                         + "      }\n"
387                         + "    }\n"
388                         + "  </script>\n"
389                         + "</head>\n"
390                         + "<body onload='test()'>\n"
391                         + "</body>\n"
392                         + "</html>";
393         loadPageVerifyTitle2(html);
394     }
395 
396     /**
397      * @throws Exception if the test fails
398      */
399     @Test
400     @Alerts({"", "#abcd", "#bcd",
401              "#hash", "http://developer.mozilla.org/?a=b#hash",
402              "", "http://developer.mozilla.org/?a=b",
403              "#undefined", "http://developer.mozilla.org/#undefined",
404              "#null", "http://developer.mozilla.org/#null"})
405     public void hash() throws Exception {
406         final String html = DOCTYPE_HTML
407                         + "<html>\n"
408                         + "<head>\n"
409                         + "  <script>\n"
410                         + LOG_TITLE_FUNCTION
411                         + "    function test() {\n"
412                         + "      if (typeof window.URL === 'function') {\n"
413                         + "        var u = new URL('http://developer.mozilla.org');\n"
414                         + "        log(u.hash);\n"
415 
416                         + "        u = new URL('http://developer.mozilla.org#abcd');\n"
417                         + "        log(u.hash);\n"
418 
419                         + "        u = new URL('http://developer.mozilla.org?a=b#bcd');\n"
420                         + "        log(u.hash);\n"
421 
422                         + "        u.hash = 'hash';\n"
423                         + "        log(u.hash);\n"
424                         + "        log(u.toString());\n"
425 
426                         + "        u.hash = '';\n"
427                         + "        log(u.hash);\n"
428                         + "        log(u.toString());\n"
429 
430                         + "        u = new URL('http://developer.mozilla.org#bcd');\n"
431                         + "        u.hash = undefined;\n"
432                         + "        log(u.hash);\n"
433                         + "        log(u.toString());\n"
434 
435                         + "        u = new URL('http://developer.mozilla.org#bcd');\n"
436                         + "        u.hash = null;\n"
437                         + "        log(u.hash);\n"
438                         + "        log(u.toString());\n"
439                         + "      }\n"
440                         + "    }\n"
441                         + "  </script>\n"
442                         + "</head>\n"
443                         + "<body onload='test()'>\n"
444                         + "</body>\n"
445                         + "</html>";
446         loadPageVerifyTitle2(html);
447     }
448 
449     /**
450      * @throws Exception if the test fails
451      */
452     @Test
453     @Alerts({"developer.mozilla.org", "developer.mozilla.org",
454              "new.host", "new.host:1234", "new.host:1234", "0.0.91.160:80",
455              "0.0.0.17:80", "0.0.6.182:80",
456              "new.host", "new.host",
457              "developer.mozilla.org", "developer.mozilla.org:4097", "developer.mozilla.org:80"})
458     public void host() throws Exception {
459         final String html = DOCTYPE_HTML
460                         + "<html>\n"
461                         + "<head>\n"
462                         + "  <script>\n"
463                         + LOG_TITLE_FUNCTION
464                         + "    function test() {\n"
465                         + "      if (typeof window.URL === 'function') {\n"
466                         + "        var u = new URL('https://developer.mozilla.org/en-US/docs/Web/API/URL/host');\n"
467                         + "        log(u.host);\n"
468 
469                         + "        u.host = '';\n"
470                         + "        log(u.host);\n"
471 
472                         + "        u.host = 'new.host';\n"
473                         + "        log(u.host);\n"
474 
475                         + "        u.host = 'new.host:1234';\n"
476                         + "        log(u.host);\n"
477 
478                         + "        u.host = ':447';\n"
479                         + "        log(u.host);\n"
480 
481                         + "        u.host = '23456:80';\n"
482                         + "        log(u.host);\n"
483 
484                         + "        u.host = 17;\n"
485                         + "        log(u.host);\n"
486 
487                         + "        u.host = 1718;\n"
488                         + "        log(u.host);\n"
489 
490                         + "        var u = new URL('https://host.com');\n"
491                         + "        u.host = 'new.host:443';\n" //same port as protocol
492                         + "        log(u.host);\n"
493 
494                         + "        var u = new URL('http://host.com');\n"
495                         + "        u.host = 'new.host:80';\n" //same port as protocol
496                         + "        log(u.host);\n"
497 
498                         + "        u = new URL('https://developer.mozilla.org/en-US/docs/Web/API/URL/host');\n"
499                         + "        log(u.host);"
500 
501                         + "        u = new URL('https://developer.mozilla.org:4097/en-US/docs/Web/API/URL/host');\n"
502                         + "        log(u.host);"
503 
504                         + "        u = new URL('https://developer.mozilla.org:80/en-US/docs/Web/API/URL/host');\n"
505                         + "        log(u.host);"
506                         + "      }\n"
507                         + "    }\n"
508                         + "  </script>\n"
509                         + "</head>\n"
510                         + "<body onload='test()'>\n"
511                         + "</body>\n"
512                         + "</html>";
513         loadPageVerifyTitle2(html);
514     }
515 
516     /**
517      * @throws Exception if the test fails
518      */
519     @Test
520     @Alerts(DEFAULT = {"developer.mozilla.org",
521                        "developer.mozilla.org", "https://developer.mozilla.org/en-US/docs/Web/API/URL/host",
522                        "htmlunit-dev.org", "https://htmlunit-dev.org/en-US/docs/Web/API/URL/host",
523                        "htmlunit-dev.org", "https://htmlunit-dev.org/en-US/docs/Web/API/URL/host"},
524             CHROME =  {"developer.mozilla.org",
525                        "developer.mozilla.org", "https://developer.mozilla.org/en-US/docs/Web/API/URL/host",
526                        "htmlunit-dev.org", "https://htmlunit-dev.org/en-US/docs/Web/API/URL/host",
527                        "%20%20", "https://%20%20/en-US/docs/Web/API/URL/host"},
528             EDGE = {"developer.mozilla.org",
529                     "developer.mozilla.org", "https://developer.mozilla.org/en-US/docs/Web/API/URL/host",
530                     "htmlunit-dev.org", "https://htmlunit-dev.org/en-US/docs/Web/API/URL/host",
531                     "%20%20", "https://%20%20/en-US/docs/Web/API/URL/host"})
532     @HtmlUnitNYI(CHROME =  {"developer.mozilla.org",
533                             "developer.mozilla.org", "https://developer.mozilla.org/en-US/docs/Web/API/URL/host",
534                             "htmlunit-dev.org", "https://htmlunit-dev.org/en-US/docs/Web/API/URL/host",
535                             "%20%20", "https:// /en-US/docs/Web/API/URL/host"},
536                 EDGE = {"developer.mozilla.org",
537                         "developer.mozilla.org", "https://developer.mozilla.org/en-US/docs/Web/API/URL/host",
538                         "htmlunit-dev.org", "https://htmlunit-dev.org/en-US/docs/Web/API/URL/host",
539                         "%20%20", "https:// /en-US/docs/Web/API/URL/host"})
540     public void hostname() throws Exception {
541         final String html = DOCTYPE_HTML
542                         + "<html>\n"
543                         + "<head>\n"
544                         + "  <script>\n"
545                         + LOG_TITLE_FUNCTION
546                         + "    function test() {\n"
547                         + "      if (typeof window.URL === 'function') {\n"
548                         + "        var u = new URL('https://developer.mozilla.org:443/en-US/docs/Web/API/URL/host');\n"
549                         + "        log(u.hostname);\n"
550 
551                         + "        u.hostname = '';\n"
552                         + "        log(u.hostname);\n"
553                         + "        log(u.toString());\n"
554 
555                         + "        u.hostname = 'htmlunit-dev.org';\n"
556                         + "        log(u.hostname);\n"
557                         + "        log(u.toString());\n"
558 
559                         + "        u.hostname = '  ';\n"
560                         + "        log(u.hostname);\n"
561                         + "        log(u.toString());\n"
562                         + "      }\n"
563                         + "    }\n"
564                         + "  </script>\n"
565                         + "</head>\n"
566                         + "<body onload='test()'>\n"
567                         + "</body>\n"
568                         + "</html>";
569         loadPageVerifyTitle2(html);
570     }
571 
572     /**
573      * @throws Exception if the test fails
574      */
575     @Test
576     @Alerts({"https://developer.mozilla.org/en-US/docs/Web/API/URL/host",
577              "http://new.com/href", "http://new.com/hrefWithPort"})
578     public void href() throws Exception {
579         final String html = DOCTYPE_HTML
580                         + "<html>\n"
581                         + "<head>\n"
582                         + "  <script>\n"
583                         + LOG_TITLE_FUNCTION
584                         + "    function test() {\n"
585                         + "      if (typeof window.URL === 'function') {\n"
586                         + "        var u = new URL('https://developer.mozilla.org:443/en-US/docs/Web/API/URL/host');\n"
587                         + "        log(u.href);\n"
588 
589                         + "        u.href = 'http://new.com/href';\n"
590                         + "        log(u.href);\n"
591 
592                         + "        u.href = 'http://new.com:80/hrefWithPort';\n"
593                         + "        log(u.href);\n"
594                         + "      }\n"
595                         + "    }\n"
596                         + "  </script>\n"
597                         + "</head>\n"
598                         + "<body onload='test()'>\n"
599                         + "</body>\n"
600                         + "</html>";
601         loadPageVerifyTitle2(html);
602     }
603 
604     /**
605      * @throws Exception if the test fails
606      */
607     @Test
608     @Alerts({"flabada",
609              "", "https://anonymous@developer.mozilla.org/",
610              "pass", "https://anonymous:pass@developer.mozilla.org/",
611              "17", "https://anonymous:17@developer.mozilla.org/",
612              "undefined", "https://anonymous:undefined@developer.mozilla.org/",
613              "null", "https://anonymous:null@developer.mozilla.org/"})
614     public void password() throws Exception {
615         final String html = DOCTYPE_HTML
616                         + "<html>\n"
617                         + "<head>\n"
618                         + "  <script>\n"
619                         + LOG_TITLE_FUNCTION
620                         + "    function test() {\n"
621                         + "      if (typeof window.URL === 'function') {\n"
622                         + "        var u = new URL('https://anonymous:flabada@developer.mozilla.org');\n"
623                         + "        log(u.password);\n"
624 
625                         + "        u.password = '';\n"
626                         + "        log(u.password);\n"
627                         + "        log(u.toString());\n"
628 
629                         + "        u.password = 'pass';\n"
630                         + "        log(u.password);\n"
631                         + "        log(u.toString());\n"
632 
633                         + "        u.password = 17;\n"
634                         + "        log(u.password);\n"
635                         + "        log(u.toString());\n"
636 
637                         + "        u.password = undefined;\n"
638                         + "        log(u.password);\n"
639                         + "        log(u.toString());\n"
640 
641                         + "        u.password = null;\n"
642                         + "        log(u.password);\n"
643                         + "        log(u.toString());\n"
644                         + "      }\n"
645                         + "    }\n"
646                         + "  </script>\n"
647                         + "</head>\n"
648                         + "<body onload='test()'>\n"
649                         + "</body>\n"
650                         + "</html>";
651         loadPageVerifyTitle2(html);
652     }
653 
654     /**
655      * @throws Exception if the test fails
656      */
657     @Test
658     @Alerts({"80", "123", "", "https://mydomain.com/svn/Repos/",
659              "", "http://mydomain.com/svn/Repos/"})
660     public void port() throws Exception {
661         final String html = DOCTYPE_HTML
662                         + "<html>\n"
663                         + "<head>\n"
664                         + "  <script>\n"
665                         + LOG_TITLE_FUNCTION
666                         + "    function test() {\n"
667                         + "      if (typeof window.URL === 'function') {\n"
668                         + "        var u = new URL('https://mydomain.com:80/svn/Repos/');\n"
669                         + "        log(u.port);\n"
670                         + "        u.port = '123';\n"
671                         + "        log(u.port);\n"
672                         + "        u.port = '443';\n"
673                         + "        log(u.port);\n"
674                         + "        log(u.toString());\n"
675                         + "        u = new URL('http://mydomain.com:123/svn/Repos/');\n"
676                         + "        u.port = '80';\n"
677                         + "        log(u.port);\n"
678                         + "        log(u.toString());\n"
679                         + "      }\n"
680                         + "    }\n"
681                         + "  </script>\n"
682                         + "</head>\n"
683                         + "<body onload='test()'>\n"
684                         + "</body>\n"
685                         + "</html>";
686         loadPageVerifyTitle2(html);
687     }
688 
689     /**
690      * @throws Exception if the test fails
691      */
692     @Test
693     @Alerts({"https:",
694              "http:", "http://mydomain.com/svn/Repos/",
695              "http:", "http://mydomain.com/svn/Repos/",
696              "http:", "http://mydomain.com/svn/Repos/",
697              "http:", "http://mydomain.com/svn/Repos/",
698              "http:", "http://mydomain.com/svn/Repos/",
699              "http:", "http://mydomain.com/svn/Repos/",
700              "http:", "http://mydomain.com/svn/Repos/",
701              "http:", "http://mydomain.com/svn/Repos/",
702              "ex-unknown", "ReferenceError"})
703     public void protocol() throws Exception {
704         final String html = DOCTYPE_HTML
705                         + "<html>\n"
706                         + "<head>\n"
707                         + "  <script>\n"
708                         + LOG_TITLE_FUNCTION
709                         + "    function test() {\n"
710                         + "      if (typeof window.URL === 'function') {\n"
711                         + "        var u = new URL('https://mydomain.com:80/svn/Repos/');\n"
712                         + "        log(u.protocol);\n"
713 
714                         + "        u.protocol = 'http';\n"
715                         + "        log(u.protocol);\n"
716                         + "        log(u.toString());\n"
717 
718                         + "        u.protocol = '';\n"
719                         + "        log(u.protocol);\n"
720                         + "        log(u.toString());\n"
721 
722                         + "        u.protocol = 'axdeg';\n"
723                         + "        log(u.protocol);\n"
724                         + "        log(u.toString());\n"
725 
726                         + "        u.protocol = 'hTTp';\n"
727                         + "        log(u.protocol);\n"
728                         + "        log(u.toString());\n"
729 
730                         + "        u.protocol = ' http ';\n"
731                         + "        log(u.protocol);\n"
732                         + "        log(u.toString());\n"
733 
734                         + "        u.protocol = 'axdeg ';\n"
735                         + "        log(u.protocol);\n"
736                         + "        log(u.toString());\n"
737 
738                         + "        u.protocol = ' axdeg ';\n"
739                         + "        log(u.protocol);\n"
740                         + "        log(u.toString());\n"
741 
742                         + "        try {\n"
743                         + "          u.protocol = null;\n"
744                         + "          log(u.protocol);\n"
745                         + "          log(u.toString());\n"
746                         + "        } catch(e) { log('ex-null'); logEx(e); }\n"
747 
748                         + "        try {\n"
749                         + "          u.protocol = unknown;\n"
750                         + "          log(u.protocol);\n"
751                         + "          log(u.toString());\n"
752                         + "        } catch(e) { log('ex-unknown'); logEx(e); }\n"
753                         + "      }\n"
754                         + "    }\n"
755                         + "  </script>\n"
756                         + "</head>\n"
757                         + "<body onload='test()'>\n"
758                         + "</body>\n"
759                         + "</html>";
760         loadPageVerifyTitle2(html);
761     }
762 
763     /**
764      * @throws Exception if the test fails
765      */
766     @Test
767     @Alerts({"https:",
768              "http:", "http://mydomain.com/svn/Repos/",
769              "http:", "http://mydomain.com/svn/Repos/",
770              "http:", "http://mydomain.com/svn/Repos/",
771              "http:", "http://mydomain.com/svn/Repos/",
772              "http:", "http://mydomain.com/svn/Repos/",
773              "http:", "http://mydomain.com/svn/Repos/",
774              "http:", "http://mydomain.com/svn/Repos/",
775              "ex-unknown", "ReferenceError"})
776     public void protocol2() throws Exception {
777         final String html = DOCTYPE_HTML
778                         + "<html>\n"
779                         + "<head>\n"
780                         + "  <script>\n"
781                         + LOG_TITLE_FUNCTION
782                         + "    function test() {\n"
783                         + "      if (typeof window.URL === 'function') {\n"
784                         + "        var u = new URL('https://mydomain.com:80/svn/Repos/');\n"
785                         + "        log(u.protocol);\n"
786 
787                         + "        u.protocol = 'http:';\n"
788                         + "        log(u.protocol);\n"
789                         + "        log(u.toString());\n"
790 
791                         + "        u.protocol = '';\n"
792                         + "        log(u.protocol);\n"
793                         + "        log(u.toString());\n"
794 
795                         + "        u.protocol = 'axdeg:';\n"
796                         + "        log(u.protocol);\n"
797                         + "        log(u.toString());\n"
798 
799                         + "        u.protocol = 'hTTp:';\n"
800                         + "        log(u.protocol);\n"
801                         + "        log(u.toString());\n"
802 
803                         + "        u.protocol = 'axdeg: ';\n"
804                         + "        log(u.protocol);\n"
805                         + "        log(u.toString());\n"
806 
807                         + "        u.protocol = ' axdeg: ';\n"
808                         + "        log(u.protocol);\n"
809                         + "        log(u.toString());\n"
810 
811                         + "        try {\n"
812                         + "          u.protocol = null;\n"
813                         + "          log(u.protocol);\n"
814                         + "          log(u.toString());\n"
815                         + "        } catch(e) { log('ex-null'); logEx(e); }\n"
816 
817                         + "        try {\n"
818                         + "          u.protocol = unknown;\n"
819                         + "          log(u.protocol);\n"
820                         + "          log(u.toString());\n"
821                         + "        } catch(e) { log('ex-unknown'); logEx(e); }\n"
822                         + "      }\n"
823                         + "    }\n"
824                         + "  </script>\n"
825                         + "</head>\n"
826                         + "<body onload='test()'>\n"
827                         + "</body>\n"
828                         + "</html>";
829         loadPageVerifyTitle2(html);
830     }
831 
832     /**
833      * @throws Exception if the test fails
834      */
835     @Test
836     @Alerts({"https:",
837              "http:", "http://mydomain.com/svn/Repos/",
838              "http:", "http://mydomain.com/svn/Repos/",
839              "http:", "http://mydomain.com/svn/Repos/",
840              "http:", "http://mydomain.com/svn/Repos/",
841              "http:", "http://mydomain.com/svn/Repos/",
842              "http:", "http://mydomain.com/svn/Repos/",
843              "http:", "http://mydomain.com/svn/Repos/",
844              "ex-unknown", "ReferenceError"})
845     public void protocol3() throws Exception {
846         final String html = DOCTYPE_HTML
847                         + "<html>\n"
848                         + "<head>\n"
849                         + "  <script>\n"
850                         + LOG_TITLE_FUNCTION
851                         + "    function test() {\n"
852                         + "      if (typeof window.URL === 'function') {\n"
853                         + "        var u = new URL('https://mydomain.com:80/svn/Repos/');\n"
854                         + "        log(u.protocol);\n"
855 
856                         + "        u.protocol = 'http://www.htmlunit.org';\n"
857                         + "        log(u.protocol);\n"
858                         + "        log(u.toString());\n"
859 
860                         + "        u.protocol = '';\n"
861                         + "        log(u.protocol);\n"
862                         + "        log(u.toString());\n"
863 
864                         + "        u.protocol = 'axdeg://www.htmlunit.org';\n"
865                         + "        log(u.protocol);\n"
866                         + "        log(u.toString());\n"
867 
868                         + "        u.protocol = 'hTTp://www.htmlunit.org';\n"
869                         + "        log(u.protocol);\n"
870                         + "        log(u.toString());\n"
871 
872                         + "        u.protocol = 'axdeg://www.htmlunit.org ';\n"
873                         + "        log(u.protocol);\n"
874                         + "        log(u.toString());\n"
875 
876                         + "        u.protocol = ' axdeg://www.htmlunit.org ';\n"
877                         + "        log(u.protocol);\n"
878                         + "        log(u.toString());\n"
879 
880                         + "        try {\n"
881                         + "          u.protocol = null;\n"
882                         + "          log(u.protocol);\n"
883                         + "          log(u.toString());\n"
884                         + "        } catch(e) { log('ex-null'); logEx(e); }\n"
885 
886                         + "        try {\n"
887                         + "          u.protocol = unknown;\n"
888                         + "          log(u.protocol);\n"
889                         + "          log(u.toString());\n"
890                         + "        } catch(e) { log('ex-unknown'); logEx(e); }\n"
891                         + "      }\n"
892                         + "    }\n"
893                         + "  </script>\n"
894                         + "</head>\n"
895                         + "<body onload='test()'>\n"
896                         + "</body>\n"
897                         + "</html>";
898         loadPageVerifyTitle2(html);
899     }
900 
901     /**
902      * @throws Exception if the test fails
903      */
904     @Test
905     @Alerts(DEFAULT = {"https:",
906                        "http:", "http://mydomain.com/svn/Repos/",
907                        "https:", "https://mydomain.com/svn/Repos/",
908                        "ftp:", "ftp://mydomain.com/svn/Repos/",
909                        "ftp:", "ftp://mydomain.com/svn/Repos/",
910                        "ws:", "ws://mydomain.com/svn/Repos/",
911                        "wss:", "wss://mydomain.com/svn/Repos/",
912                        "file:", "file://mydomain.com/svn/Repos/"},
913             FF = {"https:",
914                   "http:", "http://mydomain.com/svn/Repos/",
915                   "https:", "https://mydomain.com/svn/Repos/",
916                   "ftp:", "ftp://mydomain.com/svn/Repos/",
917                   "ftp:", "ftp://mydomain.com/svn/Repos/",
918                   "ws:", "ws://mydomain.com/svn/Repos/",
919                   "wss:", "wss://mydomain.com/svn/Repos/",
920                   "file:", "file:///svn/Repos/"},
921             FF_ESR = {"https:",
922                       "http:", "http://mydomain.com/svn/Repos/",
923                       "https:", "https://mydomain.com/svn/Repos/",
924                       "ftp:", "ftp://mydomain.com/svn/Repos/",
925                       "ftp:", "ftp://mydomain.com/svn/Repos/",
926                       "ws:", "ws://mydomain.com/svn/Repos/",
927                       "wss:", "wss://mydomain.com/svn/Repos/",
928                       "file:", "file:///svn/Repos/"})
929     @HtmlUnitNYI(
930             FF = {"https:",
931                   "http:", "http://mydomain.com/svn/Repos/",
932                   "https:", "https://mydomain.com/svn/Repos/",
933                   "ftp:", "ftp://mydomain.com/svn/Repos/",
934                   "ftp:", "ftp://mydomain.com/svn/Repos/",
935                   "ws:", "ws://mydomain.com/svn/Repos/",
936                   "wss:", "wss://mydomain.com/svn/Repos/",
937                   "file:", "file://mydomain.com/svn/Repos/"},
938             FF_ESR = {"https:",
939                       "http:", "http://mydomain.com/svn/Repos/",
940                       "https:", "https://mydomain.com/svn/Repos/",
941                       "ftp:", "ftp://mydomain.com/svn/Repos/",
942                       "ftp:", "ftp://mydomain.com/svn/Repos/",
943                       "ws:", "ws://mydomain.com/svn/Repos/",
944                       "wss:", "wss://mydomain.com/svn/Repos/",
945                       "file:", "file://mydomain.com/svn/Repos/"})
946     public void specialScheme() throws Exception {
947         final String html = DOCTYPE_HTML
948                         + "<html>\n"
949                         + "<head>\n"
950                         + "  <script>\n"
951                         + LOG_TITLE_FUNCTION
952                         + "    function test() {\n"
953                         + "      if (typeof window.URL === 'function') {\n"
954                         + "        var u = new URL('https://mydomain.com:80/svn/Repos/');\n"
955                         + "        log(u.protocol);\n"
956 
957                         + "        u.protocol = 'http';\n"
958                         + "        log(u.protocol);\n"
959                         + "        log(u.toString());\n"
960 
961                         + "        u.protocol = 'https';\n"
962                         + "        log(u.protocol);\n"
963                         + "        log(u.toString());\n"
964 
965                         + "        u.protocol = 'ftp';\n"
966                         + "        log(u.protocol);\n"
967                         + "        log(u.toString());\n"
968 
969                         + "        u.protocol = 'ftps';\n"
970                         + "        log(u.protocol);\n"
971                         + "        log(u.toString());\n"
972 
973                         + "        u.protocol = 'ws';\n"
974                         + "        log(u.protocol);\n"
975                         + "        log(u.toString());\n"
976 
977                         + "        u.protocol = 'wss';\n"
978                         + "        log(u.protocol);\n"
979                         + "        log(u.toString());\n"
980 
981                         + "        u.protocol = 'file';\n"
982                         + "        log(u.protocol);\n"
983                         + "        log(u.toString());\n"
984                         + "      }\n"
985                         + "    }\n"
986                         + "  </script>\n"
987                         + "</head>\n"
988                         + "<body onload='test()'>\n"
989                         + "</body>\n"
990                         + "</html>";
991         loadPageVerifyTitle2(html);
992     }
993 
994     /**
995      * @throws Exception if the test fails
996      */
997     @Test
998     @Alerts({"?q=123",
999              "?a=b&c=d", "https://developer.mozilla.org/search?a=b&c=d",
1000              "?a=7", "https://developer.mozilla.org/search?a=7",
1001              "?17", "https://developer.mozilla.org/search?17",
1002              "", "https://developer.mozilla.org/search",
1003              "?Html%20Unit", "https://developer.mozilla.org/search?Html%20Unit",
1004              "?Html?Unit", "https://developer.mozilla.org/search?Html?Unit",
1005              "?Html/Unit", "https://developer.mozilla.org/search?Html/Unit",
1006              "?undefined", "https://developer.mozilla.org/search?undefined",
1007              "?null", "https://developer.mozilla.org/search?null"})
1008     public void search() throws Exception {
1009         final String html = DOCTYPE_HTML
1010                         + "<html>\n"
1011                         + "<head>\n"
1012                         + "  <script>\n"
1013                         + LOG_TITLE_FUNCTION
1014                         + "    function test() {\n"
1015                         + "      if (typeof window.URL === 'function') {\n"
1016                         + "        var u = new URL('https://developer.mozilla.org/search?q=123');\n"
1017                         + "        log(u.search);\n"
1018 
1019                         + "        u.search = 'a=b&c=d';\n"
1020                         + "        log(u.search);\n"
1021                         + "        log(u.toString());\n"
1022 
1023                         + "        u.search = '?a=7';\n"
1024                         + "        log(u.search);\n"
1025                         + "        log(u.toString());\n"
1026 
1027                         + "        u.search = 17;\n"
1028                         + "        log(u.search);\n"
1029                         + "        log(u.toString());\n"
1030 
1031                         + "        u.search = '';\n"
1032                         + "        log(u.search);\n"
1033                         + "        log(u.toString());\n"
1034 
1035                         + "        u.search = 'Html Unit';\n"
1036                         + "        log(u.search);\n"
1037                         + "        log(u.toString());\n"
1038 
1039                         + "        u.search = 'Html?Unit';\n"
1040                         + "        log(u.search);\n"
1041                         + "        log(u.toString());\n"
1042 
1043                         + "        u.search = 'Html/Unit';\n"
1044                         + "        log(u.search);\n"
1045                         + "        log(u.toString());\n"
1046 
1047                         + "        u = new URL('https://developer.mozilla.org/search?q=123');\n"
1048                         + "        u.search = undefined;\n"
1049                         + "        log(u.search);\n"
1050                         + "        log(u.toString());\n"
1051 
1052                         + "        u.search = null;\n"
1053                         + "        log(u.search);\n"
1054                         + "        log(u.toString());\n"
1055                         + "      }\n"
1056                         + "    }\n"
1057                         + "  </script>\n"
1058                         + "</head>\n"
1059                         + "<body onload='test()'>\n"
1060                         + "</body>\n"
1061                         + "</html>";
1062         loadPageVerifyTitle2(html);
1063     }
1064 
1065     /**
1066      * @throws Exception if the test fails
1067      */
1068     @Test
1069     @Alerts({"https://developer.mozilla.org/search?q%20a=1%202%203", "?q%20a=1%202%203"})
1070     @HtmlUnitNYI(CHROME = {"https://developer.mozilla.org/search?q a=1 2 3", "?q a=1 2 3"},
1071                  EDGE = {"https://developer.mozilla.org/search?q a=1 2 3", "?q a=1 2 3"},
1072                  FF = {"https://developer.mozilla.org/search?q a=1 2 3", "?q a=1 2 3"},
1073                  FF_ESR = {"https://developer.mozilla.org/search?q a=1 2 3", "?q a=1 2 3"})
1074     public void searchEncoding() throws Exception {
1075         final String html = DOCTYPE_HTML
1076                         + "<html>\n"
1077                         + "<head>\n"
1078                         + "  <script>\n"
1079                         + LOG_TITLE_FUNCTION
1080                         + "    function test() {\n"
1081                         + "      if (typeof window.URL === 'function') {\n"
1082                         + "        var u = new URL('https://developer.mozilla.org/search?q a=1 2 3');\n"
1083                         + "        log(u);\n"
1084                         + "        log(u.search);\n"
1085                         + "      }\n"
1086                         + "    }\n"
1087                         + "  </script>\n"
1088                         + "</head>\n"
1089                         + "<body onload='test()'>\n"
1090                         + "</body>\n"
1091                         + "</html>";
1092         loadPageVerifyTitle2(html);
1093     }
1094 
1095     /**
1096      * @throws Exception if the test fails
1097      */
1098     @Test
1099     @Alerts({"anonymous",
1100              "user", "https://user:flabada@developer.mozilla.org/",
1101              "", "https://:flabada@developer.mozilla.org/",
1102              "anonymous", "anonymous", "", "",
1103              "user", "https://user:pass@developer.mozilla.org/",
1104              "17", "https://17:pass@developer.mozilla.org/",
1105              "undefined", "https://undefined:pass@developer.mozilla.org/",
1106              "null", "https://null:pass@developer.mozilla.org/"})
1107     public void username() throws Exception {
1108         final String html = DOCTYPE_HTML
1109                         + "<html>\n"
1110                         + "<head>\n"
1111                         + "  <script>\n"
1112                         + LOG_TITLE_FUNCTION
1113                         + "    function test() {\n"
1114                         + "      if (typeof window.URL === 'function') {\n"
1115                         + "        var u = new URL('https://anonymous:flabada@developer.mozilla.org');\n"
1116                         + "        log(u.username);\n"
1117 
1118                         + "        u.username = 'user';\n"
1119                         + "        log(u.username);\n"
1120                         + "        log(u.toString());\n"
1121 
1122                         + "        u.username = '';\n"
1123                         + "        log(u.username);\n"
1124                         + "        log(u.toString());\n"
1125 
1126                         + "        u = new URL('https://anonymous@developer.mozilla.org');\n"
1127                         + "        log(u.username);\n"
1128 
1129                         + "        u = new URL('https://anonymous:@developer.mozilla.org');\n"
1130                         + "        log(u.username);\n"
1131 
1132                         + "        u = new URL('https://developer.mozilla.org:443');\n"
1133                         + "        log(u.username);\n"
1134 
1135                         + "        u = new URL('https://:pass@developer.mozilla.org:443');\n"
1136                         + "        log(u.username);\n"
1137 
1138                         + "        u.username = 'user';\n"
1139                         + "        log(u.username);\n"
1140                         + "        log(u.toString());\n"
1141 
1142                         + "        u.username = 17;\n"
1143                         + "        log(u.username);\n"
1144                         + "        log(u.toString());\n"
1145 
1146                         + "        u.username = undefined;\n"
1147                         + "        log(u.username);\n"
1148                         + "        log(u.toString());\n"
1149 
1150                         + "        u.username = null;\n"
1151                         + "        log(u.username);\n"
1152                         + "        log(u.toString());\n"
1153                         + "      }\n"
1154                         + "    }\n"
1155                         + "  </script>\n"
1156                         + "</head>\n"
1157                         + "<body onload='test()'>\n"
1158                         + "</body>\n"
1159                         + "</html>";
1160         loadPageVerifyTitle2(html);
1161     }
1162 
1163     /**
1164      * @throws Exception if the test fails
1165      */
1166     @Test
1167     @Alerts({"function URL() { [native code] }",
1168              "function URL() { [native code] }",
1169              "function URL() { [native code] }",
1170              "https://developer.mozilla.org/",
1171              "https://developer.mozilla.org/",
1172              "https://developer.mozilla.org/"})
1173     public void testToString() throws Exception {
1174         final String html = DOCTYPE_HTML
1175             + "<html><body>\n"
1176             + "<script>\n"
1177             + LOG_TITLE_FUNCTION
1178             + "  if (typeof window.URL === 'function') {\n"
1179             + "    log(URL);\n"
1180             + "    log('' + URL);\n"
1181             + "    log(URL.toString());\n"
1182 
1183             + "    var u = new URL('/', 'https://developer.mozilla.org');\n"
1184             + "    log(u);\n"
1185             + "    log('' + u);\n"
1186             + "    log(u.toString());\n"
1187             + "  }\n"
1188             + "</script>\n"
1189             + "</body></html>";
1190 
1191         loadPageVerifyTitle2(html);
1192     }
1193 
1194     /**
1195      * @throws Exception if an error occurs
1196      */
1197     @Test
1198     @Alerts("https://developer.mozilla.org/")
1199     public void testToJSON() throws Exception {
1200         final String html = DOCTYPE_HTML
1201                 + "<html><body>\n"
1202                 + "<script>\n"
1203                 + LOG_TITLE_FUNCTION
1204                 + "  if (typeof window.URL === 'function') {\n"
1205                 + "    var u = new URL('/', 'https://developer.mozilla.org');\n"
1206                 + "    log(u.toJSON());\n"
1207                 + "  }\n"
1208                 + "</script>\n"
1209                 + "</body></html>";
1210 
1211         loadPageVerifyTitle2(html);
1212     }
1213 
1214     /**
1215      * @throws Exception if the test fails
1216      */
1217     @Test
1218     @Alerts({"https://htmlunit.org/", "https://htmlunit.org/", "true"})
1219     public void webkitURL() throws Exception {
1220         final String html = DOCTYPE_HTML
1221             + "<html><head>\n"
1222             + "<script>\n"
1223             + LOG_TITLE_FUNCTION
1224             + "function test() {\n"
1225             + "  if (typeof window.URL === 'function') {\n"
1226             + "    var url = new URL('https://htmlunit.org');\n"
1227             + "    var wkUrl = new webkitURL('https://htmlunit.org');\n"
1228             + "    log(url);\n"
1229             + "    log(wkUrl);\n"
1230             + "    log(Object.getPrototypeOf(url) == Object.getPrototypeOf(wkUrl));\n"
1231             + "  }\n"
1232             + "}\n"
1233             + "</script></head>\n"
1234             + "<body onload='test()'>\n"
1235             + "</body></html>";
1236 
1237         loadPageVerifyTitle2(html);
1238     }
1239 }