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.File;
18  import java.io.InputStream;
19  import java.net.URL;
20  import java.util.Collections;
21  
22  import org.apache.commons.io.FileUtils;
23  import org.apache.commons.io.IOUtils;
24  import org.htmlunit.Page;
25  import org.htmlunit.SimpleWebTestCase;
26  import org.htmlunit.junit.BrowserRunner;
27  import org.htmlunit.junit.annotation.Alerts;
28  import org.htmlunit.util.MimeType;
29  import org.junit.Test;
30  import org.junit.runner.RunWith;
31  
32  /**
33   * Tests for {@link HtmlImage}.
34   *
35   * @author Marc Guillemot
36   * @author Ahmed Ashour
37   * @author Ronald Brill
38   */
39  @RunWith(BrowserRunner.class)
40  public class HtmlImageTest extends SimpleWebTestCase {
41  
42      /**
43       * @throws Exception if the test fails
44       */
45      @Test
46      public void isMapClick() throws Exception {
47          isMapClick("img1", Boolean.FALSE, "?0,0", "?25,30");
48          isMapClick("img2", Boolean.FALSE, "", "");
49          isMapClick("img3", Boolean.TRUE, "", "");
50          isMapClick("img3", Boolean.TRUE, "", "");
51      }
52  
53      private void isMapClick(final String imgId, final Boolean samePage,
54              final String urlSuffixClick, final String urlSuffixClickXY) throws Exception {
55  
56          final URL urlImage = new URL(URL_FIRST, "img.jpg");
57          try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
58              final byte[] directBytes = IOUtils.toByteArray(is);
59              getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
60          }
61  
62          final String htmlContent = DOCTYPE_HTML
63              + "<html>\n"
64              + "<head><title>foo</title></head>\n"
65              + "<body>\n"
66              + "  <a href='http://server/foo'>\n"
67              + "    <img id='img1' src='" + urlImage + "' ismap>\n"
68              + "    <img id='img2' src='" + urlImage + "'>\n"
69              + "  </a>\n"
70              + "  <img id='img3' src='" + urlImage + "' ismap>\n"
71              + "  <img id='img4' src='" + urlImage + "'>\n"
72              + "</body></html>";
73          final HtmlPage page = loadPage(htmlContent);
74  
75          final HtmlImage img = page.getHtmlElementById(imgId);
76  
77          final Page page2 = img.click();
78          assertEquals("same page after click", samePage, Boolean.valueOf(page == page2));
79          if (!samePage.booleanValue()) {
80              assertEquals("http://server/foo" + urlSuffixClick, page2.getUrl());
81          }
82  
83          final Page page3 = img.click(25, 30);
84          assertEquals("same page after click(25, 30)", samePage, Boolean.valueOf(page == page3));
85          if (!samePage.booleanValue()) {
86              assertEquals("http://server/foo" + urlSuffixClickXY, page3.getUrl());
87          }
88      }
89  
90      /**
91       * @throws Exception if the test fails
92       */
93      @Test
94      public void useMapClick() throws Exception {
95          useMapClick(0, 0, "/");
96          useMapClick(10, 10, "a.html");
97          useMapClick(19, 10, "a.html");
98          useMapClick(29, 10, "b.html");
99          useMapClick(50, 50, "/");
100     }
101 
102     /**
103      * @throws Exception if the test fails
104      */
105     private void useMapClick(final int x, final int y, final String urlSuffix) throws Exception {
106         final URL urlImage = new URL(URL_FIRST, "img.jpg");
107         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
108             final byte[] directBytes = IOUtils.toByteArray(is);
109             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
110         }
111 
112         final String htmlContent = DOCTYPE_HTML
113             + "<html>\n"
114             + "<head><title>foo</title></head>\n"
115             + "<body>\n"
116             + "  <img id='myImg' src='" + urlImage + "' usemap='#map1'>\n"
117             + "  <map name='map1'>\n"
118             + "    <area href='a.html' shape='rect' coords='5,5,20,20'>\n"
119             + "    <area href='b.html' shape='circle' coords='25,10,10'>\n"
120             + "  </map>\n"
121             + "</body></html>";
122         final HtmlPage page = loadPage(htmlContent);
123 
124         final HtmlImage img = page.getHtmlElementById("myImg");
125 
126         final Page page2 = img.click(x, y);
127         final URL url = page2.getUrl();
128         assertTrue(url.toExternalForm(), url.toExternalForm().endsWith(urlSuffix));
129     }
130 
131     /**
132      * @throws Exception if the test fails
133      */
134     @Test
135     public void asXml() throws Exception {
136         final String content = DOCTYPE_HTML
137             + "<html><head><title>foo</title></head><body>\n"
138             + "<img id='img1' src='foo.png'>\n"
139             + "<img id='img2' name='testName' src='foo.png' alt='young'>\n"
140             + "<img id='img3' src='foo.png' width='11' height='17px'>\n"
141             + "<img id='img4' src='foo.png' width='11em' height='17%'>\n"
142             + "</body></html>";
143         final HtmlPage page = loadPage(content);
144 
145         HtmlImage img = page.getHtmlElementById("img1");
146         String expected = "<img id=\"img1\" src=\"foo.png\"/>";
147         assertEquals(expected, img.asXml().trim());
148 
149         img = page.getHtmlElementById("img2");
150         expected = "<img id=\"img2\" name=\"testName\" src=\"foo.png\" alt=\"young\"/>";
151         assertEquals(expected, img.asXml().trim());
152 
153         img = page.getHtmlElementById("img3");
154         expected = "<img id=\"img3\" src=\"foo.png\" width=\"11\" height=\"17px\"/>";
155         assertEquals(expected, img.asXml().trim());
156 
157         img = page.getHtmlElementById("img4");
158         expected = "<img id=\"img4\" src=\"foo.png\" width=\"11em\" height=\"17%\"/>";
159         assertEquals(expected, img.asXml().trim());
160     }
161 
162     /**
163      * Test case for issue #1833.
164      * Simply save the image without any parsing.
165      *
166      * @throws Exception if the test fails
167      */
168     @Test
169     public void saveAsNotSupportedImageType() throws Exception {
170         try (InputStream is = getClass().getClassLoader().
171                 getResourceAsStream("testfiles/not_supported_type.jpg")) {
172             final byte[] directBytes = IOUtils.toByteArray(is);
173             final URL urlImage = new URL(URL_FIRST, "img.jpg");
174             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
175         }
176 
177         final String html = DOCTYPE_HTML
178             + "<html><head>\n"
179             + "</head>\n"
180             + "<body>\n"
181             + "  <img id='myImage' src='img.jpg' >\n"
182             + "</body></html>";
183 
184         final HtmlPage page = loadPage(html);
185 
186         final HtmlImage img = page.getHtmlElementById("myImage");
187         final File tempFile = File.createTempFile("img", ".tmp");
188         img.saveAs(tempFile);
189         FileUtils.deleteQuietly(tempFile);
190     }
191 
192     /**
193      * @throws Exception if the test fails
194      */
195     @Test
196     public void determineWidthHeightFromImage() throws Exception {
197         try (InputStream is = getClass().getClassLoader().
198                 getResourceAsStream("testfiles/4x7.jpg")) {
199             final byte[] directBytes = IOUtils.toByteArray(is);
200             final URL urlImage = new URL(URL_FIRST, "4x7.jpg");
201             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
202         }
203         try (InputStream is = getClass().getClassLoader().
204                 getResourceAsStream("testfiles/tiny-jpg.img")) {
205             final byte[] directBytes = IOUtils.toByteArray(is);
206             final URL urlImage = new URL(URL_FIRST, "img.jpg");
207             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
208         }
209 
210         final String html = DOCTYPE_HTML
211             + "<html><head>\n"
212             + "</head>\n"
213             + "<body>\n"
214             + "  <img id='myImage' src='4x7.jpg' >\n"
215             + "</body></html>";
216 
217         final HtmlPage page = loadPage(html);
218 
219         final HtmlImage img = page.getHtmlElementById("myImage");
220         assertEquals(4, img.getWidth());
221         assertEquals(7, img.getHeight());
222 
223         // source change has to force new determination
224         img.setAttribute("src", "img.jpg");
225         assertEquals(1, img.getWidth());
226         assertEquals(1, img.getHeight());
227     }
228 
229     /**
230      * @throws Exception on test failure
231      */
232     @Test
233     @Alerts(DEFAULT = {"16", "16", "2"},
234             FF = {"24", "24", "2"},
235             FF_ESR = {"24", "24", "2"})
236     public void retrieveImagePerDefault() throws Exception {
237         final String html = DOCTYPE_HTML
238                 + "<html>\n"
239                 + "<head></head>\n"
240                 + "<body>\n"
241                 + "  <img id='myImage' src='4x7.jpg' >\n"
242                 + "</body></html>";
243 
244         final int count = getMockWebConnection().getRequestCount();
245 
246         final HtmlPage page = loadPage(html);
247         final HtmlImage img = page.getHtmlElementById("myImage");
248         assertEquals(Integer.parseInt(getExpectedAlerts()[0]), img.getWidthOrDefault());
249         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), img.getHeightOrDefault());
250 
251         assertEquals(Integer.parseInt(getExpectedAlerts()[2]), getMockWebConnection().getRequestCount() - count);
252     }
253 
254     /**
255      * @throws Exception on test failure
256      */
257     @Test
258     @Alerts({"4x7.jpg", "§§URL§§4x7.jpg"})
259     public void src() throws Exception {
260         final String html = DOCTYPE_HTML
261                 + "<html>\n"
262                 + "<head></head>\n"
263                 + "<body>\n"
264                 + "  <img id='myImage' src='4x7.jpg' >\n"
265                 + "</body></html>";
266 
267         final HtmlPage page = loadPage(html);
268         final HtmlImage img = page.getHtmlElementById("myImage");
269 
270         expandExpectedAlertsVariables(URL_FIRST);
271         assertEquals(getExpectedAlerts()[0], img.getSrcAttribute());
272         assertEquals(getExpectedAlerts()[1], img.getSrc());
273     }
274 
275     /**
276      * @throws Exception if the test fails
277      */
278     @Test
279     @Alerts({"8-8-18-18-", "10-15-18-18-"})
280     public void clickWithCoordinates() throws Exception {
281         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-gif.img")) {
282             final byte[] directBytes = IOUtils.toByteArray(is);
283             final URL urlImage = new URL(URL_SECOND, "img.gif");
284             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok",
285                     MimeType.IMAGE_GIF, Collections.emptyList());
286         }
287 
288         final String html = DOCTYPE_HTML
289             + "<html><head>\n"
290             + "<script>\n"
291             + "  function log(msg) { window.document.title += msg + '-';}\n"
292             + "  function clickImage(event) {\n"
293             + "    log(event.clientX);\n"
294             + "    log(event.clientY);\n"
295             + "    log(event.screenX);\n"
296             + "    log(event.screenY);\n"
297             + "  }\n"
298             + "</script>\n"
299             + "</head>\n"
300             + "<body>\n"
301             + "  <img id='myImage' src='" + URL_SECOND + "img.gif' "
302                     + "width='100px' height='42px' onclick='clickImage(event)'>\n"
303             + "</body>\n"
304             + "</html>";
305 
306         final HtmlPage page = loadPage(html);
307         final HtmlImage img = page.getHtmlElementById("myImage");
308 
309         img.click();
310         assertEquals(getExpectedAlerts()[0], page.getTitleText());
311 
312         img.click(2, 7);
313         assertEquals(getExpectedAlerts()[0] + getExpectedAlerts()[1], page.getTitleText());
314     }
315 }