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