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