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 static java.nio.charset.StandardCharsets.UTF_8;
18  
19  import java.io.InputStream;
20  import java.net.URL;
21  import java.net.URLEncoder;
22  import java.util.Collections;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.apache.commons.io.IOUtils;
27  import org.htmlunit.HttpHeader;
28  import org.htmlunit.HttpMethod;
29  import org.htmlunit.MockWebConnection;
30  import org.htmlunit.WebDriverTestCase;
31  import org.htmlunit.junit.annotation.Alerts;
32  import org.htmlunit.junit.annotation.BuggyWebDriver;
33  import org.htmlunit.junit.annotation.HtmlUnitNYI;
34  import org.htmlunit.util.MimeType;
35  import org.htmlunit.util.NameValuePair;
36  import org.junit.jupiter.api.Test;
37  import org.openqa.selenium.By;
38  import org.openqa.selenium.Keys;
39  import org.openqa.selenium.WebDriver;
40  import org.openqa.selenium.WebElement;
41  import org.openqa.selenium.interactions.Actions;
42  
43  /**
44   * Tests for {@link HtmlAnchor}.
45   *
46   * @author Ahmed Ashour
47   * @author Ronald Brill
48   * @author Frank Danek
49   */
50  public class HtmlAnchorTest extends WebDriverTestCase {
51  
52      /**
53       * @throws Exception if an error occurs
54       */
55      @Test
56      @Alerts({"hi", "%28%29"})
57      public void href_js_escaping() throws Exception {
58          final String html = DOCTYPE_HTML
59              + "<html><head>\n"
60              + "<script>\n"
61              + LOG_TITLE_FUNCTION
62              + "  function sayHello(text) {\n"
63              + "    log(text);\n"
64              + "  }\n"
65              + "</script></head>\n"
66              + "<body>\n"
67              + "  <a id='myAnchor' href=\"javascript:sayHello%28'hi'%29\">My Link</a>\n"
68              + "  <input id='myButton' type=button onclick=\"javascript:sayHello('%28%29')\" value='My Button'>\n"
69              + "</body></html>";
70  
71          final WebDriver driver = loadPage2(html);
72  
73          driver.findElement(By.id("myAnchor")).click();
74          verifyTitle2(driver, getExpectedAlerts()[0]);
75  
76          driver.findElement(By.id("myButton")).click();
77          verifyTitle2(driver, getExpectedAlerts());
78      }
79  
80      /**
81       * @throws Exception if an error occurs
82       */
83      @Test
84      @Alerts({"(*%a", "%28%A"})
85      public void href_js_escaping2() throws Exception {
86          final String html = DOCTYPE_HTML
87              + "<html><head><script>\n"
88              + "  function sayHello(text) {\n"
89              + "    alert(text);\n"
90              + "  }\n"
91              + "</script></head>\n"
92              + "<body>\n"
93              + "  <a id='myAnchor' href=\"javascript:sayHello%28'%28%2a%a'%29\">My Link</a>\n"
94              + "  <input id='myButton' type=button onclick=\"javascript:sayHello('%28%A')\" value='My Button'>\n"
95              + "</body></html>";
96  
97          final WebDriver driver = loadPage2(html);
98          driver.findElement(By.id("myAnchor")).click();
99          verifyAlerts(driver, getExpectedAlerts()[0]);
100         driver.findElement(By.id("myButton")).click();
101         verifyAlerts(driver, getExpectedAlerts()[1]);
102     }
103 
104     /**
105      * @throws Exception if an error occurs
106      */
107     @Test
108     public void clickNestedElement() throws Exception {
109         final String html = DOCTYPE_HTML
110             + "<html>\n"
111             + "<body>\n"
112             + "  <a href='page2.html'>\n"
113             + "    <span id='theSpan'>My Link</span>\n"
114             + "  </a>\n"
115             + "</body></html>";
116 
117         getMockWebConnection().setDefaultResponse("");
118         final WebDriver driver = loadPage2(html);
119         final WebElement span = driver.findElement(By.id("theSpan"));
120         assertEquals("span", span.getTagName());
121         span.click();
122         assertEquals(URL_FIRST + "page2.html", driver.getCurrentUrl());
123     }
124 
125     /**
126      * @throws Exception if an error occurs
127      */
128     @Test
129     @Alerts("§§URL§§page2.html")
130     public void clickNestedButtonElement() throws Exception {
131         final String html = DOCTYPE_HTML
132             + "<html>\n"
133             + "<body>\n"
134             + "  <a href='page2.html'>\n"
135             + "    <button id='theButton'></button>\n"
136             + "  </a>\n"
137             + "</body></html>";
138 
139         expandExpectedAlertsVariables(URL_FIRST);
140         getMockWebConnection().setDefaultResponse("");
141         final WebDriver driver = loadPage2(html);
142         final WebElement button = driver.findElement(By.id("theButton"));
143         assertEquals("button", button.getTagName());
144         button.click();
145         assertEquals(getExpectedAlerts()[0], driver.getCurrentUrl());
146     }
147 
148     /**
149      * @throws Exception if an error occurs
150      */
151     @Test
152     @Alerts("")
153     public void clickNestedCheckboxElement() throws Exception {
154         final String html = DOCTYPE_HTML
155             + "<html>\n"
156             + "<body>\n"
157             + "  <a href='page2.html'>\n"
158             + "    <input type='checkbox' id='theCheckbox' name='myCheckbox' value='Milk'>\n"
159             + "  </a>\n"
160             + "</body></html>";
161 
162         getMockWebConnection().setDefaultResponse("");
163         final WebDriver driver = loadPage2(html);
164         final WebElement checkbox = driver.findElement(By.id("theCheckbox"));
165         assertEquals("input", checkbox.getTagName());
166         checkbox.click();
167         assertEquals(URL_FIRST + getExpectedAlerts()[0], driver.getCurrentUrl());
168     }
169 
170     /**
171      * @throws Exception if an error occurs
172      */
173     @Test
174     public void clickNestedImageElement() throws Exception {
175         final URL urlImage = new URL(URL_FIRST, "img.jpg");
176         try (InputStream is = getClass().getClassLoader().
177                 getResourceAsStream("testfiles/not_supported_type.jpg")) {
178             final byte[] directBytes = IOUtils.toByteArray(is);
179             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
180         }
181 
182         final String html = DOCTYPE_HTML
183             + "<html>\n"
184             + "<body>\n"
185             + "  <a href='page2.html'>\n"
186             + "    <img id='theImage' src='" + urlImage + "' />\n"
187             + "  </a>\n"
188             + "</body></html>";
189 
190         getMockWebConnection().setDefaultResponse("");
191         final WebDriver driver = loadPage2(html);
192         final WebElement img = driver.findElement(By.id("theImage"));
193         assertEquals("img", img.getTagName());
194         img.click();
195         assertEquals(URL_FIRST + "page2.html", driver.getCurrentUrl());
196     }
197 
198     /**
199      * @throws Exception if an error occurs
200      */
201     @Test
202     @Alerts("page2.html")
203     public void clickNestedInputImageElement() throws Exception {
204         final String html = DOCTYPE_HTML
205             + "<html>\n"
206             + "<body>\n"
207             + "  <a href='page2.html'>\n"
208             + "    <input type='image' id='theInput' />\n"
209             + "  </a>\n"
210             + "</body></html>";
211 
212         getMockWebConnection().setDefaultResponse("");
213         final WebDriver driver = loadPage2(html);
214         final WebElement input = driver.findElement(By.id("theInput"));
215         assertEquals("input", input.getTagName());
216         input.click();
217         assertEquals(URL_FIRST + getExpectedAlerts()[0], driver.getCurrentUrl());
218     }
219 
220     /**
221      * @throws Exception if an error occurs
222      */
223     @Test
224     @Alerts("page2.html")
225     public void clickNestedInputTextElement() throws Exception {
226         final String html = DOCTYPE_HTML
227             + "<html>\n"
228             + "<body>\n"
229             + "  <a href='page2.html'>\n"
230             + "    <input type='text' id='theInput' />\n"
231             + "  </a>\n"
232             + "</body></html>";
233 
234         getMockWebConnection().setDefaultResponse("");
235         final WebDriver driver = loadPage2(html);
236         final WebElement input = driver.findElement(By.id("theInput"));
237         assertEquals("input", input.getTagName());
238         input.click();
239         assertEquals(URL_FIRST + getExpectedAlerts()[0], driver.getCurrentUrl());
240     }
241 
242     /**
243      * @throws Exception if an error occurs
244      */
245     @Test
246     @Alerts("page2.html")
247     public void clickNestedInputPasswordElement() throws Exception {
248         final String html = DOCTYPE_HTML
249             + "<html>\n"
250             + "<body>\n"
251             + "  <a href='page2.html'>\n"
252             + "    <input type='password' id='theInput' />\n"
253             + "  </a>\n"
254             + "</body></html>";
255 
256         getMockWebConnection().setDefaultResponse("");
257         final WebDriver driver = loadPage2(html);
258         final WebElement input = driver.findElement(By.id("theInput"));
259         assertEquals("input", input.getTagName());
260         input.click();
261         assertEquals(URL_FIRST + getExpectedAlerts()[0], driver.getCurrentUrl());
262     }
263 
264     /**
265      * @throws Exception if an error occurs
266      */
267     @Test
268     @Alerts("§§URL§§page2.html")
269     @BuggyWebDriver(FF = "§§URL§§",
270                     FF_ESR = "§§URL§§")
271     public void clickNestedOptionElement() throws Exception {
272         final String html = DOCTYPE_HTML
273             + "<html>\n"
274             + "<body>\n"
275             + "  <a href='page2.html'>\n"
276             + "    <select size=2>\n"
277             + "      <option id='theOption'>test</option>\n"
278             + "    </select>\n"
279             + "  </a>\n"
280             + "</body></html>";
281 
282         expandExpectedAlertsVariables(URL_FIRST);
283         getMockWebConnection().setDefaultResponse("");
284         final WebDriver driver = loadPage2(html);
285         final WebElement option = driver.findElement(By.id("theOption"));
286         assertEquals("option", option.getTagName());
287         option.click();
288 
289         assertEquals(getExpectedAlerts()[0], driver.getCurrentUrl());
290     }
291 
292     /**
293      * @throws Exception if an error occurs
294      */
295     @Test
296     @Alerts("")
297     public void clickNestedRadioElement() throws Exception {
298         final String html = DOCTYPE_HTML
299             + "<html>\n"
300             + "<body>\n"
301             + "  <a href='page2.html'>\n"
302             + "    <input type='radio' id='theRadio' name='myRadio' value='Milk'>\n"
303             + "  </a>\n"
304             + "</body></html>";
305 
306         getMockWebConnection().setDefaultResponse("");
307         final WebDriver driver = loadPage2(html);
308         final WebElement radio = driver.findElement(By.id("theRadio"));
309         assertEquals("input", radio.getTagName());
310         radio.click();
311         assertEquals(URL_FIRST + getExpectedAlerts()[0], driver.getCurrentUrl());
312     }
313 
314     /**
315      * @throws Exception if an error occurs
316      */
317     @Test
318     @Alerts("page2.html")
319     public void clickNestedResetElement() throws Exception {
320         final String html = DOCTYPE_HTML
321             + "<html>\n"
322             + "<body>\n"
323             + "  <a href='page2.html'>\n"
324             + "    <input type='reset' id='theInput' />\n"
325             + "  </a>\n"
326             + "</body></html>";
327 
328         getMockWebConnection().setDefaultResponse("");
329         final WebDriver driver = loadPage2(html);
330         final WebElement input = driver.findElement(By.id("theInput"));
331         assertEquals("input", input.getTagName());
332         input.click();
333         assertEquals(URL_FIRST + getExpectedAlerts()[0], driver.getCurrentUrl());
334     }
335 
336     /**
337      * @throws Exception if an error occurs
338      */
339     @Test
340     @Alerts("page2.html")
341     public void clickNestedSubmitElement() throws Exception {
342         final String html = DOCTYPE_HTML
343             + "<html>\n"
344             + "<body>\n"
345             + "  <a href='page2.html'>\n"
346             + "    <input type='submit' id='theInput' />\n"
347             + "  </a>\n"
348             + "</body></html>";
349 
350         getMockWebConnection().setDefaultResponse("");
351         final WebDriver driver = loadPage2(html);
352         final WebElement input = driver.findElement(By.id("theInput"));
353         assertEquals("input", input.getTagName());
354         input.click();
355         assertEquals(URL_FIRST + getExpectedAlerts()[0], driver.getCurrentUrl());
356     }
357 
358     /**
359      * @throws Exception if an error occurs
360      */
361     @Test
362     public void clickBlankTargetHashOnly() throws Exception {
363         final String html = DOCTYPE_HTML
364                 + "<html>\n"
365                 + "<head><title>foo</title></head>\n"
366                 + "<body>\n"
367                 + "<a id='a' target='_blank' href='#'>Foo</a>\n"
368                 + "</body></html>\n";
369 
370         final WebDriver driver = loadPage2(html);
371         assertEquals(1, driver.getWindowHandles().size());
372 
373         final WebElement tester = driver.findElement(By.id("a"));
374         tester.click();
375 
376         Thread.sleep(100);
377         assertEquals(2, driver.getWindowHandles().size());
378     }
379 
380     /**
381      * @throws Exception if an error occurs
382      */
383     @Test
384     @Alerts({"My Link", "", "abcd"})
385     public void getText() throws Exception {
386         final String html = DOCTYPE_HTML
387             + "<html><head><script>\n"
388             + LOG_TITLE_FUNCTION
389             + "  function test() {\n"
390             + "    log(document.getElementById('myAnchor').text);\n"
391             + "    log(document.getElementById('myImgAnchor').text);\n"
392             + "    log(document.getElementById('myImgTxtAnchor').text);\n"
393             + "  }\n"
394             + "</script></head>\n"
395             + "<body onload=test()>\n"
396             + "  <a id='myAnchor'>My Link</a>\n"
397             + "  <a id='myImgAnchor'><img src='test.png' /></a>\n"
398             + "  <a id='myImgTxtAnchor'>ab<img src='test.png' />cd</a>\n"
399             + "</body></html>";
400         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
401 
402         loadPageVerifyTitle2(html);
403     }
404 
405     /**
406      * @throws Exception if an error occurs
407      */
408     @Test
409     @Alerts({"My Link 0", "Hello 0", " 1", "Hello 0", "a 2", "Hello 0"})
410     public void setText() throws Exception {
411         final String html = DOCTYPE_HTML
412             + "<html><head><script>\n"
413             + LOG_TITLE_FUNCTION
414             + "  function test() {\n"
415             + "    try {\n"
416             + "      var anchor = document.getElementById('myAnchor');\n"
417             + "      log(anchor.text + ' ' + anchor.children.length);\n"
418             + "      anchor.text = 'Hello';\n"
419             + "      log(anchor.text + ' ' + anchor.children.length);\n"
420 
421             + "      anchor = document.getElementById('myImgAnchor');\n"
422             + "      log(anchor.text + ' ' + anchor.children.length);\n"
423             + "      anchor.text = 'Hello';\n"
424             + "      log(anchor.text + ' ' + anchor.children.length);\n"
425 
426             + "      anchor = document.getElementById('myImgTxtAnchor');\n"
427             + "      log(anchor.text + ' ' + anchor.children.length);\n"
428             + "      anchor.text = 'Hello';\n"
429             + "      log(anchor.text + ' ' + anchor.children.length);\n"
430             + "    } catch(e) { log('exception' + e) }\n"
431             + "  }\n"
432             + "</script></head>\n"
433             + "<body onload=test()>\n"
434             + "  <a id='myAnchor'>My Link</a>\n"
435             + "  <a id='myImgAnchor'><img src='test.png' /></a>\n"
436             + "  <a id='myImgTxtAnchor'><img src='test.png' />a<img src='test.png' /></a>\n"
437             + "</body></html>";
438         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
439 
440         loadPageVerifyTitle2(html);
441     }
442 
443     /**
444      * Attributes aren't usually quoted in IE, but <tt>href</tt> attributes of anchor elements are.
445      * @throws Exception if the test fails
446      */
447     @Test
448     @Alerts("<a\\sid=\"a\"\\shref=\"#x\">foo</a>")
449     public void innerHtmlHrefQuotedEvenInIE() throws Exception {
450         final String html = DOCTYPE_HTML
451             + "<html>\n"
452             + "<head><script>\n"
453             + LOG_TITLE_FUNCTION_NORMALIZE
454             + "</script></head>\n"
455             + "<body onload='log(document.getElementById(\"d\").innerHTML)'>\n"
456             + "<div id='d'><a id='a' href='#x'>foo</a></div></body></html>";
457 
458         loadPageVerifyTitle2(html);
459     }
460 
461     /**
462      * @throws Exception if the test fails
463      */
464     @Test
465     public void click() throws Exception {
466         final String html = DOCTYPE_HTML
467             + "<html>\n"
468             + "<head><title>foo</title></head>\n"
469             + "<body>\n"
470             + "<a href='http://www.foo1.com' id='a1'>link to foo1</a>\n"
471             + "<a href='" + URL_SECOND + "' id='a2'>link to foo2</a>\n"
472             + "</body></html>";
473 
474         final String secondContent = DOCTYPE_HTML
475             + "<html><head><title>Second</title></head><body></body></html>";
476 
477         final MockWebConnection webConnection = getMockWebConnection();
478         webConnection.setDefaultResponse(secondContent);
479 
480         final WebDriver driver = loadPage2(html);
481         assertEquals(1, webConnection.getRequestCount());
482 
483         // Test that the correct value is being passed back up to the server
484         driver.findElement(By.id("a2")).click();
485 
486         assertEquals(URL_SECOND.toExternalForm(), driver.getCurrentUrl());
487         assertSame("method", HttpMethod.GET, webConnection.getLastMethod());
488         assertTrue(webConnection.getLastParameters().isEmpty());
489 
490         assertEquals(2, webConnection.getRequestCount());
491     }
492 
493     /**
494      * @throws Exception if the test fails
495      */
496     @Test
497     public void clickAnchorName() throws Exception {
498         final String html = DOCTYPE_HTML
499             + "<html>\n"
500             + "<head><title>foo</title></head>\n"
501             + "<body>\n"
502             + "  <a href='#clickedAnchor' id='a1'>link to foo1</a>\n"
503             + "</body></html>";
504 
505         final MockWebConnection webConnection = getMockWebConnection();
506         final WebDriver driver = loadPage2(html);
507 
508         assertEquals(1, webConnection.getRequestCount());
509 
510         driver.findElement(By.id("a1")).click();
511         assertEquals(1, webConnection.getRequestCount()); // no second server hit
512     }
513 
514     /**
515      * @throws Exception if the test fails
516      */
517     @Test
518     @Alerts({"", "#anchor", "#!bang"})
519     public void dontReloadHashBang() throws Exception {
520         final String html = DOCTYPE_HTML
521             + "<html>\n"
522             + "<head></head>\n"
523             + "<body>\n"
524             + "  <a href='" + URL_FIRST + "test' id='a1'>link1</a>\n"
525             + "  <a href='" + URL_FIRST + "test#anchor' id='a2'>link2</a>\n"
526             + "  <a href='" + URL_FIRST + "test#!bang' id='a3'>link3</a>\n"
527             + "  <script>\n"
528             + LOG_TITLE_FUNCTION
529             + "    log(document.getElementById('a1').hash);\n"
530             + "    log(document.getElementById('a2').hash);\n"
531             + "    log(document.getElementById('a3').hash);\n"
532             + "  </script>\n"
533             + "</body></html>";
534 
535         final MockWebConnection webConnection = getMockWebConnection();
536         webConnection.setDefaultResponse(html);
537 
538         final WebDriver driver = loadPageVerifyTitle2(html);
539 
540         assertEquals(1, webConnection.getRequestCount());
541 
542         driver.findElement(By.id("a1")).click();
543         assertEquals(2, webConnection.getRequestCount());
544         verifyTitle2(driver, getExpectedAlerts());
545 
546         driver.findElement(By.id("a2")).click();
547         assertEquals(2, webConnection.getRequestCount());
548 
549         driver.findElement(By.id("a3")).click();
550         assertEquals(2, webConnection.getRequestCount());
551     }
552 
553     /**
554      * Test case for issue #1492.
555      *
556      * @throws Exception if the test fails
557      */
558     @Test
559     @Alerts({"#!board/WebDev", "#!article/WebDev/35", "#!article/WebDev/35"})
560     public void dontReloadHashBang2() throws Exception {
561         final String html = DOCTYPE_HTML
562             + "<html>\n"
563             + "<head></head>\n"
564             + "<body>\n"
565             + "  <a href='" + URL_FIRST + "test/#!board/WebDev' id='a1'>link1</a>\n"
566             + "  <a href='" + URL_FIRST + "test/#!article/WebDev/35' id='a2'>link2</a>\n"
567             + "  <a href='" + URL_FIRST + "test#!article/WebDev/35' id='a3'>link2</a>\n"
568             + "  <script>\n"
569             + LOG_TITLE_FUNCTION
570             + "    log(document.getElementById('a1').hash);\n"
571             + "    log(document.getElementById('a2').hash);\n"
572             + "    log(document.getElementById('a3').hash);\n"
573             + "  </script>\n"
574             + "</body></html>";
575 
576         final MockWebConnection webConnection = getMockWebConnection();
577         webConnection.setDefaultResponse(html);
578 
579         final WebDriver driver = loadPageVerifyTitle2(html);
580 
581         assertEquals(1, webConnection.getRequestCount());
582 
583         driver.findElement(By.id("a1")).click();
584         assertEquals(2, webConnection.getRequestCount());
585         verifyTitle2(driver, getExpectedAlerts());
586 
587         driver.findElement(By.id("a2")).click();
588         assertEquals(2, webConnection.getRequestCount());
589 
590         driver.findElement(By.id("a3")).click();
591         assertEquals(3, webConnection.getRequestCount());
592         verifyTitle2(driver, getExpectedAlerts());
593     }
594 
595     /**
596      * FF behaves is different.
597      * @throws Exception if an error occurs
598      */
599     @Test
600     @Alerts({"click", "href", "click", "doubleClick", "href"})
601     @HtmlUnitNYI(CHROME = {"click", "href", "click", "href", "doubleClick"},
602             EDGE = {"click", "href", "click", "href", "doubleClick"},
603             FF = {"click", "href", "click", "href", "doubleClick"},
604             FF_ESR = {"click", "href", "click", "href", "doubleClick"})
605     public void doubleClick() throws Exception {
606         final String html = DOCTYPE_HTML
607               + "<html>\n"
608               + "<head>\n"
609               + "<script>\n"
610               + LOG_TEXTAREA_FUNCTION
611               + "</script>\n"
612               + "</head>\n"
613             + "<body>\n"
614             + "  <a id='myAnchor' "
615             +       "href=\"javascript:log('href');void(0);\" "
616             +       "onClick=\"log('click');\" "
617             +       "onDblClick=\"log('doubleClick');\">foo</a>\n"
618             + LOG_TEXTAREA
619             + "</body></html>";
620 
621         final WebDriver driver = loadPage2(html);
622 
623         final Actions action = new Actions(driver);
624         action.doubleClick(driver.findElement(By.id("myAnchor")));
625         action.perform();
626 
627         verifyTextArea2(driver, getExpectedAlerts());
628     }
629 
630     /**
631      * @throws Exception if the test fails
632      */
633     @Test
634     @Alerts({"§§URL§§bug.html?h%C3%B6=G%C3%BCnter", "h\u00F6", "G\u00FCnter"})
635     public void encoding() throws Exception {
636         final String href = "bug.html?" + URLEncoder.encode("h\u00F6", "UTF-8")
637                 + '=' + URLEncoder.encode("G\u00FCnter", "UTF-8");
638         final String html = DOCTYPE_HTML
639             + "<html>\n"
640             + "<head>\n"
641             + "  <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>\n"
642             + "</head>\n"
643             + "<body>\n"
644             + "  <a href='" + href + "' id='myLink'>Click me</a>\n"
645             + "</body></html>";
646 
647         getMockWebConnection().setDefaultResponse(html, MimeType.TEXT_HTML, UTF_8);
648 
649         expandExpectedAlertsVariables(URL_FIRST);
650         final WebDriver driver = loadPage2(html, URL_FIRST);
651         driver.findElement(By.id("myLink")).click();
652 
653         assertEquals(getExpectedAlerts()[0], driver.getCurrentUrl());
654 
655         final List<NameValuePair> requestedParams =
656                 getMockWebConnection().getLastWebRequest().getRequestParameters();
657         assertEquals(1, requestedParams.size());
658         assertEquals(getExpectedAlerts()[1], requestedParams.get(0).getName());
659         assertEquals(getExpectedAlerts()[2], requestedParams.get(0).getValue());
660     }
661 
662     /**
663      * @throws Exception if the test fails
664      */
665     @Test
666     public void javascriptWithReturn() throws Exception {
667         final String html = DOCTYPE_HTML
668             + "<html><head><title>First</title></head><body>\n"
669             + "  <a id='myLink' href='javascript:return true'>hi</a>\n"
670             + "</body></html>";
671         final WebDriver webDriver = loadPage2(html);
672         webDriver.findElement(By.id("myLink")).click();
673     }
674 
675     /**
676      * @throws Exception if the test fails
677      */
678     @Test
679     public void javascriptWithReturnWhitespace() throws Exception {
680         final String html = DOCTYPE_HTML
681             + "<html><head><title>First</title></head><body>\n"
682             + "  <a id='myLink' href='javascript: return true'>hi</a>\n"
683             + "</body></html>";
684         final WebDriver webDriver = loadPage2(html);
685         webDriver.findElement(By.id("myLink")).click();
686     }
687 
688     /**
689      * @exception Exception If the test fails
690      */
691     @Test
692     @Alerts({"1", "First"})
693     public void shiftClick() throws Exception {
694         final String html = DOCTYPE_HTML
695             + "<html><head><title>First</title></head><body>\n"
696             + "<a href='" + URL_SECOND + "'>Click Me</a>\n"
697             + "</form></body></html>";
698 
699         getMockWebConnection().setResponse(URL_SECOND, "<head><title>Second</title>");
700         final WebDriver driver = loadPage2(html);
701 
702         final WebElement link = driver.findElement(By.linkText("Click Me"));
703 
704         final int windowsSize = driver.getWindowHandles().size();
705 
706         new Actions(driver)
707             .moveToElement(link)
708             .keyDown(Keys.SHIFT)
709             .click()
710             .keyUp(Keys.SHIFT)
711             .perform();
712 
713         Thread.sleep(100);
714         assertEquals("Should have opened a new window",
715                 windowsSize + Integer.parseInt(getExpectedAlerts()[0]), driver.getWindowHandles().size());
716         assertEquals("Should not have navigated away", getExpectedAlerts()[1], driver.getTitle());
717     }
718 
719     /**
720      * @exception Exception If the test fails
721      */
722     @Test
723     @Alerts({"1", "First"})
724     public void ctrlClick() throws Exception {
725         final String html = DOCTYPE_HTML
726             + "<html><head><title>First</title></head><body>\n"
727             + "<a href='" + URL_SECOND + "'>Click Me</a>\n"
728             + "</form></body></html>";
729 
730         getMockWebConnection().setResponse(URL_SECOND, "<head><title>Second</title>");
731         final WebDriver driver = loadPage2(html);
732 
733         final WebElement link = driver.findElement(By.linkText("Click Me"));
734 
735         final int windowsSize = driver.getWindowHandles().size();
736 
737         new Actions(driver)
738                 .moveToElement(link)
739                 .keyDown(Keys.CONTROL)
740                 .click()
741                 .keyUp(Keys.CONTROL)
742                 .perform();
743 
744         Thread.sleep(DEFAULT_WAIT_TIME.toMillis());
745         assertEquals("Should have opened a new window",
746                 windowsSize + Integer.parseInt(getExpectedAlerts()[0]), driver.getWindowHandles().size());
747         assertEquals("Should not have navigated away", getExpectedAlerts()[1], driver.getTitle());
748     }
749 
750     /**
751      * Tests the 'Referer' HTTP header.
752      * @throws Exception on test failure
753      */
754     @Test
755     @Alerts("§§URL§§index.html?test")
756     public void click_refererHeader() throws Exception {
757         final String firstContent = DOCTYPE_HTML
758             + "<html><head><title>Page A</title></head>\n"
759             + "<body><a href='" + URL_SECOND + "' id='link'>link</a></body>\n"
760             + "</html>";
761         final String secondContent = DOCTYPE_HTML
762             + "<html><head><title>Page B</title></head>\n"
763             + "<body></body>\n"
764             + "</html>";
765 
766         expandExpectedAlertsVariables(URL_FIRST);
767 
768         final URL indexUrl = new URL(URL_FIRST.toString() + "index.html");
769 
770         getMockWebConnection().setResponse(indexUrl, firstContent);
771         getMockWebConnection().setResponse(URL_SECOND, secondContent);
772 
773         final WebDriver driver = loadPage2(firstContent, new URL(URL_FIRST.toString() + "index.html?test#ref"));
774         driver.findElement(By.id("link")).click();
775 
776         assertEquals(2, getMockWebConnection().getRequestCount());
777 
778         final Map<String, String> lastAdditionalHeaders = getMockWebConnection().getLastAdditionalHeaders();
779         assertEquals(getExpectedAlerts()[0], lastAdditionalHeaders.get(HttpHeader.REFERER));
780     }
781 
782     /**
783      * Tests the 'Referer' HTTP header for rel='noreferrer'.
784      * @throws Exception on test failure
785      */
786     @Test
787     public void click_refererHeaderNoReferrer() throws Exception {
788         final String firstContent = DOCTYPE_HTML
789             + "<html><head><title>Page A</title></head>\n"
790             + "<body><a href='" + URL_SECOND + "' id='link' rel='noreferrer'>link</a></body>\n"
791             + "</html>";
792         final String secondContent = DOCTYPE_HTML
793             + "<html><head><title>Page B</title></head>\n"
794             + "<body></body>\n"
795             + "</html>";
796 
797         final URL indexUrl = new URL(URL_FIRST.toString() + "index.html");
798 
799         getMockWebConnection().setResponse(indexUrl, firstContent);
800         getMockWebConnection().setResponse(URL_SECOND, secondContent);
801 
802         final WebDriver driver = loadPage2(firstContent, new URL(URL_FIRST.toString() + "index.html?test#ref"));
803         driver.findElement(By.id("link")).click();
804 
805         assertEquals(2, getMockWebConnection().getRequestCount());
806 
807         final Map<String, String> lastAdditionalHeaders = getMockWebConnection().getLastAdditionalHeaders();
808         assertNull(lastAdditionalHeaders.get(HttpHeader.REFERER));
809     }
810 
811     /**
812      * Tests the 'Referer' HTTP header for rel='noreferrer'.
813      * @throws Exception on test failure
814      */
815     @Test
816     public void click_refererHeaderNoReferrerCaseSensitive() throws Exception {
817         final String firstContent = DOCTYPE_HTML
818             + "<html><head><title>Page A</title></head>\n"
819             + "<body><a href='" + URL_SECOND + "' id='link' rel='NoReferrer'>link</a></body>\n"
820             + "</html>";
821         final String secondContent = DOCTYPE_HTML
822             + "<html><head><title>Page B</title></head>\n"
823             + "<body></body>\n"
824             + "</html>";
825 
826         final URL indexUrl = new URL(URL_FIRST.toString() + "index.html");
827 
828         getMockWebConnection().setResponse(indexUrl, firstContent);
829         getMockWebConnection().setResponse(URL_SECOND, secondContent);
830 
831         final WebDriver driver = loadPage2(firstContent, new URL(URL_FIRST.toString() + "index.html?test#ref"));
832         driver.findElement(By.id("link")).click();
833 
834         assertEquals(2, getMockWebConnection().getRequestCount());
835 
836         final Map<String, String> lastAdditionalHeaders = getMockWebConnection().getLastAdditionalHeaders();
837         assertNull(lastAdditionalHeaders.get(HttpHeader.REFERER));
838     }
839 
840     /**
841      * @throws Exception if the test fails
842      */
843     @Test
844     @Alerts("§§URL§§index.html?test")
845     public void controlClick_refererHeader() throws Exception {
846         final String firstContent = DOCTYPE_HTML
847             + "<html><head><title>Page A</title></head>\n"
848             + "<body>\n"
849             + "  <a href='" + URL_SECOND + "' id='link'>link</a>\n"
850             + "</body>\n"
851             + "</html>";
852         final String secondContent = DOCTYPE_HTML
853             + "<html><head><title>Page B</title></head>\n"
854             + "<body></body>\n"
855             + "</html>";
856 
857         expandExpectedAlertsVariables(URL_FIRST);
858 
859         final URL indexUrl = new URL(URL_FIRST.toString() + "index.html");
860 
861         getMockWebConnection().setResponse(indexUrl, firstContent);
862         getMockWebConnection().setResponse(URL_SECOND, secondContent);
863 
864         final WebDriver driver = loadPage2(firstContent, new URL(URL_FIRST.toString() + "index.html?test#ref"));
865         new Actions(driver)
866                 .keyDown(Keys.CONTROL)
867                 .click(driver.findElement(By.id("link")))
868                 .keyUp(Keys.CONTROL)
869                 .build().perform();
870 
871         Thread.sleep(DEFAULT_WAIT_TIME.toMillis() / 10);
872 
873         assertEquals(2, getMockWebConnection().getRequestCount());
874 
875         final Map<String, String> lastAdditionalHeaders = getMockWebConnection().getLastAdditionalHeaders();
876         assertEquals(getExpectedAlerts()[0], lastAdditionalHeaders.get(HttpHeader.REFERER));
877     }
878 
879 }