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 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.WebElement;
23  
24  /**
25   * Tests for {@link HtmlHiddenInput}.
26   *
27   * @author Marc Guillemot
28   * @author Ronald Brill
29   * @author Frank Danek
30   */
31  public class HtmlHiddenInputTest extends WebDriverTestCase {
32  
33      /**
34       * Verifies that getText() returns an empty string.
35       * @throws Exception if the test fails
36       */
37      @Test
38      public void getText() throws Exception {
39          final String htmlContent = DOCTYPE_HTML
40              + "<html>\n"
41              + "<head></head>\n"
42              + "<body>\n"
43              + "<form id='form1'>\n"
44              + "  <input type='hidden' name='foo' id='foo' value='bla'>\n"
45              + "</form></body></html>";
46  
47          final WebDriver driver = loadPage2(htmlContent);
48  
49          final WebElement input = driver.findElement(By.id("foo"));
50          assertEquals("", input.getText());
51      }
52  
53      /**
54       * @throws Exception if an error occurs
55       */
56      @Test
57      public void setValueOnChange() throws Exception {
58          final String html = DOCTYPE_HTML
59                + "<html>\n"
60                + "<head>\n"
61                + "<script>\n"
62                + LOG_TITLE_FUNCTION
63                + "</script>\n"
64                + "</head>\n"
65                + "<body>\n"
66                + "  <input type='hidden' id='h' value='Hello world'"
67                      + " onChange='log(\"foo\");log(event.type);'>\n"
68                + "  <button id='b'>some button</button>\n"
69                + "  <button id='set' onclick='document.getElementById(\"h\").value=\"HtmlUnit\"'>setValue</button>\n"
70                + "</body></html>";
71  
72          final WebDriver driver = loadPage2(html);
73          driver.findElement(By.id("set")).click();
74  
75          assertEquals("", driver.getTitle());
76  
77          // trigger lost focus
78          driver.findElement(By.id("b")).click();
79          assertEquals("", driver.getTitle());
80      }
81  
82      /**
83       * @throws Exception if an error occurs
84       */
85      @Test
86      public void setDefaultValueOnChange() throws Exception {
87          final String html =
88                "<html>\n"
89                + "<head>\n"
90                + "<script>\n"
91                + LOG_TITLE_FUNCTION
92                + "</script>\n"
93                + "</head>\n"
94                + "<body>\n"
95                + "  <input type='hidden' id='h' value='Hello world'"
96                      + " onChange='log(\"foo\");log(event.type);'>\n"
97                + "  <button id='b'>some button</button>\n"
98                + "  <button id='set' onclick='document.getElementById(\"h\").defaultValue=\"HtmlUnit\"'>"
99                        + "setValue</button>\n"
100               + "</body></html>";
101 
102         final WebDriver driver = loadPage2(html);
103         driver.findElement(By.id("set")).click();
104 
105         assertEquals("", driver.getTitle());
106 
107         // trigger lost focus
108         driver.findElement(By.id("b")).click();
109         assertEquals("", driver.getTitle());
110     }
111 
112     /**
113      * @throws Exception if the test fails
114      */
115     @Test
116     @Alerts({"--null", "--null", "--null"})
117     public void defaultValues() throws Exception {
118         final String html = DOCTYPE_HTML
119             + "<html><head>\n"
120             + "<script>\n"
121             + LOG_TITLE_FUNCTION
122             + "  function test() {\n"
123             + "    var input = document.getElementById('hidden1');\n"
124             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
125 
126             + "    input = document.createElement('input');\n"
127             + "    input.type = 'hidden';\n"
128             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
129 
130             + "    var builder = document.createElement('div');\n"
131             + "    builder.innerHTML = '<input type=\"hidden\">';\n"
132             + "    input = builder.firstChild;\n"
133             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
134             + "  }\n"
135             + "</script>\n"
136             + "</head><body onload='test()'>\n"
137             + "<form>\n"
138             + "  <input type='hidden' id='hidden1'>\n"
139             + "</form>\n"
140             + "</body></html>";
141 
142         loadPageVerifyTitle2(html);
143     }
144 
145     /**
146      * @throws Exception if the test fails
147      */
148     @Test
149     @Alerts({"--null", "--null", "--null"})
150     public void defaultValuesAfterClone() throws Exception {
151         final String html = DOCTYPE_HTML
152             + "<html><head>\n"
153             + "<script>\n"
154             + LOG_TITLE_FUNCTION
155             + "  function test() {\n"
156             + "    var input = document.getElementById('hidden1');\n"
157             + "    input = input.cloneNode(false);\n"
158             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
159 
160             + "    input = document.createElement('input');\n"
161             + "    input.type = 'hidden';\n"
162             + "    input = input.cloneNode(false);\n"
163             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
164 
165             + "    var builder = document.createElement('div');\n"
166             + "    builder.innerHTML = '<input type=\"hidden\">';\n"
167             + "    input = builder.firstChild;\n"
168             + "    input = input.cloneNode(false);\n"
169             + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
170             + "  }\n"
171             + "</script>\n"
172             + "</head><body onload='test()'>\n"
173             + "<form>\n"
174             + "  <input type='hidden' id='hidden1'>\n"
175             + "</form>\n"
176             + "</body></html>";
177 
178         loadPageVerifyTitle2(html);
179     }
180 
181     /**
182      * @throws Exception if the test fails
183      */
184     @Test
185     @Alerts({"initial-initial-initial", "initial-initial-initial",
186                 "newValue-newValue-newValue", "newValue-newValue-newValue",
187                 "newDefault-newDefault-newDefault", "newDefault-newDefault-newDefault"})
188     public void resetByClick() throws Exception {
189         final String html = DOCTYPE_HTML
190             + "<html><head>\n"
191             + "<script>\n"
192             + LOG_TITLE_FUNCTION
193             + "  function test() {\n"
194             + "    var hidden = document.getElementById('testId');\n"
195             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
196 
197             + "    document.getElementById('testReset').click;\n"
198             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
199 
200             + "    hidden.value = 'newValue';\n"
201             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
202 
203             + "    document.getElementById('testReset').click;\n"
204             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
205 
206             + "    hidden.defaultValue = 'newDefault';\n"
207             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
208 
209             + "    document.forms[0].reset;\n"
210             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
211             + "  }\n"
212             + "</script>\n"
213             + "</head><body onload='test()'>\n"
214             + "<form>\n"
215             + "  <input type='hidden' id='testId' value='initial'>\n"
216             + "  <input type='reset' id='testReset'>\n"
217             + "</form>\n"
218             + "</body></html>";
219 
220         loadPageVerifyTitle2(html);
221     }
222 
223     /**
224      * @throws Exception if the test fails
225      */
226     @Test
227     @Alerts({"initial-initial-initial", "initial-initial-initial",
228                 "newValue-newValue-newValue", "newValue-newValue-newValue",
229                 "newDefault-newDefault-newDefault", "newDefault-newDefault-newDefault"})
230     public void resetByJS() throws Exception {
231         final String html = DOCTYPE_HTML
232             + "<html><head>\n"
233             + "<script>\n"
234             + LOG_TITLE_FUNCTION
235             + "  function test() {\n"
236             + "    var hidden = document.getElementById('testId');\n"
237             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
238 
239             + "    document.forms[0].reset;\n"
240             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
241 
242             + "    hidden.value = 'newValue';\n"
243             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
244 
245             + "    document.forms[0].reset;\n"
246             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
247 
248             + "    hidden.defaultValue = 'newDefault';\n"
249             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
250 
251             + "    document.forms[0].reset;\n"
252             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
253             + "  }\n"
254             + "</script>\n"
255             + "</head><body onload='test()'>\n"
256             + "<form>\n"
257             + "  <input type='hidden' id='testId' value='initial'>\n"
258             + "</form>\n"
259             + "</body></html>";
260 
261         loadPageVerifyTitle2(html);
262     }
263 
264     /**
265      * @throws Exception if the test fails
266      */
267     @Test
268     @Alerts({"initial-initial-initial", "default-default-default",
269                 "newValue-newValue-newValue", "attribValue-attribValue-attribValue",
270                 "newDefault-newDefault-newDefault"})
271     public void value() throws Exception {
272         final String html = DOCTYPE_HTML
273             + "<html><head>\n"
274             + "<script>\n"
275             + LOG_TITLE_FUNCTION
276             + "  function test() {\n"
277             + "    var hidden = document.getElementById('testId');\n"
278             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
279 
280             + "    hidden.defaultValue = 'default';\n"
281             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
282 
283             + "    hidden.value = 'newValue';\n"
284             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
285 
286             + "    hidden.setAttribute('value', 'attribValue');\n"
287             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
288 
289             + "    hidden.defaultValue = 'newDefault';\n"
290             + "    log(hidden.value + '-' + hidden.defaultValue + '-' + hidden.getAttribute('value'));\n"
291             + "  }\n"
292             + "</script>\n"
293             + "</head><body onload='test()'>\n"
294             + "<form>\n"
295             + "  <input type='hidden' id='testId' value='initial'>\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(DEFAULT = "textLength not available",
307             FF = "7",
308             FF_ESR = "7")
309     public void textLength() throws Exception {
310         final String html = DOCTYPE_HTML
311             + "<html><head>\n"
312             + "<script>\n"
313             + LOG_TITLE_FUNCTION
314             + "  function test() {\n"
315             + "    var text = document.getElementById('testId');\n"
316             + "    if(text.textLength) {\n"
317             + "      log(text.textLength);\n"
318             + "    } else {\n"
319             + "      log('textLength not available');\n"
320             + "    }\n"
321             + "  }\n"
322             + "</script>\n"
323             + "</head><body onload='test()'>\n"
324             + "<form>\n"
325             + "  <input type='text' id='testId' value='initial'>\n"
326             + "</form>\n"
327             + "</body></html>";
328 
329         loadPageVerifyTitle2(html);
330     }
331 
332     /**
333      * @throws Exception if the test fails
334      */
335     @Test
336     @Alerts("--")
337     public void minMaxStep() throws Exception {
338         final String html = DOCTYPE_HTML
339             + "<html>\n"
340             + "<head>\n"
341             + "<script>\n"
342             + LOG_TITLE_FUNCTION
343             + "  function test() {\n"
344             + "    var input = document.getElementById('tester');\n"
345             + "    log(input.min + '-' + input.max + '-' + input.step);\n"
346             + "  }\n"
347             + "</script>\n"
348             + "</head>\n"
349             + "<body onload='test()'>\n"
350             + "<form>\n"
351             + "  <input type='hidden' id='tester'>\n"
352             + "</form>\n"
353             + "</body>\n"
354             + "</html>";
355 
356         loadPageVerifyTitle2(html);
357     }
358 
359     /**
360      * @throws Exception if an error occurs
361      */
362     @Test
363     @Alerts({"false", "false", "false", "false", "false"})
364     public void willValidate() throws Exception {
365         final String html = DOCTYPE_HTML
366                 + "<html><head>\n"
367                 + "  <script>\n"
368                 + LOG_TITLE_FUNCTION
369                 + "    function test() {\n"
370                 + "      log(document.getElementById('o1').willValidate);\n"
371                 + "      log(document.getElementById('o2').willValidate);\n"
372                 + "      log(document.getElementById('o3').willValidate);\n"
373                 + "      log(document.getElementById('o4').willValidate);\n"
374                 + "      log(document.getElementById('o5').willValidate);\n"
375                 + "    }\n"
376                 + "  </script>\n"
377                 + "</head>\n"
378                 + "<body onload='test()'>\n"
379                 + "  <form>\n"
380                 + "    <input type='hidden' id='o1'>\n"
381                 + "    <input type='hidden' id='o2' disabled>\n"
382                 + "    <input type='hidden' id='o3' hidden>\n"
383                 + "    <input type='hidden' id='o4' readonly>\n"
384                 + "    <input type='hidden' id='o5' style='display: none'>\n"
385                 + "  </form>\n"
386                 + "</body></html>";
387 
388         loadPageVerifyTitle2(html);
389     }
390 
391     /**
392      * @throws Exception if an error occurs
393      */
394     @Test
395     @Alerts({"true",
396              "false-false-false-false-false-false-false-false-false-true-false",
397              "false"})
398     public void validationEmpty() throws Exception {
399         validation("<input type='hidden' id='e1'>\n", "");
400     }
401 
402     /**
403      * @throws Exception if an error occurs
404      */
405     @Test
406     @Alerts({"true",
407              "false-true-false-false-false-false-false-false-false-false-false",
408              "false"})
409     public void validationCustomValidity() throws Exception {
410         validation("<input type='hidden' id='e1'>\n", "elem.setCustomValidity('Invalid');");
411     }
412 
413     /**
414      * @throws Exception if an error occurs
415      */
416     @Test
417     @Alerts({"true",
418              "false-true-false-false-false-false-false-false-false-false-false",
419              "false"})
420     public void validationBlankCustomValidity() throws Exception {
421         validation("<input type='hidden' id='e1'>\n", "elem.setCustomValidity(' ');\n");
422     }
423 
424     /**
425      * @throws Exception if an error occurs
426      */
427     @Test
428     @Alerts({"true",
429              "false-false-false-false-false-false-false-false-false-true-false",
430              "false"})
431     public void validationResetCustomValidity() throws Exception {
432         validation("<input type='hidden' id='e1'>\n",
433                 "elem.setCustomValidity('Invalid');elem.setCustomValidity('');");
434     }
435 
436     /**
437      * @throws Exception if an error occurs
438      */
439     @Test
440     @Alerts({"true",
441              "false-false-false-false-false-false-false-false-false-true-false",
442              "false"})
443     public void validationRequired() throws Exception {
444         validation("<input type='hidden' id='e1' required>\n", "");
445     }
446 
447     /**
448      * @throws Exception if an error occurs
449      */
450     @Test
451     @Alerts({"true",
452              "false-false-false-false-false-false-false-false-false-true-false",
453              "false"})
454     public void validationRequiredValueSet() throws Exception {
455         validation("<input type='hidden' id='e1' required>\n", "elem.value='secret';");
456     }
457 
458     private void validation(final String htmlPart, final String jsPart) throws Exception {
459         final String html = DOCTYPE_HTML
460                 + "<html><head>\n"
461                 + "  <script>\n"
462                 + LOG_TITLE_FUNCTION
463                 + "    function logValidityState(s) {\n"
464                 + "      log(s.badInput"
465                         + "+ '-' + s.customError"
466                         + "+ '-' + s.patternMismatch"
467                         + "+ '-' + s.rangeOverflow"
468                         + "+ '-' + s.rangeUnderflow"
469                         + "+ '-' + s.stepMismatch"
470                         + "+ '-' + s.tooLong"
471                         + "+ '-' + s.tooShort"
472                         + " + '-' + s.typeMismatch"
473                         + " + '-' + s.valid"
474                         + " + '-' + s.valueMissing);\n"
475                 + "    }\n"
476                 + "    function test() {\n"
477                 + "      var elem = document.getElementById('e1');\n"
478                 + jsPart
479                 + "      log(elem.checkValidity());\n"
480                 + "      logValidityState(elem.validity);\n"
481                 + "      log(elem.willValidate);\n"
482                 + "    }\n"
483                 + "  </script>\n"
484                 + "</head>\n"
485                 + "<body onload='test()'>\n"
486                 + "  <form>\n"
487                 + htmlPart
488                 + "  </form>\n"
489                 + "</body></html>";
490 
491         loadPageVerifyTitle2(html);
492     }
493 }