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