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