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