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