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.util.List;
18  
19  import org.htmlunit.WebDriverTestCase;
20  import org.htmlunit.junit.annotation.Alerts;
21  import org.htmlunit.util.NameValuePair;
22  import org.junit.jupiter.api.Test;
23  import org.openqa.selenium.By;
24  import org.openqa.selenium.WebDriver;
25  import org.openqa.selenium.WebElement;
26  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
27  
28  /**
29   * Tests for {@link HtmlButton}.
30   *
31   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
32   * @author David K. Taylor
33   * @author Brad Clarke
34   * @author Marc Guillemot
35   * @author Ahmed Ashour
36   * @author Ronald Brill
37   * @author Frank Danek
38   */
39  public class HtmlButton2Test extends WebDriverTestCase {
40  
41      /**
42       * @throws Exception if the test fails
43       */
44      @Test
45      @Alerts("[object HTMLButtonElement]")
46      public void simpleScriptable() throws Exception {
47          final String html = "<html><head>\n"
48              + "<script>\n"
49              + LOG_TITLE_FUNCTION
50              + "  function test() {\n"
51              + "    log(document.getElementById('myId'));\n"
52              + "  }\n"
53              + "</script>\n"
54              + "</head><body onload='test()'>\n"
55              + "<button id='myId'>OK</button>\n"
56              + "</body></html>";
57  
58          final WebDriver driver = loadPageVerifyTitle2(html);
59          if (driver instanceof HtmlUnitDriver) {
60              final HtmlPage page = (HtmlPage) getEnclosedPage();
61              assertTrue(HtmlButton.class.isInstance(page.getHtmlElementById("myId")));
62          }
63      }
64  
65      /**
66       * @throws Exception if the test fails
67       */
68      @Test
69      @Alerts({"-undefined", "-undefined", "-"})
70      public void defaultValues() throws Exception {
71          final String html = "<!DOCTYPE HTML>\n<html><head>\n"
72              + "<script>\n"
73              + LOG_TITLE_FUNCTION
74              + "  function test() {\n"
75              + "    var input = document.getElementById('button1');\n"
76              + "    log(input.value + '-' + input.defaultValue);\n"
77  
78              + "    input = document.createElement('button');\n"
79              + "    log(input.value + '-' + input.defaultValue);\n"
80  
81              + "    var builder = document.createElement('div');\n"
82              + "    builder.innerHTML = '<input type=\"button\">';\n"
83              + "    input = builder.firstChild;\n"
84              + "    log(input.value + '-' + input.defaultValue);\n"
85              + "  }\n"
86              + "</script>\n"
87              + "</head><body onload='test()'>\n"
88              + "<form>\n"
89              + "  <button id='button1'>OK</button>\n"
90              + "</form>\n"
91              + "</body></html>";
92  
93          loadPageVerifyTitle2(html);
94      }
95  
96      /**
97       * @throws Exception if the test fails
98       */
99      @Test
100     @Alerts({"-undefined", "-", "-"})
101     public void defaultValuesAfterClone() throws Exception {
102         final String html = "<!DOCTYPE HTML>\n<html><head>\n"
103             + "<script>\n"
104             + LOG_TITLE_FUNCTION
105             + "  function test() {\n"
106             + "    var input = document.getElementById('button1');\n"
107             + "    input = input.cloneNode(false);\n"
108             + "    log(input.value + '-' + input.defaultValue);\n"
109 
110             + "    input = document.createElement('input');\n"
111             + "    input.type = 'button';\n"
112             + "    input = input.cloneNode(false);\n"
113             + "    log(input.value + '-' + input.defaultValue);\n"
114 
115             + "    var builder = document.createElement('div');\n"
116             + "    builder.innerHTML = '<input type=\"button\">';\n"
117             + "    input = builder.firstChild;\n"
118             + "    input = input.cloneNode(false);\n"
119             + "    log(input.value + '-' + input.defaultValue);\n"
120             + "  }\n"
121             + "</script>\n"
122             + "</head><body onload='test()'>\n"
123             + "<form>\n"
124             + "  <button id='button1'>OK</button>\n"
125             + "</form>\n"
126             + "</body></html>";
127 
128         loadPageVerifyTitle2(html);
129     }
130 
131     /**
132      * @throws Exception if the test fails
133      */
134     @Test
135     @Alerts({"initial-undefined", "initial-undefined", "newValue-undefined", "newValue-undefined",
136                 "newValue-newDefault", "newValue-newDefault"})
137     public void resetByClick() throws Exception {
138         final String html = "<!DOCTYPE HTML>\n<html><head>\n"
139             + "<script>\n"
140             + LOG_TITLE_FUNCTION
141             + "  function test() {\n"
142             + "    var button = document.getElementById('testId');\n"
143             + "    log(button.value + '-' + button.defaultValue);\n"
144 
145             + "    document.getElementById('testReset').click;\n"
146             + "    log(button.value + '-' + button.defaultValue);\n"
147 
148             + "    button.value = 'newValue';\n"
149             + "    log(button.value + '-' + button.defaultValue);\n"
150 
151             + "    document.getElementById('testReset').click;\n"
152             + "    log(button.value + '-' + button.defaultValue);\n"
153 
154             + "    button.defaultValue = 'newDefault';\n"
155             + "    log(button.value + '-' + button.defaultValue);\n"
156 
157             + "    document.forms[0].reset;\n"
158             + "    log(button.value + '-' + button.defaultValue);\n"
159             + "  }\n"
160             + "</script>\n"
161             + "</head><body onload='test()'>\n"
162             + "<form>\n"
163             + "  <button id='testId' value='initial'>OK</button>\n"
164             + "  <input type='reset' id='testReset'>\n"
165             + "</form>\n"
166             + "</body></html>";
167 
168         loadPageVerifyTitle2(html);
169     }
170 
171     /**
172      * @throws Exception if the test fails
173      */
174     @Test
175     @Alerts({"initial-undefined", "initial-undefined", "newValue-undefined", "newValue-undefined",
176                 "newValue-newDefault", "newValue-newDefault"})
177     public void resetByJS() throws Exception {
178         final String html = "<!DOCTYPE HTML>\n<html><head>\n"
179             + "<script>\n"
180             + LOG_TITLE_FUNCTION
181             + "  function test() {\n"
182             + "    var button = document.getElementById('testId');\n"
183             + "    log(button.value + '-' + button.defaultValue);\n"
184 
185             + "    document.forms[0].reset;\n"
186             + "    log(button.value + '-' + button.defaultValue);\n"
187 
188             + "    button.value = 'newValue';\n"
189             + "    log(button.value + '-' + button.defaultValue);\n"
190 
191             + "    document.forms[0].reset;\n"
192             + "    log(button.value + '-' + button.defaultValue);\n"
193 
194             + "    button.defaultValue = 'newDefault';\n"
195             + "    log(button.value + '-' + button.defaultValue);\n"
196 
197             + "    document.forms[0].reset;\n"
198             + "    log(button.value + '-' + button.defaultValue);\n"
199             + "  }\n"
200             + "</script>\n"
201             + "</head><body onload='test()'>\n"
202             + "<form>\n"
203             + "  <button id='testId' value='initial'>OK</button>\n"
204             + "</form>\n"
205             + "</body></html>";
206 
207         loadPageVerifyTitle2(html);
208     }
209 
210     /**
211      * @throws Exception if the test fails
212      */
213     @Test
214     @Alerts({"initial-undefined", "initial-default", "newValue-default", "newValue-newDefault"})
215     public void defaultValue() throws Exception {
216         final String html = "<!DOCTYPE HTML>\n<html><head>\n"
217             + "<script>\n"
218             + LOG_TITLE_FUNCTION
219             + "  function test() {\n"
220             + "    var button = document.getElementById('testId');\n"
221             + "    log(button.value + '-' + button.defaultValue);\n"
222 
223             + "    button.defaultValue = 'default';\n"
224             + "    log(button.value + '-' + button.defaultValue);\n"
225 
226             + "    button.value = 'newValue';\n"
227             + "    log(button.value + '-' + button.defaultValue);\n"
228             + "    button.defaultValue = 'newDefault';\n"
229             + "    log(button.value + '-' + button.defaultValue);\n"
230             + "  }\n"
231             + "</script>\n"
232             + "</head><body onload='test()'>\n"
233             + "<form>\n"
234             + "  <button id='testId' value='initial'>OK</button>\n"
235             + "</form>\n"
236             + "</body></html>";
237 
238         loadPageVerifyTitle2(html);
239     }
240 
241     /**
242      * @throws Exception if the test fails
243      */
244     @Test
245     @Alerts({"initial-OK", "newValue-OK", "newValue-OK"})
246     public void innerHtml() throws Exception {
247         final String html = "<!DOCTYPE HTML>\n<html><head>\n"
248             + "<script>\n"
249             + LOG_TITLE_FUNCTION
250             + "  function test() {\n"
251             + "    var button = document.getElementById('testId');\n"
252             + "    log(button.value + '-' + button.innerHTML);\n"
253 
254             + "    button.value = 'newValue';\n"
255             + "    log(button.value + '-' + button.innerHTML);\n"
256 
257             + "    button.innerHtml = 'Cancel';\n"
258             + "    log(button.value + '-' + button.innerHTML);\n"
259             + "  }\n"
260             + "</script>\n"
261             + "</head><body onload='test()'>\n"
262             + "<form>\n"
263             + "  <button id='testId' value='initial'>OK</button>\n"
264             + "</form>\n"
265             + "</body></html>";
266 
267         loadPageVerifyTitle2(html);
268     }
269 
270     /**
271      * @throws Exception if the test fails
272      */
273     @Test
274     @Alerts({"initial-OK", "newValue-OK", "newValue-Cancel"})
275     public void innerText() throws Exception {
276         final String html = "<!DOCTYPE HTML>\n<html><head>\n"
277             + "<script>\n"
278             + LOG_TITLE_FUNCTION
279             + "  function test() {\n"
280             + "    var button = document.getElementById('testId');\n"
281             + "    log(button.value + '-' + button.innerText);\n"
282 
283             + "    button.value = 'newValue';\n"
284             + "    log(button.value + '-' + button.innerText);\n"
285 
286             + "    button.innerText = 'Cancel';\n"
287             + "    log(button.value + '-' + button.innerText);\n"
288             + "  }\n"
289             + "</script>\n"
290             + "</head><body onload='test()'>\n"
291             + "<form>\n"
292             + "  <button id='testId' value='initial'>OK</button>\n"
293             + "</form>\n"
294             + "</body></html>";
295 
296         loadPageVerifyTitle2(html);
297     }
298 
299     /**
300      * @throws Exception if the test fails
301      */
302     @Test
303     @Alerts({"initial-initial-OK", "newValue-newValue-OK", "newValue-newValue-OK"})
304     public void valueAttributeNode() throws Exception {
305         final String html = "<!DOCTYPE HTML>\n<html><head>\n"
306             + "<script>\n"
307             + LOG_TITLE_FUNCTION
308             + "  function test() {\n"
309             + "    var button = document.getElementById('testId');\n"
310             + "    var attr = button.getAttributeNode('value');\n"
311             + "    log(attr.value + '-' + button.value + '-' + button.innerHTML);\n"
312 
313             + "    attr.value = 'newValue';\n"
314             + "    log(attr.value + '-' + button.value + '-' + button.innerHTML);\n"
315 
316             + "    button.innerHtml = 'Cancel';\n"
317             + "    log(attr.value + '-' + button.value + '-' + button.innerHTML);\n"
318             + "  }\n"
319             + "</script>\n"
320             + "</head><body onload='test()'>\n"
321             + "<form>\n"
322             + "  <button id='testId' value='initial'>OK</button>\n"
323             + "</form>\n"
324             + "</body></html>";
325 
326         loadPageVerifyTitle2(html);
327     }
328 
329     /**
330      * According to the HTML spec, the default type for a button is "submit".
331      * IE is different than the HTML spec and has a default type of "button".
332      * @throws Exception if the test fails
333      */
334     @Test
335     @Alerts({"submit", "1", "button-pushme", "Second"})
336     public void defaultButtonType_StandardsCompliantBrowser() throws Exception {
337         final String firstContent = DOCTYPE_HTML
338             + "<html><head><title>First</title></head><body>\n"
339             + "<form id='form1' action='" + URL_SECOND + "' method='post'>\n"
340             + "  <button name='button' id='button' value='pushme'>PushMe</button>\n"
341             + "</form></body></html>";
342         final String secondContent = DOCTYPE_HTML
343             + "<html><head><title>Second</title></head><body'></body></html>";
344 
345         getMockWebConnection().setResponse(URL_SECOND, secondContent);
346 
347         final WebDriver driver = loadPage2(firstContent);
348         final WebElement button = driver.findElement(By.id("button"));
349 
350         assertEquals(getExpectedAlerts()[0], button.getAttribute("type"));
351 
352         button.click();
353         if (useRealBrowser()) {
354             Thread.sleep(400);
355         }
356 
357         final List<NameValuePair> params = getMockWebConnection().getLastParameters();
358         assertEquals(getExpectedAlerts()[1], "" + params.size());
359 
360         if (params.size() > 0) {
361             assertEquals(getExpectedAlerts()[2], params.get(0).getName() + "-" + params.get(0).getValue());
362         }
363         assertTitle(driver, getExpectedAlerts()[3]);
364     }
365 
366     /**
367      * @throws Exception if the test fails
368      */
369     @Test
370     @Alerts("2")
371     public void typeUnknown() throws Exception {
372         final String html = DOCTYPE_HTML
373             + "<html><head><title>first</title></head><body>\n"
374             + "  <p>hello world</p>\n"
375             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
376             + "    <button type='unknown' id='myButton'>Explicit Submit</button>\n"
377             + "  </form>\n"
378             + "</body></html>";
379         final String secondContent = DOCTYPE_HTML
380             + "<html><head><title>second</title></head><body>\n"
381             + "  <p>hello world</p>\n"
382             + "</body></html>";
383 
384         getMockWebConnection().setDefaultResponse(secondContent);
385 
386         final WebDriver driver = loadPage2(html);
387         driver.findElement(By.id("myButton")).click();
388         if (useRealBrowser()) {
389             Thread.sleep(400);
390         }
391 
392         final int expectedReqCount = Integer.parseInt(getExpectedAlerts()[0]);
393         assertEquals(expectedReqCount, getMockWebConnection().getRequestCount());
394         if (expectedReqCount > 1) {
395             assertEquals(URL_SECOND.toString(), getMockWebConnection().getLastWebRequest().getUrl());
396         }
397     }
398 
399     /**
400      * @throws Exception if the test fails
401      */
402     @Test
403     public void typeSubmit() throws Exception {
404         final String html = DOCTYPE_HTML
405             + "<html><head><title>first</title></head><body>\n"
406             + "  <p>hello world</p>\n"
407             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
408             + "    <input name='text' type='text'>\n"
409             + "    <button type='submit' id='myButton'>Explicit Submit</button>\n"
410             + "  </form>\n"
411             + "</body></html>";
412         final String secondContent = DOCTYPE_HTML
413             + "<html><head><title>second</title></head><body>\n"
414             + "  <p>hello world</p>\n"
415             + "</body></html>";
416 
417         getMockWebConnection().setDefaultResponse(secondContent);
418 
419         final WebDriver driver = loadPage2(html);
420         driver.findElement(By.id("myButton")).click();
421         if (useRealBrowser()) {
422             Thread.sleep(400);
423         }
424 
425         assertEquals(2, getMockWebConnection().getRequestCount());
426         assertEquals(URL_SECOND.toString() + "?text=", getMockWebConnection().getLastWebRequest().getUrl());
427     }
428 
429     /**
430      * @throws Exception if the test fails
431      */
432     @Test
433     public void typeReset() throws Exception {
434         final String html = DOCTYPE_HTML
435             + "<html><head><title>first</title></head><body>\n"
436             + "  <p>hello world</p>\n"
437             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
438             + "    <button type='reset' id='myButton'>Explicit Submit</button>\n"
439             + "  </form>\n"
440             + "</body></html>";
441         final String secondContent = DOCTYPE_HTML
442             + "<html><head><title>second</title></head><body>\n"
443             + "  <p>hello world</p>\n"
444             + "</body></html>";
445 
446         getMockWebConnection().setDefaultResponse(secondContent);
447 
448         final WebDriver driver = loadPage2(html);
449         driver.findElement(By.id("myButton")).click();
450 
451         assertEquals(1, getMockWebConnection().getRequestCount());
452     }
453 
454     /**
455      * @throws Exception if the test fails
456      */
457     @Test
458     public void typeButton() throws Exception {
459         final String html = DOCTYPE_HTML
460             + "<html><head><title>first</title></head><body>\n"
461             + "  <p>hello world</p>\n"
462             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
463             + "    <button type='button' id='myButton'>Explicit Submit</button>\n"
464             + "  </form>\n"
465             + "</body></html>";
466         final String secondContent = DOCTYPE_HTML
467             + "<html><head><title>second</title></head><body>\n"
468             + "  <p>hello world</p>\n"
469             + "</body></html>";
470 
471         getMockWebConnection().setDefaultResponse(secondContent);
472 
473         final WebDriver driver = loadPage2(html);
474         driver.findElement(By.id("myButton")).click();
475 
476         assertEquals(1, getMockWebConnection().getRequestCount());
477     }
478 
479     /**
480      * @throws Exception if the test fails
481      */
482     @Test
483     public void typeEmpty() throws Exception {
484         final String html = DOCTYPE_HTML
485             + "<html><head><title>first</title></head><body>\n"
486             + "  <p>hello world</p>\n"
487             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
488             + "    <button type='button' id='myButton'>Explicit Submit</button>\n"
489             + "  </form>\n"
490             + "</body></html>";
491         final String secondContent = DOCTYPE_HTML
492             + "<html><head><title>second</title></head><body>\n"
493             + "  <p>hello world</p>\n"
494             + "</body></html>";
495 
496         getMockWebConnection().setDefaultResponse(secondContent);
497 
498         final WebDriver driver = loadPage2(html);
499         driver.findElement(By.id("myButton")).click();
500 
501         assertEquals(1, getMockWebConnection().getRequestCount());
502     }
503 
504     /**
505      * @throws Exception if the test fails
506      */
507     @Test
508     @Alerts("2")
509     public void submitWithoutType() throws Exception {
510         final String html = DOCTYPE_HTML
511             + "<html><head><title>first</title></head><body>\n"
512             + "  <p>hello world</p>\n"
513             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
514             + "    <button id='myButton'>Implicit Submit</button>\n"
515             + "  </form>\n"
516             + "</body></html>";
517         final String secondContent = DOCTYPE_HTML
518             + "<html><head><title>second</title></head><body>\n"
519             + "  <p>hello world</p>\n"
520             + "</body></html>";
521 
522         getMockWebConnection().setDefaultResponse(secondContent);
523 
524         final WebDriver driver = loadPage2(html);
525         driver.findElement(By.id("myButton")).click();
526         if (useRealBrowser()) {
527             Thread.sleep(400);
528         }
529 
530         final int expectedReqCount = Integer.parseInt(getExpectedAlerts()[0]);
531         assertEquals(expectedReqCount, getMockWebConnection().getRequestCount());
532         if (expectedReqCount > 1) {
533             assertEquals(URL_SECOND.toString(), getMockWebConnection().getLastWebRequest().getUrl());
534         }
535     }
536 
537     /**
538      * @throws Exception if the test fails
539      */
540     @Test
541     @Alerts("2")
542     public void typeUnknownExternal() throws Exception {
543         final String html = DOCTYPE_HTML
544             + "<html><head><title>first</title></head><body>\n"
545             + "  <p>hello world</p>\n"
546             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
547             + "  </form>\n"
548             + "  <button type='unknown' id='myButton' form='myForm'>Explicit Submit</button>\n"
549             + "</body></html>";
550         final String secondContent = DOCTYPE_HTML
551             + "<html><head><title>second</title></head><body>\n"
552             + "  <p>hello world</p>\n"
553             + "</body></html>";
554 
555         getMockWebConnection().setDefaultResponse(secondContent);
556 
557         final WebDriver driver = loadPage2(html);
558         driver.findElement(By.id("myButton")).click();
559         if (useRealBrowser()) {
560             Thread.sleep(400);
561         }
562 
563         final int expectedReqCount = Integer.parseInt(getExpectedAlerts()[0]);
564         assertEquals(expectedReqCount, getMockWebConnection().getRequestCount());
565         if (expectedReqCount > 1) {
566             assertEquals(URL_SECOND.toString(), getMockWebConnection().getLastWebRequest().getUrl());
567         }
568     }
569 
570     /**
571      * @throws Exception if the test fails
572      */
573     @Test
574     @Alerts("2")
575     public void typeSubmitExternal() throws Exception {
576         final String html = DOCTYPE_HTML
577             + "<html><head><title>first</title></head><body>\n"
578             + "  <p>hello world</p>\n"
579             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
580             + "  </form>\n"
581             + "  <button type='submit' id='myButton' form='myForm'>Explicit Submit</button>\n"
582             + "</body></html>";
583         final String secondContent = DOCTYPE_HTML
584             + "<html><head><title>second</title></head><body>\n"
585             + "  <p>hello world</p>\n"
586             + "</body></html>";
587 
588         getMockWebConnection().setDefaultResponse(secondContent);
589 
590         final WebDriver driver = loadPage2(html);
591         driver.findElement(By.id("myButton")).click();
592         if (useRealBrowser()) {
593             Thread.sleep(400);
594         }
595 
596         final int expectedReqCount = Integer.parseInt(getExpectedAlerts()[0]);
597         assertEquals(expectedReqCount, getMockWebConnection().getRequestCount());
598         if (expectedReqCount > 1) {
599             assertEquals(URL_SECOND.toString(), getMockWebConnection().getLastWebRequest().getUrl());
600         }
601     }
602 
603     /**
604      * @throws Exception if the test fails
605      */
606     @Test
607     @Alerts("1")
608     public void typeResetExternal() throws Exception {
609         final String html = DOCTYPE_HTML
610             + "<html><head><title>first</title></head><body>\n"
611             + "  <p>hello world</p>\n"
612             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
613             + "  </form>\n"
614             + "  <button type='reset' id='myButton' form='myForm'>Explicit Submit</button>\n"
615             + "</body></html>";
616         final String secondContent = DOCTYPE_HTML
617             + "<html><head><title>second</title></head><body>\n"
618             + "  <p>hello world</p>\n"
619             + "</body></html>";
620 
621         getMockWebConnection().setDefaultResponse(secondContent);
622 
623         final WebDriver driver = loadPage2(html);
624         driver.findElement(By.id("myButton")).click();
625 
626         final int expectedReqCount = Integer.parseInt(getExpectedAlerts()[0]);
627         assertEquals(expectedReqCount, getMockWebConnection().getRequestCount());
628         if (expectedReqCount > 1) {
629             assertEquals(URL_SECOND.toString(), getMockWebConnection().getLastWebRequest().getUrl());
630         }
631     }
632 
633     /**
634      * @throws Exception if the test fails
635      */
636     @Test
637     @Alerts("2")
638     public void submitWithoutTypeExternal() throws Exception {
639         final String html = DOCTYPE_HTML
640             + "<html><head><title>first</title></head><body>\n"
641             + "  <p>hello world</p>\n"
642             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
643             + "  </form>\n"
644             + "  <button id='myButton' form='myForm'>Implicit Submit</button>\n"
645             + "</body></html>";
646         final String secondContent = DOCTYPE_HTML
647             + "<html><head><title>second</title></head><body>\n"
648             + "  <p>hello world</p>\n"
649             + "</body></html>";
650 
651         getMockWebConnection().setDefaultResponse(secondContent);
652 
653         final WebDriver driver = loadPage2(html);
654         driver.findElement(By.id("myButton")).click();
655         if (useRealBrowser()) {
656             Thread.sleep(400);
657         }
658 
659         final int expectedReqCount = Integer.parseInt(getExpectedAlerts()[0]);
660         assertEquals(expectedReqCount, getMockWebConnection().getRequestCount());
661         if (expectedReqCount > 1) {
662             assertEquals(URL_SECOND.toString(), getMockWebConnection().getLastWebRequest().getUrl());
663         }
664     }
665 
666     /**
667      * @throws Exception if the test fails
668      */
669     @Test
670     @Alerts("1")
671     public void externalUnknownFrom() throws Exception {
672         final String html = DOCTYPE_HTML
673             + "<html><head><title>first</title></head><body>\n"
674             + "  <p>hello world</p>\n"
675             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
676             + "  </form>\n"
677             + "  <button type='submit' id='myButton' form='unknown'>Explicit Submit</button>\n"
678             + "</body></html>";
679         final String secondContent = DOCTYPE_HTML
680             + "<html><head><title>second</title></head><body>\n"
681             + "  <p>hello world</p>\n"
682             + "</body></html>";
683 
684         getMockWebConnection().setDefaultResponse(secondContent);
685 
686         final WebDriver driver = loadPage2(html);
687         driver.findElement(By.id("myButton")).click();
688 
689         final int expectedReqCount = Integer.parseInt(getExpectedAlerts()[0]);
690         assertEquals(expectedReqCount, getMockWebConnection().getRequestCount());
691         if (expectedReqCount > 1) {
692             assertEquals(URL_SECOND.toString(), getMockWebConnection().getLastWebRequest().getUrl());
693         }
694     }
695 
696     /**
697      * @throws Exception if the test fails
698      */
699     @Test
700     @Alerts({"2", "second"})
701     public void externalPreferenceFrom() throws Exception {
702         final String html = DOCTYPE_HTML
703             + "<html><head><title>first</title></head><body>\n"
704             + "  <p>hello world</p>\n"
705             + "  <form id='myForm2' action='" + URL_SECOND + "'>\n"
706             + "  </form>\n"
707             + "  <form id='myForm3' action='" + URL_THIRD + "'>\n"
708             + "    <button type='submit' id='myButton' form='myForm2'>Explicit Submit</button>\n"
709             + "  </form>\n"
710             + "</body></html>";
711         final String secondContent = DOCTYPE_HTML
712             + "<html><head><title>second</title></head><body>\n"
713             + "  <p>hello world</p>\n"
714             + "</body></html>";
715         final String thirdContent = DOCTYPE_HTML
716             + "<html><head><title>third</title></head><body>\n"
717             + "  <p>hello world</p>\n"
718             + "</body></html>";
719 
720         getMockWebConnection().setResponse(URL_SECOND, secondContent);
721         getMockWebConnection().setResponse(URL_THIRD, thirdContent);
722 
723         final WebDriver driver = loadPage2(html);
724         driver.findElement(By.id("myButton")).click();
725         if (useRealBrowser()) {
726             Thread.sleep(400);
727         }
728 
729         final int expectedReqCount = Integer.parseInt(getExpectedAlerts()[0]);
730         assertEquals(expectedReqCount, getMockWebConnection().getRequestCount());
731         assertTitle(driver, getExpectedAlerts()[1]);
732     }
733 
734     /**
735      * @throws Exception if the test fails
736      */
737     @Test
738     @Alerts({"2", "second"})
739     public void internalDifferentFrom() throws Exception {
740         final String html = DOCTYPE_HTML
741             + "<html><head><title>first</title></head><body>\n"
742             + "  <p>hello world</p>\n"
743             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
744             + "  </form>\n"
745             + "  <form id='other' action='" + URL_THIRD + "'>\n"
746             + "    <button type='submit' id='myButton' form='myForm'>Explicit Submit</button>\n"
747             + "  </form>\n"
748             + "</body></html>";
749         final String secondContent = DOCTYPE_HTML
750             + "<html><head><title>second</title></head><body>\n"
751             + "  <p>hello world</p>\n"
752             + "</body></html>";
753         final String thirdContent = DOCTYPE_HTML
754             + "<html><head><title>third</title></head><body>\n"
755             + "  <p>hello world</p>\n"
756             + "</body></html>";
757 
758         getMockWebConnection().setResponse(URL_SECOND, secondContent);
759         getMockWebConnection().setResponse(URL_THIRD, thirdContent);
760 
761         final WebDriver driver = loadPage2(html);
762         driver.findElement(By.id("myButton")).click();
763         if (useRealBrowser()) {
764             Thread.sleep(400);
765         }
766 
767         final int expectedReqCount = Integer.parseInt(getExpectedAlerts()[0]);
768         assertEquals(expectedReqCount, getMockWebConnection().getRequestCount());
769         assertTitle(driver, getExpectedAlerts()[1]);
770     }
771 
772     /**
773      * @throws Exception if the test fails
774      */
775     @Test
776     @Alerts("submit")
777     public void type() throws Exception {
778         final String html = DOCTYPE_HTML
779             + "<html><head>\n"
780             + "<script>\n"
781             + LOG_TITLE_FUNCTION
782             + "  function test() {\n"
783             + "    var button = document.getElementById('testId');\n"
784             + "    log(button.type);\n"
785             + "  }\n"
786             + "</script>\n"
787             + "</head><body onload='test()'>\n"
788             + "<form>\n"
789             + "  <button id='testId'>OK</button>\n"
790             + "</form>\n"
791             + "</body></html>";
792 
793         loadPageVerifyTitle2(html);
794     }
795 
796     /**
797      * @throws Exception if the test fails
798      */
799     @Test
800     @Alerts("submit")
801     public void typeStandards() throws Exception {
802         final String html = DOCTYPE_HTML
803             + "<html><head>\n"
804             + "<script>\n"
805             + LOG_TITLE_FUNCTION
806             + "  function test() {\n"
807             + "    var button = document.getElementById('testId');\n"
808             + "    log(button.type);\n"
809             + "  }\n"
810             + "</script>\n"
811             + "</head><body onload='test()'>\n"
812             + "<form>\n"
813             + "  <button id='testId'>OK</button>\n"
814             + "</form>\n"
815             + "</body></html>";
816 
817         loadPageVerifyTitle2(html);
818     }
819 
820     /**
821      * @throws Exception if the test fails
822      */
823     @Test
824     @Alerts("1")
825     public void onclickDisablesSubmit() throws Exception {
826         final String html = DOCTYPE_HTML
827             + "<html>\n"
828             + "<head>\n"
829             + "  <script type='text/javascript'>\n"
830             + "    function submitForm() {\n"
831             + "      document.deliveryChannelForm.submitBtn.disabled = true;\n"
832             + "    }\n"
833             + "  </script>\n"
834             + "</head>\n"
835             + "<body>\n"
836             + "  <form action='test' name='deliveryChannelForm'>\n"
837             + "    <button name='submitBtn' type='submit' onclick='submitForm();'>Save</button>\n"
838             + "  </form>\n"
839             + "</body>\n"
840             + "</html>";
841 
842         getMockWebConnection().setDefaultResponse("");
843         final WebDriver webDriver = loadPage2(html);
844         final WebElement input = webDriver.findElement(By.name("submitBtn"));
845         input.click();
846 
847         assertEquals(Integer.parseInt(getExpectedAlerts()[0]), getMockWebConnection().getRequestCount());
848     }
849 
850     /**
851      * @throws Exception if the test fails
852      */
853     @Test
854     @Alerts({"foo", "foonewValue", "foonewValue"})
855     public void onclickDisablesReset() throws Exception {
856         final String html = DOCTYPE_HTML
857             + "<html><head>\n"
858             + "  <script type='text/javascript'>\n"
859             + "    function submitForm() {\n"
860             + "      document.deliveryChannelForm.resetBtn.disabled = true;\n"
861             + "    }\n"
862             + "  </script>\n"
863             + "</head>\n"
864             + "<body>\n"
865             + "  <form action='test' name='deliveryChannelForm'>\n"
866             + "    <input type='text' id='textfield' value='foo'/>\n"
867             + "    <button name='resetBtn' type='reset' title='Save' onclick='submitForm();'>Save</button>\n"
868             + "  </form>"
869             + "</script>\n"
870             + "</body></html>";
871 
872         final WebDriver webDriver = loadPage2(html);
873 
874         final WebElement textfield = webDriver.findElement(By.id("textfield"));
875         assertEquals(getExpectedAlerts()[0], textfield.getDomAttribute("value"));
876         assertEquals(getExpectedAlerts()[0], textfield.getDomProperty("value"));
877 
878         textfield.sendKeys("newValue");
879         assertEquals(getExpectedAlerts()[0], textfield.getDomAttribute("value"));
880         assertEquals(getExpectedAlerts()[1], textfield.getDomProperty("value"));
881 
882         final WebElement reset = webDriver.findElement(By.name("resetBtn"));
883         reset.click();
884         assertEquals(getExpectedAlerts()[0], textfield.getDomAttribute("value"));
885         assertEquals(getExpectedAlerts()[2], textfield.getDomProperty("value"));
886     }
887 
888     /**
889      * @throws Exception if an error occurs
890      */
891     @Test
892     @Alerts(DEFAULT = {"true", "false", "true", "false", "true", "true", "false", "false", "true", "true"},
893             FF = {"true", "false", "true", "true", "true", "true", "false", "false", "true", "true"},
894             FF_ESR = {"true", "false", "true", "true", "true", "true", "false", "false", "true", "true"})
895     public void willValidate() throws Exception {
896         final String html = DOCTYPE_HTML
897                 + "<html><head>\n"
898                 + "  <script>\n"
899                 + LOG_TITLE_FUNCTION
900                 + "    function test() {\n"
901                 + "      log(document.getElementById('b1').willValidate);\n"
902                 + "      log(document.getElementById('b2').willValidate);\n"
903                 + "      log(document.getElementById('b3').willValidate);\n"
904                 + "      log(document.getElementById('b4').willValidate);\n"
905                 + "      log(document.getElementById('b5').willValidate);\n"
906                 + "      log(document.getElementById('b6').willValidate);\n"
907                 + "      log(document.getElementById('b7').willValidate);\n"
908                 + "      log(document.getElementById('b8').willValidate);\n"
909                 + "      log(document.getElementById('b9').willValidate);\n"
910                 + "      log(document.getElementById('b10').willValidate);\n"
911                 + "    }\n"
912                 + "  </script>\n"
913                 + "</head>\n"
914                 + "<body onload='test()'>\n"
915                 + "  <form>\n"
916                 + "    <button id='b1'>b1</button>\n"
917                 + "    <button id='b2' disabled>b2</button>\n"
918                 + "    <button id='b3' hidden>b3</button>\n"
919                 + "    <button id='b4' readonly>b4</button>\n"
920                 + "    <button id='b5' style='display: none'>b5</button>\n"
921                 + "    <button id='b6' type='submit'>b6</button>\n"
922                 + "    <button id='b7' type='reset'>b7</button>\n"
923                 + "    <button id='b8' type='button'>b8</button>\n"
924                 + "    <button id='b9' type='unknown'>b9</button>\n"
925                 + "    <button id='b10' type=''>b10</button>\n"
926                 + "  </form>\n"
927                 + "</body></html>";
928 
929         loadPageVerifyTitle2(html);
930     }
931 
932     /**
933      * @throws Exception if an error occurs
934      */
935     @Test
936     @Alerts({"true",
937              "false-false-false-false-false-false-false-false-false-true-false",
938              "true"})
939     public void validationEmpty() throws Exception {
940         validation("<button id='b1'>b1</button>\n", "");
941     }
942 
943     /**
944      * @throws Exception if an error occurs
945      */
946     @Test
947     @Alerts({"true",
948              "false-false-false-false-false-false-false-false-false-true-false",
949              "true"})
950     public void validationEmpty_Submit() throws Exception {
951         validation("<button id='b1' type='submit'>b1</button>\n", "");
952     }
953 
954     /**
955      * @throws Exception if an error occurs
956      */
957     @Test
958     @Alerts({"true",
959              "false-false-false-false-false-false-false-false-false-true-false",
960              "false"})
961     public void validationEmpty_Reset() throws Exception {
962         validation("<button id='b1' type='reset'>b1</button>\n", "");
963     }
964 
965     /**
966      * @throws Exception if an error occurs
967      */
968     @Test
969     @Alerts({"false",
970              "false-true-false-false-false-false-false-false-false-false-false",
971              "true"})
972     public void validationCustomValidity() throws Exception {
973         validation("<button id='b1'>b1</button>\n", "elem.setCustomValidity('Invalid');");
974     }
975 
976     /**
977      * @throws Exception if an error occurs
978      */
979     @Test
980     @Alerts({"false",
981              "false-true-false-false-false-false-false-false-false-false-false",
982              "true"})
983     public void validationCustomValidity_Submit() throws Exception {
984         validation("<button id='b1' type='submit'>b1</button>\n", "elem.setCustomValidity('Invalid');");
985     }
986 
987     /**
988      * @throws Exception if an error occurs
989      */
990     @Test
991     @Alerts({"true",
992              "false-true-false-false-false-false-false-false-false-false-false",
993              "false"})
994     public void validationCustomValidity_Reset() throws Exception {
995         validation("<button id='b1' type='reset'>b1</button>\n", "elem.setCustomValidity('Invalid');");
996     }
997 
998     /**
999      * @throws Exception if an error occurs
1000      */
1001     @Test
1002     @Alerts({"false",
1003              "false-true-false-false-false-false-false-false-false-false-false",
1004              "true"})
1005     public void validationBlankCustomValidity() throws Exception {
1006         validation("<button id='b1'>b1</button>\n", "elem.setCustomValidity(' ');\n");
1007     }
1008 
1009     /**
1010      * @throws Exception if an error occurs
1011      */
1012     @Test
1013     @Alerts({"false",
1014              "false-true-false-false-false-false-false-false-false-false-false",
1015              "true"})
1016     public void validationBlankCustomValidity_Submit() throws Exception {
1017         validation("<button id='b1' type='submit'>b1</button>\n", "elem.setCustomValidity(' ');\n");
1018     }
1019 
1020     /**
1021      * @throws Exception if an error occurs
1022      */
1023     @Test
1024     @Alerts({"true",
1025              "false-true-false-false-false-false-false-false-false-false-false",
1026              "false"})
1027     public void validationBlankCustomValidity_Reset() throws Exception {
1028         validation("<button id='b1' type='reset'>b1</button>\n", "elem.setCustomValidity(' ');\n");
1029     }
1030 
1031     /**
1032      * @throws Exception if an error occurs
1033      */
1034     @Test
1035     @Alerts({"true",
1036              "false-false-false-false-false-false-false-false-false-true-false",
1037              "true"})
1038     public void validationResetCustomValidity() throws Exception {
1039         validation("<button id='b1'>b1</button>\n",
1040                 "elem.setCustomValidity('Invalid');elem.setCustomValidity('');");
1041     }
1042 
1043     /**
1044      * @throws Exception if an error occurs
1045      */
1046     @Test
1047     @Alerts({"true",
1048              "false-false-false-false-false-false-false-false-false-true-false",
1049              "true"})
1050     public void validationResetCustomValidity_Submit() throws Exception {
1051         validation("<button id='b1' type='submit'>b1</button>\n",
1052                 "elem.setCustomValidity('Invalid');elem.setCustomValidity('');");
1053     }
1054 
1055     /**
1056      * @throws Exception if an error occurs
1057      */
1058     @Test
1059     @Alerts({"true",
1060              "false-false-false-false-false-false-false-false-false-true-false",
1061              "false"})
1062     public void validationResetCustomValidity_Reset() throws Exception {
1063         validation("<button id='b1' type='reset'>b1</button>\n",
1064                 "elem.setCustomValidity('Invalid');elem.setCustomValidity('');");
1065     }
1066 
1067     /**
1068      * @throws Exception if an error occurs
1069      */
1070     @Test
1071     @Alerts({"true",
1072              "false-false-false-false-false-false-false-false-false-true-false",
1073              "true"})
1074     public void validationRequired() throws Exception {
1075         validation("<button id='b1' required>b1</button>\n", "");
1076     }
1077 
1078     /**
1079      * @throws Exception if an error occurs
1080      */
1081     @Test
1082     @Alerts({"true",
1083              "false-false-false-false-false-false-false-false-false-true-false",
1084              "true"})
1085     public void validationRequired_Submit() throws Exception {
1086         validation("<button id='b1' type='submit' required>b1</button>\n", "");
1087     }
1088 
1089     /**
1090      * @throws Exception if an error occurs
1091      */
1092     @Test
1093     @Alerts({"true",
1094              "false-false-false-false-false-false-false-false-false-true-false",
1095              "false"})
1096     public void validationRequired_Reset() throws Exception {
1097         validation("<button id='b1' type='reset' required>b1</button>\n", "");
1098     }
1099 
1100     private void validation(final String htmlPart, final String jsPart) throws Exception {
1101         final String html = DOCTYPE_HTML
1102                 + "<html><head>\n"
1103                 + "  <script>\n"
1104                 + LOG_TITLE_FUNCTION
1105                 + "    function logValidityState(s) {\n"
1106                 + "      log(s.badInput"
1107                         + "+ '-' + s.customError"
1108                         + "+ '-' + s.patternMismatch"
1109                         + "+ '-' + s.rangeOverflow"
1110                         + "+ '-' + s.rangeUnderflow"
1111                         + "+ '-' + s.stepMismatch"
1112                         + "+ '-' + s.tooLong"
1113                         + "+ '-' + s.tooShort"
1114                         + " + '-' + s.typeMismatch"
1115                         + " + '-' + s.valid"
1116                         + " + '-' + s.valueMissing);\n"
1117                 + "    }\n"
1118                 + "    function test() {\n"
1119                 + "      var elem = document.getElementById('b1');\n"
1120                 + jsPart
1121                 + "      log(elem.checkValidity());\n"
1122                 + "      logValidityState(elem.validity);\n"
1123                 + "      log(elem.willValidate);\n"
1124                 + "    }\n"
1125                 + "  </script>\n"
1126                 + "</head>\n"
1127                 + "<body onload='test()'>\n"
1128                 + "  <form>\n"
1129                 + htmlPart
1130                 + "  </form>\n"
1131                 + "</body></html>";
1132 
1133         loadPageVerifyTitle2(html);
1134     }
1135 }