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