View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.html;
16  
17  import java.io.InputStream;
18  import java.net.URL;
19  import java.util.Collections;
20  import java.util.Map;
21  
22  import org.apache.commons.io.IOUtils;
23  import org.htmlunit.HttpHeader;
24  import org.htmlunit.Page;
25  import org.htmlunit.WebDriverTestCase;
26  import org.htmlunit.junit.BrowserRunner;
27  import org.htmlunit.junit.annotation.Alerts;
28  import org.htmlunit.junit.annotation.BuggyWebDriver;
29  import org.junit.Test;
30  import org.junit.runner.RunWith;
31  import org.openqa.selenium.By;
32  import org.openqa.selenium.WebDriver;
33  import org.openqa.selenium.WebDriverException;
34  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
35  
36  /**
37   * Tests for {@link HtmlArea}.
38   *
39   * @author Ahmed Ashour
40   * @author Ronald Brill
41   */
42  @RunWith(BrowserRunner.class)
43  public class HtmlAreaTest extends WebDriverTestCase {
44  
45      private WebDriver createWebClient(final String onClick) throws Exception {
46          final URL urlImage = new URL(URL_FIRST, "img.jpg");
47          try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
48              final byte[] directBytes = IOUtils.toByteArray(is);
49              getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
50          }
51  
52          final String firstContent = DOCTYPE_HTML
53              + "<html><head><title>first</title></head>\n"
54              + "<body>\n"
55              + "  <img src='" + urlImage + "' width='145' height='126' usemap='#planetmap'>\n"
56              + "  <map id='planetmap' name='planetmap'>\n"
57              + "    <area shape='rect' onClick=\"" + onClick + "\" coords='0,0,82,126' id='second' "
58                          + "href='" + URL_SECOND + "'>\n"
59              + "    <area shape='circle' coords='90,58,3' id='third' href='" + URL_THIRD + "'>\n"
60              + "  </map>\n"
61              + "</body></html>";
62          final String secondContent = DOCTYPE_HTML + "<html><head><title>second</title></head><body></body></html>";
63          final String thirdContent = DOCTYPE_HTML + "<html><head><title>third</title></head><body></body></html>";
64  
65          getMockWebConnection().setResponse(URL_SECOND, secondContent);
66          getMockWebConnection().setResponse(URL_THIRD, thirdContent);
67  
68          return loadPage2(firstContent);
69      }
70  
71      /**
72       * @throws Exception if the test fails
73       */
74      @Test
75      @Alerts("§§URL§§")
76      @BuggyWebDriver(FF = "WebDriverException",
77                      FF_ESR = "WebDriverException")
78      public void referer() throws Exception {
79          expandExpectedAlertsVariables(URL_FIRST);
80  
81          final WebDriver driver = createWebClient("");
82          driver.get(URL_FIRST.toExternalForm());
83          try {
84              driver.findElement(By.id("third")).click();
85  
86              final Map<String, String> lastAdditionalHeaders = getMockWebConnection().getLastAdditionalHeaders();
87              assertEquals(getExpectedAlerts()[0], lastAdditionalHeaders.get(HttpHeader.REFERER));
88          }
89          catch (final WebDriverException e) {
90              e.printStackTrace();
91              assertEquals(getExpectedAlerts()[0], "WebDriverException");
92          }
93      }
94  
95      /**
96       * @throws Exception if an error occurs
97       */
98      @Test
99      public void isDisplayedRect() throws Exception {
100         final String html = DOCTYPE_HTML
101                 + "<html><head><title>Page A</title></head>\n"
102                 + "<body>\n"
103                 + "  <img id='myImg' usemap='#imgmap'"
104                         + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
105                         + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='>\n"
106                 + "  <map id='myMap' name='imgmap'>\n"
107                 + "    <area id='myArea' shape='rect' coords='0,0,1,1'>\n"
108                 + "  </map>\n"
109                 + "</body></html>";
110 
111         final WebDriver driver = loadPage2(html);
112 
113         boolean displayed = driver.findElement(By.id("myImg")).isDisplayed();
114         assertTrue(displayed);
115 
116         displayed = driver.findElement(By.id("myMap")).isDisplayed();
117         assertTrue(displayed);
118 
119         displayed = driver.findElement(By.id("myArea")).isDisplayed();
120         assertTrue(displayed);
121     }
122 
123     /**
124      * @throws Exception if an error occurs
125      */
126     @Test
127     public void isDisplayedCircle() throws Exception {
128         final String html = DOCTYPE_HTML
129                 + "<html><head><title>Page A</title></head>\n"
130                 + "<body>\n"
131                 + "  <img id='myImg' usemap='#imgmap'"
132                         + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
133                         + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='>\n"
134                 + "  <map id='myMap' name='imgmap'>\n"
135                 + "    <area id='myArea' shape='circle' coords='0,0,1'>\n"
136                 + "  </map>\n"
137                 + "</body></html>";
138 
139         final WebDriver driver = loadPage2(html);
140 
141         boolean displayed = driver.findElement(By.id("myImg")).isDisplayed();
142         assertTrue(displayed);
143 
144         displayed = driver.findElement(By.id("myMap")).isDisplayed();
145         assertTrue(displayed);
146 
147         displayed = driver.findElement(By.id("myArea")).isDisplayed();
148         assertTrue(displayed);
149     }
150 
151     /**
152      * @throws Exception if an error occurs
153      */
154     @Test
155     public void isDisplayedPolygon() throws Exception {
156         final String html = DOCTYPE_HTML
157                 + "<html><head><title>Page A</title></head>\n"
158                 + "<body>\n"
159                 + "  <img id='myImg' usemap='#imgmap'"
160                         + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
161                         + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='>\n"
162                 + "  <map id='myMap' name='imgmap'>\n"
163                 + "    <area id='myArea' shape='poly' coords='7,9,5,1,2,2'>\n"
164                 + "  </map>\n"
165                 + "</body></html>";
166 
167         final WebDriver driver = loadPage2(html);
168 
169         boolean displayed = driver.findElement(By.id("myImg")).isDisplayed();
170         assertTrue(displayed);
171 
172         displayed = driver.findElement(By.id("myMap")).isDisplayed();
173         assertTrue(displayed);
174 
175         displayed = driver.findElement(By.id("myArea")).isDisplayed();
176         assertTrue(displayed);
177     }
178 
179     /**
180      * @throws Exception if an error occurs
181      */
182     @Test
183     public void isDisplayedHiddenImage() throws Exception {
184         final String html = DOCTYPE_HTML
185                 + "<html><head><title>Page A</title></head>\n"
186                 + "<body>\n"
187                 + "  <img id='myImg' usemap='#imgmap' style='display: none'"
188                         + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
189                         + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='>\n"
190                 + "  <map id='myMap' name='imgmap'>\n"
191                 + "    <area id='myArea' shape='rect' coords='0,0,1,1'>\n"
192                 + "  </map>\n"
193                 + "</body></html>";
194 
195         final WebDriver driver = loadPage2(html);
196 
197         boolean displayed = driver.findElement(By.id("myImg")).isDisplayed();
198         assertFalse(displayed);
199 
200         displayed = driver.findElement(By.id("myMap")).isDisplayed();
201         assertFalse(displayed);
202 
203         displayed = driver.findElement(By.id("myArea")).isDisplayed();
204         assertFalse(displayed);
205     }
206 
207     /**
208      * @throws Exception if an error occurs
209      */
210     @Test
211     public void isDisplayedHiddenMap() throws Exception {
212         final String html = DOCTYPE_HTML
213                 + "<html><head><title>Page A</title></head>\n"
214                 + "<body>\n"
215                 + "  <img id='myImg' usemap='#imgmap'"
216                         + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
217                         + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='>\n"
218                 + "  <map id='myMap' name='imgmap' style='display: none'>\n"
219                 + "    <area id='myArea' shape='rect' coords='0,0,1,1'>\n"
220                 + "  </map>\n"
221                 + "</body></html>";
222 
223         final WebDriver driver = loadPage2(html);
224 
225         boolean displayed = driver.findElement(By.id("myImg")).isDisplayed();
226         assertTrue(displayed);
227 
228         displayed = driver.findElement(By.id("myMap")).isDisplayed();
229         assertTrue(displayed);
230 
231         displayed = driver.findElement(By.id("myArea")).isDisplayed();
232         assertTrue(displayed);
233     }
234 
235     /**
236      * @throws Exception if an error occurs
237      */
238     @Test
239     @Alerts({"false", "false", "false", "false", "false", "true"})
240     public void isDisplayedEmptyRect() throws Exception {
241         final String html = DOCTYPE_HTML
242                 + "<html><head><title>Page A</title></head>\n"
243                 + "<body>\n"
244                 + "  <img id='myImg' usemap='#imgmap'"
245                         + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
246                         + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='>\n"
247                 + "  <map id='myMap' name='imgmap'>\n"
248                 + "    <area id='myArea1' shape='rect' coords='0,0,0,1'>\n"
249                 + "    <area id='myArea2' shape='rect' coords='0,0,1,0'>\n"
250                 + "    <area id='myArea3' shape='rect' coords='0,0,0,0'>\n"
251                 + "    <area id='myArea4' shape='rect' >\n"
252                 + "    <area id='myArea5' >\n"
253                 + "    <area id='myArea6' shape='rect' coords='0,0,1,1'>\n"
254                 + "  </map>\n"
255                 + "</body></html>";
256 
257         final String[] expected = getExpectedAlerts();
258 
259         setExpectedAlerts(new String[] {});
260         final WebDriver driver = loadPage2(html);
261 
262         boolean displayed = driver.findElement(By.id("myArea1")).isDisplayed();
263         assertEquals(Boolean.parseBoolean(expected[0]), displayed);
264 
265         displayed = driver.findElement(By.id("myArea2")).isDisplayed();
266         assertEquals(Boolean.parseBoolean(expected[1]), displayed);
267 
268         displayed = driver.findElement(By.id("myArea3")).isDisplayed();
269         assertEquals(Boolean.parseBoolean(expected[2]), displayed);
270 
271         displayed = driver.findElement(By.id("myArea4")).isDisplayed();
272         assertEquals(Boolean.parseBoolean(expected[3]), displayed);
273 
274         displayed = driver.findElement(By.id("myArea5")).isDisplayed();
275         assertEquals(Boolean.parseBoolean(expected[4]), displayed);
276 
277         displayed = driver.findElement(By.id("myArea6")).isDisplayed();
278         assertEquals(Boolean.parseBoolean(expected[5]), displayed);
279     }
280 
281     /**
282      * @throws Exception if an error occurs
283      */
284     @Test
285     @Alerts({"false", "false", "true"})
286     public void isDisplayedEmptyCircle() throws Exception {
287         final String html = DOCTYPE_HTML
288                 + "<html><head><title>Page A</title></head>\n"
289                 + "<body>\n"
290                 + "  <img id='myImg' usemap='#imgmap'"
291                         + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
292                         + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='>\n"
293                 + "  <map id='myMap' name='imgmap'>\n"
294                 + "    <area id='myArea1' shape='circle' coords='0,0,0'>\n"
295                 + "    <area id='myArea2' shape='circle' >\n"
296                 + "    <area id='myArea3' shape='circle' coords='0,0,0.8'>\n"
297                 + "  </map>\n"
298                 + "</body></html>";
299 
300         final String[] expected = getExpectedAlerts();
301 
302         setExpectedAlerts(new String[] {});
303         final WebDriver driver = loadPage2(html);
304 
305         boolean displayed = driver.findElement(By.id("myArea1")).isDisplayed();
306         assertEquals(Boolean.parseBoolean(expected[0]), displayed);
307 
308         displayed = driver.findElement(By.id("myArea2")).isDisplayed();
309         assertEquals(Boolean.parseBoolean(expected[1]), displayed);
310 
311         displayed = driver.findElement(By.id("myArea3")).isDisplayed();
312         assertEquals(Boolean.parseBoolean(expected[2]), displayed);
313     }
314 
315 
316     /**
317      * @throws Exception if an error occurs
318      */
319     @Test
320     @Alerts({"false", "true", "false", "true"})
321     public void isDisplayedEmptyPolygon() throws Exception {
322         final String html = DOCTYPE_HTML
323                 + "<html><head><title>Page A</title></head>\n"
324                 + "<body>\n"
325                 + "  <img id='myImg' usemap='#imgmap'"
326                         + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
327                         + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='>\n"
328                 + "  <map id='myMap' name='imgmap'>\n"
329                 + "    <area id='myArea1' shape='poly' coords='0,0'>\n"
330                 + "    <area id='myArea2' shape='poly' coords='0,0,1,1'>\n"
331                 + "    <area id='myArea3' shape='poly' >\n"
332                 + "    <area id='myArea4' shape='poly' coords='0,0,1,0,0,1'>\n"
333                 + "  </map>\n"
334                 + "</body></html>";
335 
336         final String[] expected = getExpectedAlerts();
337 
338         setExpectedAlerts(new String[] {});
339         final WebDriver driver = loadPage2(html);
340 
341         boolean displayed = driver.findElement(By.id("myArea1")).isDisplayed();
342         assertEquals(Boolean.parseBoolean(expected[0]), displayed);
343 
344         displayed = driver.findElement(By.id("myArea2")).isDisplayed();
345         assertEquals(Boolean.parseBoolean(expected[1]), displayed);
346 
347         displayed = driver.findElement(By.id("myArea3")).isDisplayed();
348         assertEquals(Boolean.parseBoolean(expected[2]), displayed);
349 
350         displayed = driver.findElement(By.id("myArea4")).isDisplayed();
351         assertEquals(Boolean.parseBoolean(expected[3]), displayed);
352     }
353 
354     /**
355      * @throws Exception if an error occurs
356      */
357     @Test
358     public void isDisplayedMissingImage() throws Exception {
359         final String html = DOCTYPE_HTML
360                 + "<html><head><title>Page A</title></head>\n"
361                 + "<body>\n"
362                 + "  <map id='myMap' name='imgmap' style='display: none'>\n"
363                 + "    <area id='myArea' shape='rect' coords='0,0,1,1'>\n"
364                 + "  </map>\n"
365                 + "</body></html>";
366 
367         final WebDriver driver = loadPage2(html);
368 
369         boolean displayed = driver.findElement(By.id("myMap")).isDisplayed();
370         assertFalse(displayed);
371 
372         displayed = driver.findElement(By.id("myArea")).isDisplayed();
373         assertFalse(displayed);
374     }
375 
376     /**
377      * @throws Exception if the test fails
378      */
379     @Test
380     public void click_javascriptUrl() throws Exception {
381         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
382             final byte[] directBytes = IOUtils.toByteArray(is);
383             final URL urlImage = new URL(URL_FIRST, "img.jpg");
384             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
385         }
386 
387         final String html = DOCTYPE_HTML
388             + "<html><head><script>" + LOG_TITLE_FUNCTION + "</script></head><body>\n"
389             + "<img src='img.jpg' width='145' height='126' usemap='#somename'>\n"
390             + "<map name='somename'>\n"
391             + "  <area href='javascript:log(\"clicked\")' id='a2' shape='rect' coords='0,0,30,30'/>\n"
392             + "</map></body></html>";
393 
394         final WebDriver driver = loadPage2(html);
395         final Page page;
396         if (driver instanceof HtmlUnitDriver) {
397             page = getEnclosedPage();
398         }
399         else {
400             page = null;
401         }
402 
403         verifyTitle2(driver);
404 
405         driver.findElement(By.id("a2")).click();
406 
407         verifyTitle2(driver, "clicked");
408         if (driver instanceof HtmlUnitDriver) {
409             final Page secondPage = getEnclosedPage();
410             assertSame(page, secondPage);
411         }
412     }
413 
414     /**
415      * @throws Exception if the test fails
416      */
417     @Test
418     @Alerts("clicked")
419     @BuggyWebDriver(FF = "Todo", FF_ESR = "Todo")
420     public void click_javascriptUrlMixedCase() throws Exception {
421         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
422             final byte[] directBytes = IOUtils.toByteArray(is);
423             final URL urlImage = new URL(URL_FIRST, "img.jpg");
424             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
425         }
426 
427         final String html = DOCTYPE_HTML
428             + "<html><head><script>" + LOG_TITLE_FUNCTION + "</script></head><body>\n"
429             + "<img src='img.jpg' width='145' height='126' usemap='#somename'>\n"
430             + "<map name='somename'>\n"
431             + "  <area href='javasCRIpT:log(\"clicked\")' id='a2' shape='rect' coords='0,0,30,30'/>\n"
432             + "</map>\n"
433             + "</body></html>";
434 
435         final WebDriver driver = loadPage2(html);
436         final Page page;
437         if (driver instanceof HtmlUnitDriver) {
438             page = getEnclosedPage();
439         }
440         else {
441             page = null;
442         }
443 
444         verifyTitle2(driver);
445 
446         driver.findElement(By.id("a2")).click();
447 
448         verifyTitle2(driver, getExpectedAlerts());
449         if (driver instanceof HtmlUnitDriver) {
450             final Page secondPage = getEnclosedPage();
451             assertSame(page, secondPage);
452         }
453     }
454 
455     /**
456      * @throws Exception if the test fails
457      */
458     @Test
459     @Alerts("clicked")
460     @BuggyWebDriver(FF = "Todo", FF_ESR = "Todo")
461     public void click_javascriptUrlLeadingWhitespace() throws Exception {
462         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
463             final byte[] directBytes = IOUtils.toByteArray(is);
464             final URL urlImage = new URL(URL_FIRST, "img.jpg");
465             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
466         }
467 
468         final String html = DOCTYPE_HTML
469             + "<html><head><script>" + LOG_TITLE_FUNCTION + "</script></head><body>\n"
470             + "<img src='img.jpg' width='145' height='126' usemap='#somename'>\n"
471             + "<map name='somename'>\n"
472             + "  <area href='    javascript:log(\"clicked\")' id='a2' shape='rect' coords='0,0,30,30'/>\n"
473             + "</map></body></html>";
474 
475         final WebDriver driver = loadPage2(html);
476         final Page page;
477         if (driver instanceof HtmlUnitDriver) {
478             page = getEnclosedPage();
479         }
480         else {
481             page = null;
482         }
483 
484         verifyTitle2(driver);
485 
486         driver.findElement(By.id("a2")).click();
487 
488         verifyTitle2(driver, getExpectedAlerts());
489         if (driver instanceof HtmlUnitDriver) {
490             final Page secondPage = getEnclosedPage();
491             assertSame(page, secondPage);
492         }
493     }
494 
495     /**
496      * In action "this" should be the window and not the area.
497      * @throws Exception if the test fails
498      */
499     @Test
500     @Alerts("true")
501     @BuggyWebDriver(FF = "Todo", FF_ESR = "Todo")
502     public void thisInJavascriptHref() throws Exception {
503         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
504             final byte[] directBytes = IOUtils.toByteArray(is);
505             final URL urlImage = new URL(URL_FIRST, "img.jpg");
506             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
507         }
508 
509         final String html = DOCTYPE_HTML
510             + "<html><head><script>" + LOG_TITLE_FUNCTION + "</script></head><body>\n"
511             + "<img src='img.jpg' width='145' height='126' usemap='#somename'>\n"
512             + "<map name='somename'>\n"
513             + "  <area href='javascript:log(this == window)' id='a2' shape='rect' coords='0,0,30,30'/>\n"
514             + "</map></body></html>";
515 
516         final WebDriver driver = loadPage2(html);
517         final Page page;
518         if (driver instanceof HtmlUnitDriver) {
519             page = getEnclosedPage();
520         }
521         else {
522             page = null;
523         }
524 
525         verifyTitle2(driver);
526 
527         driver.findElement(By.id("a2")).click();
528 
529         verifyTitle2(driver, getExpectedAlerts());
530         if (driver instanceof HtmlUnitDriver) {
531             final Page secondPage = getEnclosedPage();
532             assertSame(page, secondPage);
533         }
534     }
535 
536 }