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.htmlunit.junit.annotation.BuggyWebDriver;
21  import org.junit.Test;
22  import org.junit.runner.RunWith;
23  import org.openqa.selenium.By;
24  import org.openqa.selenium.WebDriver;
25  import org.openqa.selenium.WebElement;
26  
27  /**
28   * Tests for {@link HtmlDateInput}.
29   *
30   * @author Ahmed Ashour
31   * @author Ronald Brill
32   * @author Anton Demydenko
33   */
34  @RunWith(BrowserRunner.class)
35  public class HtmlDateInputTest extends WebDriverTestCase {
36  
37      /**
38       * @throws Exception if the test fails
39       */
40      @Test
41      @Alerts({"--null", "--null", "--null"})
42      public void defaultValues() throws Exception {
43          final String html = DOCTYPE_HTML
44              + "<html><head>\n"
45              + "<script>\n"
46              + LOG_TITLE_FUNCTION
47              + "  function test() {\n"
48              + "    var input = document.getElementById('text1');\n"
49              + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
50  
51              + "    try {\n"
52              + "      input = document.createElement('input');\n"
53              + "      input.type = 'date';\n"
54              + "      log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
55              + "    } catch(e)  { logEx(e); }\n"
56  
57              + "    var builder = document.createElement('div');\n"
58              + "    builder.innerHTML = '<input type=\"date\">';\n"
59              + "    input = builder.firstChild;\n"
60              + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
61              + "  }\n"
62              + "</script>\n"
63              + "</head><body onload='test()'>\n"
64              + "<form>\n"
65              + "  <input type='date' id='text1'>\n"
66              + "</form>\n"
67              + "</body></html>";
68  
69          loadPageVerifyTitle2(html);
70      }
71  
72      /**
73       * @throws Exception if the test fails
74       */
75      @Test
76      @Alerts({"--null", "--null", "--null"})
77      public void defaultValuesAfterClone() throws Exception {
78          final String html = DOCTYPE_HTML
79              + "<html><head>\n"
80              + "<script>\n"
81              + LOG_TITLE_FUNCTION
82              + "  function test() {\n"
83              + "    var input = document.getElementById('text1');\n"
84              + "    input = input.cloneNode(false);\n"
85              + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
86  
87              + "    try {\n"
88              + "      input = document.createElement('input');\n"
89              + "      input.type = 'date';\n"
90              + "      input = input.cloneNode(false);\n"
91              + "      log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
92              + "    } catch(e)  { logEx(e); }\n"
93  
94              + "    var builder = document.createElement('div');\n"
95              + "    builder.innerHTML = '<input type=\"date\">';\n"
96              + "    input = builder.firstChild;\n"
97              + "    input = input.cloneNode(false);\n"
98              + "    log(input.value + '-' + input.defaultValue + '-' + input.getAttribute('value'));\n"
99              + "  }\n"
100             + "</script>\n"
101             + "</head><body onload='test()'>\n"
102             + "<form>\n"
103             + "  <input type='date' id='text1'>\n"
104             + "</form>\n"
105             + "</body></html>";
106 
107         loadPageVerifyTitle2(html);
108     }
109 
110     /**
111      * @throws Exception if an error occurs
112      */
113     @Test
114     @Alerts({"text-datetime", "date-Date"})
115     public void type() throws Exception {
116         final String html = DOCTYPE_HTML
117               + "<html>\n"
118               + "<head>\n"
119               + "<script>\n"
120               + LOG_TITLE_FUNCTION
121               + "  function test() {\n"
122               + "    var input = document.getElementById('input1');\n"
123               + "    log(input.type + '-' + input.getAttribute('type'));\n"
124               + "    input = document.getElementById('input2');\n"
125               + "    log(input.type + '-' + input.getAttribute('type'));\n"
126               + "  }\n"
127               + "</script>\n"
128               + "</head>\n"
129               + "<body onload='test()'>\n"
130               + "  <input id='input1' type='datetime'>\n"
131               + "  <input id='input2' type='Date'>\n"
132               + "</body></html>";
133 
134         loadPageVerifyTitle2(html);
135     }
136 
137     /**
138      * @throws Exception if an error occurs
139      */
140     @Test
141     @Alerts("2018-03-22")
142     @BuggyWebDriver(CHROME = "80322-02-01",
143                     EDGE = "80322-02-01")
144     public void typeInto() throws Exception {
145         final String html = DOCTYPE_HTML
146               + "<html>\n"
147               + "<head>\n"
148               + "<script>\n"
149               + "  function test() {\n"
150               + "    var input = document.getElementById('input');\n"
151               + "    alert(input.value);\n"
152               + "  }\n"
153               + "</script>\n"
154               + "</head>\n"
155               + "<body>\n"
156               + "  <input id='input' type='date'>\n"
157               + "  <button id='tester' onclick='test()'>Test</button>\n"
158               + "</body></html>";
159 
160         final WebDriver driver = loadPage2(html);
161         driver.findElement(By.id("input")).sendKeys("2018-03-22");
162         driver.findElement(By.id("tester")).click();
163 
164         verifyAlerts(driver, getExpectedAlerts());
165     }
166 
167     /**
168      * @throws Exception if an error occurs
169      */
170     @Test
171     @Alerts({"2018-03-22", ""})
172     public void clearInput() throws Exception {
173         final String html = DOCTYPE_HTML
174               + "<html>\n"
175               + "<body>\n"
176               + "  <input id='input' type='date' value='2018-03-22'>\n"
177               + "</body></html>";
178 
179         final WebDriver driver = loadPage2(html);
180         final WebElement input = driver.findElement(By.id("input"));
181 
182         assertEquals(getExpectedAlerts()[0], input.getDomAttribute("value"));
183         assertEquals(getExpectedAlerts()[0], input.getDomProperty("value"));
184 
185         input.clear();
186         assertEquals(getExpectedAlerts()[0], input.getDomAttribute("value"));
187         assertEquals(getExpectedAlerts()[1], input.getDomProperty("value"));
188     }
189 
190     /**
191      * @throws Exception if the test fails
192      */
193     @Test
194     @Alerts("--")
195     public void minMaxStep() throws Exception {
196         final String html = DOCTYPE_HTML
197             + "<html>\n"
198             + "<head>\n"
199             + "<script>\n"
200             + LOG_TITLE_FUNCTION
201             + "  function test() {\n"
202             + "    var input = document.getElementById('tester');\n"
203             + "    log(input.min + '-' + input.max + '-' + input.step);\n"
204             + "  }\n"
205             + "</script>\n"
206             + "</head>\n"
207             + "<body onload='test()'>\n"
208             + "<form>\n"
209             + "  <input type='date' id='tester'>\n"
210             + "</form>\n"
211             + "</body>\n"
212             + "</html>";
213 
214         loadPageVerifyTitle2(html);
215     }
216 
217     /**
218      * @throws Exception if the test fails
219      */
220     @Test
221     @Alerts("false-true")
222     public void minValidation() throws Exception {
223         final String html = DOCTYPE_HTML
224             + "<html>\n"
225             + "<head>\n"
226             + "<script>\n"
227             + LOG_TITLE_FUNCTION
228             + "  function test() {\n"
229             + "    var foo = document.getElementById('foo');\n"
230             + "    var bar = document.getElementById('bar');\n"
231             + "    log(foo.checkValidity() + '-' + bar.checkValidity() );\n"
232             + "  }\n"
233             + "</script>\n"
234             + "</head>\n"
235             + "<body onload='test()'>\n"
236             + "  <input type='date' min='2018-12-01' id='foo' value='2018-11-01'>\n"
237             + "  <input type='date' min='2018-12-01' id='bar' value='2018-12-02'>\n"
238             + "</body>\n"
239             + "</html>";
240 
241         loadPageVerifyTitle2(html);
242     }
243 
244     /**
245      * @throws Exception if the test fails
246      */
247     @Test
248     @Alerts("false-true")
249     public void maxValidation() throws Exception {
250         final String html = DOCTYPE_HTML
251             + "<html>\n"
252             + "<head>\n"
253             + "<script>\n"
254             + LOG_TITLE_FUNCTION
255             + "  function test() {\n"
256             + "    var foo = document.getElementById('foo');\n"
257             + "    var bar = document.getElementById('bar');\n"
258             + "    log(foo.checkValidity() + '-' + bar.checkValidity() );\n"
259             + "  }\n"
260             + "</script>\n"
261             + "</head>\n"
262             + "<body onload='test()'>\n"
263             + "  <input type='date' max='2018-12-01' id='foo' value='2018-12-11'>\n"
264             + "  <input type='date' max='2018-12-01' id='bar' value='2018-11-01'>\n"
265             + "</body>\n"
266             + "</html>";
267 
268         loadPageVerifyTitle2(html);
269     }
270 
271     /**
272      * @throws Exception if an error occurs
273      */
274     @Test
275     @Alerts({"true", "false", "true", "false", "true"})
276     public void willValidate() throws Exception {
277         final String html = DOCTYPE_HTML
278                 + "<html><head>\n"
279                 + "  <script>\n"
280                 + LOG_TITLE_FUNCTION
281                 + "    function test() {\n"
282                 + "      log(document.getElementById('o1').willValidate);\n"
283                 + "      log(document.getElementById('o2').willValidate);\n"
284                 + "      log(document.getElementById('o3').willValidate);\n"
285                 + "      log(document.getElementById('o4').willValidate);\n"
286                 + "      log(document.getElementById('o5').willValidate);\n"
287                 + "    }\n"
288                 + "  </script>\n"
289                 + "</head>\n"
290                 + "<body onload='test()'>\n"
291                 + "  <form>\n"
292                 + "    <input type='date' id='o1'>\n"
293                 + "    <input type='date' id='o2' disabled>\n"
294                 + "    <input type='date' id='o3' hidden>\n"
295                 + "    <input type='date' id='o4' readonly>\n"
296                 + "    <input type='date' id='o5' style='display: none'>\n"
297                 + "  </form>\n"
298                 + "</body></html>";
299 
300         loadPageVerifyTitle2(html);
301     }
302 
303     /**
304      * @throws Exception if an error occurs
305      */
306     @Test
307     @Alerts({"true",
308              "false-false-false-false-false-false-false-false-false-true-false",
309              "true"})
310     public void validationEmpty() throws Exception {
311         validation("<input type='date' id='e1'>\n", "");
312     }
313 
314     /**
315      * @throws Exception if an error occurs
316      */
317     @Test
318     @Alerts({"false",
319              "false-true-false-false-false-false-false-false-false-false-false",
320              "true"})
321     public void validationCustomValidity() throws Exception {
322         validation("<input type='date' id='e1'>\n", "elem.setCustomValidity('Invalid');");
323     }
324 
325     /**
326      * @throws Exception if an error occurs
327      */
328     @Test
329     @Alerts({"false",
330              "false-true-false-false-false-false-false-false-false-false-false",
331              "true"})
332     public void validationBlankCustomValidity() throws Exception {
333         validation("<input type='date' id='e1'>\n", "elem.setCustomValidity(' ');\n");
334     }
335 
336     /**
337      * @throws Exception if an error occurs
338      */
339     @Test
340     @Alerts({"true",
341              "false-false-false-false-false-false-false-false-false-true-false",
342              "true"})
343     public void validationResetCustomValidity() throws Exception {
344         validation("<input type='date' id='e1'>\n",
345                 "elem.setCustomValidity('Invalid');elem.setCustomValidity('');");
346     }
347 
348     /**
349      * @throws Exception if an error occurs
350      */
351     @Test
352     @Alerts({"false",
353              "false-false-false-false-false-false-false-false-false-false-true",
354              "true"})
355     public void validationRequired() throws Exception {
356         validation("<input type='date' id='e1' required>\n",
357                 "elem.setCustomValidity('Invalid');elem.setCustomValidity('');");
358     }
359 
360     /**
361      * @throws Exception if an error occurs
362      */
363     @Test
364     @Alerts({"true",
365              "false-false-false-false-false-false-false-false-false-true-false",
366              "true"})
367     public void validationRequiredValueSet() throws Exception {
368         validation("<input type='date' id='e1' required>\n", "elem.value='2018-12-01';");
369     }
370 
371     private void validation(final String htmlPart, final String jsPart) throws Exception {
372         final String html = DOCTYPE_HTML
373                 + "<html><head>\n"
374                 + "  <script>\n"
375                 + LOG_TITLE_FUNCTION
376                 + "    function logValidityState(s) {\n"
377                 + "      log(s.badInput"
378                         + "+ '-' + s.customError"
379                         + "+ '-' + s.patternMismatch"
380                         + "+ '-' + s.rangeOverflow"
381                         + "+ '-' + s.rangeUnderflow"
382                         + "+ '-' + s.stepMismatch"
383                         + "+ '-' + s.tooLong"
384                         + "+ '-' + s.tooShort"
385                         + " + '-' + s.typeMismatch"
386                         + " + '-' + s.valid"
387                         + " + '-' + s.valueMissing);\n"
388                 + "    }\n"
389                 + "    function test() {\n"
390                 + "      var elem = document.getElementById('e1');\n"
391                 + jsPart
392                 + "      log(elem.checkValidity());\n"
393                 + "      logValidityState(elem.validity);\n"
394                 + "      log(elem.willValidate);\n"
395                 + "    }\n"
396                 + "  </script>\n"
397                 + "</head>\n"
398                 + "<body onload='test()'>\n"
399                 + "  <form>\n"
400                 + htmlPart
401                 + "  </form>\n"
402                 + "</body></html>";
403 
404         loadPageVerifyTitle2(html);
405     }
406 }