View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.html;
16  
17  import java.io.File;
18  import java.io.FileInputStream;
19  import java.io.InputStream;
20  import java.net.URL;
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.List;
24  
25  import org.apache.commons.io.IOUtils;
26  import org.htmlunit.MockWebConnection;
27  import org.htmlunit.WebDriverTestCase;
28  import org.htmlunit.junit.annotation.Alerts;
29  import org.htmlunit.junit.annotation.BuggyWebDriver;
30  import org.htmlunit.junit.annotation.HtmlUnitNYI;
31  import org.htmlunit.util.MimeType;
32  import org.junit.jupiter.api.Test;
33  import org.openqa.selenium.By;
34  import org.openqa.selenium.WebDriver;
35  import org.openqa.selenium.WebElement;
36  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
37  
38  /**
39   * Tests for {@link HTMLImageElement}.
40   *
41   * @author <a href="mailto:george@murnock.com">George Murnock</a>
42   * @author Marc Guillemot
43   * @author Ronald Brill
44   * @author Frank Danek
45   * @author Ahmed Ashour
46   */
47  public class HTMLImageElementTest extends WebDriverTestCase {
48  
49      /**
50       * @throws Exception if the test fails
51       */
52      @Test
53      @Alerts({"[object HTMLImageElement]", "[object HTMLImageElement]"})
54      public void simpleScriptable() throws Exception {
55          final String html = DOCTYPE_HTML
56              + "<html><head>\n"
57              + "<script>\n"
58              + LOG_TITLE_FUNCTION
59              + "  function test() {\n"
60              + "    log(document.getElementById('myId1'));\n"
61              + "    log(document.getElementById('myId2'));\n"
62              + "  }\n"
63              + "</script>\n"
64              + "</head><body onload='test()'>\n"
65              + "  <img id='myId1'>\n"
66              + "  <image id='myId2'>\n"
67              + "</body></html>";
68  
69          loadPageVerifyTitle2(html);
70      }
71  
72      /**
73       * @throws Exception if the test fails
74       */
75      @Test
76      @Alerts({"IMG", "IMG"})
77      public void nodeName() throws Exception {
78          final String html = DOCTYPE_HTML
79              + "<html><head>\n"
80              + "<script>\n"
81              + LOG_TITLE_FUNCTION
82              + "  function test() {\n"
83              + "    log(document.getElementById('myId1').nodeName);\n"
84              + "    log(document.getElementById('myId2').nodeName);\n"
85              + "  }\n"
86              + "</script>\n"
87              + "</head><body onload='test()'>\n"
88              + "  <img id='myId1'>\n"
89              + "  <image id='myId2'>\n"
90              + "</body></html>";
91  
92          loadPageVerifyTitle2(html);
93      }
94  
95      /**
96       * @throws Exception if the test fails
97       */
98      @Test
99      @Alerts({"IMG", "IMG"})
100     public void tagName() throws Exception {
101         final String html = DOCTYPE_HTML
102             + "<html><head>\n"
103             + "<script>\n"
104             + LOG_TITLE_FUNCTION
105             + "  function test() {\n"
106             + "    log(document.getElementById('myId1').tagName);\n"
107             + "    log(document.getElementById('myId2').tagName);\n"
108             + "  }\n"
109             + "</script>\n"
110             + "</head><body onload='test()'>\n"
111             + "  <img id='myId1'>\n"
112             + "  <image id='myId2'>\n"
113             + "</body></html>";
114 
115         loadPageVerifyTitle2(html);
116     }
117 
118     /**
119      * @throws Exception if the test fails
120      */
121     @Test
122     @Alerts(DEFAULT = {"[object HTMLImageElement]", "[object HTMLUnknownElement]", "IMG", "IMAGE",
123                        "[object HTMLImageElement]", "[object HTMLImageElement]", "IMG", "IMG"},
124             FF = {"[object HTMLImageElement]", "[object HTMLElement]", "IMG", "IMAGE",
125                   "[object HTMLImageElement]", "[object HTMLImageElement]", "IMG", "IMG"},
126             FF_ESR = {"[object HTMLImageElement]", "[object HTMLElement]", "IMG", "IMAGE",
127                       "[object HTMLImageElement]", "[object HTMLImageElement]", "IMG", "IMG"})
128     public void image() throws Exception {
129         final String html = DOCTYPE_HTML
130             + "<html><head>\n"
131             + "<script>\n"
132             + LOG_TITLE_FUNCTION
133             + "  function test() {\n"
134             + "    log(document.createElement('img'));\n"
135             + "    log(document.createElement('image'));\n"
136             + "    log(document.createElement('img').nodeName);\n"
137             + "    log(document.createElement('image').nodeName);\n"
138             + "    log(document.getElementById('myId1'));\n"
139             + "    log(document.getElementById('myId2'));\n"
140             + "    log(document.getElementById('myId1').nodeName);\n"
141             + "    log(document.getElementById('myId2').nodeName);\n"
142             + "  }\n"
143             + "</script>\n"
144             + "</head><body onload='test()'>\n"
145             + "  <img id='myId1'>\n"
146             + "  <image id='myId2'>\n"
147             + "</body></html>";
148 
149         loadPageVerifyTitle2(html);
150     }
151 
152     /**
153      * @throws Exception if the test fails
154      */
155     @Test
156     @Alerts({"", "undefined", "", ""})
157     public void src() throws Exception {
158         final String html = DOCTYPE_HTML
159             + "<html><head>\n"
160             + "<script>\n"
161             + LOG_TITLE_FUNCTION
162             + "  function test() {\n"
163             + "    log(document.createElement('img').src);\n"
164             + "    log(document.createElement('image').src);\n"
165             + "    log(document.getElementById('myId1').src);\n"
166             + "    log(document.getElementById('myId2').src);\n"
167             + "  }\n"
168             + "</script>\n"
169             + "</head><body onload='test()'>\n"
170             + "  <img id='myId1'>\n"
171             + "  <image id='myId2'>\n"
172             + "</body></html>";
173 
174         loadPageVerifyTitle2(html);
175     }
176 
177     /**
178      * This test verifies that JavaScript can be used to get the <tt>src</tt> attribute of an <tt>&lt;img&gt;</tt> tag.
179      * @throws Exception if the test fails
180      */
181     @Test
182     @Alerts("§§URL§§foo.gif")
183     public void getSrc() throws Exception {
184         final String html = DOCTYPE_HTML
185             + "<html><head>\n"
186             + "<script>\n"
187             + LOG_TITLE_FUNCTION
188             + "function doTest() {\n"
189             + "  log(document.getElementById('anImage').src);\n"
190             + "}\n"
191             + "</script></head><body onload='doTest()'>\n"
192             + "<img src='foo.gif' id='anImage'/>\n"
193             + "</body></html>";
194 
195         getMockWebConnection().setDefaultResponse(""); // to have a dummy response for the image
196         expandExpectedAlertsVariables(URL_FIRST);
197         loadPageVerifyTitle2(html);
198     }
199 
200     /**
201      * @throws Exception if the test fails
202      */
203     @Test
204     @Alerts("")
205     public void getSrc_newImage_srcNotSet() throws Exception {
206         final String html = DOCTYPE_HTML
207             + "<html><head>\n"
208             + "<script>\n"
209             + LOG_TITLE_FUNCTION
210             + "function doTest() {\n"
211             + "  var oImg = new Image();\n"
212             + "  log(oImg.src);\n"
213             + "}\n"
214             + "</script></head><body onload='doTest()'>\n"
215             + "</body></html>";
216 
217         loadPageVerifyTitle2(html);
218     }
219 
220     /**
221      * This test verifies that when JavaScript is used to modify the <tt>src</tt> attribute, the value is
222      * persisted to the corresponding <tt>&lt;img&gt;</tt> node in the DOM tree.
223      * @throws Exception if the test fails
224      */
225     @Test
226     public void setSrc() throws Exception {
227         final String html = DOCTYPE_HTML
228             + "<html><head><script>\n"
229             + "function doTest() {\n"
230             + "  document.getElementById('anImage').src = 'bar.gif';\n"
231             + "}\n"
232             + "</script></head><body onload='doTest()'>\n"
233             + "<img src='foo.gif' id='anImage'/>\n"
234             + "</body></html>";
235         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
236 
237         final WebDriver driver = loadPage2(html);
238         final WebElement image = driver.findElement(By.id("anImage"));
239         assertEquals(URL_FIRST + "bar.gif", image.getAttribute("src"));
240     }
241 
242     /**
243      * JavaScript can be used to preload images, as follows:
244      * <code>var newImage = new Image(); newImage.src = 'foo.gif';</code>.
245      * When <code>new Image()</code> is called, HtmlUnit creates a new JavaScript
246      * Image object. However, no corresponding DOM node is created, which is
247      * just as well, since browsers don't create one either.
248      * This test verifies that the above JavaScript code can be invoked without
249      * throwing an "IllegalStateException: DomNode has not been set for this
250      * SimpleScriptable."
251      * @throws Exception if the test fails
252      */
253     @Test
254     @Alerts({"onLoad", "§§URL§§bar.gif"})
255     public void setSrc_newImage() throws Exception {
256         final String html = DOCTYPE_HTML
257             + "<html><head>\n"
258             + "<script>\n"
259             + LOG_TITLE_FUNCTION
260             + "function doTest() {\n"
261             + "  var preloadImage = new Image();\n"
262             + "  preloadImage.onload = log('onLoad');\n"
263             + "  preloadImage.src = 'bar.gif';\n"
264             + "  log(preloadImage.src);\n"
265             + "}\n"
266             + "</script></head><body onload='doTest()'>\n"
267             + "</body></html>";
268 
269         getMockWebConnection().setDefaultResponse(""); // to have a dummy response for the image
270         expandExpectedAlertsVariables(URL_FIRST);
271         loadPageVerifyTitle2(html);
272     }
273 
274     /**
275      * @throws Exception if the test fails
276      */
277     @Test
278     @Alerts("foo")
279     public void attributeName() throws Exception {
280         final String html = DOCTYPE_HTML
281             + "<html><head>\n"
282             + "<script>\n"
283             + LOG_TITLE_FUNCTION
284             + "function test() {\n"
285             + "  var oImg = document.getElementById('myImage');\n"
286             + "  oImg.name = 'foo';\n"
287             + "  log(oImg.name);\n"
288             + "}\n"
289             + "</script></head><body onload='test()'>\n"
290             + "<img src='foo.png' id='myImage'>\n"
291             + "</body></html>";
292 
293         getMockWebConnection().setDefaultResponse(""); // to have a dummy response for the image
294         loadPageVerifyTitle2(html);
295     }
296 
297     /**
298      * @throws Exception if an error occurs
299      */
300     @Test
301     public void onLoad_BadUrl() throws Exception {
302         final String html = DOCTYPE_HTML
303                 + "<html><body><img src='http:// [/url]http://x.com/a/b' onload='alert(1)'/></body></html>";
304         loadPageWithAlerts2(html);
305     }
306 
307     /**
308      * @throws Exception if the test fails
309      */
310     @Test
311     @Alerts({"true", "relative", "", ""})
312     public void newImage() throws Exception {
313         final String html = DOCTYPE_HTML
314             + "<html><head>\n"
315             + "<script>\n"
316             + LOG_TITLE_FUNCTION
317             + "function doTest() {\n"
318             + "  var i = new Image();\n"
319             + "  log(i.style != null);\n"
320             + "  i.style.position = 'relative';\n"
321             + "  log(i.style.position);\n"
322             + "  log(i.border);\n"
323             + "  log(i.alt);\n"
324             + "}\n"
325             + "</script></head><body onload='doTest()'>\n"
326             + "</body></html>";
327 
328         loadPageVerifyTitle2(html);
329     }
330 
331     /**
332      * @throws Exception if an error occurs
333      */
334     @Test
335     @Alerts(DEFAULT = {"left", "right", "center", "justify", "bottom", "middle",
336                        "top", "absbottom", "absmiddle", "baseline", "texttop", "wrong", ""},
337             FF = {"left", "right", "middle", "justify", "bottom", "middle",
338                   "top", "absbottom", "absmiddle", "bottom", "texttop", "wrong", ""},
339             FF_ESR = {"left", "right", "middle", "justify", "bottom", "middle",
340                       "top", "absbottom", "absmiddle", "bottom", "texttop", "wrong", ""})
341     @HtmlUnitNYI(FF = {"left", "right", "center", "justify", "bottom", "middle",
342                        "top", "absbottom", "absmiddle", "baseline", "texttop", "wrong", ""},
343             FF_ESR = {"left", "right", "center", "justify", "bottom", "middle",
344                       "top", "absbottom", "absmiddle", "baseline", "texttop", "wrong", ""})
345     public void getAlign() throws Exception {
346         final String html = DOCTYPE_HTML
347             + "<html><body>\n"
348             + "  <img id='i1' align='left' />\n"
349             + "  <img id='i2' align='right' />\n"
350             + "  <img id='i3' align='center' />\n"
351             + "  <img id='i4' align='justify' />\n"
352             + "  <img id='i5' align='bottom' />\n"
353             + "  <img id='i6' align='middle' />\n"
354             + "  <img id='i7' align='top' />\n"
355             + "  <img id='i8' align='absbottom' />\n"
356             + "  <img id='i9' align='absmiddle' />\n"
357             + "  <img id='i10' align='baseline' />\n"
358             + "  <img id='i11' align='texttop' />\n"
359             + "  <img id='i12' align='wrong' />\n"
360             + "  <img id='i13' />\n"
361 
362             + "<script>\n"
363             + LOG_TITLE_FUNCTION
364             + "  for (var i = 1; i <= 13; i++) {\n"
365             + "    log(document.getElementById('i' + i).align);\n"
366             + "  }\n"
367             + "</script>\n"
368             + "</body></html>";
369 
370         loadPageVerifyTitle2(html);
371     }
372 
373     /**
374      * @throws Exception if an error occurs
375      */
376     @Test
377     @Alerts(DEFAULT = {"CenTer", "8", "foo", "left", "right", "center", "justify",
378                        "bottom", "middle", "top", "absbottom", "absmiddle", "baseline", "texttop"},
379             FF = {"CenTer", "8", "foo", "left", "right", "middle", "justify",
380                   "bottom", "middle", "top", "absbottom", "absmiddle", "bottom", "texttop"},
381             FF_ESR = {"CenTer", "8", "foo", "left", "right", "middle", "justify",
382                       "bottom", "middle", "top", "absbottom", "absmiddle", "bottom", "texttop"})
383     @HtmlUnitNYI(FF = {"CenTer", "8", "foo", "left", "right", "center", "justify",
384                        "bottom", "middle", "top", "absbottom", "absmiddle", "baseline", "texttop"},
385             FF_ESR = {"CenTer", "8", "foo", "left", "right", "center", "justify",
386                       "bottom", "middle", "top", "absbottom", "absmiddle", "baseline", "texttop"})
387     public void setAlign() throws Exception {
388         final String html = DOCTYPE_HTML
389             + "<html><body>\n"
390             + "  <img id='i1' align='left' />\n"
391 
392             + "<script>\n"
393             + LOG_TITLE_FUNCTION
394             + "  function setAlign(elem, value) {\n"
395             + "    try {\n"
396             + "      elem.align = value;\n"
397             + "    } catch(e) { logEx(e); }\n"
398             + "    log(elem.align);\n"
399             + "  }\n"
400 
401             + "  var elem = document.getElementById('i1');\n"
402             + "  setAlign(elem, 'CenTer');\n"
403 
404             + "  setAlign(elem, '8');\n"
405             + "  setAlign(elem, 'foo');\n"
406 
407             + "  setAlign(elem, 'left');\n"
408             + "  setAlign(elem, 'right');\n"
409             + "  setAlign(elem, 'center');\n"
410             + "  setAlign(elem, 'justify');\n"
411             + "  setAlign(elem, 'bottom');\n"
412             + "  setAlign(elem, 'middle');\n"
413             + "  setAlign(elem, 'top');\n"
414             + "  setAlign(elem, 'absbottom');\n"
415             + "  setAlign(elem, 'absmiddle');\n"
416             + "  setAlign(elem, 'baseline');\n"
417             + "  setAlign(elem, 'texttop');\n"
418             + "</script>\n"
419             + "</body></html>";
420         loadPageVerifyTitle2(html);
421     }
422 
423     /**
424      * Test image's width and height.
425      * Regression test for bug
426      * <a href="http://sourceforge.net/tracker/?func=detail&atid=448266&aid=2861064&group_id=47038">issue 915</a>
427      * @throws Exception if the test fails
428      */
429     @Test
430     @Alerts({"number: 300", "number: 200", "number: 0", "number: 0", "number: 0", "number: 0"})
431     public void widthHeightWithoutSource() throws Exception {
432         final String html = DOCTYPE_HTML
433             + "<html><head>\n"
434             + "<script>\n"
435             + LOG_TITLE_FUNCTION
436             + "  function showInfo(imageId) {\n"
437             + "    var img = document.getElementById(imageId);\n"
438             + "    log(typeof(img.width) + ': ' + img.width);\n"
439             + "    log(typeof(img.height) + ': ' + img.height);\n"
440             + "  }\n"
441             + "  function test() {\n"
442             + "    showInfo('myImage1');\n"
443             + "    showInfo('myImage2');\n"
444             + "    showInfo('myImage3');\n"
445             + "  }\n"
446             + "</script>\n"
447             + "</head><body onload='test()'>\n"
448             + "  <img id='myImage1' width='300' height='200'>\n"
449             + "  <img id='myImage2'>\n"
450             + "  <img id='myImage3' width='hello' height='hello'>\n"
451             + "</body></html>";
452 
453         loadPageVerifyTitle2(html);
454     }
455 
456     /**
457      * Test that image's width and height are numbers.
458      * @throws Exception if the test fails
459      */
460     @Test
461     @Alerts({"number: 300", "number: 200", "number: 1", "number: 1", "number: 1", "number: 1"})
462     public void widthHeightWithSource() throws Exception {
463         getMockWebConnection().setDefaultResponse("");
464 
465         final String html = DOCTYPE_HTML
466             + "<html><head>\n"
467             + "<script>\n"
468             + LOG_TITLE_FUNCTION
469             + "  function showInfo(imageId) {\n"
470             + "    var img = document.getElementById(imageId);\n"
471             + "    log(typeof(img.width) + ': ' + img.width);\n"
472             + "    log(typeof(img.height) + ': ' + img.height);\n"
473             + "  }\n"
474             + "  function test() {\n"
475             + "    showInfo('myImage1');\n"
476             + "    showInfo('myImage2');\n"
477             + "    showInfo('myImage3');\n"
478             + "  }\n"
479             + "</script>\n"
480             + "</head><body onload='test()'>\n"
481             + "  <img id='myImage1' src='" + URL_SECOND + "' width='300' height='200'>\n"
482             + "  <img id='myImage2' src='" + URL_SECOND + "' >\n"
483             + "  <img id='myImage3' src='" + URL_SECOND + "' width='hello' height='hello'>\n"
484             + "</body></html>";
485 
486         final URL url = getClass().getClassLoader().getResource("testfiles/tiny-jpg.img");
487         try (FileInputStream fis = new FileInputStream(new File(url.toURI()))) {
488             final byte[] directBytes = IOUtils.toByteArray(fis);
489 
490             final MockWebConnection webConnection = getMockWebConnection();
491             webConnection.setResponse(URL_SECOND, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
492         }
493 
494         loadPageVerifyTitle2(html);
495     }
496 
497     /**
498      * Test that image's width and height are numbers.
499      * @throws Exception if the test fails
500      */
501     @Test
502     @Alerts({"number: 300", "number: 200", "number: 0", "number: 0", "number: 0", "number: 0"})
503     public void widthHeightEmptySource() throws Exception {
504         getMockWebConnection().setDefaultResponse("");
505 
506         final String html = DOCTYPE_HTML
507             + "<html><head>\n"
508             + "<script>\n"
509             + LOG_TITLE_FUNCTION
510             + "  function showInfo(imageId) {\n"
511             + "    var img = document.getElementById(imageId);\n"
512             + "    log(typeof(img.width) + ': ' + img.width);\n"
513             + "    log(typeof(img.height) + ': ' + img.height);\n"
514             + "  }\n"
515             + "  function test() {\n"
516             + "    showInfo('myImage1');\n"
517             + "    showInfo('myImage2');\n"
518             + "    showInfo('myImage3');\n"
519             + "  }\n"
520             + "</script>\n"
521             + "</head><body onload='test()'>\n"
522             + "  <img id='myImage1' src='' width='300' height='200'>\n"
523             + "  <img id='myImage2' src='' >\n"
524             + "  <img id='myImage3' src='' width='hello' height='hello'>\n"
525             + "</body></html>";
526 
527         final URL url = getClass().getClassLoader().getResource("testfiles/tiny-jpg.img");
528         try (FileInputStream fis = new FileInputStream(new File(url.toURI()))) {
529             final byte[] directBytes = IOUtils.toByteArray(fis);
530             final MockWebConnection webConnection = getMockWebConnection();
531             webConnection.setResponse(URL_SECOND, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
532         }
533 
534         loadPageVerifyTitle2(html);
535     }
536 
537     /**
538      * Test that image's width and height are numbers.
539      * @throws Exception if the test fails
540      */
541     @Test
542     @Alerts(DEFAULT = {"number: 300", "number: 200", "number: 24", "number: 24", "number: 24", "number: 24"},
543             CHROME = {"number: 300", "number: 200", "number: 0", "number: 0", "number: 0", "number: 0"},
544             EDGE = {"number: 300", "number: 200", "number: 0", "number: 0", "number: 0", "number: 0"})
545     public void widthHeightBlankSource() throws Exception {
546         getMockWebConnection().setDefaultResponse("");
547 
548         final String html = DOCTYPE_HTML
549             + "<html><head>\n"
550             + "<script>\n"
551             + LOG_TITLE_FUNCTION
552             + "  function showInfo(imageId) {\n"
553             + "    var img = document.getElementById(imageId);\n"
554             + "    log(typeof(img.width) + ': ' + img.width);\n"
555             + "    log(typeof(img.height) + ': ' + img.height);\n"
556             + "  }\n"
557             + "  function test() {\n"
558             + "    showInfo('myImage1');\n"
559             + "    showInfo('myImage2');\n"
560             + "    showInfo('myImage3');\n"
561             + "  }\n"
562             + "</script>\n"
563             + "</head><body onload='test()'>\n"
564             + "  <img id='myImage1' src=' ' width='300' height='200'>\n"
565             + "  <img id='myImage2' src=' ' >\n"
566             + "  <img id='myImage3' src=' ' width='hello' height='hello'>\n"
567             + "</body></html>";
568 
569         final URL url = getClass().getClassLoader().getResource("testfiles/tiny-jpg.img");
570         try (FileInputStream fis = new FileInputStream(new File(url.toURI()))) {
571             final byte[] directBytes = IOUtils.toByteArray(fis);
572             final MockWebConnection webConnection = getMockWebConnection();
573             webConnection.setResponse(URL_SECOND, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
574         }
575 
576         loadPageVerifyTitle2(html);
577     }
578 
579     /**
580      * Test that image's width and height are numbers.
581      * @throws Exception if the test fails
582      */
583     @Test
584     @Alerts(DEFAULT = {"number: 300", "number: 200", "number: 24", "number: 24", "number: 24", "number: 24"},
585             CHROME = {"number: 300", "number: 200", "number: 16", "number: 16", "number: 16", "number: 16"},
586             EDGE = {"number: 300", "number: 200", "number: 16", "number: 16", "number: 16", "number: 16"})
587     public void widthHeightInvalidSource() throws Exception {
588         getMockWebConnection().setDefaultResponse("");
589 
590         final String html = DOCTYPE_HTML
591             + "<html><head>\n"
592             + "<script>\n"
593             + LOG_TITLE_FUNCTION
594             + "  function showInfo(imageId) {\n"
595             + "    var img = document.getElementById(imageId);\n"
596             + "    log(typeof(img.width) + ': ' + img.width);\n"
597             + "    log(typeof(img.height) + ': ' + img.height);\n"
598             + "  }\n"
599             + "  function test() {\n"
600             + "    showInfo('myImage1');\n"
601             + "    showInfo('myImage2');\n"
602             + "    showInfo('myImage3');\n"
603             + "  }\n"
604             + "</script>\n"
605             + "</head><body onload='test()'>\n"
606             + "  <img id='myImage1' src='" + URL_SECOND + "' width='300' height='200'>\n"
607             + "  <img id='myImage2' src='" + URL_SECOND + "' >\n"
608             + "  <img id='myImage3' src='" + URL_SECOND + "' width='hello' height='hello'>\n"
609             + "</body></html>";
610 
611         loadPageVerifyTitle2(html);
612     }
613 
614     /**
615      * @throws Exception if the test fails
616      */
617     @Test
618     @Alerts({"true", "true", "true", "true"})
619     public void complete() throws Exception {
620         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
621             final byte[] directBytes = IOUtils.toByteArray(is);
622 
623             final URL urlImage = new URL(URL_SECOND, "img.jpg");
624             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
625             getMockWebConnection().setDefaultResponse("Test");
626         }
627 
628         final String html = DOCTYPE_HTML
629             + "<html><head>\n"
630             + "<script>\n"
631             + LOG_TITLE_FUNCTION
632             + "  function showInfo(imageId) {\n"
633             + "    var img = document.getElementById(imageId);\n"
634             + "    log(img.complete);\n"
635             + "  }\n"
636             + "  function test() {\n"
637             + "    showInfo('myImage1');\n"
638             + "    showInfo('myImage2');\n"
639             + "    showInfo('myImage3');\n"
640             + "    showInfo('myImage4');\n"
641             + "  }\n"
642             + "</script>\n"
643             + "</head><body onload='test()'>\n"
644             + "  <img id='myImage1' >\n"
645             + "  <img id='myImage2' src=''>\n"
646             + "  <img id='myImage3' src='" + URL_SECOND + "'>\n"
647             + "  <img id='myImage4' src='" + URL_SECOND + "img.jpg'>\n"
648             + "</body></html>";
649         final WebDriver driver = getWebDriver();
650         if (driver instanceof HtmlUnitDriver) {
651             ((HtmlUnitDriver) driver).setDownloadImages(true);
652         }
653 
654         loadPageVerifyTitle2(html);
655     }
656 
657     /**
658      * @throws Exception if the test fails
659      */
660     @Test
661     @Alerts(DEFAULT = {"error2;error3;error4;load5;", "3"},
662             FF = {"error2;error3;error4;load5;", "4"},
663             FF_ESR = {"error2;error3;error4;load5;", "4"})
664     // at the moment we do not check the image content
665     @HtmlUnitNYI(CHROME = {"error2;error3;load4;load5;", "3"},
666             EDGE = {"error2;error3;load4;load5;", "3"},
667             FF = {"error2;load3;load4;load5;", "4"},
668             FF_ESR = {"error2;load3;load4;load5;", "4"})
669     public void onload() throws Exception {
670         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
671             final byte[] directBytes = IOUtils.toByteArray(is);
672 
673             final URL urlImage = new URL(URL_SECOND, "img.jpg");
674             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
675             getMockWebConnection().setResponse(URL_SECOND, "Test", 200, "OK",
676                     MimeType.TEXT_HTML, Collections.emptyList());
677             getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
678         }
679 
680         final String html = DOCTYPE_HTML
681             + "<html><head>\n"
682             + "<script>\n"
683             + "  function showInfo(text) {\n"
684             + "    document.title += text + ';';\n"
685             + "  }\n"
686             + "</script>\n"
687             + "</head><body>\n"
688             + "  <img id='myImage1' onload='showInfo(\"load1\")' onerror='showInfo(\"error1\")'>\n"
689             + "  <img id='myImage2' src='' onload='showInfo(\"load2\")' onerror='showInfo(\"error2\")'>\n"
690             + "  <img id='myImage3' src='  ' onload='showInfo(\"load3\")' onerror='showInfo(\"error3\")'>\n"
691             + "  <img id='myImage4' src='" + URL_SECOND + "' onload='showInfo(\"load4\")' "
692                     + "onerror='showInfo(\"error4\")'>\n"
693             + "  <img id='myImage5' src='" + URL_SECOND + "img.jpg' onload='showInfo(\"load5\")' "
694                     + "onerror='showInfo(\"error5\")'>\n"
695             + "</body></html>";
696 
697         final int count = getMockWebConnection().getRequestCount();
698         final WebDriver driver = getWebDriver();
699         if (driver instanceof HtmlUnitDriver) {
700             ((HtmlUnitDriver) driver).setDownloadImages(true);
701         }
702         loadPage2(html);
703 
704         assertTitle(driver, getExpectedAlerts()[0]);
705         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
706     }
707 
708     /**
709      * @throws Exception if the test fails
710      */
711     @Test
712     @Alerts({"load;", "2"})
713     public void emptyMimeType() throws Exception {
714         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
715             final byte[] directBytes = IOUtils.toByteArray(is);
716 
717             final URL urlImage = new URL(URL_SECOND, "img.jpg");
718             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "", Collections.emptyList());
719             getMockWebConnection().setDefaultResponse("Test");
720         }
721 
722         final String html = DOCTYPE_HTML
723             + "<html><head>\n"
724             + "<script>\n"
725             + "  function showInfo(text) {\n"
726             + "    document.title += text + ';';\n"
727             + "  }\n"
728             + "</script>\n"
729             + "</head><body>\n"
730             + "  <img id='myImage5' src='" + URL_SECOND + "img.jpg' onload='showInfo(\"load\")' "
731                     + "onerror='showInfo(\"error\")'>\n"
732             + "</body></html>";
733 
734         final int count = getMockWebConnection().getRequestCount();
735         final WebDriver driver = getWebDriver();
736         if (driver instanceof HtmlUnitDriver) {
737             ((HtmlUnitDriver) driver).setDownloadImages(true);
738         }
739         loadPage2(html);
740 
741         assertTitle(driver, getExpectedAlerts()[0]);
742         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
743     }
744 
745     /**
746      * @throws Exception if the test fails
747      */
748     @Test
749     @Alerts({"load;", "2"})
750     public void wrongMimeType() throws Exception {
751         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
752             final byte[] directBytes = IOUtils.toByteArray(is);
753 
754             final URL urlImage = new URL(URL_SECOND, "img.jpg");
755             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "text/html", Collections.emptyList());
756             getMockWebConnection().setDefaultResponse("Test");
757         }
758 
759         final String html = DOCTYPE_HTML
760             + "<html><head>\n"
761             + "<script>\n"
762             + "  function showInfo(text) {\n"
763             + "    document.title += text + ';';\n"
764             + "  }\n"
765             + "</script>\n"
766             + "</head><body>\n"
767             + "  <img id='myImage5' src='" + URL_SECOND + "img.jpg' onload='showInfo(\"load\")' "
768                     + "onerror='showInfo(\"error\")'>\n"
769             + "</body></html>";
770 
771         final int count = getMockWebConnection().getRequestCount();
772         final WebDriver driver = getWebDriver();
773         if (driver instanceof HtmlUnitDriver) {
774             ((HtmlUnitDriver) driver).setDownloadImages(true);
775         }
776         loadPage2(html);
777 
778         assertTitle(driver, getExpectedAlerts()[0]);
779         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
780     }
781 
782     /**
783      * @throws Exception if an error occurs
784      */
785     @Test
786     @Alerts({"test", "string", "hui", "", "null", "false", "true", ""})
787     public void alt() throws Exception {
788         final String html = DOCTYPE_HTML
789             + "<html>\n"
790             + "  <head>\n"
791             + "    <script>\n"
792             + LOG_TITLE_FUNCTION
793             + "      function test() {\n"
794             + "        var testImg = document.getElementById('myImage');\n"
795             + "        log(testImg.alt);\n"
796             + "        log(typeof testImg.alt);\n"
797 
798             + "        testImg.alt = 'hui';\n"
799             + "        log(testImg.alt);\n"
800 
801             + "        testImg.alt = '';\n"
802             + "        log(testImg.alt);\n"
803 
804             + "        testImg.alt = null;\n"
805             + "        log(testImg.alt);\n"
806             + "        log(testImg.alt === null);\n"
807             + "        log(testImg.alt === 'null');\n"
808 
809             + "        var testImg = document.getElementById('myImageWithoutAlt');\n"
810             + "        log(testImg.alt);\n"
811             + "      }\n"
812             + "    </script>\n"
813             + "  </head>\n"
814             + "  <body onload='test()'>\n"
815             + "    <img id='myImage' src='" + URL_SECOND + "' alt='test'>\n"
816             + "    <img id='myImageWithoutAlt' src='" + URL_SECOND + "'>\n"
817             + "  </body>\n"
818             + "</html>";
819         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
820 
821         loadPageVerifyTitle2(html);
822     }
823 
824     /**
825      * @throws Exception if the test fails
826      */
827     @Test
828     @Alerts({"myImage clicked", "myImageNone clicked"})
829     public void click() throws Exception {
830         final String html = DOCTYPE_HTML
831             + "<html><head>\n"
832             + "<script>\n"
833             + LOG_TITLE_FUNCTION
834             + "  function test() {\n"
835             + "    document.getElementById('myImage').click();\n"
836             + "    document.getElementById('myImageNone').click();\n"
837             + "  }\n"
838             + "</script>\n"
839             + "</head><body onload='test()'>\n"
840             + "  <img id='myImage' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
841                                     + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='"
842                             + " onclick='log(\"myImage clicked\");'>\n"
843             + "  <img id='myImageNone' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
844                                     + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='"
845                             + " style='display: none' onclick='log(\"myImageNone clicked\");'>\n"
846             + "</body></html>";
847 
848         loadPageVerifyTitle2(html);
849     }
850 
851     /**
852      * @throws Exception if the test fails
853      */
854     @Test
855     @Alerts("myImageWithMap clicked")
856     public void clickWithMap() throws Exception {
857         final String html = DOCTYPE_HTML
858             + "<html><head>\n"
859             + "<script>\n"
860             + LOG_TITLE_FUNCTION
861             + "  function test() {\n"
862             + "    document.getElementById('myImageWithMap').click();\n"
863             + "  }\n"
864             + "</script>\n"
865             + "</head><body onload='test()'>\n"
866             + "  <img id='myImageWithMap' usemap='#dot'"
867                                 + " src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAA"
868                                 + "HElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='"
869                             + " onclick='log(\"myImageWithMap clicked\");'>\n"
870                 + "  <map name='dot'>\n"
871                 + "    <area id='a0' shape='rect' coords='0 0 7 7' onclick='log(\"a0 clicked\");'/>\n"
872                 + "    <area id='a1' shape='rect' coords='0,0,1,1' onclick='log(\"a1 clicked\");'/>\n"
873                 + "  <map>\n"
874             + "</body></html>";
875 
876         loadPageVerifyTitle2(html);
877     }
878 
879     /**
880      * @throws Exception if an error occurs
881      */
882     @Test
883     @Alerts({"done;", "2"})
884     public void img_download() throws Exception {
885         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
886             final byte[] directBytes = IOUtils.toByteArray(is);
887             final URL urlImage = new URL(URL_FIRST, "img.jpg");
888             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
889         }
890 
891         final String html = DOCTYPE_HTML
892             + "<html><body>\n"
893             + "<script>\n"
894             + "  var i = new Image();\n"
895             + "  i.src = 'img.jpg';\n"
896             + "  document.title += 'done;';\n"
897             + "</script></body></html>";
898 
899         final int count = getMockWebConnection().getRequestCount();
900         final WebDriver driver = getWebDriver();
901         if (driver instanceof HtmlUnitDriver) {
902             ((HtmlUnitDriver) driver).setDownloadImages(true);
903         }
904         loadPage2(html);
905 
906         assertTitle(driver, getExpectedAlerts()[0]);
907         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
908         assertEquals(URL_FIRST + "img.jpg", getMockWebConnection().getLastWebRequest().getUrl());
909     }
910 
911     /**
912      * @throws Exception if an error occurs
913      */
914     @Test
915     @Alerts({"done;onload;", "2"})
916     public void img_download_onloadBefore() throws Exception {
917         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
918             final byte[] directBytes = IOUtils.toByteArray(is);
919             final URL urlImage = new URL(URL_FIRST, "img.jpg");
920             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
921         }
922 
923         final String html = DOCTYPE_HTML
924             + "<html><body>\n"
925             + "<script>\n"
926             + "  var i = new Image();\n"
927             + "  i.onload = function() { document.title += 'onload;'; };\n"
928             + "  i.src = 'img.jpg';\n"
929             + "  document.title += 'done;';\n"
930             + "</script></body></html>";
931 
932         final int count = getMockWebConnection().getRequestCount();
933         final WebDriver driver = getWebDriver();
934         if (driver instanceof HtmlUnitDriver) {
935             ((HtmlUnitDriver) driver).setDownloadImages(true);
936         }
937         loadPage2(html);
938 
939         assertTitle(driver, getExpectedAlerts()[0]);
940         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
941         assertEquals(URL_FIRST + "img.jpg", getMockWebConnection().getLastWebRequest().getUrl());
942     }
943 
944     /**
945      * @throws Exception if an error occurs
946      */
947     @Test
948     @Alerts({"done;onload;", "2"})
949     public void img_download_onloadAfter() throws Exception {
950         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
951             final byte[] directBytes = IOUtils.toByteArray(is);
952             final URL urlImage = new URL(URL_FIRST, "img.jpg");
953             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
954         }
955 
956         final String html = DOCTYPE_HTML
957             + "<html><body>\n"
958             + "<script>\n"
959             + "  var i = new Image();\n"
960             + "  i.src = 'img.jpg';\n"
961             + "  document.title += 'done;';\n"
962             + "  i.onload = function() { document.title += 'onload;'; };\n"
963             + "</script></body></html>";
964 
965         final int count = getMockWebConnection().getRequestCount();
966         final WebDriver driver = getWebDriver();
967         if (driver instanceof HtmlUnitDriver) {
968             ((HtmlUnitDriver) driver).setDownloadImages(true);
969         }
970         loadPage2(html);
971 
972         assertTitle(driver, getExpectedAlerts()[0]);
973         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
974         assertEquals(URL_FIRST + "img.jpg", getMockWebConnection().getLastWebRequest().getUrl());
975     }
976 
977     /**
978      * Verifies that if an image has an <tt>onload</tt> attribute, it gets downloaded
979      * and the <tt>onload</tt> handler gets invoked.
980      * @throws Exception if an error occurs
981      */
982     @Test
983     @Alerts({"done;onload;", "2"})
984     public void img_onLoad_calledWhenImageDownloaded_dynamic() throws Exception {
985         // this seems to need a fresh browser to pass
986         shutDownAll();
987 
988         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
989             final byte[] directBytes = IOUtils.toByteArray(is);
990 
991             URL urlImage = new URL(URL_FIRST, "img.jpg");
992             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
993 
994             urlImage = new URL(URL_FIRST, "img2.jpg");
995             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
996         }
997 
998         final String html = DOCTYPE_HTML
999             + "<html><body>\n"
1000             + "<script>\n"
1001             + "  var i = new Image();\n"
1002             + "  i.src = 'img.jpg';\n"
1003             + "  i.src = 'img2.jpg';\n"
1004             + "  document.title += 'done;';\n"
1005             + "  i.onload = function() { document.title += 'onload;'; };\n"
1006             + "</script></body></html>";
1007 
1008         final int count = getMockWebConnection().getRequestCount();
1009         final WebDriver driver = getWebDriver();
1010         if (driver instanceof HtmlUnitDriver) {
1011             ((HtmlUnitDriver) driver).setDownloadImages(true);
1012         }
1013         loadPage2(html);
1014 
1015         assertTitle(driver, getExpectedAlerts()[0]);
1016         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
1017         assertEquals(URL_FIRST + "img2.jpg", getMockWebConnection().getLastWebRequest().getUrl());
1018     }
1019 
1020     /**
1021      * Verifies that if an image has an <tt>onload</tt> attribute, it gets downloaded
1022      * and the <tt>onload</tt> handler gets invoked.
1023      * @throws Exception if an error occurs
1024      */
1025     @Test
1026     @Alerts({"done;onload;", "2"})
1027     public void img_onLoad_calledWhenImageDownloaded_dynamic2() throws Exception {
1028         // this seems to need a fresh browser to pass
1029         shutDownAll();
1030 
1031         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1032             final byte[] directBytes = IOUtils.toByteArray(is);
1033 
1034             URL urlImage = new URL(URL_FIRST, "img.jpg");
1035             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
1036 
1037             urlImage = new URL(URL_FIRST, "img2.jpg");
1038             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
1039         }
1040 
1041         final String html = DOCTYPE_HTML
1042             + "<html><body>\n"
1043             + "<script>\n"
1044             + "  var i = new Image();\n"
1045             + "  i.onload = function() { document.title += 'onload;'; };\n"
1046             + "  i.src = 'img.jpg';\n"
1047             + "  i.src = 'img2.jpg';\n"
1048             + "  document.title += 'done;';\n"
1049             + "</script></body></html>";
1050 
1051         final int count = getMockWebConnection().getRequestCount();
1052         final WebDriver driver = getWebDriver();
1053         if (driver instanceof HtmlUnitDriver) {
1054             ((HtmlUnitDriver) driver).setDownloadImages(true);
1055         }
1056         loadPage2(html);
1057 
1058         assertTitle(driver, getExpectedAlerts()[0]);
1059         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
1060         assertEquals(URL_FIRST + "img2.jpg", getMockWebConnection().getLastWebRequest().getUrl());
1061     }
1062 
1063     /**
1064      * Verifies that if an image is created if the page is already
1065      * finished, the onload handler is called.
1066      * @throws Exception if an error occurs
1067      */
1068     @Test
1069     @Alerts({"done;onload;onload2;", "3"})
1070     public void img_onLoad_calledWhenImageDownloaded_dynamic_twoSteps() throws Exception {
1071         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1072             final byte[] directBytes = IOUtils.toByteArray(is);
1073 
1074             URL urlImage = new URL(URL_FIRST, "img.jpg");
1075             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
1076 
1077             urlImage = new URL(URL_FIRST, "img2.jpg");
1078             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
1079         }
1080 
1081         final String html = DOCTYPE_HTML
1082                 + "<html><body>\n"
1083                 + "<script>\n"
1084                 + "  var i = new Image();\n"
1085                 + "  i.src = 'img.jpg';\n"
1086                 + "  i.onload = function() {\n"
1087                 + "    document.title += 'onload;';\n"
1088                 + "    var i2 = document.createElement('img');\n"
1089                 + "    i2.src = 'img2.jpg';\n"
1090                 + "    i2.onload = function() {\n"
1091                 + "      document.title += 'onload2;';\n"
1092                 + "    };\n"
1093                 + "  };\n"
1094                 + "  document.title += 'done;';\n"
1095                 + "</script></body></html>";
1096 
1097         final int count = getMockWebConnection().getRequestCount();
1098         final WebDriver driver = getWebDriver();
1099         if (driver instanceof HtmlUnitDriver) {
1100             ((HtmlUnitDriver) driver).setDownloadImages(true);
1101         }
1102         loadPage2(html);
1103 
1104         assertTitle(driver, getExpectedAlerts()[0]);
1105         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
1106         assertEquals(URL_FIRST + "img2.jpg", getMockWebConnection().getLastWebRequest().getUrl());
1107     }
1108 
1109     /**
1110      * Verifies that if an image has an <tt>onload</tt> attribute set from a script, it gets downloaded
1111      * and the <tt>onload</tt> handler gets invoked.
1112      * @throws Exception if an error occurs
1113      */
1114     @Test
1115     @Alerts({"image one;image two;", "3"})
1116     public void img_onLoad_calledWhenImageDownloaded_mixed() throws Exception {
1117         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1118             final byte[] directBytes = IOUtils.toByteArray(is);
1119 
1120             URL urlImage = new URL(URL_FIRST, "img.jpg");
1121             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
1122 
1123             urlImage = new URL(URL_FIRST, "img2.jpg");
1124             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", Collections.emptyList());
1125         }
1126 
1127         final String html = DOCTYPE_HTML
1128                 + "<html><body><img id='img' name='img'/><script>\n"
1129                 + "  var i = new Image();\n"
1130                 + "  i.onload = function() {\n"
1131                 + "    document.title += 'image one;';\n"
1132                 + "    i.onload = function() {\n"
1133                 + "      document.title += 'image two;';\n"
1134                 + "    };\n"
1135                 + "    i.src = 'img2.jpg';\n"
1136                 + "  };\n"
1137                 + "  i.setAttribute('src','img.jpg');\n"
1138                 + "  var t = setTimeout(function() {clearTimeout(t);}, 500);\n"
1139                 + "</script></body></html>";
1140 
1141         final int count = getMockWebConnection().getRequestCount();
1142         final WebDriver driver = getWebDriver();
1143         if (driver instanceof HtmlUnitDriver) {
1144             ((HtmlUnitDriver) driver).setDownloadImages(true);
1145         }
1146         loadPage2(html);
1147 
1148         assertTitle(driver, getExpectedAlerts()[0]);
1149         assertEquals(Integer.parseInt(getExpectedAlerts()[1]), getMockWebConnection().getRequestCount() - count);
1150 
1151         final List<String> requestedUrls = getMockWebConnection().getRequestedUrls(URL_FIRST);
1152         assertEquals("", requestedUrls.get(0));
1153         assertEquals("img.jpg", requestedUrls.get(1));
1154         assertEquals("img2.jpg", requestedUrls.get(2));
1155     }
1156 
1157     /**
1158      * @throws Exception if an error occurs
1159      */
1160     @Test
1161     @Alerts("[object HTMLImageElement]")
1162     public void ctorImage() throws Exception {
1163         final String html = DOCTYPE_HTML
1164             + "<html>\n"
1165             + "  <head>\n"
1166             + "    <script>\n"
1167             + LOG_TITLE_FUNCTION
1168             + "      function doTest() {\n"
1169             + "        var htmlImageElement = new Image(1, 1);"
1170             + "        log('' + htmlImageElement);\n"
1171             + "      }\n"
1172             + "    </script>\n"
1173             + "  </head>\n"
1174             + "  <body onload='doTest()'>\n"
1175             + "  </body>\n"
1176             + "</html>";
1177 
1178         loadPageVerifyTitle2(html);
1179     }
1180 
1181     /**
1182      * @throws Exception if an error occurs
1183      */
1184     @Test
1185     @Alerts("TypeError")
1186     public void ctorHTMLImageElement() throws Exception {
1187         final String html = DOCTYPE_HTML
1188             + "<html>\n"
1189             + "  <head>\n"
1190             + "    <script>\n"
1191             + LOG_TITLE_FUNCTION
1192             + "      function doTest() {\n"
1193             + "        try {\n"
1194             + "          var htmlImageElement = new HTMLImageElement(1, 1);"
1195             + "          log('' + htmlImageElement);\n"
1196             + "        } catch(e) { logEx(e); }\n"
1197             + "      }\n"
1198             + "    </script>\n"
1199             + "  </head>\n"
1200             + "  <body onload='doTest()'>\n"
1201             + "  </body>\n"
1202             + "</html>";
1203 
1204         loadPageVerifyTitle2(html);
1205     }
1206 
1207     /**
1208      * @throws Exception if an error occurs
1209      */
1210     @Test
1211     @Alerts("{\"enumerable\":true,\"configurable\":true}")
1212     public void imagePrototype() throws Exception {
1213         final String html = DOCTYPE_HTML
1214             + "<html>\n"
1215             + "  <head>\n"
1216             + "    <script>\n"
1217             + LOG_TITLE_FUNCTION
1218             + "      function doTest() {\n"
1219             + "        var desc = Object.getOwnPropertyDescriptor(Image.prototype, 'src');"
1220             + "        log(JSON.stringify(desc));\n"
1221             + "      }\n"
1222             + "    </script>\n"
1223             + "  </head>\n"
1224             + "  <body onload='doTest()'>\n"
1225             + "  </body>\n"
1226             + "</html>";
1227 
1228         loadPageVerifyTitle2(html);
1229     }
1230 
1231     /**
1232      * Verifies that if an image has an <tt>onload</tt> attribute, it gets downloaded
1233      * and the <tt>onload</tt> handler gets invoked.
1234      * @throws Exception if an error occurs
1235      */
1236     @Test
1237     @Alerts({"0", "1"})
1238     public void onLoad_calledWhenImageDownloaded_static() throws Exception {
1239         final URL urlImage = new URL(URL_FIRST, "img.jpg");
1240         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1241             final byte[] directBytes = IOUtils.toByteArray(is);
1242 
1243             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok",
1244                     MimeType.IMAGE_JPEG, Collections.emptyList());
1245         }
1246 
1247         final String html = DOCTYPE_HTML
1248                 + "<html>\n"
1249                 + "<body>\n"
1250                 + "  <img src='img.jpg' onload='test()'>\n"
1251                 + LOG_TEXTAREA
1252 
1253                 + "  <script>\n"
1254                 + LOG_TEXTAREA_FUNCTION
1255                     // first script to be sure that img onload doesn't get executed after first JS execution
1256                 + "    log(0);\n"
1257                 + "  </script>\n"
1258                 + "  <script>\n"
1259                 + "    function test() {\n"
1260                 + "      log(1);\n"
1261                 + "    }\n"
1262                 + "  </script>\n"
1263                 + "</body></html>";
1264 
1265         loadPageVerifyTextArea2(html);
1266         assertEquals(urlImage, getMockWebConnection().getLastWebRequest().getUrl());
1267     }
1268 
1269     /**
1270      * Verifies that if an image has an <tt>onload</tt> attribute, it gets downloaded
1271      * and the <tt>onload</tt> handler gets invoked.
1272      * @throws Exception if an error occurs
1273      */
1274     @Test
1275     @Alerts("1")
1276     public void onLoad_calledWhenImageDownloaded_dynamic() throws Exception {
1277         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1278             final byte[] directBytes = IOUtils.toByteArray(is);
1279 
1280             getMockWebConnection().setResponse(URL_SECOND, directBytes, 200, "ok",
1281                     MimeType.IMAGE_JPEG, Collections.emptyList());
1282             getMockWebConnection().setResponse(URL_THIRD, directBytes, 200, "ok",
1283                     MimeType.IMAGE_JPEG, Collections.emptyList());
1284         }
1285 
1286         final String html = DOCTYPE_HTML
1287             + "<html><body>\n"
1288             + LOG_TEXTAREA
1289             + "<script>\n"
1290             + LOG_TEXTAREA_FUNCTION
1291             + "  var i = document.createElement('img');\n"
1292             + "  i.src = '" + URL_SECOND + "';\n"
1293             + "  i.src = '" + URL_THIRD + "';\n"
1294             + "  i.onload = function() { log(1); };\n"
1295             + "</script></body></html>";
1296 
1297         loadPageVerifyTextArea2(html);
1298         assertEquals(URL_THIRD, getMockWebConnection().getLastWebRequest().getUrl());
1299     }
1300 
1301     /**
1302      * Verifies that if an image has an <tt>onload</tt> attribute, it gets downloaded
1303      * and the <tt>onload</tt> handler gets invoked.
1304      * @throws Exception if an error occurs
1305      */
1306     @Test
1307     @Alerts("1")
1308     public void onLoad_calledWhenImageDownloaded_dynamic_onLoad_already_set() throws Exception {
1309         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1310             final byte[] directBytes = IOUtils.toByteArray(is);
1311 
1312             getMockWebConnection().setResponse(URL_SECOND, directBytes, 200, "ok",
1313                     MimeType.IMAGE_JPEG, Collections.emptyList());
1314         }
1315 
1316         final String html = DOCTYPE_HTML
1317             + "<html><body>\n"
1318             + LOG_TEXTAREA
1319             + "<script>\n"
1320             + LOG_TEXTAREA_FUNCTION
1321             + "  var i = document.createElement('img');\n"
1322             + "  i.onload = function() { log(1); };\n"
1323             + "  i.src = '" + URL_SECOND + "';\n"
1324             + "</script></body></html>";
1325 
1326         loadPageVerifyTextArea2(html);
1327         assertEquals(URL_SECOND, getMockWebConnection().getLastWebRequest().getUrl());
1328     }
1329 
1330     /**
1331      * Verifies that if an image is created if the page is already
1332      * finished, the onload handler is called.
1333      * @throws Exception if an error occurs
1334      */
1335     @Test
1336     @Alerts({"1", "2"})
1337     public void onLoad_calledWhenImageDownloaded_dynamic_twoSteps() throws Exception {
1338         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1339             final byte[] directBytes = IOUtils.toByteArray(is);
1340 
1341             getMockWebConnection().setResponse(URL_SECOND, directBytes, 200, "ok",
1342                     MimeType.IMAGE_JPEG, Collections.emptyList());
1343             getMockWebConnection().setResponse(URL_THIRD, directBytes, 200, "ok",
1344                     MimeType.IMAGE_JPEG, Collections.emptyList());
1345         }
1346 
1347         final String html = DOCTYPE_HTML
1348             + "<html><body>\n"
1349             + LOG_TEXTAREA
1350             + "<script>\n"
1351             + LOG_TEXTAREA_FUNCTION
1352             + "  var i = document.createElement('img');\n"
1353             + "  i.src = '" + URL_SECOND + "';\n"
1354             + "  i.onload = function() {\n"
1355             + "    log(1);\n"
1356             + "    var i2 = document.createElement('img');\n"
1357             + "    i2.src = '" + URL_THIRD + "';\n"
1358             + "    i2.onload = function() {\n"
1359             + "      log(2);\n"
1360             + "    };\n"
1361             + "  };\n"
1362             + "</script></body></html>";
1363 
1364         loadPageVerifyTextArea2(html);
1365         assertEquals(URL_THIRD, getMockWebConnection().getLastWebRequest().getUrl());
1366     }
1367 
1368     /**
1369      * Verifies that if an image has an <tt>onload</tt> attribute set from a script, it gets downloaded
1370      * and the <tt>onload</tt> handler gets invoked.
1371      * @throws Exception if an error occurs
1372      */
1373     @Test
1374     @Alerts({"image one", "image two"})
1375     public void onLoad_calledWhenImageDownloaded_mixed() throws Exception {
1376         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1377             final byte[] directBytes = IOUtils.toByteArray(is);
1378 
1379             getMockWebConnection().setResponse(URL_SECOND, directBytes, 200, "ok",
1380                     MimeType.IMAGE_JPEG, Collections.emptyList());
1381             getMockWebConnection().setResponse(URL_THIRD, directBytes, 200, "ok",
1382                     MimeType.IMAGE_JPEG, Collections.emptyList());
1383         }
1384 
1385         final String html = DOCTYPE_HTML
1386             + "<html><body>\n"
1387             + LOG_TEXTAREA
1388             + "<img id='img' name='img'/>\n"
1389             + "<script>\n"
1390             + LOG_TEXTAREA_FUNCTION
1391             + "  var i = document.getElementById('img');\n"
1392             + "  i.onload = function() {\n"
1393             + "    log('image one');\n"
1394             + "    i.onload = function() {\n"
1395             + "      log('image two');\n"
1396             + "    };\n"
1397             + "    i.src = '" + URL_THIRD + "';\n"
1398             + "  };\n"
1399             + "  i.setAttribute('src','" + URL_SECOND + "');\n"
1400             + "  var t = setTimeout(function() {clearTimeout(t);}, 500);\n"
1401             + "</script></body></html>";
1402 
1403         loadPageVerifyTextArea2(html);
1404 
1405         final List<String> requestedUrls = getMockWebConnection().getRequestedUrls(URL_FIRST);
1406         assertEquals(requestedUrls.size(), 3);
1407         assertEquals("", requestedUrls.get(0));
1408         assertEquals("second/", requestedUrls.get(1));
1409         assertEquals(URL_THIRD.toString(), requestedUrls.get(2));
1410         assertEquals(URL_THIRD, getMockWebConnection().getLastWebRequest().getUrl());
1411     }
1412 
1413     /**
1414      * Verifies that if an image has an <tt>onload</tt> attribute, the <tt>onload</tt> handler
1415      * does not get invoked if we can't download the image.
1416      * @throws Exception if an error occurs
1417      */
1418     @Test
1419     public void onLoad_notCalledWhenImageNotDownloaded() throws Exception {
1420         final String html = DOCTYPE_HTML
1421             + "<html><body>\n"
1422             + LOG_TEXTAREA
1423             + "<script>\n"
1424             + LOG_TEXTAREA_FUNCTION
1425             + "</script>\n"
1426             + "<img src='" + URL_SECOND + "' onload='log(1)'>\n"
1427             + "</body></html>";
1428 
1429         final MockWebConnection conn = getMockWebConnection();
1430         conn.setResponse(URL_SECOND, "foo", 404, "Not Found", MimeType.TEXT_HTML, new ArrayList<>());
1431 
1432         loadPageVerifyTextArea2(html);
1433         assertEquals(URL_SECOND, conn.getLastWebRequest().getUrl());
1434     }
1435 
1436     /**
1437      * @throws Exception if an error occurs
1438      */
1439     @Test
1440     @Alerts({"0", "2", "1"})
1441     public void onLoad_order() throws Exception {
1442         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1443             final byte[] directBytes = IOUtils.toByteArray(is);
1444 
1445             getMockWebConnection().setResponse(URL_SECOND, directBytes, 200, "ok",
1446                     MimeType.IMAGE_JPEG, Collections.emptyList());
1447         }
1448 
1449         final String html = DOCTYPE_HTML
1450             + "<html><body>\n"
1451             + LOG_TEXTAREA
1452             + "<script>\n"
1453             + LOG_TEXTAREA_FUNCTION
1454             + "  log('0');"
1455             + "  var i = document.createElement('img');\n"
1456             + "  i.onload = function() {\n"
1457             + "    log(1);\n"
1458             + "  };\n"
1459             + "  i.src = '" + URL_SECOND + "';\n"
1460             + "  log('2');"
1461             + "</script></body></html>";
1462 
1463         loadPageVerifyTextArea2(html);
1464         assertEquals(URL_SECOND, getMockWebConnection().getLastWebRequest().getUrl());
1465     }
1466 
1467     /**
1468      * @throws Exception if an error occurs
1469      */
1470     @Test
1471     @Alerts({"0", "2", "1"})
1472     public void onLoad_orderNotAttached() throws Exception {
1473         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1474             final byte[] directBytes = IOUtils.toByteArray(is);
1475 
1476             getMockWebConnection().setResponse(URL_SECOND, directBytes, 200, "ok",
1477                     MimeType.IMAGE_JPEG, Collections.emptyList());
1478         }
1479 
1480         final String html = DOCTYPE_HTML
1481             + "<html><body>\n"
1482             + LOG_TEXTAREA
1483             + "<script>\n"
1484             + LOG_TEXTAREA_FUNCTION
1485             + "  log('0');"
1486             + "  var i = new Image();\n"
1487             + "  i.onload = function() {\n"
1488             + "    log(1);\n"
1489             + "  };\n"
1490             + "  i.src = '" + URL_SECOND + "';\n"
1491             + "  log('2');"
1492             + "</script></body></html>";
1493 
1494         loadPageVerifyTextArea2(html);
1495         assertEquals(URL_SECOND, getMockWebConnection().getLastWebRequest().getUrl());
1496     }
1497 
1498     /**
1499      * @throws Exception on test failure
1500      */
1501     @Test
1502     @Alerts({"in", "out", "Image.onload(0)",
1503              "mousedown", "in", "out", "Image.onload(1)",
1504              "mouseup", "in", "out",
1505              "click", "in", "out", "Image.onload(2)", "Image.onload(3)"})
1506     @BuggyWebDriver({"in", "out", "Image.onload(0)",
1507         "mousedown", "in", "out",
1508         "mouseup", "in", "out",
1509         "click", "in", "out", "Image.onload(1)", "Image.onload(2)", "Image.onload(3)"})
1510     public void onload_complex() throws Exception {
1511         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-jpg.img")) {
1512             final byte[] directBytes = IOUtils.toByteArray(is);
1513 
1514             getMockWebConnection().setResponse(URL_SECOND, directBytes, 200, "ok",
1515                     MimeType.IMAGE_JPEG, Collections.emptyList());
1516         }
1517 
1518         final String html = DOCTYPE_HTML
1519                 + "<html>\n"
1520                 + "<head>\n"
1521                 + "<script>\n"
1522                 + LOG_TEXTAREA_FUNCTION
1523 
1524                 + "  function test(i) {\n"
1525                 + "    log('in');\n"
1526                 + "    var image = new Image();\n"
1527                 + "    image.onload = function () { log(\"Image.onload(\" + i + \")\") };\n"
1528                 + "    image.src = '" + URL_SECOND + "';\n"
1529                 + "    log('out');\n"
1530                 + "  }\n"
1531                 + "</script>\n"
1532                 + "</head>\n"
1533                 + "<body onload=\"test(0)\">\n"
1534                 + "<button id='myId'"
1535                 +           "onmousedown=\"log('mousedown'); test(1)\" "
1536                 +           "onmouseup=\"log('mouseup'); test(2)\" "
1537                 +           "onclick=\"log('click'); test(3)\"></button>\n"
1538                 + LOG_TEXTAREA
1539                 + "</body>\n"
1540                 + "</html>\n";
1541 
1542         final WebDriver driver = loadPage2(html);
1543         driver.findElement(By.id("myId")).click();
1544         verifyTextArea2(driver, getExpectedAlerts());
1545     }
1546 }