View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.html;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.BrowserRunner;
19  import org.htmlunit.junit.annotation.Alerts;
20  import org.junit.Test;
21  import org.junit.runner.RunWith;
22  import org.openqa.selenium.By;
23  import org.openqa.selenium.WebDriver;
24  import org.openqa.selenium.interactions.Actions;
25  
26  /**
27   * Tests for {@link HTMLButtonElement}.
28   *
29   * @author Daniel Gredler
30   * @author Ahmed Ashour
31   * @author Ronald Brill
32   * @author Frank Danek
33   */
34  @RunWith(BrowserRunner.class)
35  public class HTMLButtonElementTest extends WebDriverTestCase {
36  
37      /**
38       * @throws Exception if an error occurs
39       */
40      @Test
41      @Alerts({"", "A", "a", "A", "a8", "8Afoo", "8", "@"})
42      public void readWriteAccessKey() throws Exception {
43          final String html = DOCTYPE_HTML
44              + "<html><body>\n"
45              + "<button id='a1'>a1</button><button id='a2' accesskey='A'>a2</button>\n"
46              + "<script>\n"
47              + LOG_TITLE_FUNCTION
48              + "var a1 = document.getElementById('a1'), a2 = document.getElementById('a2');\n"
49              + "log(a1.accessKey);\n"
50              + "log(a2.accessKey);\n"
51              + "a1.accessKey = 'a';\n"
52              + "a2.accessKey = 'A';\n"
53              + "log(a1.accessKey);\n"
54              + "log(a2.accessKey);\n"
55              + "a1.accessKey = 'a8';\n"
56              + "a2.accessKey = '8Afoo';\n"
57              + "log(a1.accessKey);\n"
58              + "log(a2.accessKey);\n"
59              + "a1.accessKey = '8';\n"
60              + "a2.accessKey = '@';\n"
61              + "log(a1.accessKey);\n"
62              + "log(a2.accessKey);\n"
63              + "</script></body></html>";
64  
65          loadPageVerifyTitle2(html);
66      }
67  
68      /**
69       * Tests setting the <tt>type</tt> property.
70       * @throws Exception if the test fails
71       */
72      @Test
73      @Alerts({"submit", "button", "submit"})
74      public void type() throws Exception {
75          final String html = DOCTYPE_HTML
76              + "<html><head>\n"
77              + "<script>\n"
78              + LOG_TITLE_FUNCTION
79              + "  function test() {\n"
80              + "    var b = document.createElement('button');\n"
81              + "    log(b.type);\n"
82              + "    try {\n"
83              + "      b.type = 'button';\n"
84              + "    } catch(e) { logEx(e) }\n"
85              + "    log(b.type);\n"
86              + "    b.removeAttribute('type');\n"
87              + "    log(b.type);\n"
88              + "  }\n"
89              + "</script></head><body onload='test()'>\n"
90              + "</body></html>";
91  
92          loadPageVerifyTitle2(html);
93      }
94  
95      /**
96       * @throws Exception if the test fails
97       */
98      @Test
99      @Alerts({"submit", "submit", "submit", "submit", "reset", "button", "submit"})
100     public void getType() throws Exception {
101         final String html = DOCTYPE_HTML
102             + "<html>\n"
103             + "<head>\n"
104             + "<script>\n"
105             + LOG_TITLE_FUNCTION
106             + "  function test() {\n"
107             + "    log(document.getElementById('myNone').type);\n"
108             + "    log(document.getElementById('myEmpty').type);\n"
109             + "    log(document.getElementById('mySubmit').type);\n"
110             + "    log(document.getElementById('mySubmitTrim').type);\n"
111             + "    log(document.getElementById('myReset').type);\n"
112             + "    log(document.getElementById('myButton').type);\n"
113             + "    log(document.getElementById('myUnknown').type);\n"
114             + "  }\n"
115             + "</script>\n"
116             + "</head>\n"
117             + "<body onload='test()'>\n"
118             + "  <p>hello world</p>\n"
119             + "  <form id='myForm' action='" + URL_SECOND + "'>\n"
120             + "    <button id='myNone'></button>\n"
121             + "    <button type='' id='myEmpty'></button>\n"
122             + "    <button type='submit' id='mySubmit'></button>\n"
123             + "    <button type=' Submit\t' id='mySubmitTrim'></button>\n"
124             + "    <button type='reSet' id='myReset'></button>\n"
125             + "    <button type='button' id='myButton'></button>\n"
126             + "    <button type='unknown' id='myUnknown'></button>\n"
127             + "  </form>\n"
128             + "</body></html>";
129 
130         loadPageVerifyTitle2(html);
131     }
132 
133     /**
134      * @throws Exception if the test fails
135      */
136     @Test
137     @Alerts({"myFormId", "null", "null", "null", "null", "myFormId", "null", "myForm2Id", "myForm2Id"})
138     public void getForm() throws Exception {
139         final String html = DOCTYPE_HTML
140             + "<html>\n"
141             + "<head>\n"
142             + "<script>\n"
143             + LOG_TITLE_FUNCTION
144             + "  function show(id) {\n"
145             + "    elem = document.getElementById(id);\n"
146             + "    if (elem.form) {\n"
147             + "      log(elem.form.id);\n"
148             + "    } else {\n"
149             + "      log(elem.form);\n"
150             + "    }\n"
151             + "  }\n"
152             + "  function test() {\n"
153             + "    show('myNone');\n"
154             + "    show('myEmptyInside');\n"
155             + "    show('myEmptyOutside');\n"
156             + "    show('myFormTrim');\n"
157             + "    show('myFormCase');\n"
158             + "    show('myOutside');\n"
159             + "    show('myUnknown');\n"
160             + "    show('myFormOther');\n"
161             + "    show('myFormOtherOutside');\n"
162             + "  }\n"
163             + "</script>\n"
164             + "</head>\n"
165             + "<body onload='test()'>\n"
166             + "  <p>hello world</p>\n"
167             + "  <form id='myFormId' action='" + URL_SECOND + "'>\n"
168             + "    <button id='myNone'></button>\n"
169             + "    <button form='' id='myEmptyInside'></button>\n"
170             + "    <button form='myFormId' id='myForm'></button>\n"
171             + "    <button form=' myFormId\t' id='myFormTrim'></button>\n"
172             + "    <button form='myformid' id='myFormCase'></button>\n"
173             + "    <button form='unknown' id='myUnknown'></button>\n"
174             + "    <button form='myForm2Id' id='myFormOther'></button>\n"
175             + "  </form>\n"
176             + "  <form id='myForm2Id' action='" + URL_SECOND + "'>\n"
177             + "  </form>\n"
178             + "  <button form='myFormId' id='myOutside'></button>\n"
179             + "  <button form='' id='myEmptyOutside'></button>\n"
180             + "  <button form='myForm2Id' id='myFormOtherOutside'></button>\n"
181             + "</body></html>";
182 
183         loadPageVerifyTitle2(html);
184     }
185 
186     /**
187      * @throws Exception if an error occurs
188      */
189     @Test
190     @Alerts({"test", "4", "42", "2", "[object HTMLButtonElement]", "26"})
191     public void getAttributeAndSetValue() throws Exception {
192         final String html = DOCTYPE_HTML
193             + "<html>\n"
194             + "  <head>\n"
195             + "    <script>\n"
196             + LOG_TITLE_FUNCTION
197             + "      function test() {\n"
198             + "        var t = document.getElementById('t');\n"
199             + "        t.value = 'test';\n"
200             + "        log(t.value);\n"
201             + "        if (t.value != null)\n"
202             + "          log(t.value.length);\n"
203 
204             + "        t.value = 42;\n"
205             + "        log(t.value);\n"
206             + "        if (t.value != null)\n"
207             + "          log(t.value.length);\n"
208 
209             + "        t.value = document.getElementById('t');\n"
210             + "        log(t.value);\n"
211             + "        if (t.value != null)\n"
212             + "          log(t.value.length);\n"
213             + "      }\n"
214             + "    </script>\n"
215             + "  </head>\n"
216             + "  <body onload='test()'>\n"
217             + "    <button id='t'>abc</button>\n"
218             + "  </body>\n"
219             + "</html>";
220 
221         loadPageVerifyTitle2(html);
222     }
223 
224     /**
225      * @throws Exception if an error occurs
226      */
227     @Test
228     @Alerts({"null", "4", "null", "4"})
229     public void getAttributeAndSetValueNull() throws Exception {
230         final String html = DOCTYPE_HTML
231             + "<html>\n"
232             + "  <head>\n"
233             + "    <script>\n"
234             + LOG_TITLE_FUNCTION
235             + "      function test() {\n"
236             + "        var t = document.getElementById('t');\n"
237             + "        t.value = 'null';\n"
238             + "        log(t.value);\n"
239             + "        if (t.value != null)\n"
240             + "          log(t.value.length);\n"
241 
242             + "        t.value = null;\n"
243             + "        log(t.value);\n"
244             + "        if (t.value != null)\n"
245             + "          log(t.value.length);\n"
246             + "      }\n"
247             + "    </script>\n"
248             + "  </head>\n"
249             + "  <body onload='test()'>\n"
250             + "    <button id='t'>abc</button>\n"
251             + "  </body>\n"
252             + "</html>";
253 
254         loadPageVerifyTitle2(html);
255     }
256 
257     /**
258      * @throws Exception if an error occurs
259      */
260     @Test
261     @Alerts({"0", "2", "1", "2", "1", "1"})
262     public void labels() throws Exception {
263         final String html = DOCTYPE_HTML
264             + "<html><head>\n"
265             + "  <script>\n"
266             + LOG_TITLE_FUNCTION
267             + "    function test() {\n"
268             + "      debug(document.getElementById('e1'));\n"
269             + "      debug(document.getElementById('e2'));\n"
270             + "      debug(document.getElementById('e3'));\n"
271             + "      debug(document.getElementById('e4'));\n"
272             + "      var labels = document.getElementById('e4').labels;\n"
273             + "      document.body.removeChild(document.getElementById('l4'));\n"
274             + "      debug(document.getElementById('e4'));\n"
275             + "      log(labels ? labels.length : labels);\n"
276             + "    }\n"
277             + "    function debug(e) {\n"
278             + "      log(e.labels ? e.labels.length : e.labels);\n"
279             + "    }\n"
280             + "  </script>\n"
281             + "</head>\n"
282             + "<body onload='test()'>\n"
283             + "  <button id='e1'>e 1</button><br>\n"
284             + "  <label>something <label> click here <button id='e2'>e 2</button></label></label><br>\n"
285             + "  <label for='e3'> and here</label>\n"
286             + "  <button id='e3'>e 3</button><br>\n"
287             + "  <label id='l4' for='e4'> what about</label>\n"
288             + "  <label> this<button id='e4'>e 4</button></label><br>\n"
289             + "</body></html>";
290 
291         loadPageVerifyTitle2(html);
292     }
293 
294     /**
295      * @throws Exception if the test fails
296      */
297     @Test
298     @Alerts("[object HTMLFormElement]")
299     public void form() throws Exception {
300         final String html = DOCTYPE_HTML
301             + "<html>\n"
302             + "<body>\n"
303             + "  <form>\n"
304             + "    <button id='a'>button</button><br>\n"
305             + "  </form>"
306             + "  <script>\n"
307             + LOG_TITLE_FUNCTION
308             + "    log(document.getElementById('a').form);\n"
309             + "  </script>"
310             + "</body>"
311             + "</html>";
312 
313         loadPageVerifyTitle2(html);
314     }
315 
316     /**
317      * @throws Exception if an error occurs
318      */
319     @Test
320     @Alerts("mouse over [btn]")
321     public void mouseOver() throws Exception {
322         final String html = DOCTYPE_HTML
323             + "<html>\n"
324             + "  <head>\n"
325             + "    <script>\n"
326             + LOG_TITLE_FUNCTION
327             + "    function dumpEvent(event) {\n"
328             + "      // target\n"
329             + "      var eTarget;\n"
330             + "      if (event.target) {\n"
331             + "        eTarget = event.target;\n"
332             + "      } else if (event.srcElement) {\n"
333             + "        eTarget = event.srcElement;\n"
334             + "      }\n"
335             + "      // defeat Safari bug\n"
336             + "      if (eTarget.nodeType == 3) {\n"
337             + "        eTarget = eTarget.parentNode;\n"
338             + "      }\n"
339             + "      var msg = 'mouse over';\n"
340             + "      if (eTarget.name) {\n"
341             + "        msg = msg + ' [' + eTarget.name + ']';\n"
342             + "      } else {\n"
343             + "        msg = msg + ' [' + eTarget.id + ']';\n"
344             + "      }\n"
345             + "      log(msg);\n"
346             + "    }\n"
347             + "    </script>\n"
348             + "  </head>\n"
349             + "<body>\n"
350             + "  <form id='form1'>\n"
351             + "    <button id='btn' onmouseover='dumpEvent(event);'>button</button><br>\n"
352             + "  </form>\n"
353             + "</body></html>";
354 
355         final WebDriver driver = loadPage2(html);
356 
357         final Actions actions = new Actions(driver);
358         actions.moveToElement(driver.findElement(By.id("btn")));
359         actions.perform();
360 
361         verifyTitle2(driver, getExpectedAlerts());
362     }
363 
364     /**
365      * @throws Exception if an error occurs
366      */
367     @Test
368     @Alerts("Test:mouse over [disabledBtn]")
369     public void mouseOverDiabled() throws Exception {
370         final String html = DOCTYPE_HTML
371             + "<html>\n"
372             + "  <head>\n"
373             + "    <title>Test:</title>\n"
374             + "    <script>\n"
375             + "    function dumpEvent(event) {\n"
376             + "      // target\n"
377             + "      var eTarget;\n"
378             + "      if (event.target) {\n"
379             + "        eTarget = event.target;\n"
380             + "      } else if (event.srcElement) {\n"
381             + "        eTarget = event.srcElement;\n"
382             + "      }\n"
383             + "      // defeat Safari bug\n"
384             + "      if (eTarget.nodeType == 3) {\n"
385             + "        eTarget = eTarget.parentNode;\n"
386             + "      }\n"
387             + "      var msg = 'mouse over';\n"
388             + "      if (eTarget.name) {\n"
389             + "        msg = msg + ' [' + eTarget.name + ']';\n"
390             + "      } else {\n"
391             + "        msg = msg + ' [' + eTarget.id + ']';\n"
392             + "      }\n"
393             + "      document.title += msg;\n"
394             + "    }\n"
395             + "    </script>\n"
396             + "  </head>\n"
397             + "<body>\n"
398             + "  <form id='form1'>\n"
399             + "    <button id='disabledBtn' onmouseover='dumpEvent(event);' disabled>disabled button</button><br>\n"
400             + "  </form>\n"
401             + "</body></html>";
402 
403         final WebDriver driver = loadPage2(html);
404 
405         final Actions actions = new Actions(driver);
406         actions.moveToElement(driver.findElement(By.id("disabledBtn")));
407         actions.perform();
408 
409         assertTitle(driver, getExpectedAlerts()[0]);
410     }
411 
412     /**
413      * @throws Exception if the test fails
414      */
415     @Test
416     @Alerts({"false", "false", "true", "false"})
417     public void formNoValidate() throws Exception {
418         final String html = DOCTYPE_HTML
419             + "<html><head>\n"
420             + "<script>\n"
421             + LOG_TITLE_FUNCTION
422             + "  function test() {\n"
423             + "    var b = document.createElement('button');\n"
424             + "    log(b.formNoValidate);\n"
425 
426             + "    b.formNoValidate = '';\n"
427             + "    log(b.formNoValidate);\n"
428 
429             + "    b.formNoValidate = 'yes';\n"
430             + "    log(b.formNoValidate);\n"
431 
432             + "    b.removeAttribute('formNoValidate');\n"
433             + "    log(b.formNoValidate);\n"
434             + "  }\n"
435             + "</script></head><body onload='test()'>\n"
436             + "</body></html>";
437 
438         loadPageVerifyTitle2(html);
439     }
440 
441     /**
442      * @throws Exception if an error occurs
443      */
444     @Test
445     @Alerts(DEFAULT = {"true", "false", "true", "false", "true"},
446             FF = {"true", "false", "true", "true", "true"},
447             FF_ESR = {"true", "false", "true", "true", "true"})
448     public void willValidate() throws Exception {
449         final String html = DOCTYPE_HTML
450                 + "<html><head>\n"
451                 + "  <script>\n"
452                 + LOG_TITLE_FUNCTION
453                 + "    function test() {\n"
454                 + "      log(document.getElementById('i1').willValidate);\n"
455                 + "      log(document.getElementById('i2').willValidate);\n"
456                 + "      log(document.getElementById('i3').willValidate);\n"
457                 + "      log(document.getElementById('i4').willValidate);\n"
458                 + "      log(document.getElementById('i5').willValidate);\n"
459                 + "    }\n"
460                 + "  </script>\n"
461                 + "</head>\n"
462                 + "<body onload='test()'>\n"
463                 + "  <form>\n"
464                 + "    <button id='i1'>button</button>"
465                 + "    <button id='i2' disabled></button>"
466                 + "    <button id='i3' hidden></button>"
467                 + "    <button id='i4' readonly></button>"
468                 + "    <button id='i5' style='display: none'></button>"
469                 + "  </form>\n"
470                 + "</body></html>";
471 
472         loadPageVerifyTitle2(html);
473     }
474 }