View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.html;
16  
17  import java.io.InputStream;
18  import java.net.URL;
19  import java.util.Collections;
20  
21  import org.apache.commons.io.IOUtils;
22  import org.htmlunit.WebDriverTestCase;
23  import org.htmlunit.junit.annotation.Alerts;
24  import org.htmlunit.junit.annotation.HtmlUnitNYI;
25  import org.htmlunit.util.MimeType;
26  import org.junit.jupiter.api.Test;
27  import org.openqa.selenium.By;
28  import org.openqa.selenium.WebDriver;
29  import org.openqa.selenium.WebElement;
30  import org.openqa.selenium.interactions.Actions;
31  
32  /**
33   * Tests for {@link HtmlImageInput}.
34   *
35   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
36   * @author Marc Guillemot
37   * @author Ahmed Ashour
38   * @author Ronald Brill
39   */
40  public class HtmlImageInputTest extends WebDriverTestCase {
41  
42      /**
43       * @throws Exception if the test fails
44       */
45      @Test
46      @Alerts(DEFAULT = "§§URL§§?button.x=0&button.y=0",
47              CHROME = "§§URL§§?button.x=16&button.y=8",
48              EDGE = "§§URL§§?button.x=16&button.y=8")
49      @HtmlUnitNYI(CHROME = "§§URL§§?button.x=0&button.y=0",
50              EDGE = "§§URL§§?button.x=0&button.y=0")
51      public void click_NoPosition() throws Exception {
52          final String html = DOCTYPE_HTML
53              + "<html><head><title>foo</title></head><body>\n"
54              + "<form id='form1'>\n"
55              + "  <input type='image' name='aButton' value='foo'/>\n"
56              + "  <input type='image' name='button' value='foo'/>\n"
57              + "  <input type='image' name='anotherButton' value='foo'/>\n"
58              + "</form></body></html>";
59          final WebDriver webDriver = loadPage2(html);
60          webDriver.findElement(By.name("button")).click();
61          if (useRealBrowser()) {
62              Thread.sleep(400);
63          }
64  
65          expandExpectedAlertsVariables(URL_FIRST);
66          assertEquals(getExpectedAlerts()[0], webDriver.getCurrentUrl());
67      }
68  
69      /**
70       * @throws Exception if the test fails
71       */
72      @Test
73      @Alerts(DEFAULT = "§§URL§§?button.x=0&button.y=0",
74              CHROME = "§§URL§§?button.x=28&button.y=8",
75              EDGE = "§§URL§§?button.x=28&button.y=8")
76      @HtmlUnitNYI(CHROME = "§§URL§§?button.x=0&button.y=0",
77              EDGE = "§§URL§§?button.x=0&button.y=0")
78      public void click_NoPosition_NoValue() throws Exception {
79          final String html = DOCTYPE_HTML
80              + "<html><head><title>foo</title></head><body>\n"
81              + "<form id='form1'>\n"
82              + "  <input type='image' name='button'>\n"
83              + "</form></body></html>";
84          final WebDriver webDriver = loadPage2(html);
85          webDriver.findElement(By.name("button")).click();
86          if (useRealBrowser()) {
87              Thread.sleep(400);
88          }
89  
90          expandExpectedAlertsVariables(URL_FIRST);
91          assertEquals(getExpectedAlerts()[0], webDriver.getCurrentUrl());
92      }
93  
94      /**
95       * @throws Exception if the test fails
96       */
97      @Test
98      @Alerts(DEFAULT = "§§URL§§?button.x=0&button.y=0",
99              CHROME = "§§URL§§?button.x=18&button.y=12",
100             EDGE = "§§URL§§?button.x=18&button.y=12")
101     @HtmlUnitNYI(CHROME = "§§URL§§?button.x=0&button.y=0",
102             EDGE = "§§URL§§?button.x=0&button.y=0")
103     public void click_Position() throws Exception {
104         final String html = DOCTYPE_HTML
105             + "<html><head><title>foo</title></head><body>\n"
106             + "<form id='form1'>\n"
107             + "  <input type='image' name='button' value='foo'/>\n"
108             + "</form></body></html>";
109         final WebDriver webDriver = loadPage2(html);
110 
111         final WebElement elem = webDriver.findElement(By.name("button"));
112         final Actions actions = new Actions(webDriver);
113         actions.moveToElement(elem).moveByOffset(1, 4).click().perform();
114         if (useRealBrowser()) {
115             Thread.sleep(400);
116         }
117 
118         expandExpectedAlertsVariables(URL_FIRST);
119         assertEquals(getExpectedAlerts()[0], webDriver.getCurrentUrl());
120     }
121 
122     /**
123      * @throws Exception if the test fails
124      */
125     @Test
126     @Alerts({"--null", "--null", "--null"})
127     public void defaultValues() throws Exception {
128         final String html = DOCTYPE_HTML
129             + "<html><head>\n"
130             + "<script>\n"
131             + LOG_TITLE_FUNCTION
132             + "  function test() {\n"
133             + "    var input = document.getElementById('image1');\n"
134             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
135 
136             + "    input = document.createElement('input');\n"
137             + "    input.type = 'image';\n"
138             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
139 
140             + "    var builder = document.createElement('div');\n"
141             + "    builder.innerHTML = '<input type=\"image\">';\n"
142             + "    input = builder.firstChild;\n"
143             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
144             + "  }\n"
145             + "</script>\n"
146             + "</head><body onload='test()'>\n"
147             + "<form>\n"
148             + "  <input type='image' id='image1'>\n"
149             + "</form>\n"
150             + "</body></html>";
151 
152         loadPageVerifyTitle2(html);
153     }
154 
155     /**
156      * @throws Exception if the test fails
157      */
158     @Test
159     @Alerts({"--null", "--null", "--null"})
160     public void defaultValuesAfterClone() throws Exception {
161         final String html = DOCTYPE_HTML
162             + "<html><head>\n"
163             + "<script>\n"
164             + LOG_TITLE_FUNCTION
165             + "  function test() {\n"
166             + "    var input = document.getElementById('image1');\n"
167             + "    input = input.cloneNode(false);\n"
168             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
169 
170             + "    input = document.createElement('input');\n"
171             + "    input.type = 'image';\n"
172             + "    input = input.cloneNode(false);\n"
173             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
174 
175             + "    var builder = document.createElement('div');\n"
176             + "    builder.innerHTML = '<input type=\"image\">';\n"
177             + "    input = builder.firstChild;\n"
178             + "    input = input.cloneNode(false);\n"
179             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
180             + "  }\n"
181             + "</script>\n"
182             + "</head><body onload='test()'>\n"
183             + "<form>\n"
184             + "  <input type='image' id='image1'>\n"
185             + "</form>\n"
186             + "</body></html>";
187 
188         loadPageVerifyTitle2(html);
189     }
190 
191     /**
192      * @throws Exception if the test fails
193      */
194     @Test
195     @Alerts({"initial-initial-initial", "initial-initial-initial",
196                 "newValue-newValue-newValue", "newValue-newValue-newValue",
197                 "newDefault-newDefault-newDefault", "newDefault-newDefault-newDefault"})
198     public void resetByClick() throws Exception {
199         final String html = DOCTYPE_HTML
200             + "<html><head>\n"
201             + "<script>\n"
202             + LOG_TITLE_FUNCTION
203             + "  function test() {\n"
204             + "    var image = document.getElementById('testId');\n"
205             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
206 
207             + "    document.getElementById('testReset').click;\n"
208             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
209 
210             + "    image.value = 'newValue';\n"
211             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
212 
213             + "    document.getElementById('testReset').click;\n"
214             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
215 
216             + "    image.defaultValue = 'newDefault';\n"
217             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
218 
219             + "    document.forms[0].reset;\n"
220             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
221             + "  }\n"
222             + "</script>\n"
223             + "</head><body onload='test()'>\n"
224             + "<form>\n"
225             + "  <input type='image' id='testId' value='initial'>\n"
226             + "  <input type='reset' id='testReset'>\n"
227             + "</form>\n"
228             + "</body></html>";
229 
230         loadPageVerifyTitle2(html);
231     }
232 
233     /**
234      * @throws Exception if the test fails
235      */
236     @Test
237     @Alerts({"initial-initial-initial", "initial-initial-initial",
238                 "newValue-newValue-newValue", "newValue-newValue-newValue",
239                 "newDefault-newDefault-newDefault", "newDefault-newDefault-newDefault"})
240     public void resetByJS() throws Exception {
241         final String html = DOCTYPE_HTML
242             + "<html><head>\n"
243             + "<script>\n"
244             + LOG_TITLE_FUNCTION
245             + "  function test() {\n"
246             + "    var image = document.getElementById('testId');\n"
247             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
248 
249             + "    document.forms[0].reset;\n"
250             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
251 
252             + "    image.value = 'newValue';\n"
253             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
254 
255             + "    document.forms[0].reset;\n"
256             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
257 
258             + "    image.defaultValue = 'newDefault';\n"
259             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
260 
261             + "    document.forms[0].reset;\n"
262             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
263             + "  }\n"
264             + "</script>\n"
265             + "</head><body onload='test()'>\n"
266             + "<form>\n"
267             + "  <input type='image' id='testId' value='initial'>\n"
268             + "</form>\n"
269             + "</body></html>";
270 
271         loadPageVerifyTitle2(html);
272     }
273 
274     /**
275      * @throws Exception if the test fails
276      */
277     @Test
278     @Alerts({"initial-initial-initial", "default-default-default",
279                 "newValue-newValue-newValue", "attribValue-attribValue-attribValue",
280                 "newDefault-newDefault-newDefault"})
281     public void value() throws Exception {
282         final String html = DOCTYPE_HTML
283             + "<html><head>\n"
284             + "<script>\n"
285             + LOG_TITLE_FUNCTION
286             + "  function test() {\n"
287             + "    var image = document.getElementById('testId');\n"
288             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
289 
290             + "    image.defaultValue = 'default';\n"
291             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
292 
293             + "    image.value = 'newValue';\n"
294             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
295 
296             + "    image.setAttribute('value', 'attribValue');\n"
297             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
298 
299             + "    image.defaultValue = 'newDefault';\n"
300             + "    log(image.value + '-' + image.defaultValue + '-' + image.getAttribute('value'));\n"
301             + "  }\n"
302             + "</script>\n"
303             + "</head><body onload='test()'>\n"
304             + "<form>\n"
305             + "  <input type='image' id='testId' value='initial'>\n"
306             + "</form>\n"
307             + "</body></html>";
308 
309         loadPageVerifyTitle2(html);
310     }
311 
312     /**
313      * @throws Exception if the test fails
314      */
315     @Test
316     @Alerts(DEFAULT = "textLength not available",
317             FF = "7",
318             FF_ESR = "7")
319     public void textLength() throws Exception {
320         final String html = DOCTYPE_HTML
321             + "<html><head>\n"
322             + "<script>\n"
323             + LOG_TITLE_FUNCTION
324             + "  function test() {\n"
325             + "    var text = document.getElementById('testId');\n"
326             + "    if(text.textLength) {\n"
327             + "      log(text.textLength);\n"
328             + "    } else {\n"
329             + "      log('textLength not available');\n"
330             + "    }\n"
331             + "  }\n"
332             + "</script>\n"
333             + "</head><body onload='test()'>\n"
334             + "<form>\n"
335             + "  <input type='image' id='testId' value='initial'>\n"
336             + "</form>\n"
337             + "</body></html>";
338 
339         loadPageVerifyTitle2(html);
340     }
341 
342     /**
343      * @throws Exception if the test fails
344      */
345     @Test
346     @Alerts("§§URL§§?imageInput.x=0&imageInput.y=0")
347     public void javascriptClick() throws Exception {
348         final String html = DOCTYPE_HTML
349                 + "<html><head><title>foo</title>\n"
350                 + "</head><body>\n"
351                 + "<form>\n"
352                 + "  <input type='image' name='imageInput'>\n"
353                 + "  <input type='button' id='submit' value='submit' "
354                         + "onclick='document.getElementsByName(\"imageInput\")[0].click()'>\n"
355                 + "</form>\n"
356                 + "</body></html>";
357 
358         final WebDriver webDriver = loadPage2(html);
359         webDriver.findElement(By.id("submit")).click();
360 
361         expandExpectedAlertsVariables(URL_FIRST);
362         assertEquals(getExpectedAlerts()[0], webDriver.getCurrentUrl());
363     }
364 
365     /**
366      * Test for bug #646.
367      * @throws Exception if an error occurs
368      */
369     @Test
370     @Alerts("1")
371     public void clickFiresOnMouseDown() throws Exception {
372         final String html = DOCTYPE_HTML
373                 + "<html>"
374                 + "<head>\n"
375                 + "<script>\n"
376                 + LOG_TITLE_FUNCTION
377                 + "</script>\n"
378                 + "</head>\n"
379                 + "<body><input type='image' src='x.png' id='i' onmousedown='log(1)'></body></html>";
380 
381         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
382 
383         final WebDriver webDriver = loadPage2(html);
384         webDriver.findElement(By.id("i")).click();
385 
386         verifyTitle2(webDriver, getExpectedAlerts());
387     }
388 
389     /**
390      * Test for bug #646.
391      * @throws Exception if an error occurs
392      */
393     @Test
394     @Alerts("1")
395     public void clickFiresOnMouseUp() throws Exception {
396         final String html = DOCTYPE_HTML
397                 + "<html>"
398                 + "<head>\n"
399                 + "<script>\n"
400                 + LOG_TITLE_FUNCTION
401                 + "</script>\n"
402                 + "</head>\n"
403                 + "<body><input type='image' src='x.png' id='i' onmouseup='log(1)'></body></html>";
404 
405         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
406 
407         final WebDriver webDriver = loadPage2(html);
408         webDriver.findElement(By.id("i")).click();
409 
410         verifyTitle2(webDriver, getExpectedAlerts());
411     }
412 
413     /**
414      * @throws Exception if the test fails
415      */
416     @Test
417     @Alerts("1")
418     public void outsideForm() throws Exception {
419         final String html = DOCTYPE_HTML
420             + "<html>\n"
421             + "<head>\n"
422             + "<script>\n"
423             + LOG_TITLE_FUNCTION
424             + "</script>\n"
425             + "</head>\n"
426             + "<body>\n"
427             + "<input id='myInput' type='image' src='test.png' onclick='log(1)'>\n"
428             + "</body></html>";
429 
430         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
431 
432         final WebDriver webDriver = loadPage2(html);
433         webDriver.findElement(By.id("myInput")).click();
434 
435         verifyTitle2(webDriver, getExpectedAlerts());
436     }
437 
438     /**
439      * @throws Exception if the test fails
440      */
441     @Test
442     @Alerts({"§§URL§§abcd/img.gif", "2"})
443     @HtmlUnitNYI(CHROME = {"§§URL§§abcd/img.gif", "1"},
444             EDGE = {"§§URL§§abcd/img.gif", "1"},
445             FF = {"§§URL§§abcd/img.gif", "1"},
446             FF_ESR = {"§§URL§§abcd/img.gif", "1"})
447     public void resolveImage() throws Exception {
448         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-gif.img")) {
449             final byte[] directBytes = IOUtils.toByteArray(is);
450             final URL urlImage = new URL(URL_SECOND, "abcd/img.gif");
451             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok",
452                     MimeType.IMAGE_GIF, Collections.emptyList());
453         }
454 
455         final String html = DOCTYPE_HTML
456             + "<html><head>\n"
457             + "<script>\n"
458             + LOG_TITLE_FUNCTION
459             + "  function test() {\n"
460             + "    var input = document.getElementById('myInput');\n"
461             + "    log(input.src);\n"
462             + "  }\n"
463             + "</script>\n"
464             + "</head>\n"
465             + "<body onload='test()'>\n"
466             + "  <input id='myInput' type='image' src='" + URL_SECOND + "abcd/img.gif'>\n"
467             + "</body>\n"
468             + "</html>";
469 
470         final int startCount = getMockWebConnection().getRequestCount();
471         final int expectedRequestCount = Integer.parseInt(getExpectedAlerts()[1]);
472 
473         expandExpectedAlertsVariables(URL_SECOND);
474         setExpectedAlerts(getExpectedAlerts()[0]);
475         loadPageVerifyTitle2(html);
476 
477         assertEquals(expectedRequestCount, getMockWebConnection().getRequestCount() - startCount);
478     }
479 
480     /**
481      * @throws Exception if the test fails
482      */
483     @Test
484     @Alerts({"§§URL§§abcd/img.gif", "2"})
485     @HtmlUnitNYI(CHROME = {"§§URL§§abcd/img.gif", "1"},
486             EDGE = {"§§URL§§abcd/img.gif", "1"},
487             FF = {"§§URL§§abcd/img.gif", "1"},
488             FF_ESR = {"§§URL§§abcd/img.gif", "1"})
489     public void resolveImageRelative() throws Exception {
490         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-gif.img")) {
491             final byte[] directBytes = IOUtils.toByteArray(is);
492             final URL urlImage = new URL(URL_FIRST, "abcd/img.gif");
493             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok",
494                     MimeType.IMAGE_GIF, Collections.emptyList());
495         }
496 
497         final String html = DOCTYPE_HTML
498             + "<html><head>\n"
499             + "<script>\n"
500             + LOG_TITLE_FUNCTION
501             + "  function test() {\n"
502             + "    var input = document.getElementById('myInput');\n"
503             + "    log(input.src);\n"
504             + "  }\n"
505             + "</script>\n"
506             + "</head>\n"
507             + "<body onload='test()'>\n"
508             + "  <input id='myInput' type='image' src='abcd/img.gif'>\n"
509             + "</body>\n"
510             + "</html>";
511 
512         final int startCount = getMockWebConnection().getRequestCount();
513         final int expectedRequestCount = Integer.parseInt(getExpectedAlerts()[1]);
514 
515         expandExpectedAlertsVariables(URL_FIRST);
516         setExpectedAlerts(getExpectedAlerts()[0]);
517         loadPageVerifyTitle2(html);
518 
519         assertEquals(expectedRequestCount, getMockWebConnection().getRequestCount() - startCount);
520     }
521 
522     /**
523      * @throws Exception if the test fails
524      */
525     @Test
526     @Alerts({"§§URL§§", "1"})
527     public void resolveImageEmptySource() throws Exception {
528         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-gif.img")) {
529             final byte[] directBytes = IOUtils.toByteArray(is);
530             final URL urlImage = new URL(URL_SECOND, "abcd/img.gif");
531             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok",
532                     MimeType.IMAGE_GIF, Collections.emptyList());
533         }
534 
535         final String html = DOCTYPE_HTML
536             + "<html><head>\n"
537             + "<script>\n"
538             + LOG_TITLE_FUNCTION
539             + "  function test() {\n"
540             + "    var input = document.getElementById('myInput');\n"
541             + "    log(input.src);\n"
542             + "  }\n"
543             + "</script>\n"
544             + "</head>\n"
545             + "<body onload='test()'>\n"
546             + "  <input id='myInput' type='image' src=''>\n"
547             + "</body>\n"
548             + "</html>";
549 
550         final int startCount = getMockWebConnection().getRequestCount();
551         final int expectedRequestCount = Integer.parseInt(getExpectedAlerts()[1]);
552 
553         expandExpectedAlertsVariables(URL_FIRST);
554         setExpectedAlerts(getExpectedAlerts()[0]);
555         loadPageVerifyTitle2(html);
556 
557         assertEquals(expectedRequestCount, getMockWebConnection().getRequestCount() - startCount);
558     }
559 
560     /**
561      * @throws Exception if the test fails
562      */
563     @Test
564     @Alerts({"", "1"})
565     public void resolveImageNoSource() throws Exception {
566         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-gif.img")) {
567             final byte[] directBytes = IOUtils.toByteArray(is);
568             final URL urlImage = new URL(URL_SECOND, "abcd/img.gif");
569             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok",
570                     MimeType.IMAGE_GIF, Collections.emptyList());
571         }
572 
573         final String html = DOCTYPE_HTML
574             + "<html><head>\n"
575             + "<script>\n"
576             + LOG_TITLE_FUNCTION
577             + "  function test() {\n"
578             + "    var input = document.getElementById('myInput');\n"
579             + "    log(input.src);\n"
580             + "  }\n"
581             + "</script>\n"
582             + "</head>\n"
583             + "<body onload='test()'>\n"
584             + "  <input id='myInput' type='image'>\n"
585             + "</body>\n"
586             + "</html>";
587 
588         final int startCount = getMockWebConnection().getRequestCount();
589         final int expectedRequestCount = Integer.parseInt(getExpectedAlerts()[1]);
590 
591         expandExpectedAlertsVariables(URL_FIRST);
592         setExpectedAlerts(getExpectedAlerts()[0]);
593         loadPageVerifyTitle2(html);
594 
595         assertEquals(expectedRequestCount, getMockWebConnection().getRequestCount() - startCount);
596     }
597 
598     /**
599      * @throws Exception if the test fails
600      */
601     @Test
602     @Alerts("§§URL§§abcd/img.gif")
603     public void lineBreaksInUrl() throws Exception {
604         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-gif.img")) {
605             final byte[] directBytes = IOUtils.toByteArray(is);
606             final URL urlImage = new URL(URL_SECOND, "abcd/img.gif");
607             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok",
608                     MimeType.IMAGE_GIF, Collections.emptyList());
609         }
610 
611         final String html = DOCTYPE_HTML
612             + "<html><head>\n"
613             + "<script>\n"
614             + LOG_TITLE_FUNCTION
615             + "  function test() {\n"
616             + "    var input = document.getElementById('myInput');\n"
617             + "    log(input.src);\n"
618             + "  }\n"
619             + "</script>\n"
620             + "</head>\n"
621             + "<body onload='test()'>\n"
622             + "  <input id='myInput' type='image' src='" + URL_SECOND + "a\rb\nc\r\nd/img.gif'>\n"
623             + "</body>\n"
624             + "</html>";
625 
626         expandExpectedAlertsVariables(URL_SECOND);
627         loadPageVerifyTitle2(html);
628     }
629 
630     /**
631      * @throws Exception if the test fails
632      */
633     @Test
634     @Alerts({"", "§§URL§§abcd/img.gif"})
635     public void setSrc() throws Exception {
636         final String html = DOCTYPE_HTML
637             + "<html><head>\n"
638             + "<script>\n"
639             + LOG_TITLE_FUNCTION
640             + "  function test() {\n"
641             + "    var input = document.getElementById('myInput');\n"
642             + "    log(input.src);\n"
643             + "    input.src='" + URL_FIRST + "abcd/img.gif';\n"
644             + "    log(input.src);\n"
645             + "  }\n"
646             + "</script>\n"
647             + "</head>\n"
648             + "<body onload='test()'>\n"
649             + "  <input id='myInput' type='image'>\n"
650             + "</body>\n"
651             + "</html>";
652 
653         expandExpectedAlertsVariables(URL_FIRST);
654         loadPageVerifyTitle2(html);
655     }
656 
657     /**
658      * @throws Exception if the test fails
659      */
660     @Test
661     @Alerts({"", "§§URL§§abcd/img.gif", "1", "2"})
662     @HtmlUnitNYI(CHROME = {"", "§§URL§§abcd/img.gif", "1", "1"},
663             EDGE = {"", "§§URL§§abcd/img.gif", "1", "1"},
664             FF = {"", "§§URL§§abcd/img.gif", "1", "1"},
665             FF_ESR = {"", "§§URL§§abcd/img.gif", "1", "1"})
666     public void resolveImageOnChange() throws Exception {
667         try (InputStream is = getClass().getClassLoader().getResourceAsStream("testfiles/tiny-gif.img")) {
668             final byte[] directBytes = IOUtils.toByteArray(is);
669             final URL urlImage = new URL(URL_FIRST, "abcd/img.gif");
670             getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok",
671                     MimeType.IMAGE_GIF, Collections.emptyList());
672         }
673 
674         final String html = DOCTYPE_HTML
675             + "<html><head>\n"
676             + "<script>\n"
677             + LOG_TITLE_FUNCTION
678             + "  function test() {\n"
679             + "    var input = document.getElementById('myInput');\n"
680             + "    log(input.src);\n"
681             + "  }\n"
682             + "  function update() {\n"
683             + "    var input = document.getElementById('myInput');\n"
684             + "    input.src='" + URL_FIRST + "abcd/img.gif';\n"
685             + "    log(input.src);\n"
686             + "  }\n"
687             + "</script>\n"
688             + "</head>\n"
689             + "<body onload='test()'>\n"
690             + "  <input id='myInput' type='image'>\n"
691             + "  <button id='myUpdate' onclick='update()'>Update</button>\n"
692             + "</body>\n"
693             + "</html>";
694 
695         final int startCount = getMockWebConnection().getRequestCount();
696         final int expectedRequestCount = Integer.parseInt(getExpectedAlerts()[2]);
697         final int expectedRequestCount2 = Integer.parseInt(getExpectedAlerts()[3]);
698 
699         expandExpectedAlertsVariables(URL_FIRST);
700 
701         final WebDriver driver = loadPage2(html);
702         verifyTitle2(driver, getExpectedAlerts()[0]);
703         assertEquals(expectedRequestCount, getMockWebConnection().getRequestCount() - startCount);
704 
705         driver.findElement(By.id("myUpdate")).click();
706         verifyTitle2(driver, getExpectedAlerts()[0], getExpectedAlerts()[1]);
707 
708         Thread.sleep(400); // CHROME processes the image async
709         assertEquals(expectedRequestCount2, getMockWebConnection().getRequestCount() - startCount);
710     }
711 
712     /**
713      * @throws Exception if the test fails
714      */
715     @Test
716     @Alerts("--")
717     public void minMaxStep() throws Exception {
718         final String html = DOCTYPE_HTML
719             + "<html>\n"
720             + "<head>\n"
721             + "<script>\n"
722             + LOG_TITLE_FUNCTION
723             + "  function test() {\n"
724             + "    var input = document.getElementById('tester');\n"
725             + "    log(input.min + '-' + input.max + '-' + input.step);\n"
726             + "  }\n"
727             + "</script>\n"
728             + "</head>\n"
729             + "<body onload='test()'>\n"
730             + "<form>\n"
731             + "  <input type='image' id='tester'>\n"
732             + "</form>\n"
733             + "</body>\n"
734             + "</html>";
735 
736         loadPageVerifyTitle2(html);
737     }
738 
739     /**
740      * @throws Exception if the test fails
741      */
742     @Test
743     @Alerts(DEFAULT = {"true", "true", "false", "false", "true"},
744             CHROME = {"true", "true", "true", "true", "true"},
745             EDGE = {"true", "true", "true", "true", "true"})
746     public void checkValidity() throws Exception {
747         final String html = DOCTYPE_HTML
748             + "<html>\n"
749             + "<head>\n"
750             + "<script>\n"
751             + LOG_TITLE_FUNCTION
752             + "  function test() {\n"
753             + "    var foo = document.getElementById('foo');\n"
754             + "    log(foo.checkValidity());\n"
755 
756             + "    foo.setCustomValidity('');\n"
757             + "    log(foo.checkValidity());\n"
758 
759             + "    foo.setCustomValidity(' ');\n"
760             + "    log(foo.checkValidity());\n"
761 
762             + "    foo.setCustomValidity('invalid');\n"
763             + "    log(foo.checkValidity());\n"
764 
765             + "    foo.setCustomValidity('');\n"
766             + "    log(foo.checkValidity());\n"
767             + "  }\n"
768             + "</script>\n"
769             + "</head>\n"
770             + "<body onload='test()'>\n"
771             + "  <input type='image' id='foo'>\n"
772             + "</body>\n"
773             + "</html>";
774 
775         loadPageVerifyTitle2(html);
776     }
777 }