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  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
24  
25  /**
26   * Tests for {@link HtmlTextArea}.
27   *
28   * @author Ronald Brill
29   * @author Ahmed Ashour
30   */
31  public class HtmlTextArea2Test extends WebDriverTestCase {
32  
33      /**
34       * @throws Exception if the test fails
35       */
36      @Test
37      @Alerts({"-", "-", "newValue-", "newValue-", "newValue-newDefault", "newValue-newDefault"})
38      public void resetByClick() throws Exception {
39          final String html = DOCTYPE_HTML
40              + "<html><head>\n"
41              + "<script>\n"
42              + LOG_TITLE_FUNCTION
43              + "  function test() {\n"
44              + "    var text = document.getElementById('testId');\n"
45              + "    log(text.value + '-' + text.defaultValue);\n"
46  
47              + "    document.getElementById('testReset').click;\n"
48              + "    log(text.value + '-' + text.defaultValue);\n"
49  
50              + "    text.value = 'newValue';\n"
51              + "    log(text.value + '-' + text.defaultValue);\n"
52  
53              + "    document.getElementById('testReset').click;\n"
54              + "    log(text.value + '-' + text.defaultValue);\n"
55  
56              + "    text.defaultValue = 'newDefault';\n"
57              + "    log(text.value + '-' + text.defaultValue);\n"
58  
59              + "    document.forms[0].reset;\n"
60              + "    log(text.value + '-' + text.defaultValue);\n"
61              + "  }\n"
62              + "</script>\n"
63              + "</head><body onload='test()'>\n"
64              + "<form>\n"
65              + "  <textarea id='testId' value='initial'></textarea>\n"
66              + "  <input type='reset' id='testReset'>\n"
67              + "</form>\n"
68              + "</body></html>";
69  
70          loadPageVerifyTitle2(html);
71      }
72  
73      /**
74       * @throws Exception if the test fails
75       */
76      @Test
77      @Alerts({"-", "-", "newValue-", "newValue-", "newValue-newDefault", "newValue-newDefault"})
78      public void resetByJS() throws Exception {
79          final String html = DOCTYPE_HTML
80              + "<html><head>\n"
81              + "<script>\n"
82              + LOG_TITLE_FUNCTION
83              + "  function test() {\n"
84              + "    var text = document.getElementById('testId');\n"
85              + "    log(text.value + '-' + text.defaultValue);\n"
86  
87              + "    document.forms[0].reset;\n"
88              + "    log(text.value + '-' + text.defaultValue);\n"
89  
90              + "    text.value = 'newValue';\n"
91              + "    log(text.value + '-' + text.defaultValue);\n"
92  
93              + "    document.forms[0].reset;\n"
94              + "    log(text.value + '-' + text.defaultValue);\n"
95  
96              + "    text.defaultValue = 'newDefault';\n"
97              + "    log(text.value + '-' + text.defaultValue);\n"
98  
99              + "    document.forms[0].reset;\n"
100             + "    log(text.value + '-' + text.defaultValue);\n"
101             + "  }\n"
102             + "</script>\n"
103             + "</head><body onload='test()'>\n"
104             + "<form>\n"
105             + "  <textarea id='testId' value='initial'></textarea>\n"
106             + "</form>\n"
107             + "</body></html>";
108 
109         loadPageVerifyTitle2(html);
110     }
111 
112     /**
113      * @throws Exception if the test fails
114      */
115     @Test
116     @Alerts({"-", "default-default", "some text-default", "some text-newdefault"})
117     public void defaultValue() 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 text = document.getElementById('testId');\n"
124             + "    log(text.value + '-' + text.defaultValue);\n"
125 
126             + "    text.defaultValue = 'default';\n"
127             + "    log(text.value + '-' + text.defaultValue);\n"
128 
129             + "    text.value = 'some text';\n"
130             + "    log(text.value + '-' + text.defaultValue);\n"
131             + "    text.defaultValue = 'newdefault';\n"
132             + "    log(text.value + '-' + text.defaultValue);\n"
133             + "  }\n"
134             + "</script>\n"
135             + "</head><body onload='test()'>\n"
136             + "<form>\n"
137             + "  <textarea id='testId' value='initial'></textarea>\n"
138             + "</form>\n"
139             + "</body></html>";
140 
141         loadPageVerifyTitle2(html);
142     }
143 
144     /**
145      * @throws Exception if the test fails
146      */
147     @Test
148     @Alerts("\\sfoo\\s\\n\\sbar\\n\\stest\\n\\sa\\s<p>html\\ssnippet</p>\\n")
149     public void defaultValue2() throws Exception {
150         final String html = DOCTYPE_HTML
151             + "<html><head>\n"
152             + "<script>\n"
153             + LOG_TITLE_FUNCTION_NORMALIZE
154             + "  function test() {\n"
155             + "    log(document.getElementById('textArea1').defaultValue);\n"
156             + "  }\n"
157             + "</script>\n"
158             + "</head><body onload='test()'>\n"
159             + "<form id='form1'>\n"
160             + "<textarea id='textArea1'> foo \n bar\r\n test\r a "
161             + "<p>html snippet</p>\n"
162             + "</textarea>\n"
163             + "</form></body></html>";
164 
165         loadPageVerifyTitle2(html);
166     }
167 
168     /**
169      * @throws Exception if the test fails
170      */
171     @Test
172     @Alerts("7")
173     public void textLength() throws Exception {
174         final String html = DOCTYPE_HTML
175             + "<html><head>\n"
176             + "<script>\n"
177             + LOG_TITLE_FUNCTION
178             + "  function test() {\n"
179             + "    var text = document.getElementById('testId');\n"
180             + "    if(text.textLength) {\n"
181             + "      log(text.textLength);\n"
182             + "    } else {\n"
183             + "      log('textLength not available');\n"
184             + "    }\n"
185             + "  }\n"
186             + "</script>\n"
187             + "</head><body onload='test()'>\n"
188             + "<form>\n"
189             + "  <textarea id='testId'>initial</textarea>\n"
190             + "</form>\n"
191             + "</body></html>";
192 
193         loadPageVerifyTitle2(html);
194     }
195 
196     /**
197      * @throws Exception if an error occurs
198      */
199     @Test
200     @Alerts("0")
201     public void selection() throws Exception {
202         final String html = DOCTYPE_HTML
203             + "<html><head><script>\n"
204             + LOG_TITLE_FUNCTION
205             + "  function test() {\n"
206             + "    log(getSelection(document.getElementById('text1')).length);\n"
207             + "  }\n"
208             + "  function getSelection(element) {\n"
209             + "    return element.value.substring(element.selectionStart, element.selectionEnd);\n"
210             + "  }\n"
211             + "</script></head>\n"
212             + "<body onload='test()'>\n"
213             + "  <textarea id='text1'></textarea>\n"
214             + "</body></html>";
215 
216         loadPageVerifyTitle2(html);
217     }
218 
219     /**
220      * @throws Exception if test fails
221      */
222     @Test
223     @Alerts({"0,0", "11,11", "3,11", "3,10"})
224     public void selection2_1() throws Exception {
225         selection2(3, 10);
226     }
227 
228     /**
229      * @throws Exception if test fails
230      */
231     @Test
232     @Alerts({"0,0", "11,11", "11,11", "11,11"})
233     public void selection2_2() throws Exception {
234         selection2(-3, 15);
235     }
236 
237     /**
238      * @throws Exception if test fails
239      */
240     @Test
241     @Alerts({"0,0", "11,11", "10,11", "5,5"})
242     public void selection2_3() throws Exception {
243         selection2(10, 5);
244     }
245 
246     private void selection2(final int selectionStart, final int selectionEnd) throws Exception {
247         final String html = DOCTYPE_HTML
248             + "<html>\n"
249             + "<body>\n"
250             + "<textarea id='myTextInput'>Bonjour</textarea>\n"
251             + "<script>\n"
252             + LOG_TITLE_FUNCTION
253             + "  var input = document.getElementById('myTextInput');\n"
254             + "  log(input.selectionStart + ',' + input.selectionEnd);\n"
255             + "  input.value = 'Hello there';\n"
256             + "  log(input.selectionStart + ',' + input.selectionEnd);\n"
257             + "  input.selectionStart = " + selectionStart + ";\n"
258             + "  log(input.selectionStart + ',' + input.selectionEnd);\n"
259             + "  input.selectionEnd = " + selectionEnd + ";\n"
260             + "  log(input.selectionStart + ',' + input.selectionEnd);\n"
261             + "</script>\n"
262             + "</body>\n"
263             + "</html>";
264 
265         loadPageVerifyTitle2(html);
266     }
267 
268     /**
269      * @throws Exception if test fails
270      */
271     @Test
272     @Alerts({"0,0", "4,5", "10,10", "4,4", "1,1"})
273     public void selectionOnUpdate() throws Exception {
274         final String html = DOCTYPE_HTML
275             + "<html>\n"
276             + "<body>\n"
277             + "<textarea id='myTextInput'>Hello</textarea>\n"
278             + "<script>\n"
279             + LOG_TITLE_FUNCTION
280             + "  var input = document.getElementById('myTextInput');\n"
281             + "  log(input.selectionStart + ',' + input.selectionEnd);\n"
282 
283             + "  input.selectionStart = 4;\n"
284             + "  input.selectionEnd = 5;\n"
285             + "  log(input.selectionStart + ',' + input.selectionEnd);\n"
286             + "  input.value = 'abcdefghif';\n"
287             + "  log(input.selectionStart + ',' + input.selectionEnd);\n"
288 
289             + "  input.value = 'abcd';\n"
290             + "  log(input.selectionStart + ',' + input.selectionEnd);\n"
291 
292             + "  input.selectionStart = 0;\n"
293             + "  input.selectionEnd = 4;\n"
294 
295             + "  input.value = 'a';\n"
296             + "  log(input.selectionStart + ',' + input.selectionEnd);\n"
297             + "</script>\n"
298             + "</body>\n"
299             + "</html>";
300 
301         loadPageVerifyTitle2(html);
302     }
303 
304     /**
305      * @throws Exception if the test fails
306      */
307     @Test
308     @Alerts(" foo \n bar\n test\n a <p>html snippet</p>")
309     public void getVisibleText() throws Exception {
310         final String html = DOCTYPE_HTML
311             + "<html><head><title>foo</title></head><body>\n"
312             + "<form id='form1'>\n"
313             + "<textarea id='tester'> foo \n bar\r\n test\r a "
314             + "<p>html snippet</p>\n"
315             + "</textarea>\n"
316             + "</form></body></html>";
317 
318         final WebDriver driver = loadPage2(html);
319         final String text = driver.findElement(By.id("tester")).getText();
320         assertEquals(getExpectedAlerts()[0], text);
321 
322         if (driver instanceof HtmlUnitDriver) {
323             final HtmlPage page = (HtmlPage) getEnclosedPage();
324             assertEquals(getExpectedAlerts()[0], page.getElementById("tester").getVisibleText());
325         }
326     }
327 
328     /**
329      * @throws Exception if the test fails
330      */
331     @Test
332     @Alerts("Hello World")
333     public void getVisibleTextValueChangedWithTyping() throws Exception {
334         final String html = DOCTYPE_HTML
335             + "<html>"
336             + "<head></head>\n"
337             + "<body>\n"
338             + "<form id='form1'>\n"
339             + "<textarea id='tester'>Hello World</textarea>\n"
340             + "</form>\n"
341             + "</body></html>";
342 
343         final WebDriver driver = loadPage2(html);
344         final WebElement textArea = driver.findElement(By.id("tester"));
345         textArea.sendKeys("HtmlUnit");
346         final String text = textArea.getText();
347         assertEquals(getExpectedAlerts()[0], text);
348 
349         if (driver instanceof HtmlUnitDriver) {
350             final HtmlPage page = (HtmlPage) getEnclosedPage();
351             assertEquals(getExpectedAlerts()[0], page.getElementById("tester").getVisibleText());
352         }
353     }
354 
355     /**
356      * @throws Exception if the test fails
357      */
358     @Test
359     @Alerts("Hello World")
360     public void getVisibleTextValueChangedFromJs() throws Exception {
361         final String html = DOCTYPE_HTML
362             + "<html>"
363             + "<head>\n"
364             + "<script>\n"
365             + "  function test() {\n"
366             + "    document.getElementById('tester').value = 'HtmlUnit';\n"
367             + "  }\n"
368             + "</script>\n"
369             + "</head>\n"
370             + "<body onload='test()'>\n"
371             + "<form id='form1'>\n"
372             + "<textarea id='tester'>Hello World</textarea>\n"
373             + "</form>\n"
374             + "</body></html>";
375 
376         final WebDriver driver = loadPage2(html);
377         final String text = driver.findElement(By.id("tester")).getText();
378         assertEquals(getExpectedAlerts()[0], text);
379 
380         if (driver instanceof HtmlUnitDriver) {
381             final HtmlPage page = (HtmlPage) getEnclosedPage();
382             assertEquals(getExpectedAlerts()[0], page.getElementById("tester").getVisibleText());
383         }
384     }
385 
386     /**
387      * @throws Exception if the test fails
388      */
389     @Test
390     @Alerts("")
391     public void getVisibleTextAndVisibility() throws Exception {
392         final String html = DOCTYPE_HTML
393             + "<html><head></head><body>\n"
394             + "<form id='form1'>\n"
395             + "<textarea id='tester' style='visibility:hidden'> foo \n bar "
396             + "</textarea>\n"
397             + "</form></body></html>";
398         final WebDriver driver = loadPage2(html);
399         final WebElement textArea = driver.findElement(By.id("tester"));
400         assertEquals(getExpectedAlerts()[0], textArea.getText());
401 
402         if (driver instanceof HtmlUnitDriver) {
403             final HtmlPage page = (HtmlPage) getEnclosedPage();
404             assertEquals(getExpectedAlerts()[0], page.getElementById("tester").getVisibleText());
405         }
406     }
407 
408     /**
409      * @throws Exception if the test fails
410      */
411     @Test
412     @Alerts(" foo \n bar <p>html snippet</p>")
413     public void parentAsText() throws Exception {
414         final String html = DOCTYPE_HTML
415             + "<html><head><title>foo</title></head><body>\n"
416             + "<form id='form1'>\n"
417             + "<textarea name='textArea1'> foo \n bar "
418             + "<p>html snippet</p>\n"
419             + "</textarea>\n"
420             + "</form></body></html>";
421 
422         final WebDriver driver = loadPage2(html);
423         final WebElement textArea = driver.findElement(By.id("form1"));
424         assertEquals(getExpectedAlerts()[0], textArea.getText());
425     }
426 
427     /**
428      * @throws Exception if test fails
429      */
430     @Test
431     @Alerts({"1", "a", "", "b", "<!--comment-->2", "c", "<!--comment-->", "d"})
432     public void textUpdate() throws Exception {
433         final String html = DOCTYPE_HTML
434             + "<html>\n"
435             + "<body>\n"
436             + "<textarea id='myText'>1</textarea>\n"
437             + "<textarea id='myTextEmpty'></textarea>\n"
438             + "<textarea id='myTextComment'><!--comment-->2</textarea>\n"
439             + "<textarea id='myTextCommentOnly'><!--comment--></textarea>\n"
440             + "<script>\n"
441             + LOG_TITLE_FUNCTION
442             + "  var text = document.getElementById('myText');\n"
443             + "  log(text.value);\n"
444             + "  text.value = 'a';\n"
445             + "  log(text.value);\n"
446 
447             + "  text = document.getElementById('myTextEmpty');\n"
448             + "  log(text.value);\n"
449             + "  text.value = 'b';\n"
450             + "  log(text.value);\n"
451 
452             + "  text = document.getElementById('myTextComment');\n"
453             + "  log(text.value);\n"
454             + "  text.value = 'c';\n"
455             + "  log(text.value);\n"
456 
457             + "  text = document.getElementById('myTextCommentOnly');\n"
458             + "  log(text.value);\n"
459             + "  text.value = 'd';\n"
460             + "  log(text.value);\n"
461 
462             + "</script>\n"
463             + "</body>\n"
464             + "</html>";
465 
466         loadPageVerifyTitle2(html);
467     }
468 
469     /**
470      * @throws Exception if test fails
471      */
472     @Test
473     @Alerts({"", "xyz", "1", "a", "1"})
474     public void textUpdateFromJSText() throws Exception {
475         final String html = DOCTYPE_HTML
476             + "<html>\n"
477             + "<body>\n"
478             + "<textarea id='myText'></textarea>\n"
479             + "<script>\n"
480             + LOG_TITLE_FUNCTION
481             + "  var text = document.getElementById('myText');\n"
482             + "  log(text.value);\n"
483 
484             + "  var txt = document.createTextNode('xyz');\n"
485             + "  text.appendChild(txt);\n"
486             + "  log(text.value);\n"
487             + "  log(text.childNodes.length);\n"
488 
489             + "  text.value = 'a';\n"
490             + "  log(text.value);\n"
491             + "  log(text.childNodes.length);\n"
492             + "</script>\n"
493             + "</body>\n"
494             + "</html>";
495 
496         loadPageVerifyTitle2(html);
497     }
498 
499     /**
500      * @throws Exception if test fails
501      */
502     @Test
503     @Alerts({"", "", "1", "a", "1"})
504     public void textUpdateFromJSSpan() throws Exception {
505         final String html = DOCTYPE_HTML
506             + "<html>\n"
507             + "<body>\n"
508             + "<textarea id='myText'></textarea>\n"
509             + "<script>\n"
510             + LOG_TITLE_FUNCTION
511             + "  var text = document.getElementById('myText');\n"
512             + "  log(text.value);\n"
513 
514             + "  var span = document.createElement('span');\n"
515             + "  span.innerHTML = '123';\n"
516             + "  text.appendChild(span);\n"
517             + "  log(text.value);\n"
518             + "  log(text.childNodes.length);\n"
519 
520             + "  text.value = 'a';\n"
521             + "  log(text.value);\n"
522             + "  log(text.childNodes.length);\n"
523             + "</script>\n"
524             + "</body>\n"
525             + "</html>";
526 
527         loadPageVerifyTitle2(html);
528     }
529 
530     /**
531      * @throws Exception if test fails
532      */
533     @Test
534     @Alerts({"", "", "1", "xyz", "2", "a", "2"})
535     public void textUpdateFromJSSpanAndText() throws Exception {
536         final String html = DOCTYPE_HTML
537             + "<html>\n"
538             + "<body>\n"
539             + "<textarea id='myText'></textarea>\n"
540             + "<script>\n"
541             + LOG_TITLE_FUNCTION
542             + "  var text = document.getElementById('myText');\n"
543             + "  log(text.value);\n"
544 
545             + "  var span = document.createElement('span');\n"
546             + "  span.innerHTML = '123';\n"
547             + "  text.appendChild(span);\n"
548             + "  log(text.value);\n"
549             + "  log(text.childNodes.length);\n"
550 
551             + "  var txt = document.createTextNode('xyz');\n"
552             + "  text.appendChild(txt);\n"
553             + "  log(text.value);\n"
554             + "  log(text.childNodes.length);\n"
555 
556             + "  text.value = 'a';\n"
557             + "  log(text.value);\n"
558             + "  log(text.childNodes.length);\n"
559             + "</script>\n"
560             + "</body>\n"
561             + "</html>";
562 
563         loadPageVerifyTitle2(html);
564     }
565 
566     /**
567      * @throws Exception if test fails
568      */
569     @Test
570     @Alerts({"", "", "1", "a", "1"})
571     public void textUpdateFromJSComment() throws Exception {
572         final String html = DOCTYPE_HTML
573             + "<html>\n"
574             + "<body>\n"
575             + "<textarea id='myText'></textarea>\n"
576             + "<script>\n"
577             + LOG_TITLE_FUNCTION
578             + "  var text = document.getElementById('myText');\n"
579             + "  log(text.value);\n"
580 
581             + "  var comment = document.createComment('comment');\n"
582             + "  text.appendChild(comment);\n"
583             + "  log(text.value);\n"
584             + "  log(text.childNodes.length);\n"
585 
586             + "  text.value = 'a';\n"
587             + "  log(text.value);\n"
588             + "  log(text.childNodes.length);\n"
589             + "</script>\n"
590             + "</body>\n"
591             + "</html>";
592 
593         loadPageVerifyTitle2(html);
594     }
595 
596     /**
597      * @throws Exception if an error occurs
598      */
599     @Test
600     @Alerts({"0", "2", "1", "2", "1", "1"})
601     public void labels() throws Exception {
602         final String html = DOCTYPE_HTML
603             + "<html><head>\n"
604             + "<script>\n"
605             + LOG_TITLE_FUNCTION
606             + "  function test() {\n"
607             + "    debug(document.getElementById('e1'));\n"
608             + "    debug(document.getElementById('e2'));\n"
609             + "    debug(document.getElementById('e3'));\n"
610             + "    debug(document.getElementById('e4'));\n"
611             + "    var labels = document.getElementById('e4').labels;\n"
612             + "    document.body.removeChild(document.getElementById('l4'));\n"
613             + "    debug(document.getElementById('e4'));\n"
614             + "    log(labels ? labels.length : labels);\n"
615             + "  }\n"
616             + "  function debug(e) {\n"
617             + "    log(e.labels ? e.labels.length : e.labels);\n"
618             + "  }\n"
619             + "</script>\n"
620             + "</head>\n"
621             + "<body onload='test()'>\n"
622             + "  <textarea id='e1'>e 1</textarea><br>\n"
623             + "  <label>something <label> click here <textarea id='e2'>e 2</textarea></label></label><br>\n"
624             + "  <label for='e3'> and here</label>\n"
625             + "  <textarea id='e3'>e 3</textarea><br>\n"
626             + "  <label id='l4' for='e4'> what about</label>\n"
627             + "  <label> this<textarea id='e4'>e 4</textarea></label><br>\n"
628             + "</body></html>";
629 
630         loadPageVerifyTitle2(html);
631     }
632 
633     /**
634      * @throws Exception if an error occurs
635      */
636     @Test
637     @Alerts({"true", "false", "true", "false", "true"})
638     public void willValidate() throws Exception {
639         final String html = DOCTYPE_HTML
640                 + "<html><head>\n"
641                 + "  <script>\n"
642                 + LOG_TITLE_FUNCTION
643                 + "    function test() {\n"
644                 + "      log(document.getElementById('t1').willValidate);\n"
645                 + "      log(document.getElementById('t2').willValidate);\n"
646                 + "      log(document.getElementById('t3').willValidate);\n"
647                 + "      log(document.getElementById('t4').willValidate);\n"
648                 + "      log(document.getElementById('t5').willValidate);\n"
649                 + "    }\n"
650                 + "  </script>\n"
651                 + "</head>\n"
652                 + "<body onload='test()'>\n"
653                 + "  <form>\n"
654                 + "    <textarea id='t1'>t1</textarea>\n"
655                 + "    <textarea id='t2' disabled>t2</textarea>\n"
656                 + "    <textarea id='t3' hidden>t3</textarea>\n"
657                 + "    <textarea id='t4' readonly>t4</textarea>\n"
658                 + "    <textarea id='t5' style='display: none'>t5</textarea>\n"
659                 + "  </form>\n"
660                 + "</body></html>";
661 
662         loadPageVerifyTitle2(html);
663     }
664 
665     /**
666      * @throws Exception if an error occurs
667      */
668     @Test
669     @Alerts({"true",
670              "false-false-false-false-false-false-false-false-false-true-false",
671              "true"})
672     public void validationEmpty() throws Exception {
673         validation("<textarea id='e1'>t1</textarea>\n", "");
674     }
675 
676     /**
677      * @throws Exception if an error occurs
678      */
679     @Test
680     @Alerts({"false",
681              "false-true-false-false-false-false-false-false-false-false-false",
682              "true"})
683     public void validationCustomValidity() throws Exception {
684         validation("<textarea id='e1'>t1</textarea>\n", "elem.setCustomValidity('Invalid');");
685     }
686 
687     /**
688      * @throws Exception if an error occurs
689      */
690     @Test
691     @Alerts({"false",
692              "false-true-false-false-false-false-false-false-false-false-false",
693              "true"})
694     public void validationBlankCustomValidity() throws Exception {
695         validation("<textarea id='e1'>t1</textarea>\n", "elem.setCustomValidity(' ');\n");
696     }
697 
698     /**
699      * @throws Exception if an error occurs
700      */
701     @Test
702     @Alerts({"true",
703              "false-false-false-false-false-false-false-false-false-true-false",
704              "true"})
705     public void validationResetCustomValidity() throws Exception {
706         validation("<textarea id='e1'>t1</textarea>\n",
707                 "elem.setCustomValidity('Invalid');elem.setCustomValidity('');");
708     }
709 
710     /**
711      * @throws Exception if an error occurs
712      */
713     @Test
714     @Alerts({"false",
715              "false-false-false-false-false-false-false-false-false-false-true",
716              "true"})
717     public void validationRequired() throws Exception {
718         validation("<textarea id='e1' required></textarea>\n", "");
719     }
720 
721     /**
722      * @throws Exception if an error occurs
723      */
724     @Test
725     @Alerts({"true",
726              "false-false-false-false-false-false-false-false-false-true-false",
727              "true"})
728     public void validationRequiredWithText() throws Exception {
729         validation("<textarea id='e1' required>HtmlUnit</textarea>\n", "");
730     }
731 
732     /**
733      * @throws Exception if an error occurs
734      */
735     @Test
736     @Alerts({"true",
737              "false-false-false-false-false-false-false-false-false-true-false",
738              "true"})
739     public void validationRequiredValueSet() throws Exception {
740         validation("<textarea id='e1' required></textarea>\n", "elem.value='A';");
741     }
742 
743     /**
744      * @throws Exception if an error occurs
745      */
746     @Test
747     @Alerts({"false",
748              "false-false-false-false-false-false-false-false-false-false-true",
749              "true"})
750     public void validationRequiredValueClear() throws Exception {
751         validation("<textarea id='e1' required>abc</textarea>\n", "elem.value='';");
752     }
753 
754     private void validation(final String htmlPart, final String jsPart) throws Exception {
755         final String html = DOCTYPE_HTML
756                 + "<html><head>\n"
757                 + "  <script>\n"
758                 + LOG_TITLE_FUNCTION
759                 + "    function logValidityState(s) {\n"
760                 + "      log(s.badInput"
761                         + "+ '-' + s.customError"
762                         + "+ '-' + s.patternMismatch"
763                         + "+ '-' + s.rangeOverflow"
764                         + "+ '-' + s.rangeUnderflow"
765                         + "+ '-' + s.stepMismatch"
766                         + "+ '-' + s.tooLong"
767                         + "+ '-' + s.tooShort"
768                         + " + '-' + s.typeMismatch"
769                         + " + '-' + s.valid"
770                         + " + '-' + s.valueMissing);\n"
771                 + "    }\n"
772                 + "    function test() {\n"
773                 + "      var elem = document.getElementById('e1');\n"
774                 + jsPart
775                 + "      log(elem.checkValidity());\n"
776                 + "      logValidityState(elem.validity);\n"
777                 + "      log(elem.willValidate);\n"
778                 + "    }\n"
779                 + "  </script>\n"
780                 + "</head>\n"
781                 + "<body onload='test()'>\n"
782                 + "  <form>\n"
783                 + htmlPart
784                 + "  </form>\n"
785                 + "</body></html>";
786 
787         loadPageVerifyTitle2(html);
788     }
789 }