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.javascript.host.html;
16  
17  import static java.nio.charset.StandardCharsets.ISO_8859_1;
18  import static java.nio.charset.StandardCharsets.UTF_16;
19  import static java.nio.charset.StandardCharsets.UTF_8;
20  import static org.junit.jupiter.api.Assertions.fail;
21  
22  import java.io.File;
23  import java.net.URL;
24  
25  import org.apache.commons.lang3.StringUtils;
26  import org.htmlunit.FormEncodingType;
27  import org.htmlunit.HttpHeader;
28  import org.htmlunit.MockWebConnection;
29  import org.htmlunit.WebDriverTestCase;
30  import org.htmlunit.junit.annotation.Alerts;
31  import org.htmlunit.junit.annotation.HtmlUnitNYI;
32  import org.htmlunit.util.MimeType;
33  import org.junit.jupiter.api.Test;
34  import org.openqa.selenium.By;
35  import org.openqa.selenium.NoSuchWindowException;
36  import org.openqa.selenium.WebDriver;
37  import org.openqa.selenium.WebElement;
38  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
39  
40  /**
41   * Tests for {@link HTMLFormElement}.
42   *
43   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
44   * @author David K. Taylor
45   * @author Marc Guillemot
46   * @author Chris Erskine
47   * @author Ahmed Ashour
48   * @author Ronald Brill
49   * @author Frank Danek
50   */
51  public class HTMLFormElementTest extends WebDriverTestCase {
52  
53      /**
54       * @throws Exception if the test fails
55       */
56      @Test
57      @Alerts({"16", "button1", "button2", "checkbox1", "fileupload1", "hidden1",
58               "radio1", "radio1",
59               "select1", "select2", "password1", "reset1",
60               "reset2", "submit1", "submit2", "textInput1", "textarea1"})
61      public void elementsAccessor() throws Exception {
62          final String html = DOCTYPE_HTML
63              + "<html><head><script>\n"
64              + LOG_TITLE_FUNCTION
65              + "function doTest() {\n"
66              + "  log(document.form1.length);\n"
67              + "  for (var i = 0; i < document.form1.length; i++) {\n"
68              + "    var element = document.form1.elements[i];\n"
69              + "    if (element.type != 'radio' && element != document.form1[element.name]) {\n"
70              + "      log('name index not working for '+element.name);\n"
71              + "    }\n"
72              + "    log(element.name);\n"
73              + "  }\n"
74              + "}\n"
75              + "</script></head><body onload='doTest()'>\n"
76              + "<p>hello world</p>\n"
77              + "<form name='form1'>\n"
78              + "  <input type='button' name='button1' />\n"
79              + "  <button type='button' name='button2'>button2</button>\n"
80              + "  <input type='checkbox' name='checkbox1' />\n"
81              + "  <input type='file' name='fileupload1' />\n"
82              + "  <input type='hidden' name='hidden1' />\n"
83              + "  <input type='radio' name='radio1' value='1' />\n"
84              + "  <input type='radio' name='radio1' value='2' />\n"
85              + "  <select name='select1'>\n"
86              + "    <option>foo</option>\n"
87              + "  </select>\n"
88              + "  <select multiple='multiple' name='select2'>\n"
89              + "    <option>foo</option>\n"
90              + "  </select>\n"
91              + "  <input type='password' name='password1' />\n"
92              + "  <input type='reset' name='reset1' />\n"
93              + "  <button type='reset' name='reset2'>reset2</button>\n"
94              + "  <input type='submit' name='submit1' />\n"
95              + "  <button type='submit' name='submit2'>submit2</button>\n"
96              + "  <input type='text' name='textInput1' />\n"
97              + "  <textarea name='textarea1'>foo</textarea>\n"
98              + "</form>\n"
99              + "</body></html>";
100 
101         loadPageVerifyTitle2(html);
102     }
103 
104     /**
105      * @throws Exception if the test fails
106      */
107     @Test
108     @Alerts({"undefined", "undefined"})
109     public void elementsAccessorOutOfBound() throws Exception {
110         final String html = DOCTYPE_HTML
111             + "<html><head><script>\n"
112             + LOG_TITLE_FUNCTION
113             + "function doTest() {\n"
114             + "  log(document.form1[-1]);\n"
115             + "  log(document.form1[2]);\n"
116             + "}\n"
117             + "</script></head><body onload='doTest()'>\n"
118             + "<form name='form1'>\n"
119             + "  <input type='button' name='button1'/>\n"
120             + "  <input type='submit' name='submit1'/>\n"
121             + "</form>\n"
122             + "</body></html>";
123 
124         loadPageVerifyTitle2(html);
125     }
126 
127     /**
128      * @throws Exception if the test fails
129      */
130     @Test
131     @Alerts({"3", "textInput1", "button1", "textInput3"})
132     public void elementsAccessorFormAttribute() throws Exception {
133         final String html = DOCTYPE_HTML
134             + "<html><head><script>\n"
135             + LOG_TITLE_FUNCTION
136             + "function doTest() {\n"
137             + "  log(document.form1.length);\n"
138             + "  for (var i = 0; i < document.form1.length; i++) {\n"
139             + "    var element = document.form1.elements[i];\n"
140             + "    log(element.name);\n"
141             + "  }\n"
142             + "}\n"
143             + "</script></head>\n"
144             + "<body onload='doTest()'>\n"
145 
146             + "<input type='text' name='textInput1' form='myForm'/>\n"
147             + "<input type='text' name='textInput2' form='form1'/>\n"
148 
149             + "<form id='myForm' name='form1'>\n"
150             + "  <input type='button' name='button1' />\n"
151             + "</form>\n"
152 
153             + "<input type='text' name='textInput3' form='myForm'/>\n"
154             + "<input type='text' name='textInput4' form='form1'/>\n"
155             + "</body></html>";
156 
157         loadPageVerifyTitle2(html);
158     }
159 
160     /**
161      * @throws Exception if the test fails
162      */
163     @Test
164     @Alerts({"3", "1", "2", "3"})
165     public void radioButtonArray() throws Exception {
166         final String html = DOCTYPE_HTML
167             + "<html><head><script>\n"
168             + LOG_TITLE_FUNCTION
169             + "function doTest() {\n"
170             + "  var radioArray = document.form1['radio1'];\n"
171             + "  log(radioArray.length);\n"
172             + "  for (var i = 0; i < radioArray.length; i++) {\n"
173             + "    var element = radioArray[i];\n"
174             + "    log(element.value);\n"
175             + "  }\n"
176             + "}\n"
177             + "</script></head>\n"
178             + "<body onload='doTest()'>\n"
179             + "<p>hello world</p>\n"
180             + "<form name='form1'>\n"
181             + "  <input type='radio' name='radio1' value='1'/>\n"
182             + "  <input type='radio' name='radio1' value='2'/>\n"
183             + "  <input type='radio' name='radio1' value='3'/>\n"
184             + "</form>\n"
185             + "</body></html>";
186 
187         loadPageVerifyTitle2(html);
188     }
189 
190     /**
191      * If there is only one radio button with a specified name then that radio
192      * button will be returned for the name, not an array of radio buttons. Test
193      * this.
194      * @throws Exception if the test fails
195      */
196     @Test
197     @Alerts("1")
198     public void radioButton_OnlyOne() throws Exception {
199         final String html = DOCTYPE_HTML
200             + "<html><head><script>\n"
201             + LOG_TITLE_FUNCTION
202             + "function doTest() {\n"
203             + "  log(document.form1['radio1'].value);\n"
204             + "}\n"
205             + "</script></head>\n"
206             + "<body onload='doTest()'>\n"
207             + "<p>hello world</p>\n"
208             + "<form name='form1'>\n"
209             + "  <input type='radio' name='radio1' value='1'/>\n"
210             + "</form>\n"
211             + "</body></html>";
212 
213         loadPageVerifyTitle2(html);
214     }
215 
216     /**
217      * @throws Exception if the test fails
218      */
219     @Test
220     @Alerts({"http://foo.com/", "mailto:me@bar.com", "mailto:me@bar.com"})
221     public void actionProperty() throws Exception {
222         doTestProperty("action", "action", "http://foo.com/", "mailto:me@bar.com");
223     }
224 
225     /**
226      * @throws Exception if the test fails
227      */
228     @Test
229     @Alerts({"myForm", "testForm", "testForm"})
230     public void nameProperty() throws Exception {
231         doTestProperty("name", "name", "myForm", "testForm");
232     }
233 
234     /**
235      * @throws Exception if the test fails
236      */
237     @Test
238     @Alerts("application/x-www-form-urlencoded")
239     public void defaultEnctype() throws Exception {
240         enctype(null);
241     }
242 
243     /**
244      * @throws Exception if the test fails
245      */
246     @Test
247     @Alerts("application/x-www-form-urlencoded")
248     public void emptyEnctype() throws Exception {
249         enctype("");
250     }
251 
252     /**
253      * @throws Exception if the test fails
254      */
255     @Test
256     @Alerts("application/x-www-form-urlencoded")
257     public void blankEnctype() throws Exception {
258         enctype(" ");
259     }
260 
261     /**
262      * @throws Exception if the test fails
263      */
264     @Test
265     @Alerts("application/x-www-form-urlencoded")
266     public void unknownEnctype() throws Exception {
267         enctype("unknown");
268     }
269 
270     /**
271      * @throws Exception if the test fails
272      */
273     @Test
274     @Alerts("application/x-www-form-urlencoded")
275     public void urlencodedEnctype() throws Exception {
276         enctype("application/x-www-form-urlencoded");
277     }
278 
279     /**
280      * @throws Exception if the test fails
281      */
282     @Test
283     @Alerts("multipart/form-data")
284     public void multipartEnctype() throws Exception {
285         enctype("multipart/form-data");
286     }
287 
288     /**
289      * @throws Exception if the test fails
290      */
291     @Test
292     @Alerts("text/plain")
293     public void plainEnctype() throws Exception {
294         enctype("text/plain");
295     }
296 
297     /**
298      * @throws Exception if the test fails
299      */
300     @Test
301     @Alerts("application/x-www-form-urlencoded")
302     public void xmlEnctype() throws Exception {
303         enctype("text/xml");
304     }
305 
306     /**
307      * @throws Exception if the test fails
308      */
309     @Test
310     @Alerts("application/x-www-form-urlencoded")
311     public void jsonEnctype() throws Exception {
312         enctype("application/json");
313     }
314 
315     private void enctype(final String encoding) throws Exception {
316         String html = DOCTYPE_HTML
317             + "<html><head><script>\n"
318             + LOG_TITLE_FUNCTION
319             + "function doTest() {\n"
320             + "  log(document.forms[0].encoding);\n"
321             + "}\n"
322             + "</script></head><body onload='doTest()'>\n"
323             + "<form name='testForm'";
324         if (null != encoding) {
325             html = html + " enctype='" + encoding + "'";
326         }
327         html = html + ">\n"
328             + "    <input type='submit' name='submit1'/>\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({"application/x-www-form-urlencoded",
340              "application/x-www-form-urlencoded",
341              "application/x-www-form-urlencoded"})
342     public void jsDefaultEnctype() throws Exception {
343         jsEnctype(null);
344         jsEncoding(null);
345     }
346 
347     /**
348      * @throws Exception if the test fails
349      */
350     @Test
351     @Alerts({"application/x-www-form-urlencoded",
352              "application/x-www-form-urlencoded",
353              "application/x-www-form-urlencoded"})
354     public void jsEmptyEnctype() throws Exception {
355         jsEnctype("");
356         jsEncoding("");
357     }
358 
359     /**
360      * @throws Exception if the test fails
361      */
362     @Test
363     @Alerts({"application/x-www-form-urlencoded",
364              "application/x-www-form-urlencoded",
365              "application/x-www-form-urlencoded"})
366     public void jsBlankEnctype() throws Exception {
367         jsEnctype(" ");
368         jsEncoding(" ");
369     }
370 
371     /**
372      * @throws Exception if the test fails
373      */
374     @Test
375     @Alerts({"application/x-www-form-urlencoded",
376              "application/x-www-form-urlencoded",
377              "application/x-www-form-urlencoded"})
378     public void jsUnknownEnctype() throws Exception {
379         jsEnctype("unknown");
380         jsEncoding("unknown");
381     }
382 
383     /**
384      * @throws Exception if the test fails
385      */
386     @Test
387     @Alerts({"application/x-www-form-urlencoded",
388              "application/x-www-form-urlencoded",
389              "application/x-www-form-urlencoded"})
390     public void jsUrlencodedEnctype() throws Exception {
391         jsEnctype("application/x-www-form-urlencoded");
392         jsEncoding("application/x-www-form-urlencoded");
393     }
394 
395     /**
396      * @throws Exception if the test fails
397      */
398     @Test
399     @Alerts({"multipart/form-data", "multipart/form-data", "multipart/form-data"})
400     public void jsMultipartEnctype() throws Exception {
401         jsEnctype("multipart/form-data");
402         jsEncoding("multipart/form-data");
403     }
404 
405     /**
406      * @throws Exception if the test fails
407      */
408     @Test
409     @Alerts({"text/plain", "text/plain", "text/plain"})
410     public void jsPlainEnctype() throws Exception {
411         jsEnctype("text/plain");
412         jsEncoding("text/plain");
413     }
414 
415     /**
416      * @throws Exception if the test fails
417      */
418     @Test
419     @Alerts({"application/x-www-form-urlencoded",
420              "application/x-www-form-urlencoded",
421              "application/x-www-form-urlencoded"})
422     public void jsXmlEnctype() throws Exception {
423         jsEnctype("text/xml");
424         jsEncoding("text/xml");
425     }
426 
427     /**
428      * @throws Exception if the test fails
429      */
430     @Test
431     @Alerts({"application/x-www-form-urlencoded",
432              "application/x-www-form-urlencoded",
433              "application/x-www-form-urlencoded"})
434     public void jsJsonEnctype() throws Exception {
435         jsEnctype("application/json");
436         jsEncoding("application/json");
437     }
438 
439     private void jsEnctype(final String enctype) throws Exception {
440         final String html = DOCTYPE_HTML
441             + "<html>\n"
442             + "<head>\n"
443             + "  <script>\n"
444             + LOG_TITLE_FUNCTION
445             + "  function doTest() {\n"
446             + "    try {\n"
447             + "      document.forms[0].enctype = '" + enctype + "';\n"
448             + "      log(document.forms[0].enctype);\n"
449             + "    } catch(e) { logEx(e); }\n"
450             + "    log(document.forms[0].encoding);\n"
451             + "  }\n"
452             + "  </script>\n"
453             + "</head>\n"
454             + "<body onload='doTest()'>\n"
455             + "  <form id='testForm' name='testForm' method='post' action = 'page2.html'>\n"
456             + "    <input type='submit' name='submit1' />\n"
457             + "  </form>\n"
458             + "</body></html>";
459 
460         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
461 
462         final WebDriver driver = loadPage2(html);
463         verifyTitle2(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[0], getExpectedAlerts()[1]});
464 
465         driver.findElement(By.name("submit1")).click();
466         if (useRealBrowser()) {
467             Thread.sleep(400);
468         }
469         assertTitle(driver, "Response");
470         String headerValue = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
471             .get(HttpHeader.CONTENT_TYPE);
472 
473         if (headerValue.startsWith(FormEncodingType.MULTIPART.getName())) {
474             // Can't test equality for multipart/form-data as it will have the form:
475             // multipart/form-data; boundary=---------------------------42937861433140731107235900
476             headerValue = StringUtils.substringBefore(headerValue, ";");
477             assertEquals(getExpectedAlerts()[2], headerValue);
478         }
479         else {
480             assertEquals(getExpectedAlerts()[2], headerValue);
481         }
482     }
483 
484     private void jsEncoding(final String encoding) throws Exception {
485         final String html = DOCTYPE_HTML
486             + "<html>\n"
487             + "<head>\n"
488             + "  <script>\n"
489             + LOG_TITLE_FUNCTION
490             + "  function doTest() {\n"
491             + "    try {\n"
492             + "      document.forms[0].encoding = '" + encoding + "';\n"
493             + "      log(document.forms[0].encoding);\n"
494             + "    } catch(e) { logEx(e); }\n"
495             + "    log(document.forms[0].enctype);\n"
496             + "  }\n"
497             + "  </script>\n"
498             + "</head>\n"
499             + "<body onload='doTest()'>\n"
500             + "  <form id='testForm' name='testForm' method='post' action = 'page2.html'>\n"
501             + "    <input type='submit' name='submit1' />\n"
502             + "  </form>\n"
503             + "</body></html>";
504 
505         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
506 
507         final WebDriver driver = loadPage2(html);
508         verifyTitle2(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[0], getExpectedAlerts()[1]});
509 
510         driver.findElement(By.name("submit1")).click();
511         if (useRealBrowser()) {
512             Thread.sleep(400);
513         }
514         assertTitle(driver, "Response");
515         String headerValue = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
516             .get(HttpHeader.CONTENT_TYPE);
517         if (headerValue.startsWith(FormEncodingType.MULTIPART.getName())) {
518             // Can't test equality for multipart/form-data as it will have the form:
519             // multipart/form-data; boundary=---------------------------42937861433140731107235900
520             headerValue = StringUtils.substringBefore(headerValue, ";");
521             assertEquals(getExpectedAlerts()[2], headerValue);
522         }
523         else {
524             assertEquals(getExpectedAlerts()[2], headerValue);
525         }
526     }
527 
528     /**
529      * @throws Exception if the test fails
530      */
531     @Test
532     @Alerts({"multipart/form-data", "application/x-www-form-urlencoded", "application/x-www-form-urlencoded"})
533     public void encodingProperty() throws Exception {
534         doTestProperty("encoding", "enctype", "multipart/form-data", "application/x-www-form-urlencoded");
535     }
536 
537     /**
538      * @throws Exception if the test fails
539      */
540     @Test
541     @Alerts({"text/plain", "application/x-www-form-urlencoded", "newEncoding"})
542     public void encodingProperty_textPlain() throws Exception {
543         doTestProperty("encoding", "enctype", MimeType.TEXT_PLAIN, "newEncoding");
544     }
545 
546     /**
547      * @throws Exception if the test fails
548      */
549     @Test
550     @Alerts({"application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "newEncoding"})
551     public void encodingProperty_dummyValues() throws Exception {
552         doTestProperty("encoding", "enctype", "myEncoding", "newEncoding");
553     }
554 
555     /**
556      * @throws Exception if the test fails
557      */
558     @Test
559     @Alerts({"get", "post", "post"})
560     public void methodProperty() throws Exception {
561         doTestProperty("method", "method", "get", "post");
562     }
563 
564     /**
565      * @throws Exception if the test fails
566      */
567     @Test
568     @Alerts({"_top", "_parent", "_parent"})
569     public void targetProperty() throws Exception {
570         doTestProperty("target", "target", "_top", "_parent");
571     }
572 
573     private void doTestProperty(final String jsProperty, final String htmlProperty,
574             final String oldValue, final String newValue) throws Exception {
575 
576         final String html = DOCTYPE_HTML
577             + "<html><head><script>\n"
578             + LOG_TITLE_FUNCTION
579             + "function doTest() {\n"
580             + "  log(document.forms[0]." + jsProperty + ");\n"
581             + "  try {\n"
582             + "    document.forms[0]." + jsProperty + "='" + newValue + "';\n"
583             + "    log(document.forms[0]." + jsProperty + ");\n"
584             + "    log(document.forms[0].getAttribute('" + htmlProperty + "'));\n"
585             + "  } catch(e) { logEx(e); }\n"
586             + "}\n"
587             + "</script></head><body onload='doTest()'>\n"
588             + "<p>hello world</p>\n"
589             + "<form " + htmlProperty + "='" + oldValue + "'>\n"
590             + "  <input type='button' name='button1' />\n"
591             + "</form>\n"
592             + "</body></html>";
593 
594         final WebDriver wd = loadPageVerifyTitle2(html);
595 
596         final WebElement form = wd.findElement(By.xpath("//form"));
597         if (wd instanceof HtmlUnitDriver && getExpectedAlerts().length >= 3) {
598             // form.getAttribute("enctype") returns form.getAttribute("encoding") with the FF driver. Bug or feature?
599             assertEquals(getExpectedAlerts()[2], form.getAttribute(htmlProperty));
600         }
601     }
602 
603     /**
604      * @throws Exception if the test fails
605      */
606     @Test
607     @Alerts({"id2", "foo"})
608     public void inputNamedId() throws Exception {
609         doTestInputWithName("id");
610     }
611 
612     /**
613      * @throws Exception if the test fails
614      */
615     @Test
616     @Alerts({"action2", "foo"})
617     public void inputNamedAction() throws Exception {
618         doTestInputWithName("action");
619     }
620 
621     private void doTestInputWithName(final String name) throws Exception {
622         final String html = DOCTYPE_HTML
623             + "<html><head><script>\n"
624             + LOG_TITLE_FUNCTION
625             + "function go() {\n"
626             + "  log(document.simple_form." + name + ".value);\n"
627             + "  document.simple_form." + name + ".value = 'foo';\n"
628             + "  log(document.simple_form." + name + ".value);\n"
629             + "}</script></head>\n"
630             + "<body onload='go()'>\n"
631             + "<p>hello world</p>\n"
632             + "<form action='login.jsp' name='simple_form'>\n"
633             + "  <input name='" + name + "' type='hidden' value='" + name + "2'>\n"
634             + "</form>\n"
635             + "</body></html>";
636 
637         loadPageVerifyTitle2(html);
638     }
639 
640     /**
641      * Regression test that used to blow up on page load.
642      * @throws Exception if the test fails
643      */
644     @Test
645     @Alerts("value = 2")
646     public void accessingRadioButtonArrayByName_Regression() throws Exception {
647         final String html = DOCTYPE_HTML
648             + "<html><head></head>\n"
649             + "<body><form name='whatsnew'>\n"
650             + "<input type='radio' name='second' value='1'>\n"
651             + "<input type='radio' name='second' value='2' checked>\n"
652             + "</form><script>\n"
653             + LOG_TITLE_FUNCTION
654             + "clickAction();\n"
655             + "function clickAction() {\n"
656             + "  var value = -1;\n"
657             + "  radios = document.forms['whatsnew'].elements['second'];\n"
658             + "  for (var i = 0; i < radios.length; i++){\n"
659             + "    if (radios[i].checked == true) {\n"
660             + "      value = radios[i].value;\n"
661             + "      break;\n"
662             + "    }\n"
663             + "  }\n"
664             + "  log('value = ' + value);\n"
665             + "}\n"
666             + "</script></body></html>";
667 
668         loadPageVerifyTitle2(html);
669     }
670 
671     /**
672      * Test for a bug that appeared when visiting mail.yahoo.com. Setting the value of one input
673      * seems to blow away the other input. Also tests that the form input collection does not get
674      * cached before the document is finished loading.
675      * @throws Exception if the test fails
676      */
677     @Test
678     @Alerts("foo")
679     public void findInputWithoutTypeDefined() throws Exception {
680         final String html = DOCTYPE_HTML
681             + "<html><head>\n"
682             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
683             + "</head>\n"
684             + "<body onload='log(document.simple_form.login.value);'>\n"
685             + "<p>hello world</p><table><tr><td>\n"
686             + "<form action='login.jsp' name='simple_form'>\n"
687             + "  <input name='msg' type='hidden' value='0'>\n"
688             + "  <script>document.simple_form.msg.value = 1</script>\n"
689             + "  <input name='login' size='17' value='foo'>\n"
690             + "</form></td></tr></table>\n"
691             + "</body></html>";
692 
693         loadPageVerifyTitle2(html);
694     }
695 
696     /**
697      * Test form.length - This method does not count the type=image
698      * input tags.
699      * @throws Exception if the test fails
700      */
701     @Test
702     @Alerts("2")
703     public void length() throws Exception {
704         final String html = DOCTYPE_HTML
705             + "<html><head><script>\n"
706             + LOG_TITLE_FUNCTION
707             + "function doTest() {\n"
708             + "  log(document.form1.length);\n"
709             + "}\n"
710             + "</script></head><body onload='doTest()'>\n"
711             + "<form name='form1'>\n"
712             + "  <input type='radio' name='radio1' value='1'/>\n"
713             + "  <input type='image' src='foo' value='1'/>\n"
714             + "  <input type='submit' name='submit1' value='1'/>\n"
715             + "</form>\n"
716             + "</body></html>";
717 
718         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
719 
720         loadPageVerifyTitle2(html);
721     }
722 
723     /**
724      * @throws Exception if the test fails
725      */
726     @Test
727     @Alerts("button1")
728     public void get() throws Exception {
729         final String html = DOCTYPE_HTML
730             + "<html><head><script>\n"
731             + LOG_TITLE_FUNCTION
732             + "function doTest() {\n"
733             + "  log(document.form1[0].name);\n"
734             + "}\n"
735             + "</script></head><body onload='doTest()'>\n"
736             + "<p>hello world</p>\n"
737             + "<form name='form1'>\n"
738             + "  <input type='button' name='button1' />\n"
739             + "</form>\n"
740             + "</body></html>";
741 
742         loadPageVerifyTitle2(html);
743     }
744 
745     /**
746      * Test that the elements collection is live.
747      * @throws Exception if the test fails
748      */
749     @Test
750     @Alerts({"0", "1", "1", "true"})
751     public void elementsLive() throws Exception {
752         final String html = DOCTYPE_HTML
753             + "<html>\n"
754             + "<body>\n"
755             + "<form name='myForm'>\n"
756             + "<script>\n"
757             + LOG_TITLE_FUNCTION
758             + "var oElements = document.myForm.elements;\n"
759             + "log(oElements.length);\n"
760             + "</script>\n"
761             + "<input type='text' name='foo'/>\n"
762             + "<script>\n"
763             + "log(oElements.length);\n"
764             + "log(document.myForm.elements.length);\n"
765             + "log(oElements == document.myForm.elements);\n"
766             + "</script>\n"
767             + "</form>\n"
768             + "</body>\n"
769             + "</html>";
770 
771         loadPageVerifyTitle2(html);
772     }
773 
774     /**
775      * @throws Exception if the test fails
776      */
777     @Test
778     @Alerts({"1", "[object HTMLInputElement]/txt"})
779     public void elementsInputImage() throws Exception {
780         final String html = DOCTYPE_HTML
781             + "<html>\n"
782             + "<body>\n"
783             + "<form name='myForm'>\n"
784             + "  <input type='text' name='foo' id='txt'/>\n"
785             + "  <input type='image' name='fooo' id='img'/>\n"
786             + "</form>\n"
787 
788             + "<script>\n"
789             + LOG_TITLE_FUNCTION
790             + "var oElements = document.myForm.elements;\n"
791             + "log(oElements.length);\n"
792             + "log(oElements[0] + '/' + oElements[0].id);\n"
793             + "</script>\n"
794             + "</body>\n"
795             + "</html>";
796 
797         loadPageVerifyTitle2(html);
798     }
799 
800     /**
801      * @throws Exception if the test fails
802      */
803     @Test
804     @Alerts("0")
805     public void elementsImage() throws Exception {
806         final String html = DOCTYPE_HTML
807             + "<html>\n"
808             + "<body>\n"
809             + "<form name='myForm'>\n"
810             + "  <img name='foo' id='txt'>\n"
811             + "</form>\n"
812 
813             + "<script>\n"
814             + LOG_TITLE_FUNCTION
815             + "var oElements = document.myForm.elements;\n"
816             + "log(oElements.length);\n"
817             + "</script>\n"
818             + "</body>\n"
819             + "</html>";
820 
821         loadPageVerifyTitle2(html);
822     }
823 
824     /**
825      * @throws Exception if the test fails
826      */
827     @Test
828     @Alerts({"1", "[object HTMLOutputElement]"})
829     public void elementsOutput() throws Exception {
830         final String html = DOCTYPE_HTML
831             + "<html>\n"
832             + "<body>\n"
833             + "<form name='myForm'>\n"
834             + "  <output name='result'>60</output>\n"
835             + "</form>\n"
836 
837             + "<script>\n"
838             + LOG_TITLE_FUNCTION
839             + "var oElements = document.myForm.elements;\n"
840             + "log(oElements.length);\n"
841             + "log(oElements[0]);\n"
842             + "</script>\n"
843             + "</body>\n"
844             + "</html>";
845 
846         loadPageVerifyTitle2(html);
847     }
848 
849     /**
850      * @throws Exception if the test fails
851      */
852     @Test
853     @Alerts({"2", "[object HTMLFieldSetElement]", "[object HTMLInputElement]"})
854     public void elementsFieldSet() throws Exception {
855         final String html = DOCTYPE_HTML
856             + "<html>\n"
857             + "<body>\n"
858             + "<form name='myForm'>\n"
859             + "  <fieldset id='fs'>\n"
860             + "    <legend>Legend</legend>\n"
861             + "    <input type='text' name='foo'/>\n"
862             + "  </fieldset>\n"
863             + "</form>\n"
864 
865             + "<script>\n"
866             + LOG_TITLE_FUNCTION
867             + "var oElements = document.myForm.elements;\n"
868             + "log(oElements.length);\n"
869             + "log(oElements[0]);\n"
870             + "log(oElements[1]);\n"
871             + "</script>\n"
872             + "</body>\n"
873             + "</html>";
874 
875         loadPageVerifyTitle2(html);
876     }
877 
878     /**
879      * @throws Exception if the test fails
880      */
881     @Test
882     @Alerts({"2", "[object HTMLFieldSetElement]", "[object HTMLInputElement]"})
883     public void elementsFieldSetEmpty() throws Exception {
884         final String html = DOCTYPE_HTML
885             + "<html>\n"
886             + "<body>\n"
887             + "<form name='myForm'>\n"
888             + "  <fieldset id='fs'>\n"
889             + "  </fieldset>\n"
890             + "  <input type='text' name='foo'/>\n"
891             + "</form>\n"
892 
893             + "<script>\n"
894             + LOG_TITLE_FUNCTION
895             + "var oElements = document.myForm.elements;\n"
896             + "log(oElements.length);\n"
897             + "log(oElements[0]);\n"
898             + "log(oElements[1]);\n"
899             + "</script>\n"
900             + "</body>\n"
901             + "</html>";
902 
903         loadPageVerifyTitle2(html);
904     }
905 
906     /**
907      * @throws Exception if the test fails
908      */
909     @Test
910     @Alerts({"4", "[object HTMLFieldSetElement]/fs_outer",
911              "[object HTMLInputElement]/foo",
912              "[object HTMLFieldSetElement]/fs_inner",
913              "[object HTMLInputElement]/fooo"})
914     public void elementsFieldSetInsideFieldSet() throws Exception {
915         final String html = DOCTYPE_HTML
916             + "<html>\n"
917             + "<body>\n"
918             + "<form name='myForm'>\n"
919             + "  <fieldset id='fs_outer'>\n"
920             + "    <legend>Legend</legend>\n"
921             + "    <input type='text' name='foo' id='foo'/>\n"
922 
923             + "    <fieldset id='fs_inner'>\n"
924             + "      <input type='text' name='fooo' id='fooo'/>\n"
925             + "    </fieldset>\n"
926             + "  </fieldset>\n"
927             + "</form>\n"
928 
929             + "<script>\n"
930             + LOG_TITLE_FUNCTION
931             + "var oElements = document.myForm.elements;\n"
932             + "log(oElements.length);\n"
933             + "log(oElements[0] + '/' + oElements[0].id);\n"
934             + "log(oElements[1] + '/' + oElements[1].id);\n"
935             + "log(oElements[2] + '/' + oElements[2].id);\n"
936             + "log(oElements[3] + '/' + oElements[3].id);\n"
937             + "</script>\n"
938             + "</body>\n"
939             + "</html>";
940 
941         loadPageVerifyTitle2(html);
942     }
943 
944     /**
945      * @throws Exception if the test fails
946      */
947     @Test
948     @Alerts("§§URL§§foo.html")
949     public void getFormFromFormsById() throws Exception {
950         final String html = DOCTYPE_HTML
951             + "<html>\n"
952             + "<head>\n"
953             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
954             + "</head>\n"
955             + "<body onload=\"log(document.forms['myForm'].action)\">\n"
956             + "<form id='myForm' action='foo.html'>\n"
957             + "</form>\n"
958             + "</body>\n"
959             + "</html>";
960 
961         expandExpectedAlertsVariables(URL_FIRST);
962         loadPageVerifyTitle2(html);
963     }
964 
965     /**
966      * @throws Exception if the test fails
967      */
968     @Test
969     @Alerts("§§URL§§")
970     public void action() throws Exception {
971         final String html = DOCTYPE_HTML
972             + "<html>\n"
973             + "<head>\n"
974             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
975             + "</head>\n"
976             + "<body onload=\"log(document.forms['myForm'].action)\">\n"
977             + "<form id='myForm'>\n"
978             + "</form>\n"
979             + "</body>\n"
980             + "</html>";
981 
982         expandExpectedAlertsVariables(URL_FIRST);
983         loadPageVerifyTitle2(html);
984     }
985 
986     /**
987      * @throws Exception if the test fails
988      */
989     @Test
990     @Alerts("§§URL§§")
991     public void actionEmpty() throws Exception {
992         final String html = DOCTYPE_HTML
993             + "<html>\n"
994             + "<head>\n"
995             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
996             + "</head>\n"
997             + "<body onload=\"log(document.forms['myForm'].action)\">\n"
998             + "<form id='myForm' action=''>\n"
999             + "</form>\n"
1000             + "</body>\n"
1001             + "</html>";
1002 
1003         expandExpectedAlertsVariables(URL_FIRST);
1004         loadPageVerifyTitle2(html);
1005     }
1006 
1007     /**
1008      * @throws Exception if the test fails
1009      */
1010     @Test
1011     @Alerts("§§URL§§")
1012     public void actionBlank() throws Exception {
1013         final String html = DOCTYPE_HTML
1014             + "<html>\n"
1015             + "<head>\n"
1016             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
1017             + "</head>\n"
1018             + "<body onload=\"log(document.forms['myForm'].action)\">\n"
1019             + "<form id='myForm' action='  '>\n"
1020             + "</form>\n"
1021             + "</body>\n"
1022             + "</html>";
1023 
1024         expandExpectedAlertsVariables(URL_FIRST);
1025         loadPageVerifyTitle2(html);
1026     }
1027 
1028     /**
1029      * @throws Exception if the test fails
1030      */
1031     @Test
1032     @Alerts("text")
1033     public void getFieldNamedLikeForm() throws Exception {
1034         final String html = DOCTYPE_HTML
1035             + "<html>\n"
1036             + "<head>\n"
1037             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
1038             + "</head>\n"
1039             + "<body onload='log(document.login.login.type)'>\n"
1040             + "<form name='login' action='foo.html'>\n"
1041             + "<input name='login' type='text'>\n"
1042             + "</form>\n"
1043             + "</body>\n"
1044             + "</html>";
1045 
1046         loadPageVerifyTitle2(html);
1047     }
1048 
1049     /**
1050      * Verifies that document.myForm.submit returns a field name submit or the submit function
1051      * depending on the sort of the field named submit.
1052      * @throws Exception if the test fails
1053      */
1054     @Test
1055     public void fieldNamedSubmit() throws Exception {
1056         fieldNamedSubmit("<input type='text' name='submit'>\n", "INPUT");
1057         fieldNamedSubmit("<input type='password' name='submit'>\n", "INPUT");
1058         fieldNamedSubmit("<input type='submit' name='submit'>\n", "INPUT");
1059         fieldNamedSubmit("<input type='radio' name='submit'>\n", "INPUT");
1060         fieldNamedSubmit("<input type='checkbox' name='submit'>\n", "INPUT");
1061         fieldNamedSubmit("<input type='button' name='submit'>\n", "INPUT");
1062         fieldNamedSubmit("<button type='submit' name='submit'>\n", "BUTTON");
1063         fieldNamedSubmit("<textarea name='submit'></textarea>\n", "TEXTAREA");
1064         fieldNamedSubmit("<select name='submit'></select>\n", "SELECT");
1065 
1066         fieldNamedSubmit("<input type='image' name='submit'>\n", "function");
1067         fieldNamedSubmit("<input type='IMAGE' name='submit'>\n", "function");
1068         fieldNamedSubmit("<input type='IMAGE' name='submit'>\n", "function");
1069 
1070         fieldNamedSubmit("<fieldset name='submit'><legend>Legend</legend></fieldset>\n", "FIELDSET");
1071 
1072         fieldNamedSubmit("<object name='submit'></object>\n", "OBJECT");
1073 
1074         fieldNamedSubmit("<output name='submit'></output>\n", "OUTPUT");
1075 
1076         fieldNamedSubmit("<img name='submit'>\n", "IMG");
1077     }
1078 
1079     /**
1080      * @param htmlSnippet the HTML to embed in the test
1081      * @param expected the expected alert
1082      * @throws Exception if the test fails
1083      */
1084     private void fieldNamedSubmit(final String htmlSnippet, final String expected) throws Exception {
1085         final String html = DOCTYPE_HTML
1086             + "<html>\n"
1087             + "<head>\n"
1088             + "<script>\n"
1089             + LOG_TITLE_FUNCTION
1090             + "function test() {\n"
1091             + "  if (document.login.submit.tagName)\n"
1092             + "    log(document.login.submit.tagName);\n"
1093             + "  else"
1094             + "    log('function');\n"
1095             + "}\n"
1096             + "</script>\n"
1097             + "</head>\n"
1098             + "<body onload='test()'>\n"
1099             + "<form name='login' action='foo.html'>\n"
1100             + htmlSnippet
1101             + "</form>\n"
1102             + "</body>\n"
1103             + "</html>";
1104 
1105         setExpectedAlerts(expected);
1106         loadPageVerifyTitle2(html);
1107     }
1108 
1109     /**
1110      * @throws Exception if the test fails
1111      */
1112     @Test
1113     @Alerts({"before", "2", "undefined"})
1114     public void fieldFoundWithId() throws Exception {
1115         final String html = DOCTYPE_HTML
1116             + "<html><head>\n"
1117             + "<script>\n"
1118             + LOG_TITLE_FUNCTION
1119             + "function test() {\n"
1120             + "  log(IRForm.IRText.value);\n"
1121             + "  log(IRForm.myField.length);\n"
1122             + "  log(IRForm.myDiv);\n"
1123             + "}\n"
1124             + "</script>\n"
1125             + "</head>\n"
1126             + "<body onload='test()'>\n"
1127             + "  <form name='IRForm' action='#'>\n"
1128             + "    <input type='text' id='IRText' value='before'/>\n"
1129             + "    <input type='image' name='myField' src='foo.gif'/>\n"
1130             + "    <input type='image' id='myField' src='foo.gif'/>\n"
1131             + "    <input type='text' name='myField'/>\n"
1132             + "    <input type='text' id='myField'/>\n"
1133             + "    <div id='myDiv'>oooo</div>\n"
1134             + "  </form>\n"
1135             + "</body>\n"
1136             + "</html>";
1137 
1138         loadPageVerifyTitle2(html);
1139     }
1140 
1141     /**
1142      * @throws Exception if the test fails
1143      */
1144     @Test
1145     @Alerts({"[object HTMLInputElement]", "[object HTMLInputElement]"})
1146     public void fieldFoundWithIdByReference() throws Exception {
1147         final String html = DOCTYPE_HTML
1148             + "<html><head>\n"
1149             + "<script>\n"
1150             + LOG_TITLE_FUNCTION
1151             + "function test() {\n"
1152             + "  log(IRForm.IRText);\n"
1153             + "  log(IRForm.myField);\n"
1154             + "}\n"
1155             + "</script>\n"
1156             + "</head>\n"
1157             + "<body onload='test()'>\n"
1158             + "  <form name='IRForm' id='testForm' action='#'>\n"
1159             + "  </form>\n"
1160             + "  <input type='text' id='IRText' value='abc' form='testForm' />\n"
1161             + "  <input type='text' id='myField' value='xy' form='testForm'/>\n"
1162             + "</body>\n"
1163             + "</html>";
1164 
1165         loadPageVerifyTitle2(html);
1166     }
1167 
1168     /**
1169      * @throws Exception if the test fails
1170      */
1171     @Test
1172     @Alerts({"INPUT", "idImg1", "img2", "true"})
1173     public void nonFieldChildFound() throws Exception {
1174         final String html = DOCTYPE_HTML
1175             + "<html><head>\n"
1176             + "<script>\n"
1177             + LOG_TITLE_FUNCTION
1178             + "function test() {\n"
1179             + "  var oForm = document.testForm;\n"
1180             + "  log(oForm.img.tagName);\n"
1181             + "  log(oForm.img1.id);\n"
1182             + "  log(oForm.img2.id);\n"
1183             + "  log(oForm.testSpan == undefined);\n"
1184             + "}\n"
1185             + "</script>\n"
1186             + "</head>\n"
1187             + "<body onload='test()'>\n"
1188             + "  <form name='testForm' action='foo'>\n"
1189             + "    <input type='text' id='img' value='before'/>\n"
1190             + "    <img name='img' id='idImg' src='foo.png'/>\n"
1191             + "    <img name='img1' id='idImg1' src='foo.png'/>\n"
1192             + "    <img id='img2' src='foo.png'/>\n"
1193             + "    <span id='testSpan'>foo</span>\n"
1194             + "  </form>\n"
1195             + "</body>\n"
1196             + "</html>";
1197 
1198         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
1199 
1200         loadPageVerifyTitle2(html);
1201     }
1202 
1203     /**
1204      * @throws Exception if the test fails
1205      */
1206     @Test
1207     @Alerts({"[object HTMLImageElement]", "[object HTMLImageElement]"})
1208     public void findImageWhenNotDirectChild() throws Exception {
1209         final String html = DOCTYPE_HTML
1210             + "<html>\n"
1211             + "<head>\n"
1212             + "<script>\n"
1213             + LOG_TITLE_FUNCTION
1214             + "function doTest() {\n"
1215             + "  log(document.fmLogin.myImgName);\n"
1216             + "  log(document.fmLogin.myImgId);\n"
1217             + "}\n"
1218             + "</script>\n"
1219             + "</head>\n"
1220             + "<body onload='doTest()'>\n"
1221             + "  <form name='fmLogin' action='doLogin' method='POST'>\n"
1222             + "    <div>\n"
1223             + "      <img name='myImgName' src='somewhere'>\n"
1224             + "      <img id='myImgId' src='somewhere'>\n"
1225             + "    <div/>\n"
1226             + "  </form>\n"
1227             + "</body></html>";
1228 
1229         loadPageVerifyTitle2(html);
1230     }
1231 
1232     /**
1233      * This test shows a problem in current implementation of host object with visible constructors
1234      * used to retrieve JS object associated to a particular DOM node. The general problem needs
1235      * later.
1236      * @throws Exception if the test fails
1237      */
1238     @Test
1239     public void formIsNotAConstructor() throws Exception {
1240         final String html = DOCTYPE_HTML
1241             + "<html><head>\n"
1242             + "<script>\n"
1243             + "var Form = {};\n"
1244             + "function test() {\n"
1245             + "  document.getElementById('formId');\n"
1246             + "}\n"
1247             + "</script></head>\n"
1248             + "<body onload='test()'>\n"
1249             + "  <form id='formId' name='formName'>\n"
1250             + "    <input type='text' name='field1' value='barney'>\n"
1251             + "    <input type='submit'>\n"
1252             + "</body>\n"
1253             + "</html>";
1254         loadPageWithAlerts2(html);
1255     }
1256 
1257     /**
1258      * Test that the form from the right page is returned after browsing.
1259      * Regression test for
1260      * http://sourceforge.net/p/htmlunit/bugs/417/
1261      * @throws Exception if the test fails
1262      */
1263     @Test
1264     @Alerts({"page 1: formPage1", "page 2: formPage2"})
1265     public void formAccessAfterBrowsing() throws Exception {
1266         final String html = DOCTYPE_HTML
1267             + "<html><head>\n"
1268             + "<script>\n"
1269             + "function test() {\n"
1270             + "  window.name = 'page 1: ' + document.forms[0].name;\n"
1271             + "  document.location = 'page2.html';\n"
1272             + "}\n"
1273             + "</script>\n"
1274             + "</head><body onload='test()'>\n"
1275             + "<form name='formPage1' action='foo'>\n"
1276             + "</form>\n"
1277             + "</body></html>";
1278         final String secondContent = DOCTYPE_HTML
1279             + "<html><head>\n"
1280             + "<script>\n"
1281             + LOG_TITLE_FUNCTION
1282             + "function test() {\n"
1283             + "  log(window.name);\n"
1284             + "  log('page 2: ' + document.forms[0].name);\n"
1285             + "}\n"
1286             + "</script>\n"
1287             + "</head><body onload='test()'>\n"
1288             + "<form name='formPage2' action='foo'>\n"
1289             + "</form>\n"
1290             + "</body></html>";
1291 
1292         getMockWebConnection().setDefaultResponse(secondContent);
1293         loadPageVerifyTitle2(html);
1294     }
1295 
1296     /**
1297      * @throws Exception if the test fails
1298      */
1299     @Test
1300     @Alerts({"function handler() {}", "null", "null"})
1301     public void onsubmitNull() throws Exception {
1302         final String html = DOCTYPE_HTML
1303             + "<html><head>\n"
1304             + "<script>\n"
1305             + LOG_TITLE_FUNCTION
1306             + "  function handler() {}\n"
1307             + "  function test() {\n"
1308             + "    var form = document.getElementById('myForm');\n"
1309             + "    form.onsubmit = handler;\n"
1310             + "    log(String(form.onsubmit).replace(/\\n/g, ''));\n"
1311             + "    form.onsubmit = null;\n"
1312             + "    log(form.onsubmit);\n"
1313             + "    try {\n"
1314             + "      form.onsubmit = undefined;\n"
1315             + "      log(form.onsubmit);\n"
1316             + "    } catch(e) { logEx(e); }\n"
1317             + "  }\n"
1318             + "</script>\n"
1319             + "<body onload=test()>\n"
1320             + "  <form id='myForm'></form>\n"
1321             + "</body></html>";
1322 
1323         loadPageVerifyTitle2(html);
1324     }
1325 
1326     /**
1327      * @throws Exception if the test fails
1328      */
1329     @Test
1330     @Alerts({"page1.html", "page2.html", "page1.html", "page1.html"})
1331     public void changeFormActionAfterSubmit() throws Exception {
1332         final String[] expectedFiles = getExpectedAlerts();
1333         setExpectedAlerts();
1334 
1335         changeFormActionAfterSubmit("input type='button' value='Test'", expectedFiles[0]);
1336         changeFormActionAfterSubmit("input type='submit' value='Test'", expectedFiles[1]);
1337         changeFormActionAfterSubmit("input type='text' value='Test'", expectedFiles[2]);
1338         changeFormActionAfterSubmit("div", expectedFiles[3]);
1339     }
1340 
1341     private void changeFormActionAfterSubmit(final String clickable, final String expectedFile) throws Exception {
1342         final String html = DOCTYPE_HTML
1343             + "<html>\n"
1344             + "<head>\n"
1345             + "  <script type='text/javascript'>\n"
1346             + "    function submitForm() {\n"
1347             + "      document.myForm.submit();\n"
1348             + "      document.myForm.action = 'page2.html';\n"
1349             + "    }\n"
1350             + "  </script>\n"
1351             + "</head>\n"
1352             + "<body>\n"
1353             + "  <form action='page1.html' name='myForm'>\n"
1354             + "    <" + clickable + " id='x' onclick='submitForm();'>foo\n"
1355             + "  </form>\n"
1356             + "</body>\n"
1357             + "</html>";
1358 
1359         getMockWebConnection().setDefaultResponse("");
1360         final WebDriver driver = loadPageWithAlerts2(html);
1361         driver.findElement(By.id("x")).click();
1362         if (useRealBrowser()) {
1363             Thread.sleep(400);
1364         }
1365         assertEquals(URL_FIRST + expectedFile, driver.getCurrentUrl().replaceAll("\\?", ""));
1366     }
1367 
1368     /**
1369      * @throws Exception if the test fails
1370      */
1371     @Test
1372     @Alerts("TypeError")
1373     public void item() throws Exception {
1374         final String html = DOCTYPE_HTML
1375             + "<html>\n"
1376             + "<head>\n"
1377             + "  <script>\n"
1378             + LOG_TITLE_FUNCTION
1379             + "    function test() {\n"
1380             + "      try {\n"
1381             + "        log(document.forms['myForm'].item('myRadio').type);\n"
1382             + "      } catch(e) { logEx(e) }\n"
1383             + "    }\n"
1384             + "  </script>\n"
1385             + "</head>\n"
1386             + "<body onload='test()'>\n"
1387             + "  <form action='page1.html' name='myForm'>\n"
1388             + "    <input type='radio' name='myRadio'>\n"
1389             + "  </form>\n"
1390             + "</body>\n"
1391             + "</html>";
1392 
1393         loadPageVerifyTitle2(html);
1394     }
1395 
1396     /**
1397      * @throws Exception if the test fails
1398      */
1399     @Test
1400     @Alerts("TypeError")
1401     public void item_many() throws Exception {
1402         final String html = DOCTYPE_HTML
1403             + "<html>\n"
1404             + "<head>\n"
1405             + "  <script>\n"
1406             + LOG_TITLE_FUNCTION
1407             + "    function test() {\n"
1408             + "      try {\n"
1409             + "        log(document.forms['myForm'].item('myRadio').length);\n"
1410             + "      } catch(e) { logEx(e) }\n"
1411             + "    }\n"
1412             + "  </script>\n"
1413             + "</head>\n"
1414             + "<body onload='test()'>\n"
1415             + "  <form action='page1.html' name='myForm'>\n"
1416             + "    <input type='radio' name='myRadio'>\n"
1417             + "    <input type='radio' name='myRadio'>\n"
1418             + "  </form>\n"
1419             + "</body>\n"
1420             + "</html>";
1421 
1422         loadPageVerifyTitle2(html);
1423     }
1424 
1425     /**
1426      * @throws Exception if the test fails
1427      */
1428     @Test
1429     @Alerts("TypeError")
1430     public void item_many_subindex() throws Exception {
1431         final String html = DOCTYPE_HTML
1432             + "<html>\n"
1433             + "<head>\n"
1434             + "  <script>\n"
1435             + LOG_TITLE_FUNCTION
1436             + "    function test() {\n"
1437             + "      try {\n"
1438             + "        log(document.forms['myForm'].item('myRadio', 1).id);\n"
1439             + "      } catch(e) { logEx(e) }\n"
1440             + "    }\n"
1441             + "  </script>\n"
1442             + "</head>\n"
1443             + "<body onload='test()'>\n"
1444             + "  <form action='page1.html' name='myForm'>\n"
1445             + "    <input type='radio' name='myRadio' id='radio1'>\n"
1446             + "    <input type='radio' name='myRadio' id='radio2'>\n"
1447             + "  </form>\n"
1448             + "</body>\n"
1449             + "</html>";
1450 
1451         loadPageVerifyTitle2(html);
1452     }
1453 
1454     /**
1455      * @throws Exception if the test fails
1456      */
1457     @Test
1458     @Alerts("TypeError")
1459     public void item_integer() throws Exception {
1460         final String html = DOCTYPE_HTML
1461             + "<html>\n"
1462             + "<head>\n"
1463             + "  <script>\n"
1464             + LOG_TITLE_FUNCTION
1465             + "    function test() {\n"
1466             + "      try {\n"
1467             + "        log(document.forms['myForm'].item(1).id);\n"
1468             + "      } catch(e) { logEx(e) }\n"
1469             + "    }\n"
1470             + "  </script>\n"
1471             + "</head>\n"
1472             + "<body onload='test()'>\n"
1473             + "  <form action='page1.html' name='myForm'>\n"
1474             + "    <input type='radio' name='myRadio' id='radio1'>\n"
1475             + "    <input type='radio' name='myRadio' id='radio2'>\n"
1476             + "  </form>\n"
1477             + "</body>\n"
1478             + "</html>";
1479 
1480         loadPageVerifyTitle2(html);
1481     }
1482 
1483     /**
1484      * Call to form.submit() should capture the request to be done but the request itself should
1485      * be first done after the script execution... and only if it is still valid.
1486      * @throws Exception if the test fails
1487      */
1488     @Test
1489     @Alerts({"page4.html?f1=v1&f2=v2", "page4.html?f1=v1&f2=v2", "page3.html?f1=v1", "page3.html?f1=v1"})
1490     public void changesAfterCallToSubmit() throws Exception {
1491         final String[] expectedUrlSuffixes = getExpectedAlerts();
1492         setExpectedAlerts();
1493 
1494         changesAfterCallToSubmit("inputSubmitReturnTrue", expectedUrlSuffixes[0]);
1495         changesAfterCallToSubmit("inputSubmitVoid", expectedUrlSuffixes[1]);
1496 
1497         changesAfterCallToSubmit("inputSubmitReturnFalse", expectedUrlSuffixes[2]);
1498         changesAfterCallToSubmit("link", expectedUrlSuffixes[3]);
1499     }
1500 
1501     private void changesAfterCallToSubmit(final String id, final String expectedUrlSuffix) throws Exception {
1502         final String html = DOCTYPE_HTML
1503             + "<html><head><script>\n"
1504             + "function submitForm() {\n"
1505             + "  var f = document.forms[0];\n"
1506             + "  f.action = 'page3.html';\n"
1507             + "\n"
1508             + "  var h = document.createElement('input');\n"
1509             + "  h.name = 'f1';\n"
1510             + "  h.value = 'v1';\n"
1511             + "  f.appendChild(h);\n"
1512             + "\n"
1513             + "  f.submit();\n"
1514             + "\n"
1515             + "  f.action = 'page4.html';\n"
1516             + "  var h = document.createElement('input');\n"
1517             + "  h.name = 'f2';\n"
1518             + "  h.value = 'v2';\n"
1519             + "  f.appendChild(h);\n"
1520             + "  return false;\n"
1521             + "}\n"
1522             + "</script></head><body>\n"
1523             + "<form action='page1.html' name='myForm'>\n"
1524             + "  <input type='submit' id='inputSubmitReturnTrue' value='With on click on the button, return true' "
1525             + "onclick='submitForm(); return true'>\n"
1526             + "  <input type='submit' id='inputSubmitReturnFalse' value='With on click on the button, return false' "
1527             + "onclick='submitForm(); return false'>\n"
1528             + "  <input type='submit' id='inputSubmitVoid' value='With on click on the button, no return' "
1529             + "onclick='submitForm();'>\n"
1530             + "  <a id='link' href='#'  onclick='return submitForm()'><input type='submit' "
1531             + "value='With on click on the link'></a>\n"
1532             + "</form></body></html>";
1533 
1534         getMockWebConnection().setDefaultResponse("");
1535         final WebDriver wd = loadPageWithAlerts2(html);
1536         wd.findElement(By.id(id)).click();
1537         if (useRealBrowser()) {
1538             Thread.sleep(400);
1539         }
1540         assertEquals(URL_FIRST + expectedUrlSuffix, wd.getCurrentUrl());
1541     }
1542 
1543     /**
1544      * @throws Exception if the test fails
1545      */
1546     @Test
1547     @Alerts("2")
1548     public void submit_twice() throws Exception {
1549         final String html = DOCTYPE_HTML
1550             + "<html>\n"
1551             + "<head>\n"
1552             + "<script>\n"
1553             + "  function test() {\n"
1554             + "    var f = document.forms[0];\n"
1555             + "    f.submit();\n"
1556             + "    f.submit();\n"
1557             + "  }\n"
1558             + "</script></head>\n"
1559             + "<body onload='test()'>\n"
1560             + "  <form action='page1.html' name='myForm'>\n"
1561             + "    <input name='myField' value='some value'>\n"
1562             + "  </form>\n"
1563             + "</body></html>";
1564 
1565         getMockWebConnection().setDefaultResponse("");
1566         loadPage2(html);
1567         Thread.sleep(100);
1568 
1569         assertEquals(Integer.parseInt(getExpectedAlerts()[0]), getMockWebConnection().getRequestCount());
1570     }
1571 
1572     /**
1573      * @throws Exception if the test fails
1574      */
1575     @Test
1576     public void targetChangedAfterSubmitCall() throws Exception {
1577         final String html = DOCTYPE_HTML
1578             + "<html><head><script>\n"
1579             + "function test() {\n"
1580             + "  var f = document.forms[0];\n"
1581             + "  f.submit();\n"
1582             + "  f.target = 'foo2';\n"
1583             + "}\n"
1584             + "</script></head><body>\n"
1585             + "<form action='page1.html' name='myForm' target='foo1'>\n"
1586             + "  <input name='myField' value='some value'>\n"
1587             + "</form>\n"
1588             + "<div id='clickMe' onclick='test()'>click me</div></body></html>";
1589 
1590         getMockWebConnection().setDefaultResponse("<html><head>"
1591                 + "<script>document.title = 'Name: ' + window.name</script></head></html>");
1592         final WebDriver driver = loadPage2(html);
1593         driver.findElement(By.id("clickMe")).click();
1594 
1595         try {
1596             driver.switchTo().window("foo2");
1597             fail("Window foo2 found");
1598         }
1599         catch (final NoSuchWindowException e) {
1600             // ok
1601         }
1602         driver.switchTo().window("foo1");
1603         assertTitle(driver, "Name: foo1");
1604     }
1605 
1606     /**
1607      * Verify Content-Type header sent with form submission.
1608      * @throws Exception if the test fails
1609      */
1610     @Test
1611     public void enctypeGet() throws Exception {
1612         // for GET, no Content-Type header should be sent
1613         enctypeTest(false, null, "get", null);
1614         enctypeTest(false, "", "get", null);
1615         enctypeTest(false, "application/x-www-form-urlencoded", "get", null);
1616         enctypeTest(false, "multipart/form-data", "get", null);
1617         enctypeTest(false, MimeType.TEXT_PLAIN, "get", null);
1618 
1619         enctypeTest(true, null, "get", null);
1620         enctypeTest(true, "", "get", null);
1621         enctypeTest(true, "application/x-www-form-urlencoded", "get", null);
1622         enctypeTest(true, "multipart/form-data", "get", null);
1623         enctypeTest(true, MimeType.TEXT_PLAIN, "get", null);
1624     }
1625 
1626     /**
1627      * Verify Content-Type header sent with form submission.
1628      * @throws Exception if the test fails
1629      */
1630     @Test
1631     @Alerts({"application/x-www-form-urlencoded",
1632                 "application/x-www-form-urlencoded",
1633                 "application/x-www-form-urlencoded",
1634                 "multipart/form-data",
1635                 "text/plain"})
1636     public void enctypePost() throws Exception {
1637         enctypeTest(false, null, "post", getExpectedAlerts()[0]);
1638         enctypeTest(false, "", "post", getExpectedAlerts()[1]);
1639         enctypeTest(false, "application/x-www-form-urlencoded", "post", getExpectedAlerts()[2]);
1640         enctypeTest(false, "multipart/form-data", "post", getExpectedAlerts()[3]);
1641         enctypeTest(false, MimeType.TEXT_PLAIN, "post", getExpectedAlerts()[4]);
1642 
1643         enctypeTest(true, null, "post", getExpectedAlerts()[0]);
1644         enctypeTest(true, "", "post", getExpectedAlerts()[1]);
1645         enctypeTest(true, "application/x-www-form-urlencoded", "post", getExpectedAlerts()[2]);
1646         enctypeTest(true, "multipart/form-data", "post", getExpectedAlerts()[3]);
1647         enctypeTest(true, MimeType.TEXT_PLAIN, "post", getExpectedAlerts()[4]);
1648     }
1649 
1650     /**
1651      * Regression test for bug
1652      * <a href="http://sf.net/suppor/tracker.php?aid=2860721">2860721</a>: incorrect enctype form attribute
1653      * should be ignored.
1654      * @throws Exception if the test fails
1655      */
1656     @Test
1657     public void enctype_incorrect() throws Exception {
1658         enctypeTest(false, MimeType.TEXT_HTML, "post", "application/x-www-form-urlencoded");
1659         enctypeTest(false, MimeType.TEXT_HTML, "get", null);
1660 
1661         enctypeTest(true, MimeType.TEXT_HTML, "post", "application/x-www-form-urlencoded");
1662         enctypeTest(true, MimeType.TEXT_HTML, "get", null);
1663 
1664         enctypeTest(false, MimeType.TEXT_XML, "post", "application/x-www-form-urlencoded");
1665         enctypeTest(false, MimeType.TEXT_XML, "get", null);
1666 
1667         enctypeTest(true, MimeType.TEXT_XML, "post", "application/x-www-form-urlencoded");
1668         enctypeTest(true, MimeType.TEXT_XML, "get", null);
1669 
1670         enctypeTest(false, MimeType.APPLICATION_JSON, "post", "application/x-www-form-urlencoded");
1671         enctypeTest(false, MimeType.APPLICATION_JSON, "get", null);
1672 
1673         enctypeTest(true, MimeType.APPLICATION_JSON, "post", "application/x-www-form-urlencoded");
1674         enctypeTest(true, MimeType.APPLICATION_JSON, "get", null);
1675     }
1676 
1677     private void enctypeTest(final boolean html5, final String enctype,
1678                     final String method, final String expectedCntType) throws Exception {
1679         String html = "";
1680         if (html5) {
1681             html += DOCTYPE_HTML;
1682         }
1683         html += "<html><head><script>\n"
1684             + "function test() {\n"
1685             + "  var f = document.forms[0];\n"
1686             + "  f.submit();\n"
1687             + "}\n"
1688             + "</script></head><body onload='test()'>\n"
1689             + "<form action='foo.html' ";
1690         if (enctype != null) {
1691             html += "enctype='" + enctype + "' ";
1692         }
1693         html += "method='" + method + "'>\n"
1694             + "  <input name='myField' value='some value'>\n"
1695             + "</form></body></html>";
1696 
1697         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
1698         final WebDriver driver = loadPage2(html);
1699         assertTitle(driver, "Response");
1700         String headerValue = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1701             .get(HttpHeader.CONTENT_TYPE);
1702         if (headerValue != null && headerValue.startsWith(FormEncodingType.MULTIPART.getName())) {
1703             // Can't test equality for multipart/form-data as it will have the form:
1704             // multipart/form-data; boundary=---------------------------42937861433140731107235900
1705             headerValue = StringUtils.substringBefore(headerValue, ";");
1706             assertEquals(expectedCntType, headerValue);
1707         }
1708         else {
1709             assertEquals(expectedCntType, headerValue);
1710         }
1711     }
1712 
1713     /**
1714      * Verify the default value of enctype for a newly created form element.
1715      * A similar test is used by jQuery-1.9.1 in its "feature support" detection.
1716      * @throws Exception if the test fails
1717      */
1718     @Test
1719     @Alerts("application/x-www-form-urlencoded")
1720     public void enctype_defaultValue_html5() throws Exception {
1721         final String html = DOCTYPE_HTML
1722             + "<html><body><script>\n"
1723             + LOG_TITLE_FUNCTION
1724             + "log(document.createElement('form').enctype);\n"
1725             + "</script></body></html>";
1726 
1727         loadPageVerifyTitle2(html);
1728     }
1729 
1730     /**
1731      * @throws Exception in case of error
1732      */
1733     @Test
1734     @Alerts("application/x-www-form-urlencoded")
1735     public void enctype_defaultValue() throws Exception {
1736         final String html = DOCTYPE_HTML
1737             + "<html><body><script>\n"
1738             + LOG_TITLE_FUNCTION
1739             + "log(document.createElement('form').enctype);\n"
1740             + "</script></body></html>";
1741 
1742         loadPageVerifyTitle2(html);
1743     }
1744 
1745     /**
1746      * Ensure that Multipart form text fields are correctly encoded.
1747      * @throws Exception if the test fails
1748      */
1749     @Test
1750     public void submitMultipartTextFieldWithRightEncoding() throws Exception {
1751         final String html = DOCTYPE_HTML
1752             + "<html><body onload='document.forms[0].submit()'>\n"
1753             + "<form action='foo.html' enctype='multipart/form-data' method='post'>\n"
1754             + "  <input name='myField' value='éèê\u00e4\u00f6\u00fc'>\n"
1755             + "</form></body></html>";
1756 
1757         getMockWebConnection().setDefaultResponse("");
1758         loadPage2(html);
1759         Thread.sleep(100);
1760 
1761         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
1762         final String expected = "Content-Disposition: form-data; name=\"myField\"\r\n"
1763             + "\r\n"
1764             + "éèê\u00e4\u00f6\u00fc";
1765 
1766         assertTrue("Body: " + body, body.contains(expected));
1767     }
1768 
1769     /**
1770      * Ensure that text/plain form parameters are correctly encoded.
1771      * @throws Exception if the test fails
1772      */
1773     @Test
1774     @Alerts("application/x-www-form-urlencoded")
1775     public void submitUrlEncodedEmptyForm() throws Exception {
1776         final String html = DOCTYPE_HTML
1777                 + "<html>\n"
1778                 + "<body onload='document.forms[0].submit()'>\n"
1779                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1780                 + "  </form>\n"
1781                 + "</body>\n"
1782                 + "</html>";
1783 
1784         getMockWebConnection().setDefaultResponse("");
1785         loadPage2(html);
1786         Thread.sleep(100);
1787 
1788         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1789                 .get(HttpHeader.CONTENT_TYPE);
1790         assertEquals(getExpectedAlerts()[0], headerContentType);
1791 
1792         assertEquals(0, getMockWebConnection().getLastWebRequest()
1793                 .getRequestParameters().size());
1794         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1795     }
1796 
1797     /**
1798      * Ensure that text/plain form parameters are correctly encoded.
1799      * @throws Exception if the test fails
1800      */
1801     @Test
1802     @Alerts({"application/x-www-form-urlencoded", "myField=abcDEF"})
1803     public void submitUrlEncodedAsciiText() throws Exception {
1804         final String html = DOCTYPE_HTML
1805                 + "<html>\n"
1806                 + "<body onload='document.forms[0].submit()'>\n"
1807                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1808                 + "    <input name='myField' value='abcDEF'>\n"
1809                 + "  </form>\n"
1810                 + "</body>\n"
1811                 + "</html>";
1812 
1813         getMockWebConnection().setDefaultResponse("");
1814         loadPage2(html);
1815         Thread.sleep(100);
1816 
1817         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1818                 .get(HttpHeader.CONTENT_TYPE);
1819         assertEquals(getExpectedAlerts()[0], headerContentType);
1820 
1821         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1822                 .getRequestParameters().get(0).toString());
1823         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1824     }
1825 
1826     /**
1827      * Ensure that text/plain form parameters are correctly encoded.
1828      * @throws Exception if the test fails
1829      */
1830     @Test
1831     @Alerts({"application/x-www-form-urlencoded", "my\tFie ld = a b\tc \t"})
1832     public void submitUrlEncodedSpecialChars() throws Exception {
1833         final String html = DOCTYPE_HTML
1834                 + "<html>\n"
1835                 + "<body onload='document.forms[0].submit()'>\n"
1836                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1837                 + "    <input name='my\tFie ld ' value=' a b\tc \t'>\n"
1838                 + "  </form>\n"
1839                 + "</body>\n"
1840                 + "</html>";
1841 
1842         getMockWebConnection().setDefaultResponse("");
1843         loadPage2(html);
1844         Thread.sleep(100);
1845 
1846         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1847                 .get(HttpHeader.CONTENT_TYPE);
1848         assertEquals(getExpectedAlerts()[0], headerContentType);
1849 
1850         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1851                 .getRequestParameters().get(0).toString());
1852         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1853     }
1854 
1855     /**
1856      * Ensure that text/plain form parameters are correctly encoded.
1857      * @throws Exception if the test fails
1858      */
1859     @Test
1860     @Alerts({"application/x-www-form-urlencoded", "myField=éèê\u00e4\u00f6\u00fc"})
1861     public void submitUrlEncodedUnicode() throws Exception {
1862         final String html = DOCTYPE_HTML
1863                 + "<html>\n"
1864                 + "<body onload='document.forms[0].submit()'>\n"
1865                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1866                 + "    <input name='myField' value='éèê\u00e4\u00f6\u00fc'>\n"
1867                 + "  </form>\n"
1868                 + "</body>\n"
1869                 + "</html>";
1870 
1871         getMockWebConnection().setDefaultResponse("");
1872         loadPage2(html, URL_FIRST, "text/html;charset=UTF-8", UTF_8, null);
1873         Thread.sleep(100);
1874 
1875         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1876                 .get(HttpHeader.CONTENT_TYPE);
1877         assertEquals(getExpectedAlerts()[0], headerContentType);
1878 
1879         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1880                 .getRequestParameters().get(0).toString());
1881         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1882     }
1883 
1884     /**
1885      * Ensure that text/plain form parameters are correctly encoded.
1886      * @throws Exception if the test fails
1887      */
1888     @Test
1889     @Alerts({"application/x-www-form-urlencoded", "myField=HtmlUnit \u043B\u0189"})
1890     public void submitUrlEncodedUnicodeUTF8() throws Exception {
1891         final String html = DOCTYPE_HTML
1892                 + "<html>\n"
1893                 + "<body onload='document.forms[0].submit()'>\n"
1894                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1895                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
1896                 + "  </form>\n"
1897                 + "</body>\n"
1898                 + "</html>";
1899 
1900         getMockWebConnection().setDefaultResponse("");
1901         loadPage2(html, URL_FIRST, "text/html;charset=UTF-8", UTF_8, null);
1902         Thread.sleep(100);
1903 
1904         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1905                 .get(HttpHeader.CONTENT_TYPE);
1906         assertEquals(getExpectedAlerts()[0], headerContentType);
1907 
1908         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1909                 .getRequestParameters().get(0).toString());
1910         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1911     }
1912 
1913     /**
1914      * Ensure that text/plain form parameters are correctly encoded.
1915      * @throws Exception if the test fails
1916      */
1917     @Test
1918     @Alerts({"application/x-www-form-urlencoded", "myField=HtmlUnit \u043B\u0189"})
1919     public void submitUrlEncodedUnicodeUTF16() throws Exception {
1920         final String html = DOCTYPE_HTML
1921                 + "<html>\n"
1922                 + "<body onload='document.forms[0].submit()'>\n"
1923                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1924                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
1925                 + "  </form>\n"
1926                 + "</body>\n"
1927                 + "</html>";
1928 
1929         getMockWebConnection().setDefaultResponse("");
1930         loadPage2(html, URL_FIRST, "text/html;charset=UTF-16", UTF_16, null);
1931         Thread.sleep(100);
1932 
1933         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1934                 .get(HttpHeader.CONTENT_TYPE);
1935         assertEquals(getExpectedAlerts()[0], headerContentType);
1936 
1937         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1938                 .getRequestParameters().get(0).toString());
1939         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1940     }
1941 
1942     /**
1943      * Ensure that text/plain form parameters are correctly encoded.
1944      * @throws Exception if the test fails
1945      */
1946     @Test
1947     @Alerts({"application/x-www-form-urlencoded", "myFile=htmlunit-test", ".txt"})
1948     public void submitUrlEncodedFile() throws Exception {
1949         final String html = DOCTYPE_HTML
1950                 + "<html>\n"
1951                 + "<body>\n"
1952                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1953                 + "    <input type='file' id='f' name='myFile'>\n"
1954                 + "    <input id='clickMe' type='submit' value='Click Me'>\n"
1955                 + "  </form>\n"
1956                 + "</body>\n"
1957                 + "</html>";
1958 
1959         getMockWebConnection().setDefaultResponse("");
1960 
1961         final WebDriver driver = loadPage2(html);
1962 
1963         final File tmpFile = File.createTempFile("htmlunit-test", ".txt");
1964         try {
1965             final String path = tmpFile.getAbsolutePath();
1966             driver.findElement(By.id("f")).sendKeys(path);
1967             driver.findElement(By.id("clickMe")).click();
1968             if (useRealBrowser()) {
1969                 Thread.sleep(400);
1970             }
1971         }
1972         finally {
1973             assertTrue(tmpFile.delete());
1974         }
1975 
1976         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1977                 .get(HttpHeader.CONTENT_TYPE);
1978         assertEquals(getExpectedAlerts()[0], headerContentType);
1979 
1980         final String body = getMockWebConnection().getLastWebRequest()
1981                 .getRequestParameters().get(0).toString();
1982         assertTrue(body, body.startsWith(getExpectedAlerts()[1]));
1983         assertTrue(body, body.endsWith(getExpectedAlerts()[2]));
1984         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1985     }
1986 
1987     /**
1988      * Ensure that text/plain form parameters are correctly encoded.
1989      * @throws Exception if the test fails
1990      */
1991     @Test
1992     @Alerts("text/plain")
1993     public void submitPlainTextEmptyForm() throws Exception {
1994         final String html = DOCTYPE_HTML
1995                 + "<html>\n"
1996                 + "<body onload='document.forms[0].submit()'>\n"
1997                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
1998                 + "  </form>\n"
1999                 + "</body>\n"
2000                 + "</html>";
2001 
2002         getMockWebConnection().setDefaultResponse("");
2003         loadPage2(html);
2004         Thread.sleep(100);
2005 
2006         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2007                 .get(HttpHeader.CONTENT_TYPE);
2008         assertEquals(getExpectedAlerts()[0], headerContentType);
2009 
2010         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2011         assertNull(body);
2012     }
2013 
2014     /**
2015      * Ensure that text/plain form parameters are correctly encoded.
2016      * @throws Exception if the test fails
2017      */
2018     @Test
2019     @Alerts({"text/plain", "myField=abcDEF\r\n"})
2020     public void submitPlainTextAsciiText() throws Exception {
2021         final String html = DOCTYPE_HTML
2022                 + "<html>\n"
2023                 + "<body onload='document.forms[0].submit()'>\n"
2024                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2025                 + "    <input name='myField' value='abcDEF'>\n"
2026                 + "  </form>\n"
2027                 + "</body>\n"
2028                 + "</html>";
2029 
2030         getMockWebConnection().setDefaultResponse("");
2031         loadPage2(html);
2032         Thread.sleep(100);
2033 
2034         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2035                 .get(HttpHeader.CONTENT_TYPE);
2036         assertEquals(getExpectedAlerts()[0], headerContentType);
2037 
2038         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2039         assertEquals(getExpectedAlerts()[1], body);
2040     }
2041 
2042     /**
2043      * Ensure that text/plain form parameters are correctly encoded.
2044      * @throws Exception if the test fails
2045      */
2046     @Test
2047     @Alerts({"text/plain", "my\tField = abcDEF \t\r\n"})
2048     public void submitPlainTextSpecialChars() throws Exception {
2049         final String html = DOCTYPE_HTML
2050                 + "<html>\n"
2051                 + "<body onload='document.forms[0].submit()'>\n"
2052                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2053                 + "    <input name='my\tField ' value=' ab\rcD\nEF \t'>\n"
2054                 + "  </form>\n"
2055                 + "</body>\n"
2056                 + "</html>";
2057 
2058         getMockWebConnection().setDefaultResponse("");
2059         loadPage2(html);
2060         Thread.sleep(100);
2061 
2062         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2063                 .get(HttpHeader.CONTENT_TYPE);
2064         assertEquals(getExpectedAlerts()[0], headerContentType);
2065 
2066         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2067         assertEquals(getExpectedAlerts()[1], body);
2068     }
2069 
2070     /**
2071      * Ensure that text/plain form parameters are correctly encoded.
2072      * @throws Exception if the test fails
2073      */
2074     @Test
2075     @Alerts({"text/plain", "myField=éèê\u00e4\u00f6\u00fc\u00a9\r\n"})
2076     public void submitPlainTextUnicode() throws Exception {
2077         final String html = DOCTYPE_HTML
2078                 + "<html>\n"
2079                 + "<body onload='document.forms[0].submit()'>\n"
2080                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2081                 + "    <input name='myField' value='éèê\u00e4\u00f6\u00fc\u00a9'>\n"
2082                 + "  </form>\n"
2083                 + "</body>\n"
2084                 + "</html>";
2085 
2086         getMockWebConnection().setDefaultResponse("");
2087         loadPage2(html);
2088         Thread.sleep(100);
2089 
2090         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2091                 .get(HttpHeader.CONTENT_TYPE);
2092         assertEquals(getExpectedAlerts()[0], headerContentType);
2093 
2094         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2095         assertEquals(getExpectedAlerts()[1], body);
2096     }
2097 
2098     /**
2099      * Ensure that text/plain form parameters are correctly encoded.
2100      * @throws Exception if the test fails
2101      */
2102     @Test
2103     @Alerts({"text/plain", "myField=éèê\u00e4\u00f6\u00fc\u00a9?\r\n"})
2104     public void submitPlainTextISO_8859_1() throws Exception {
2105         final String html = DOCTYPE_HTML
2106                 + "<html>\n"
2107                 + "<body onload='document.forms[0].submit()'>\n"
2108                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2109                 + "    <input name='myField' value='éèê\u00e4\u00f6\u00fc\u00a9\u05d4'>\n"
2110                 + "  </form>\n"
2111                 + "</body>\n"
2112                 + "</html>";
2113 
2114         getMockWebConnection().setDefaultResponse("");
2115         loadPage2(html, URL_FIRST, "text/html;charset=ISO-8859-1", ISO_8859_1, null);
2116         Thread.sleep(100);
2117 
2118         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2119                 .get(HttpHeader.CONTENT_TYPE);
2120         assertEquals(getExpectedAlerts()[0], headerContentType);
2121 
2122         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2123         assertEquals(getExpectedAlerts()[1], body);
2124         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2125     }
2126 
2127 
2128     /**
2129      * Ensure that text/plain form parameters are correctly encoded.
2130      * @throws Exception if the test fails
2131      */
2132     @Test
2133     @Alerts({"text/plain", "myField=éèêäöü©?\r\n"})
2134     public void submitPlainTextISO_8859_1_AcceptCharsetUtf8() throws Exception {
2135         final String html = DOCTYPE_HTML
2136                 + "<html>\n"
2137                 + "<body onload='document.forms[0].submit()'>\n"
2138                 + "  <form action='foo.html' enctype='text/plain' accept-charset='utf8' method='post'>\n"
2139                 + "    <input name='myField' value='éèê\u00e4\u00f6\u00fc\u00a9\u05d4'>\n"
2140                 + "  </form>\n"
2141                 + "</body>\n"
2142                 + "</html>";
2143 
2144         getMockWebConnection().setDefaultResponse("");
2145         loadPage2(html, URL_FIRST, "text/html;charset=ISO-8859-1", ISO_8859_1, null);
2146         Thread.sleep(100);
2147 
2148         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2149                 .get(HttpHeader.CONTENT_TYPE);
2150         assertEquals(getExpectedAlerts()[0], headerContentType);
2151 
2152         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2153         assertEquals(getExpectedAlerts()[1], body);
2154         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2155     }
2156 
2157     /**
2158      * Ensure that text/plain form parameters are correctly encoded.
2159      * @throws Exception if the test fails
2160      */
2161     @Test
2162     @Alerts({"text/plain", "myField=HtmlUnit \u00D0\u00BB\u00C6\u0089\r\n"})
2163     public void submitPlainTextUnicodeUTF8() throws Exception {
2164         final String html = DOCTYPE_HTML
2165                 + "<html>\n"
2166                 + "<body onload='document.forms[0].submit()'>\n"
2167                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2168                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
2169                 + "  </form>\n"
2170                 + "</body>\n"
2171                 + "</html>";
2172 
2173         getMockWebConnection().setDefaultResponse("");
2174         loadPage2(html, URL_FIRST, "text/html;charset=UTF-8", UTF_8, null);
2175         Thread.sleep(100);
2176 
2177         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2178                 .get(HttpHeader.CONTENT_TYPE);
2179         assertEquals(getExpectedAlerts()[0], headerContentType);
2180 
2181         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2182         assertEquals(getExpectedAlerts()[1], body);
2183         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2184     }
2185 
2186     /**
2187      * Ensure that text/plain form parameters are correctly encoded.
2188      * @throws Exception if the test fails
2189      */
2190     @Test
2191     @Alerts({"text/plain", "myField=HtmlUnit \u00D0\u00BB\u00C6\u0089\r\n"})
2192     public void submitPlainTextUnicodeUTF16() throws Exception {
2193         final String html = DOCTYPE_HTML
2194                 + "<html>\n"
2195                 + "<body onload='document.forms[0].submit()'>\n"
2196                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2197                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
2198                 + "  </form>\n"
2199                 + "</body>\n"
2200                 + "</html>";
2201 
2202         getMockWebConnection().setDefaultResponse("");
2203         loadPage2(html, URL_FIRST, "text/html;charset=UTF-16", UTF_16, null);
2204         Thread.sleep(100);
2205 
2206         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2207                 .get(HttpHeader.CONTENT_TYPE);
2208         assertEquals(getExpectedAlerts()[0], headerContentType);
2209 
2210         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2211         assertEquals(getExpectedAlerts()[1], body);
2212         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2213     }
2214 
2215     /**
2216      * Ensure that text/plain form parameters are correctly encoded.
2217      * @throws Exception if the test fails
2218      */
2219     @Test
2220     @Alerts({"text/plain", "myField=HtmlUnit \u00D0\u00BB\u00C6\u0089\r\n"})
2221     public void submitPlainTextUnicodeUTF16AcceptCharsetUtf8() throws Exception {
2222         final String html = DOCTYPE_HTML
2223                 + "<html>\n"
2224                 + "<body onload='document.forms[0].submit()'>\n"
2225                 + "  <form action='foo.html' enctype='text/plain' accept-charset='utf8' method='post'>\n"
2226                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
2227                 + "  </form>\n"
2228                 + "</body>\n"
2229                 + "</html>";
2230 
2231         getMockWebConnection().setDefaultResponse("");
2232         loadPage2(html, URL_FIRST, "text/html;charset=UTF-16", UTF_16, null);
2233         Thread.sleep(100);
2234 
2235         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2236                 .get(HttpHeader.CONTENT_TYPE);
2237         assertEquals(getExpectedAlerts()[0], headerContentType);
2238 
2239         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2240         assertEquals(getExpectedAlerts()[1], body);
2241         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2242     }
2243 
2244     /**
2245      * Ensure that text/plain form parameters are correctly encoded.
2246      * @throws Exception if the test fails
2247      */
2248     @Test
2249     @Alerts({"text/plain", "myFile=htmlunit-test", ".txt\r\n"})
2250     public void submitPlainTextFile() throws Exception {
2251         final String html = DOCTYPE_HTML
2252                 + "<html>\n"
2253                 + "<body>\n"
2254                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2255                 + "    <input type='file' id='f' name='myFile'>\n"
2256                 + "    <input id='clickMe' type='submit' value='Click Me'>\n"
2257                 + "  </form>\n"
2258                 + "</body>\n"
2259                 + "</html>";
2260 
2261         getMockWebConnection().setDefaultResponse("");
2262 
2263         final WebDriver driver = loadPage2(html);
2264 
2265         final File tmpFile = File.createTempFile("htmlunit-test", ".txt");
2266         try {
2267             final String path = tmpFile.getAbsolutePath();
2268             driver.findElement(By.id("f")).sendKeys(path);
2269             driver.findElement(By.id("clickMe")).click();
2270             if (useRealBrowser()) {
2271                 Thread.sleep(400);
2272             }
2273         }
2274         finally {
2275             assertTrue(tmpFile.delete());
2276         }
2277 
2278         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2279                 .get(HttpHeader.CONTENT_TYPE);
2280         assertEquals(getExpectedAlerts()[0], headerContentType);
2281 
2282         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2283         assertTrue(body, body.startsWith(getExpectedAlerts()[1]));
2284         assertTrue(body, body.endsWith(getExpectedAlerts()[2]));
2285     }
2286 
2287     /**
2288      * Failed as of HtmlUnit-2.7-SNAPSHOT 01.12.2009 as the '#' from the
2289      * link together with the fact that submission occurs to the same url
2290      * let HtmlUnit think that it as just navigation to an anchor.
2291      * @throws Exception if the test fails
2292      */
2293     @Test
2294     public void submitToSameUrlFromLinkOnclick_post() throws Exception {
2295         submitToSameUrlFromLinkOnclick("post");
2296     }
2297 
2298     /**
2299      * @throws Exception if the test fails
2300      */
2301     @Test
2302     public void submitToSameUrlFromLinkOnclick_get() throws Exception {
2303         submitToSameUrlFromLinkOnclick("get");
2304     }
2305 
2306     private void submitToSameUrlFromLinkOnclick(final String method) throws Exception {
2307         final String html = DOCTYPE_HTML
2308             + "<html><head><title>foo</title></head><body>\n"
2309             + "<form id='form1' method='" + method + "'>\n"
2310             + "<input name='foo'>\n"
2311             + "<a href='#' onclick='document.forms[0].submit()' id='clickMe'>submit it</a>\n"
2312             + "</form></body></html>";
2313 
2314         final WebDriver driver = loadPage2(html);
2315         driver.findElement(By.id("clickMe")).click();
2316         driver.findElement(By.id("clickMe")).click(); // a second time to be sure to have same resulting Url
2317         if (useRealBrowser()) {
2318             Thread.sleep(400);
2319         }
2320 
2321         assertEquals(3, getMockWebConnection().getRequestCount());
2322     }
2323 
2324     /**
2325      * @throws Exception if the test fails
2326      */
2327     @Test
2328     @Alerts({"", "foo4?foo=", "script4.js"})
2329     @HtmlUnitNYI(CHROME = {"", "foo0?foo=", "foo1?foo=", "foo2?foo=", "foo3?foo=", "foo4?foo=", "script4.js"},
2330             EDGE = {"", "foo0?foo=", "foo1?foo=", "foo2?foo=", "foo3?foo=", "foo4?foo=", "script4.js"},
2331             FF = {"", "foo0?foo=", "foo1?foo=", "foo2?foo=", "foo3?foo=", "foo4?foo=", "script4.js"},
2332             FF_ESR = {"", "foo0?foo=", "foo1?foo=", "foo2?foo=", "foo3?foo=", "foo4?foo=", "script4.js"})
2333     public void submitTriggersRequestNotParsed() throws Exception {
2334         final String html = DOCTYPE_HTML
2335             + "<html><head><script>\n"
2336             + "function test() {\n"
2337             + "  var f = document.forms[0];\n"
2338             + "  for (var i = 0; i < 5; i++) {\n"
2339             + "    f.action = 'foo' + i;\n"
2340             + "    f.submit();\n"
2341             + "  }\n"
2342             + "}\n"
2343             + "</script></head>\n"
2344             + "<body onload='test()'>\n"
2345             + "  <form>\n"
2346             + "    <input name='foo'>\n"
2347             + "  </form>\n"
2348             + "</body></html>";
2349 
2350         final MockWebConnection connection = getMockWebConnection();
2351         for (int i = 0; i < 5; i++) {
2352             final String htmlX = DOCTYPE_HTML
2353                 + "<html><head>\n"
2354                 + "<title>Page " + i + "</title>\n"
2355                 + "<script src='script" + i + ".js'></script>\n"
2356                 + "<script>alert('page" + i + "');</script>\n"
2357                 + "</head></html>";
2358             connection.setResponse(new URL(URL_FIRST, "foo" + i), htmlX);
2359             connection.setResponse(new URL(URL_FIRST, "script" + i + ".js"), "", MimeType.TEXT_JAVASCRIPT);
2360         }
2361         final String[] expectedRequests = getExpectedAlerts();
2362 
2363         setExpectedAlerts("page4");
2364         final WebDriver driver = loadPageWithAlerts2(html); // forces to wait, what is needed for FFdriver
2365 
2366         // NB: comparing the sequence order here is not 100% safe with a real browser
2367         assertEquals(expectedRequests, getMockWebConnection().getRequestedUrls(URL_FIRST));
2368 
2369         assertTitle(driver, "Page 4");
2370     }
2371 
2372     /**
2373      * When the name of a form field changes... it is still reachable through the original name!
2374      * @throws Exception if the test fails
2375      */
2376     @Test
2377     @Alerts({"[object HTMLInputElement]", "undefined",
2378              "[object HTMLInputElement]", "[object HTMLInputElement]",
2379              "[object HTMLInputElement]", "[object HTMLInputElement]", "[object HTMLInputElement]"})
2380     public void accessByNameAfterNameChangeInput() throws Exception {
2381         accessByNameAfterNameChange("<input name='originalName'>");
2382     }
2383 
2384     /**
2385      * When the name of a form field changes... it is still reachable through the original name!
2386      * @throws Exception if the test fails
2387      */
2388     @Test
2389     @Alerts({"undefined", "undefined"})
2390     public void accessByNameAfterNameChangeInputImage() throws Exception {
2391         accessByNameAfterNameChange("<input type='image' name='originalName'>");
2392     }
2393 
2394     /**
2395      * When the name of a form field changes... it is still reachable through the original name!
2396      * @throws Exception if the test fails
2397      */
2398     @Test
2399     @Alerts({"[object HTMLButtonElement]", "undefined",
2400              "[object HTMLButtonElement]", "[object HTMLButtonElement]",
2401              "[object HTMLButtonElement]", "[object HTMLButtonElement]", "[object HTMLButtonElement]"})
2402     public void accessByNameAfterNameChangeButton() throws Exception {
2403         accessByNameAfterNameChange("<button name='originalName'>btn</button>");
2404     }
2405 
2406     /**
2407      * When the name of a form field changes... it is still reachable through the original name!
2408      * @throws Exception if the test fails
2409      */
2410     @Test
2411     @Alerts({"[object HTMLOutputElement]", "undefined",
2412              "[object HTMLOutputElement]", "[object HTMLOutputElement]",
2413              "[object HTMLOutputElement]", "[object HTMLOutputElement]", "[object HTMLOutputElement]"})
2414     public void accessByNameAfterNameChangeOutput() throws Exception {
2415         accessByNameAfterNameChange("<output name='originalName'>4711</output>");
2416     }
2417 
2418     /**
2419      * When the name of a form field changes... it is still reachable through the original name!
2420      * @throws Exception if the test fails
2421      */
2422     @Test
2423     @Alerts({"[object HTMLTextAreaElement]", "undefined",
2424              "[object HTMLTextAreaElement]", "[object HTMLTextAreaElement]",
2425              "[object HTMLTextAreaElement]", "[object HTMLTextAreaElement]", "[object HTMLTextAreaElement]"})
2426     public void accessByNameAfterNameChangeTextarea() throws Exception {
2427         accessByNameAfterNameChange("<textarea name='originalName'>foo</textarea>");
2428     }
2429 
2430     /**
2431      * When the name of a form field changes... it is still reachable through the original name!
2432      * @throws Exception if the test fails
2433      */
2434     @Test
2435     @Alerts({"[object HTMLSelectElement]", "undefined",
2436              "[object HTMLSelectElement]", "[object HTMLSelectElement]",
2437              "[object HTMLSelectElement]", "[object HTMLSelectElement]", "[object HTMLSelectElement]"})
2438     public void accessByNameAfterNameChangeSelect() throws Exception {
2439         accessByNameAfterNameChange("<select name='originalName'><option>foo</option></select>");
2440     }
2441 
2442     /**
2443      * When the name of a form field changes... it is still reachable through the original name!
2444      * @throws Exception if the test fails
2445      */
2446     @Test
2447     @Alerts({"[object HTMLFieldSetElement]", "undefined",
2448              "[object HTMLFieldSetElement]", "[object HTMLFieldSetElement]",
2449              "[object HTMLFieldSetElement]", "[object HTMLFieldSetElement]", "[object HTMLFieldSetElement]"})
2450     public void accessByNameAfterNameChangeFieldSet() throws Exception {
2451         accessByNameAfterNameChange("<fieldset name='originalName'><legend>Legend</legend></fieldset>");
2452     }
2453 
2454     private void accessByNameAfterNameChange(final String htmlElement) throws Exception {
2455         final String html = DOCTYPE_HTML
2456             + "<html><head><script>\n"
2457             + LOG_TITLE_FUNCTION
2458             + "function go() {\n"
2459             + "  log(document.simple_form.originalName);\n"
2460             + "  log(document.simple_form.newName);\n"
2461 
2462             + "  var field = document.simple_form.originalName;\n"
2463             + "  if (field === undefined) return;\n"
2464 
2465             + "  field.name = 'newName';\n"
2466             + "  log(document.simple_form.originalName);\n"
2467             + "  log(document.simple_form.newName);\n"
2468 
2469             + "  field.name = 'brandNewName';\n"
2470             + "  log(document.simple_form.originalName);\n"
2471             + "  log(document.simple_form.newName);\n"
2472             + "  log(document.simple_form.brandNewName);\n"
2473             + "}\n"
2474             + "</script></head>\n"
2475             + "<body onload='go()'>\n"
2476             + "<form name='simple_form'>\n"
2477             + htmlElement + "\n"
2478             + "</form>\n"
2479             + "</body></html>";
2480 
2481         loadPageVerifyTitle2(html);
2482     }
2483 
2484     /**
2485      * Regression test for Bug #1083: lost children should be accessible per name from HTMLFormElement.elements.
2486      * @throws Exception if the test fails
2487      */
2488     @Test
2489     @Alerts({"[object HTMLInputElement]", "[object HTMLInputElement]"})
2490     public void lostChildrenFromElements() throws Exception {
2491         final String html = DOCTYPE_HTML
2492             + "<html><body>\n"
2493             + "<div><form name='form1' >\n"
2494             + "</div>\n"
2495             + "<input name='b'/>\n"
2496             + "</form><script>\n"
2497             + LOG_TITLE_FUNCTION
2498             + "  log(document.form1['b']);\n"
2499             + "  log(document.form1.elements['b']);\n"
2500             + "</script>\n"
2501             + "</body></html>";
2502 
2503         loadPageVerifyTitle2(html);
2504     }
2505 
2506     /**
2507      * @throws Exception if the test fails
2508      */
2509     @Test
2510     @Alerts("function")
2511     public void onchangeHandler() throws Exception {
2512         final String html = DOCTYPE_HTML
2513             + "<html><head><script>\n"
2514             + LOG_TITLE_FUNCTION
2515             + "function test() {\n"
2516             + "  var form = document.getElementsByTagName('form')[0];\n"
2517             + "  log(typeof form.onchange);\n"
2518             + "}\n"
2519             + "</script></head><body onload='test()'>\n"
2520             + "<form onchange='cat=true'></form>\n"
2521             + "</body></html>";
2522 
2523         loadPageVerifyTitle2(html);
2524     }
2525 
2526     /**
2527      * @throws Exception if an error occurs
2528      */
2529     @Test
2530     @Alerts(DEFAULT = "in listener",
2531             FF = {"in listener", "page2 loaded"},
2532             FF_ESR = {"in listener", "page2 loaded"})
2533     public void dispatchEventSubmitTriggersHandlers() throws Exception {
2534         // use an iframe to capture alerts among 2 pages
2535         final String container = DOCTYPE_HTML
2536             + "<html><body><iframe src='page1'></iframe></body></html>\n";
2537         final String page1 = DOCTYPE_HTML
2538             + "<html><body>\n"
2539             + "<form action='page2' id='theForm'><span id='foo'/></form>\n"
2540             + "<script>\n"
2541             + "function listener(e) {\n"
2542             + "  alert('in listener');\n"
2543             + "}\n"
2544             + "try {\n"
2545             + "  document.forms[0].addEventListener('submit', listener, true);\n"
2546             + "  var e = document.createEvent('HTMLEvents');\n"
2547             + "  e.initEvent('submit', true, false);\n"
2548             + "  document.getElementById('theForm').dispatchEvent(e);\n"
2549             + "} catch(e) { alert('exception'); }\n"
2550             + "</script></body></html>";
2551 
2552         final String page2 = DOCTYPE_HTML
2553             + "<html><body><script>alert('page2 loaded');</script></body></html>";
2554 
2555         getMockWebConnection().setResponse(new URL(URL_FIRST, "page1"), page1);
2556         getMockWebConnection().setResponse(new URL(URL_FIRST, "page2"), page2);
2557         loadPageWithAlerts2(container);
2558     }
2559 
2560     /**
2561      * Verifies that the event object is correctly made available.
2562      * Regression test for http://sourceforge.net/p/htmlunit/bugs/425/
2563      * @throws Exception if the test fails
2564      */
2565     @Test
2566     @Alerts({"type: submit", "submitter: [object HTMLInputElement]",
2567              "srcElement null: false", "srcElement==form: true",
2568              "target null: false", "target==form: true"})
2569     public void onSubmitEvent() throws Exception {
2570         final String html = DOCTYPE_HTML
2571             + "<html><head>\n"
2572             + "<script>\n"
2573             + LOG_TITLE_FUNCTION
2574             + "function test(_event) {\n"
2575             + "  var oEvent = _event ? _event : window.event;\n"
2576             + "  log('type: ' + oEvent.type);\n"
2577             + "  log('submitter: ' + oEvent.submitter);\n"
2578             + "  log('srcElement null: ' + (oEvent.srcElement == null));\n"
2579             + "  log('srcElement==form: ' + (oEvent.srcElement == document.forms[0]));\n"
2580             + "  log('target null: ' + (oEvent.target == null));\n"
2581             + "  log('target==form: ' + (oEvent.target == document.forms[0]));\n"
2582 
2583             + "  if (_event.preventDefault) { _event.preventDefault(); }\n"
2584             + "  return false;\n"
2585             + "}\n"
2586             + "</script>\n"
2587             + "</head><body>\n"
2588             + "<form name='formPage1' action='about:blank' onsubmit='return test(event);'>\n"
2589             + "<input type='submit' id='theButton'>\n"
2590             + "</form>\n"
2591             + "</body></html>";
2592 
2593         final WebDriver driver = loadPage2(html);
2594         driver.findElement(By.id("theButton")).click();
2595         verifyTitle2(driver, getExpectedAlerts());
2596     }
2597 
2598     /**
2599      * This test is used to check that when a form having a target is submitted
2600      * and if the target is an iframe and the iframe has an onload event, then
2601      * the onload event is called.
2602      *
2603      * @throws Exception if the test fails
2604      */
2605     @Test
2606     @Alerts({"prepare frame", "submit form", "submitted ok"})
2607     public void submitWithTargetOnIFrameAndOnload_script() throws Exception {
2608         final String html = DOCTYPE_HTML
2609             + "<html><head></head><body>\n"
2610             + "<p>hello world</p>\n"
2611             + "<form id='form1' name='form1' method='get' action='" + URL_SECOND + "'>\n"
2612             + "  <input type='button' name='button1' />\n"
2613             + "</form>\n"
2614             + "<script>\n"
2615             + LOG_TITLE_FUNCTION
2616             + "  // Prepare the iframe for the target\n"
2617             + "  log('prepare frame');\n"
2618             + "  var div = document.createElement('div');\n"
2619             + "  div.style.display = 'none';\n"
2620             + "  div.innerHTML = \"<iframe name='frame' id='frame'></iframe>\";\n"
2621             + "  document.body.appendChild(div);\n"
2622             + "  // Get the form and set the target\n"
2623             + "  var form = document.getElementById('form1');\n"
2624             + "  form.target = 'frame';\n"
2625             + "  // Finally submit the form with a delay to make sure that the onload of the iframe\n"
2626             + "  // is called for the submit and not for the page creation\n"
2627             + "  var t = setTimeout(function() {\n"
2628             + "    clearTimeout(t);\n"
2629             + "    var iframe = document.getElementById('frame');\n"
2630             + "    iframe.onload = function() {\n"
2631             + "      log('submitted ' + iframe.contentWindow.document.body.getAttribute('id'));\n"
2632             + "    };\n"
2633             + "    log('submit form');\n"
2634             + "    form.submit();\n"
2635             + "  }, 1000);\n"
2636             + "</script></body></html>";
2637         final String html2
2638             = "<?xml version='1.0'?>\n"
2639             + "<html xmlns='http://www.w3.org/1999/xhtml'><body id='ok'><span id='result'>OK</span></body></html>";
2640         getMockWebConnection().setDefaultResponse(html2);
2641 
2642         loadPage2(html, URL_FIRST);
2643         verifyTitle2(DEFAULT_WAIT_TIME.multipliedBy(5), getWebDriver(), getExpectedAlerts());
2644     }
2645 
2646     /**
2647      * This test is used to check that when a form having a target is submitted
2648      * and if the target is an iframe and the iframe has an onload event, then
2649      * the onload event is called.
2650      *
2651      * @throws Exception if the test fails
2652      */
2653     @Test
2654     @Alerts({"submit form", "listener: submitted ok"})
2655     public void submitWithTargetOnIFrameAndOnload_bubbling() throws Exception {
2656         final String html = DOCTYPE_HTML
2657             + "<html><head>/head><body>\n"
2658             + "<p>hello world</p>\n"
2659             + "<form id='form1' name='form1' method='get' action='" + URL_SECOND + "' target='frame'>\n"
2660             + "  <input type='button' name='button1' />\n"
2661             + "</form>\n"
2662             + "<div style='display:none;'><iframe name='frame' id='frame'></iframe></div>\n"
2663             + "<script>\n"
2664             + LOG_TITLE_FUNCTION
2665             + "  // Get the form and set the target\n"
2666             + "  var form = document.getElementById('form1');\n"
2667             + "  var iframe = document.getElementById('frame');\n"
2668             + "  // Finally submit the form with a delay to make sure that the onload of the iframe\n"
2669             + "  // is called for the submit and not for the page creation\n"
2670             + "  var t = setTimeout(function() {\n"
2671             + "    clearTimeout(t);\n"
2672             + "    iframe.addEventListener('load', function() {\n"
2673             + "      log('listener: submitted ' + iframe.contentWindow.document.body.getAttribute('id'));\n"
2674             + "    }, true);\n"
2675             + "    log('submit form');\n"
2676             + "    form.submit();\n"
2677             + "  }, 1000);\n"
2678             + "</script>\n"
2679             + "</body></html>";
2680         final String html2
2681             = "<?xml version='1.0'?>\n"
2682             + "<html xmlns='http://www.w3.org/1999/xhtml'><body id='ok'><span id='result'>OK</span></body></html>";
2683         getMockWebConnection().setDefaultResponse(html2);
2684 
2685         loadPage2(html, URL_FIRST);
2686         verifyTitle2(DEFAULT_WAIT_TIME.multipliedBy(5), getWebDriver(), getExpectedAlerts());
2687     }
2688 
2689     /**
2690      * @throws Exception if the test fails
2691      */
2692     @Test
2693     @Alerts({"Response", "param1=value1"})
2694     public void requestSubmit() throws Exception {
2695         final String html = DOCTYPE_HTML
2696             + "<html>\n"
2697             + "<head><title>first</title>\n"
2698             + "<script>\n"
2699             + "function doTest() {\n"
2700             + "  var myForm = document.getElementById('form1');\n"
2701             + "  if (myForm.requestSubmit) {\n"
2702             + "    myForm.requestSubmit();\n"
2703             + "    return;\n"
2704             + "  }\n"
2705             + "  alert('requestSubmit() not available');\n"
2706             + "}\n"
2707             + "</script>\n"
2708             + "</head>\n"
2709 
2710             + "<body onload='doTest()'>\n"
2711             + "  <form id='form1' name='form1' method='get' action='" + URL_SECOND + "' encoding='text/plain'>\n"
2712             + "    <input name='param1' type='hidden' value='value1'>\n"
2713             + "  </form>\n"
2714             + "</body></html>";
2715 
2716         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
2717 
2718         final WebDriver driver = loadPage2(html);
2719         if (getExpectedAlerts().length == 1) {
2720             verifyAlerts(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[0]});
2721             return;
2722         }
2723 
2724         assertTitle(driver, getExpectedAlerts()[0]);
2725         final String params = getMockWebConnection().getLastWebRequest().getUrl().getQuery();
2726         assertEquals(getExpectedAlerts()[1], params);
2727     }
2728 
2729     /**
2730      * @throws Exception if the test fails
2731      */
2732     @Test
2733     @Alerts({"Response", "param1=value1"})
2734     public void requestSubmitWithSubmit() throws Exception {
2735         final String html = DOCTYPE_HTML
2736             + "<html>\n"
2737             + "<head><title>first</title>\n"
2738             + "<script>\n"
2739             + "function doTest() {\n"
2740             + "  var myForm = document.getElementById('form1');\n"
2741             + "  if (myForm.requestSubmit) {\n"
2742             + "    var sub = document.getElementById('submit1');\n"
2743             + "    myForm.requestSubmit(sub);\n"
2744             + "    return;\n"
2745             + "  }\n"
2746             + "  alert('requestSubmit() not available');\n"
2747             + "}\n"
2748             + "</script>\n"
2749             + "</head>\n"
2750 
2751             + "<body onload='doTest()'>\n"
2752             + "  <form id='form1' name='form1' method='get' action='" + URL_SECOND + "' encoding='text/plain'>\n"
2753             + "    <input name='param1' type='hidden' value='value1'>\n"
2754             + "    <input id='submit1' type='submit' />\n"
2755             + "  </form>\n"
2756             + "</body></html>";
2757 
2758         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
2759 
2760         final WebDriver driver = loadPage2(html);
2761         if (getExpectedAlerts().length == 1) {
2762             verifyAlerts(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[0]});
2763             return;
2764         }
2765 
2766         assertTitle(driver, getExpectedAlerts()[0]);
2767         final String params = getMockWebConnection().getLastWebRequest().getUrl().getQuery();
2768         assertEquals(getExpectedAlerts()[1], params);
2769     }
2770 
2771     /**
2772      * @throws Exception if the test fails
2773      */
2774     @Test
2775     @Alerts({"Response", "param1=value1&submit1="})
2776     public void requestSubmitWithButton() throws Exception {
2777         final String html = DOCTYPE_HTML
2778             + "<html>\n"
2779             + "<head><title>first</title>\n"
2780             + "<script>\n"
2781             + "function doTest() {\n"
2782             + "  var myForm = document.getElementById('form1');\n"
2783             + "  if (myForm.requestSubmit) {\n"
2784             + "    var sub = document.getElementById('submit1');\n"
2785             + "    try {\n"
2786             + "      myForm.requestSubmit(sub);\n"
2787             + "    } catch(e) { alert('requestSubmit failed' + e); }\n"
2788             + "    return;\n"
2789             + "  }\n"
2790             + "  alert('requestSubmit() not available');\n"
2791             + "}\n"
2792             + "</script>\n"
2793             + "</head>\n"
2794 
2795             + "<body onload='doTest()'>\n"
2796             + "  <form id='form1' name='form1' method='get' action='" + URL_SECOND + "' encoding='text/plain'>\n"
2797             + "    <input name='param1' type='hidden' value='value1'>\n"
2798             + "    <button type='submit' id='submit1' name='submit1'>submit1</button>\n"
2799             + "  </form>\n"
2800             + "</body></html>";
2801 
2802         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
2803 
2804         final WebDriver driver = loadPage2(html);
2805         if (getExpectedAlerts().length == 1) {
2806             verifyAlerts(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[0]});
2807             return;
2808         }
2809 
2810         assertTitle(driver, getExpectedAlerts()[0]);
2811         final String params = getMockWebConnection().getLastWebRequest().getUrl().getQuery();
2812         assertEquals(getExpectedAlerts()[1], params);
2813     }
2814 
2815     /**
2816      * @throws Exception if the test fails
2817      */
2818     @Test
2819     @Alerts({"first", "requestSubmit failed"})
2820     public void requestSubmitNotMember() throws Exception {
2821         final String html = DOCTYPE_HTML
2822             + "<html>\n"
2823             + "<head><title>first</title>\n"
2824             + "<script>\n"
2825             + "function doTest() {\n"
2826             + "  var myForm = document.getElementById('form1');\n"
2827             + "  if (myForm.requestSubmit) {\n"
2828             + "    var sub = document.getElementById('submit2');\n"
2829             + "    try {\n"
2830             + "      myForm.requestSubmit(sub);\n"
2831             + "    } catch(e) { alert('requestSubmit failed'); }\n"
2832             + "    return;\n"
2833             + "  }\n"
2834             + "  alert('requestSubmit() not available');\n"
2835             + "}\n"
2836             + "</script>\n"
2837             + "</head>\n"
2838 
2839             + "<body onload='doTest()'>\n"
2840             + "  <form id='form1' name='form1' method='get' action='" + URL_SECOND + "' encoding='text/plain'>\n"
2841             + "    <input name='param1' type='hidden' value='value1'>\n"
2842             + "  </form>\n"
2843 
2844             + "  <form id='form2' name='form2' method='get' action='" + URL_SECOND + "' encoding='text/plain'>\n"
2845             + "    <input type='submit' id='submit2' />\n"
2846             + "  </form>\n"
2847             + "</body></html>";
2848 
2849         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
2850 
2851         final WebDriver driver = loadPage2(html);
2852         if (getExpectedAlerts().length == 1) {
2853             verifyAlerts(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[0]});
2854             return;
2855         }
2856 
2857         verifyAlerts(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[1]});
2858         assertTitle(driver, getExpectedAlerts()[0]);
2859     }
2860 
2861     /**
2862      * @throws Exception if the test fails
2863      */
2864     @Test
2865     @Alerts({"first", "requestSubmit failed"})
2866     public void requestSubmitNotSubmit() throws Exception {
2867         final String html = DOCTYPE_HTML
2868             + "<html>\n"
2869             + "<head><title>first</title>\n"
2870             + "<script>\n"
2871             + "function doTest() {\n"
2872             + "  var myForm = document.getElementById('form1');\n"
2873             + "  if (myForm.requestSubmit) {\n"
2874             + "    var sub = document.getElementById('param1');\n"
2875             + "    try {\n"
2876             + "      myForm.requestSubmit(sub);\n"
2877             + "    } catch(e) { alert('requestSubmit failed'); }\n"
2878             + "    return;\n"
2879             + "  }\n"
2880             + "  alert('requestSubmit() not available');\n"
2881             + "}\n"
2882             + "</script>\n"
2883             + "</head>\n"
2884 
2885             + "<body onload='doTest()'>\n"
2886             + "  <form id='form1' name='form1' method='get' action='" + URL_SECOND + "' encoding='text/plain'>\n"
2887             + "    <input id='param1' name='param1' type='hidden' value='value1'>\n"
2888             + "  </form>\n"
2889             + "</body></html>";
2890 
2891         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
2892 
2893         final WebDriver driver = loadPage2(html);
2894         if (getExpectedAlerts().length == 1) {
2895             verifyAlerts(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[0]});
2896             return;
2897         }
2898 
2899         verifyAlerts(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[1]});
2900         assertTitle(driver, getExpectedAlerts()[0]);
2901     }
2902 
2903     /**
2904      * @throws Exception if the test fails
2905      */
2906     @Test
2907     @Alerts({"1", "false", "true", "false", "false"})
2908     public void in() throws Exception {
2909         final String html = DOCTYPE_HTML
2910             + "<html>\n"
2911             + "<head>\n"
2912             + "<script>\n"
2913             + LOG_TITLE_FUNCTION
2914             + "function doTest() {\n"
2915             + "  var f = document.testForm;\n"
2916             + "  log(f.length);\n"
2917             + "  log(-1 in f);\n"
2918             + "  log(0 in f);\n"
2919             + "  log(1 in f);\n"
2920             + "  log(42 in f);\n"
2921             + "}\n"
2922             + "</script>\n"
2923             + "</head>\n"
2924             + "<body onload='doTest()'>\n"
2925             + "  <form name='testForm' action='about:blank'>\n"
2926             + "    <input type='submit' id='theButton'>\n"
2927             + "  </form>\n"
2928             + "</body></html>";
2929 
2930         loadPageVerifyTitle2(html);
2931     }
2932 
2933     /**
2934      * @throws Exception if the test fails
2935      */
2936     @Test
2937     @Alerts("second")
2938     public void notRequired() throws Exception {
2939         required("");
2940     }
2941 
2942     /**
2943      * @throws Exception if the test fails
2944      */
2945     @Test
2946     @Alerts("first")
2947     public void required() throws Exception {
2948         required("required");
2949     }
2950 
2951     /**
2952      * @throws Exception if the test fails
2953      */
2954     @Test
2955     @Alerts("first")
2956     public void requiredEmpty() throws Exception {
2957         required("required=''");
2958     }
2959 
2960     /**
2961      * @throws Exception if the test fails
2962      */
2963     @Test
2964     @Alerts("first")
2965     public void requiredBlank() throws Exception {
2966         required("required=' '");
2967     }
2968 
2969     /**
2970      * @throws Exception if the test fails
2971      */
2972     @Test
2973     @Alerts("first")
2974     public void requiredTrue() throws Exception {
2975         required("required=true");
2976         required("required='true'");
2977     }
2978 
2979     /**
2980      * @throws Exception if the test fails
2981      */
2982     @Test
2983     @Alerts("first")
2984     public void requiredFalse() throws Exception {
2985         required("required=false");
2986         required("required='false'");
2987     }
2988 
2989     /**
2990      * @throws Exception if the test fails
2991      */
2992     @Test
2993     @Alerts("first")
2994     public void requiredArbitrary() throws Exception {
2995         required("required='Arbitrary'");
2996     }
2997 
2998     /**
2999      * @throws Exception if the test fails
3000      */
3001     @Test
3002     @Alerts("first")
3003     public void requiredRequired() throws Exception {
3004         required("required='required'");
3005     }
3006 
3007     /**
3008      * @throws Exception if the test fails
3009      */
3010     private void required(final String req) throws Exception {
3011         final String html = DOCTYPE_HTML
3012             + "<html>\n"
3013             + "<head><title>first</title></head>\n"
3014             + "<body>\n"
3015             + "  <form name='testForm' action='\" + URL_SECOND + \"'>\n"
3016             + "    <input type='submit' id='submit'>\n"
3017             + "    <input name='test' value='' " + req + " >"
3018             + "  </form>\n"
3019             + "</body></html>";
3020 
3021         final String html2 = "<?xml version='1.0'?>\n"
3022             + "<html>\n"
3023             + "<head><title>second</title></head>\n"
3024             + "<body>OK</body></html>";
3025         getMockWebConnection().setDefaultResponse(html2);
3026 
3027         final WebDriver driver = loadPage2(html);
3028         driver.findElement(By.id("submit")).click();
3029         if (useRealBrowser()) {
3030             Thread.sleep(400);
3031         }
3032 
3033         assertEquals(getExpectedAlerts()[0], driver.getTitle());
3034     }
3035 
3036     /**
3037      * @throws Exception if the test fails
3038      */
3039     @Test
3040     @Alerts({"second", "second"})
3041     public void notRequiredFileInput() throws Exception {
3042         requiredFileInput("");
3043     }
3044 
3045     /**
3046      * @throws Exception if the test fails
3047      */
3048     @Test
3049     @Alerts({"first", "second"})
3050     public void requiredFileInput() throws Exception {
3051         requiredFileInput("required");
3052     }
3053 
3054     /**
3055      * @throws Exception if the test fails
3056      */
3057     @Test
3058     @Alerts({"first", "second"})
3059     public void requiredFileInputEmpty() throws Exception {
3060         requiredFileInput("required=''");
3061     }
3062 
3063     /**
3064      * @throws Exception if the test fails
3065      */
3066     @Test
3067     @Alerts({"first", "second"})
3068     public void requiredFileInputBlank() throws Exception {
3069         requiredFileInput("required=' '");
3070     }
3071 
3072     /**
3073      * @throws Exception if the test fails
3074      */
3075     @Test
3076     @Alerts({"first", "second"})
3077     public void requiredFileInputTrue() throws Exception {
3078         requiredFileInput("required=true");
3079         requiredFileInput("required='true'");
3080     }
3081 
3082     /**
3083      * @throws Exception if the test fails
3084      */
3085     @Test
3086     @Alerts({"first", "second"})
3087     public void requiredFileInputFalse() throws Exception {
3088         requiredFileInput("required=false");
3089         requiredFileInput("required='false'");
3090     }
3091 
3092     /**
3093      * @throws Exception if the test fails
3094      */
3095     @Test
3096     @Alerts({"first", "second"})
3097     public void requiredFileInputArbitrary() throws Exception {
3098         requiredFileInput("required='Arbitrary'");
3099     }
3100 
3101     /**
3102      * @throws Exception if the test fails
3103      */
3104     @Test
3105     @Alerts({"first", "second"})
3106     public void requiredFileInputRequired() throws Exception {
3107         requiredFileInput("required='required'");
3108     }
3109 
3110     /**
3111      * @throws Exception if the test fails
3112      */
3113     private void requiredFileInput(final String req) throws Exception {
3114         final String html = DOCTYPE_HTML
3115             + "<html>\n"
3116             + "<head><title>first</title></head>\n"
3117             + "<body>\n"
3118             + "  <form name='testForm' action='\" + URL_SECOND + \"'>\n"
3119             + "    <input type='submit' id='submit'>\n"
3120             + "    <input type='file' name='test' value='' " + req + " >"
3121             + "  </form>\n"
3122             + "</body></html>";
3123 
3124         final String html2 = "<?xml version='1.0'?>\n"
3125             + "<html>\n"
3126             + "<head><title>second</title></head>\n"
3127             + "<body>OK</body></html>";
3128         getMockWebConnection().setDefaultResponse(html2);
3129 
3130         final WebDriver driver = loadPage2(html);
3131         driver.findElement(By.id("submit")).click();
3132         if (useRealBrowser()) {
3133             Thread.sleep(400);
3134         }
3135         assertEquals(getExpectedAlerts()[0], driver.getTitle());
3136 
3137         loadPage2(html);
3138         final WebElement e = driver.findElement(By.name("test"));
3139         final String absolutePath = new File("pom.xml").getAbsolutePath();
3140         e.sendKeys(absolutePath);
3141         driver.findElement(By.id("submit")).click();
3142         if (useRealBrowser()) {
3143             Thread.sleep(400);
3144         }
3145         assertEquals(getExpectedAlerts()[1], driver.getTitle());
3146     }
3147 
3148     /**
3149      * @throws Exception if the test fails
3150      */
3151     @Test
3152     @Alerts("first")
3153     public void notNovalidate() throws Exception {
3154         novalidate("");
3155     }
3156 
3157     /**
3158      * @throws Exception if the test fails
3159      */
3160     @Test
3161     @Alerts("second")
3162     public void novalidate() throws Exception {
3163         novalidate("novalidate");
3164     }
3165 
3166     /**
3167      * @throws Exception if the test fails
3168      */
3169     @Test
3170     @Alerts("second")
3171     public void novalidateEmpty() throws Exception {
3172         novalidate("novalidate=''");
3173     }
3174 
3175     /**
3176      * @throws Exception if the test fails
3177      */
3178     @Test
3179     @Alerts("second")
3180     public void novalidateBlank() throws Exception {
3181         novalidate("novalidate=' '");
3182     }
3183 
3184     /**
3185      * @throws Exception if the test fails
3186      */
3187     @Test
3188     @Alerts("second")
3189     public void novalidateTrue() throws Exception {
3190         novalidate("novalidate=true");
3191         novalidate("novalidate='true'");
3192     }
3193 
3194     /**
3195      * @throws Exception if the test fails
3196      */
3197     @Test
3198     @Alerts("second")
3199     public void novalidateFalse() throws Exception {
3200         required("novalidate=false");
3201         required("novalidate='false'");
3202     }
3203 
3204     /**
3205      * @throws Exception if the test fails
3206      */
3207     @Test
3208     @Alerts("second")
3209     public void novalidateArbitrary() throws Exception {
3210         required("novalidate='Arbitrary'");
3211     }
3212 
3213     /**
3214      * @throws Exception if the test fails
3215      */
3216     @Test
3217     @Alerts("second")
3218     public void novalidateNovalidate() throws Exception {
3219         required("novalidate='novalidate'");
3220     }
3221 
3222     /**
3223      * @throws Exception if the test fails
3224      */
3225     private void novalidate(final String novalidate) throws Exception {
3226         final String html = "<html>\n"
3227             + "<head><title>first</title></head>\n"
3228             + "<body>\n"
3229             + "  <form name='testForm' action='\" + URL_SECOND + \"' " + novalidate + " >\n"
3230             + "    <input type='submit' id='submit'>\n"
3231             + "    <input name='test' value='' required >"
3232             + "  </form>\n"
3233             + "</body></html>";
3234 
3235         final String html2 = "<?xml version='1.0'?>\n"
3236             + "<html>\n"
3237             + "<head><title>second</title></head>\n"
3238             + "<body>OK</body></html>";
3239         getMockWebConnection().setDefaultResponse(html2);
3240 
3241         final WebDriver driver = loadPage2(html);
3242         driver.findElement(By.id("submit")).click();
3243         if (useRealBrowser()) {
3244             Thread.sleep(400);
3245         }
3246 
3247         assertEquals(getExpectedAlerts()[0], driver.getTitle());
3248     }
3249 
3250     /**
3251      * @throws Exception if an error occurs
3252      */
3253     @Test
3254     @Alerts({"", "alternate help", "prefetch", "prefetch", "not supported", "notsupported"})
3255     public void readWriteRel() throws Exception {
3256         final String html = DOCTYPE_HTML
3257             + "<html><body><form id='f1'>a1</form><form id='f2' rel='alternate help'>a2</form><script>\n"
3258             + LOG_TITLE_FUNCTION
3259             + "var a1 = document.getElementById('f1'), a2 = document.getElementById('f2');\n"
3260 
3261             + "log(a1.rel);\n"
3262             + "log(a2.rel);\n"
3263 
3264             + "a1.rel = 'prefetch';\n"
3265             + "a2.rel = 'prefetch';\n"
3266             + "log(a1.rel);\n"
3267             + "log(a2.rel);\n"
3268 
3269             + "a1.rel = 'not supported';\n"
3270             + "a2.rel = 'notsupported';\n"
3271             + "log(a1.rel);\n"
3272             + "log(a2.rel);\n"
3273 
3274             + "</script></body></html>";
3275         loadPageVerifyTitle2(html);
3276     }
3277 
3278     /**
3279      * @throws Exception if an error occurs
3280      */
3281     @Test
3282     @Alerts({"0", "2", "alternate", "help"})
3283     public void relList() throws Exception {
3284         final String html = DOCTYPE_HTML
3285             + "<html><body><form id='f1'>a1</form><form id='f2' rel='alternate help'>a2</form><script>\n"
3286             + LOG_TITLE_FUNCTION
3287             + "var a1 = document.getElementById('f1'), a2 = document.getElementById('f2');\n"
3288 
3289             + "try {\n"
3290             + "  log(a1.relList.length);\n"
3291             + "  log(a2.relList.length);\n"
3292 
3293             + "  for (var i = 0; i < a2.relList.length; i++) {\n"
3294             + "    log(a2.relList[i]);\n"
3295             + "  }\n"
3296             + "} catch(e) { logEx(e); }\n"
3297 
3298             + "</script></body></html>";
3299         loadPageVerifyTitle2(html);
3300     }
3301 
3302     /**
3303      * @throws Exception if an error occurs
3304      */
3305     @Test
3306     @Alerts({"0", "2", "2", "1", "alternate", "help", "abc", "alternate help", "abc"})
3307     public void setRelListString() throws Exception {
3308         final String html = DOCTYPE_HTML
3309             + "<html><body><form id='f1'>a1</form><form id='f2' rel='alternate help'>a2</form><script>\n"
3310             + LOG_TITLE_FUNCTION
3311             + "var a1 = document.getElementById('f1'), a2 = document.getElementById('f2');\n"
3312 
3313             + "try {\n"
3314             + "  log(a1.relList.length);\n"
3315             + "  log(a2.relList.length);\n"
3316 
3317             + "  a1.relList = 'alternate help';\n"
3318             + "  a2.relList = 'abc';\n"
3319 
3320             + "  log(a1.relList.length);\n"
3321             + "  log(a2.relList.length);\n"
3322 
3323             + "  for (var i = 0; i < a1.relList.length; i++) {\n"
3324             + "    log(a1.relList[i]);\n"
3325             + "  }\n"
3326 
3327             + "  for (var i = 0; i < a2.relList.length; i++) {\n"
3328             + "    log(a2.relList[i]);\n"
3329             + "  }\n"
3330 
3331             + "  log(a1.rel);\n"
3332             + "  log(a2.rel);\n"
3333             + "} catch(e) { logEx(e); }\n"
3334 
3335             + "</script></body></html>";
3336         loadPageVerifyTitle2(html);
3337     }
3338 
3339     /**
3340      * @throws Exception if an error occurs
3341      */
3342     @Test
3343     @Alerts({"0", "2", "0", "0", "", "\\s\\s\\t"})
3344     public void setRelListStringBlank() throws Exception {
3345         final String html = DOCTYPE_HTML
3346             + "<html><body><form id='f1'>a1</form><form id='f2' rel='alternate help'>a2</form><script>\n"
3347             + LOG_TITLE_FUNCTION_NORMALIZE
3348             + "var a1 = document.getElementById('f1'), a2 = document.getElementById('f2');\n"
3349 
3350             + "try {\n"
3351             + "  log(a1.relList.length);\n"
3352             + "  log(a2.relList.length);\n"
3353 
3354             + "  a1.relList = '';\n"
3355             + "  a2.relList = '  \t';\n"
3356 
3357             + "  log(a1.relList.length);\n"
3358             + "  log(a2.relList.length);\n"
3359 
3360             + "  log(a1.rel);\n"
3361             + "  log(a2.rel);\n"
3362             + "} catch(e) { logEx(e); }\n"
3363 
3364             + "</script></body></html>";
3365         loadPageVerifyTitle2(html);
3366     }
3367 
3368     /**
3369      * @throws Exception if an error occurs
3370      */
3371     @Test
3372     @Alerts({"0", "2", "1", "1", "null", "null", "null", "null"})
3373     public void setRelListNull() throws Exception {
3374         final String html = DOCTYPE_HTML
3375             + "<html><body><form id='f1'>a1</form><form id='f2' rel='alternate help'>a2</form><script>\n"
3376             + LOG_TITLE_FUNCTION_NORMALIZE
3377             + "var a1 = document.getElementById('f1'), a2 = document.getElementById('f2');\n"
3378 
3379             + "try {\n"
3380             + "  log(a1.relList.length);\n"
3381             + "  log(a2.relList.length);\n"
3382 
3383             + "  a1.relList = null;\n"
3384             + "  a2.relList = null;\n"
3385 
3386             + "  log(a1.relList.length);\n"
3387             + "  log(a2.relList.length);\n"
3388 
3389             + "  for (var i = 0; i < a1.relList.length; i++) {\n"
3390             + "    log(a1.relList[i]);\n"
3391             + "  }\n"
3392 
3393             + "  for (var i = 0; i < a2.relList.length; i++) {\n"
3394             + "    log(a2.relList[i]);\n"
3395             + "  }\n"
3396 
3397             + "  log(a1.rel);\n"
3398             + "  log(a2.rel);\n"
3399             + "} catch(e) { logEx(e); }\n"
3400 
3401             + "</script></body></html>";
3402         loadPageVerifyTitle2(html);
3403     }
3404 
3405     /**
3406      * @throws Exception if an error occurs
3407      */
3408     @Test
3409     @Alerts({"0", "2", "1", "1", "undefined", "undefined", "undefined", "undefined"})
3410     public void setRelListUndefined() throws Exception {
3411         final String html = DOCTYPE_HTML
3412             + "<html><body><form id='f1'>a1</form><form id='f2' rel='alternate help'>a2</form><script>\n"
3413             + LOG_TITLE_FUNCTION_NORMALIZE
3414             + "var a1 = document.getElementById('f1'), a2 = document.getElementById('f2');\n"
3415 
3416             + "try {\n"
3417             + "  log(a1.relList.length);\n"
3418             + "  log(a2.relList.length);\n"
3419 
3420             + "  a1.relList = undefined;\n"
3421             + "  a2.relList = undefined;\n"
3422 
3423             + "  log(a1.relList.length);\n"
3424             + "  log(a2.relList.length);\n"
3425 
3426             + "  for (var i = 0; i < a1.relList.length; i++) {\n"
3427             + "    log(a1.relList[i]);\n"
3428             + "  }\n"
3429 
3430             + "  for (var i = 0; i < a2.relList.length; i++) {\n"
3431             + "    log(a2.relList[i]);\n"
3432             + "  }\n"
3433 
3434             + "  log(a1.rel);\n"
3435             + "  log(a2.rel);\n"
3436             + "} catch(e) { logEx(e); }\n"
3437 
3438             + "</script></body></html>";
3439         loadPageVerifyTitle2(html);
3440     }
3441 
3442     /**
3443      * @throws Exception if an error occurs
3444      */
3445     @Test
3446     @Alerts({"[object HTMLInputElement]", "[object HTMLInputElement]"})
3447     public void elementsForOf() throws Exception {
3448         final String html = DOCTYPE_HTML
3449             + "<html>\n"
3450             + "<head>\n"
3451             + "<script>\n"
3452             + LOG_TITLE_FUNCTION
3453             + "  function test() {\n"
3454             + "    var f = document.getElementById('testForm');\n"
3455             + "    for (var attr of f) {\n"
3456             + "      log(attr);\n"
3457             + "    }\n"
3458             + "  }\n"
3459             + "</script>\n"
3460             + "</head>\n"
3461             + "<body onload='test()'>\n"
3462             + "  <form name='testForm' id='testForm'>\n"
3463             + "    <input type='submit' id='submit'>\n"
3464             + "    <input type='text' name='test' value=''>"
3465             + "  </form>\n"
3466             + "</body>\n"
3467             + "</html>";
3468 
3469         loadPageVerifyTitle2(html);
3470     }
3471 }