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.Assert.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.BrowserRunner;
31  import org.htmlunit.junit.annotation.Alerts;
32  import org.htmlunit.junit.annotation.NotYetImplemented;
33  import org.htmlunit.util.MimeType;
34  import org.junit.Test;
35  import org.junit.runner.RunWith;
36  import org.openqa.selenium.By;
37  import org.openqa.selenium.NoSuchWindowException;
38  import org.openqa.selenium.WebDriver;
39  import org.openqa.selenium.WebElement;
40  import org.openqa.selenium.htmlunit.HtmlUnitDriver;
41  
42  /**
43   * Tests for {@link HTMLFormElement}.
44   *
45   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
46   * @author David K. Taylor
47   * @author Marc Guillemot
48   * @author Chris Erskine
49   * @author Ahmed Ashour
50   * @author Ronald Brill
51   * @author Frank Danek
52   */
53  @RunWith(BrowserRunner.class)
54  public class HTMLFormElementTest extends WebDriverTestCase {
55  
56      /**
57       * @throws Exception if the test fails
58       */
59      @Test
60      @Alerts({"16", "button1", "button2", "checkbox1", "fileupload1", "hidden1",
61               "radio1", "radio1",
62               "select1", "select2", "password1", "reset1",
63               "reset2", "submit1", "submit2", "textInput1", "textarea1"})
64      public void elementsAccessor() throws Exception {
65          final String html = DOCTYPE_HTML
66              + "<html><head><script>\n"
67              + LOG_TITLE_FUNCTION
68              + "function doTest() {\n"
69              + "  log(document.form1.length);\n"
70              + "  for (var i = 0; i < document.form1.length; i++) {\n"
71              + "    var element = document.form1.elements[i];\n"
72              + "    if (element.type != 'radio' && element != document.form1[element.name]) {\n"
73              + "      log('name index not working for '+element.name);\n"
74              + "    }\n"
75              + "    log(element.name);\n"
76              + "  }\n"
77              + "}\n"
78              + "</script></head><body onload='doTest()'>\n"
79              + "<p>hello world</p>\n"
80              + "<form name='form1'>\n"
81              + "  <input type='button' name='button1' />\n"
82              + "  <button type='button' name='button2'>button2</button>\n"
83              + "  <input type='checkbox' name='checkbox1' />\n"
84              + "  <input type='file' name='fileupload1' />\n"
85              + "  <input type='hidden' name='hidden1' />\n"
86              + "  <input type='radio' name='radio1' value='1' />\n"
87              + "  <input type='radio' name='radio1' value='2' />\n"
88              + "  <select name='select1'>\n"
89              + "    <option>foo</option>\n"
90              + "  </select>\n"
91              + "  <select multiple='multiple' name='select2'>\n"
92              + "    <option>foo</option>\n"
93              + "  </select>\n"
94              + "  <input type='password' name='password1' />\n"
95              + "  <input type='reset' name='reset1' />\n"
96              + "  <button type='reset' name='reset2'>reset2</button>\n"
97              + "  <input type='submit' name='submit1' />\n"
98              + "  <button type='submit' name='submit2'>submit2</button>\n"
99              + "  <input type='text' name='textInput1' />\n"
100             + "  <textarea name='textarea1'>foo</textarea>\n"
101             + "</form>\n"
102             + "</body></html>";
103 
104         loadPageVerifyTitle2(html);
105     }
106 
107     /**
108      * @throws Exception if the test fails
109      */
110     @Test
111     @Alerts({"undefined", "undefined"})
112     public void elementsAccessorOutOfBound() throws Exception {
113         final String html = DOCTYPE_HTML
114             + "<html><head><script>\n"
115             + LOG_TITLE_FUNCTION
116             + "function doTest() {\n"
117             + "  log(document.form1[-1]);\n"
118             + "  log(document.form1[2]);\n"
119             + "}\n"
120             + "</script></head><body onload='doTest()'>\n"
121             + "<form name='form1'>\n"
122             + "  <input type='button' name='button1'/>\n"
123             + "  <input type='submit' name='submit1'/>\n"
124             + "</form>\n"
125             + "</body></html>";
126 
127         loadPageVerifyTitle2(html);
128     }
129 
130     /**
131      * @throws Exception if the test fails
132      */
133     @Test
134     @Alerts({"3", "textInput1", "button1", "textInput3"})
135     public void elementsAccessorFormAttribute() throws Exception {
136         final String html = DOCTYPE_HTML
137             + "<html><head><script>\n"
138             + LOG_TITLE_FUNCTION
139             + "function doTest() {\n"
140             + "  log(document.form1.length);\n"
141             + "  for (var i = 0; i < document.form1.length; i++) {\n"
142             + "    var element = document.form1.elements[i];\n"
143             + "    log(element.name);\n"
144             + "  }\n"
145             + "}\n"
146             + "</script></head>\n"
147             + "<body onload='doTest()'>\n"
148 
149             + "<input type='text' name='textInput1' form='myForm'/>\n"
150             + "<input type='text' name='textInput2' form='form1'/>\n"
151 
152             + "<form id='myForm' name='form1'>\n"
153             + "  <input type='button' name='button1' />\n"
154             + "</form>\n"
155 
156             + "<input type='text' name='textInput3' form='myForm'/>\n"
157             + "<input type='text' name='textInput4' form='form1'/>\n"
158             + "</body></html>";
159 
160         loadPageVerifyTitle2(html);
161     }
162 
163     /**
164      * @throws Exception if the test fails
165      */
166     @Test
167     @Alerts({"3", "1", "2", "3"})
168     public void radioButtonArray() throws Exception {
169         final String html = DOCTYPE_HTML
170             + "<html><head><script>\n"
171             + LOG_TITLE_FUNCTION
172             + "function doTest() {\n"
173             + "  var radioArray = document.form1['radio1'];\n"
174             + "  log(radioArray.length);\n"
175             + "  for (var i = 0; i < radioArray.length; i++) {\n"
176             + "    var element = radioArray[i];\n"
177             + "    log(element.value);\n"
178             + "  }\n"
179             + "}\n"
180             + "</script></head>\n"
181             + "<body onload='doTest()'>\n"
182             + "<p>hello world</p>\n"
183             + "<form name='form1'>\n"
184             + "  <input type='radio' name='radio1' value='1'/>\n"
185             + "  <input type='radio' name='radio1' value='2'/>\n"
186             + "  <input type='radio' name='radio1' value='3'/>\n"
187             + "</form>\n"
188             + "</body></html>";
189 
190         loadPageVerifyTitle2(html);
191     }
192 
193     /**
194      * If there is only one radio button with a specified name then that radio
195      * button will be returned for the name, not an array of radio buttons. Test
196      * this.
197      * @throws Exception if the test fails
198      */
199     @Test
200     @Alerts("1")
201     public void radioButton_OnlyOne() throws Exception {
202         final String html = DOCTYPE_HTML
203             + "<html><head><script>\n"
204             + LOG_TITLE_FUNCTION
205             + "function doTest() {\n"
206             + "  log(document.form1['radio1'].value);\n"
207             + "}\n"
208             + "</script></head>\n"
209             + "<body onload='doTest()'>\n"
210             + "<p>hello world</p>\n"
211             + "<form name='form1'>\n"
212             + "  <input type='radio' name='radio1' value='1'/>\n"
213             + "</form>\n"
214             + "</body></html>";
215 
216         loadPageVerifyTitle2(html);
217     }
218 
219     /**
220      * @throws Exception if the test fails
221      */
222     @Test
223     @Alerts({"http://foo.com/", "mailto:me@bar.com", "mailto:me@bar.com"})
224     public void actionProperty() throws Exception {
225         doTestProperty("action", "action", "http://foo.com/", "mailto:me@bar.com");
226     }
227 
228     /**
229      * @throws Exception if the test fails
230      */
231     @Test
232     @Alerts({"myForm", "testForm", "testForm"})
233     public void nameProperty() throws Exception {
234         doTestProperty("name", "name", "myForm", "testForm");
235     }
236 
237     /**
238      * @throws Exception if the test fails
239      */
240     @Test
241     @Alerts("application/x-www-form-urlencoded")
242     public void defaultEnctype() throws Exception {
243         enctype(null);
244     }
245 
246     /**
247      * @throws Exception if the test fails
248      */
249     @Test
250     @Alerts("application/x-www-form-urlencoded")
251     public void emptyEnctype() throws Exception {
252         enctype("");
253     }
254 
255     /**
256      * @throws Exception if the test fails
257      */
258     @Test
259     @Alerts("application/x-www-form-urlencoded")
260     public void blankEnctype() throws Exception {
261         enctype(" ");
262     }
263 
264     /**
265      * @throws Exception if the test fails
266      */
267     @Test
268     @Alerts("application/x-www-form-urlencoded")
269     public void unknownEnctype() throws Exception {
270         enctype("unknown");
271     }
272 
273     /**
274      * @throws Exception if the test fails
275      */
276     @Test
277     @Alerts("application/x-www-form-urlencoded")
278     public void urlencodedEnctype() throws Exception {
279         enctype("application/x-www-form-urlencoded");
280     }
281 
282     /**
283      * @throws Exception if the test fails
284      */
285     @Test
286     @Alerts("multipart/form-data")
287     public void multipartEnctype() throws Exception {
288         enctype("multipart/form-data");
289     }
290 
291     /**
292      * @throws Exception if the test fails
293      */
294     @Test
295     @Alerts("text/plain")
296     public void plainEnctype() throws Exception {
297         enctype("text/plain");
298     }
299 
300     /**
301      * @throws Exception if the test fails
302      */
303     @Test
304     @Alerts("application/x-www-form-urlencoded")
305     public void xmlEnctype() throws Exception {
306         enctype("text/xml");
307     }
308 
309     /**
310      * @throws Exception if the test fails
311      */
312     @Test
313     @Alerts("application/x-www-form-urlencoded")
314     public void jsonEnctype() throws Exception {
315         enctype("application/json");
316     }
317 
318     private void enctype(final String encoding) throws Exception {
319         String html = DOCTYPE_HTML
320             + "<html><head><script>\n"
321             + LOG_TITLE_FUNCTION
322             + "function doTest() {\n"
323             + "  log(document.forms[0].encoding);\n"
324             + "}\n"
325             + "</script></head><body onload='doTest()'>\n"
326             + "<form name='testForm'";
327         if (null != encoding) {
328             html = html + " enctype='" + encoding + "'";
329         }
330         html = html + ">\n"
331             + "    <input type='submit' name='submit1'/>\n"
332             + "</form>\n"
333             + "</body></html>";
334 
335         loadPageVerifyTitle2(html);
336     }
337 
338     /**
339      * @throws Exception if the test fails
340      */
341     @Test
342     @Alerts({"application/x-www-form-urlencoded",
343              "application/x-www-form-urlencoded",
344              "application/x-www-form-urlencoded"})
345     public void jsDefaultEnctype() throws Exception {
346         jsEnctype(null);
347         jsEncoding(null);
348     }
349 
350     /**
351      * @throws Exception if the test fails
352      */
353     @Test
354     @Alerts({"application/x-www-form-urlencoded",
355              "application/x-www-form-urlencoded",
356              "application/x-www-form-urlencoded"})
357     public void jsEmptyEnctype() throws Exception {
358         jsEnctype("");
359         jsEncoding("");
360     }
361 
362     /**
363      * @throws Exception if the test fails
364      */
365     @Test
366     @Alerts({"application/x-www-form-urlencoded",
367              "application/x-www-form-urlencoded",
368              "application/x-www-form-urlencoded"})
369     public void jsBlankEnctype() throws Exception {
370         jsEnctype(" ");
371         jsEncoding(" ");
372     }
373 
374     /**
375      * @throws Exception if the test fails
376      */
377     @Test
378     @Alerts({"application/x-www-form-urlencoded",
379              "application/x-www-form-urlencoded",
380              "application/x-www-form-urlencoded"})
381     public void jsUnknownEnctype() throws Exception {
382         jsEnctype("unknown");
383         jsEncoding("unknown");
384     }
385 
386     /**
387      * @throws Exception if the test fails
388      */
389     @Test
390     @Alerts({"application/x-www-form-urlencoded",
391              "application/x-www-form-urlencoded",
392              "application/x-www-form-urlencoded"})
393     public void jsUrlencodedEnctype() throws Exception {
394         jsEnctype("application/x-www-form-urlencoded");
395         jsEncoding("application/x-www-form-urlencoded");
396     }
397 
398     /**
399      * @throws Exception if the test fails
400      */
401     @Test
402     @Alerts({"multipart/form-data", "multipart/form-data", "multipart/form-data"})
403     public void jsMultipartEnctype() throws Exception {
404         jsEnctype("multipart/form-data");
405         jsEncoding("multipart/form-data");
406     }
407 
408     /**
409      * @throws Exception if the test fails
410      */
411     @Test
412     @Alerts({"text/plain", "text/plain", "text/plain"})
413     public void jsPlainEnctype() throws Exception {
414         jsEnctype("text/plain");
415         jsEncoding("text/plain");
416     }
417 
418     /**
419      * @throws Exception if the test fails
420      */
421     @Test
422     @Alerts({"application/x-www-form-urlencoded",
423              "application/x-www-form-urlencoded",
424              "application/x-www-form-urlencoded"})
425     public void jsXmlEnctype() throws Exception {
426         jsEnctype("text/xml");
427         jsEncoding("text/xml");
428     }
429 
430     /**
431      * @throws Exception if the test fails
432      */
433     @Test
434     @Alerts({"application/x-www-form-urlencoded",
435              "application/x-www-form-urlencoded",
436              "application/x-www-form-urlencoded"})
437     public void jsJsonEnctype() throws Exception {
438         jsEnctype("application/json");
439         jsEncoding("application/json");
440     }
441 
442     private void jsEnctype(final String enctype) throws Exception {
443         final String html = DOCTYPE_HTML
444             + "<html>\n"
445             + "<head>\n"
446             + "  <script>\n"
447             + LOG_TITLE_FUNCTION
448             + "  function doTest() {\n"
449             + "    try {\n"
450             + "      document.forms[0].enctype = '" + enctype + "';\n"
451             + "      log(document.forms[0].enctype);\n"
452             + "    } catch(e) { logEx(e); }\n"
453             + "    log(document.forms[0].encoding);\n"
454             + "  }\n"
455             + "  </script>\n"
456             + "</head>\n"
457             + "<body onload='doTest()'>\n"
458             + "  <form id='testForm' name='testForm' method='post' action = 'page2.html'>\n"
459             + "    <input type='submit' name='submit1' />\n"
460             + "  </form>\n"
461             + "</body></html>";
462 
463         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
464 
465         final WebDriver driver = loadPage2(html);
466         verifyTitle2(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[0], getExpectedAlerts()[1]});
467 
468         driver.findElement(By.name("submit1")).click();
469         if (useRealBrowser()) {
470             Thread.sleep(400);
471         }
472         assertTitle(driver, "Response");
473         String headerValue = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
474             .get(HttpHeader.CONTENT_TYPE);
475 
476         if (headerValue.startsWith(FormEncodingType.MULTIPART.getName())) {
477             // Can't test equality for multipart/form-data as it will have the form:
478             // multipart/form-data; boundary=---------------------------42937861433140731107235900
479             headerValue = StringUtils.substringBefore(headerValue, ";");
480             assertEquals(getExpectedAlerts()[2], headerValue);
481         }
482         else {
483             assertEquals(getExpectedAlerts()[2], headerValue);
484         }
485     }
486 
487     private void jsEncoding(final String encoding) throws Exception {
488         final String html = DOCTYPE_HTML
489             + "<html>\n"
490             + "<head>\n"
491             + "  <script>\n"
492             + LOG_TITLE_FUNCTION
493             + "  function doTest() {\n"
494             + "    try {\n"
495             + "      document.forms[0].encoding = '" + encoding + "';\n"
496             + "      log(document.forms[0].encoding);\n"
497             + "    } catch(e) { logEx(e); }\n"
498             + "    log(document.forms[0].enctype);\n"
499             + "  }\n"
500             + "  </script>\n"
501             + "</head>\n"
502             + "<body onload='doTest()'>\n"
503             + "  <form id='testForm' name='testForm' method='post' action = 'page2.html'>\n"
504             + "    <input type='submit' name='submit1' />\n"
505             + "  </form>\n"
506             + "</body></html>";
507 
508         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
509 
510         final WebDriver driver = loadPage2(html);
511         verifyTitle2(DEFAULT_WAIT_TIME, driver, new String[] {getExpectedAlerts()[0], getExpectedAlerts()[1]});
512 
513         driver.findElement(By.name("submit1")).click();
514         if (useRealBrowser()) {
515             Thread.sleep(400);
516         }
517         assertTitle(driver, "Response");
518         String headerValue = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
519             .get(HttpHeader.CONTENT_TYPE);
520         if (headerValue.startsWith(FormEncodingType.MULTIPART.getName())) {
521             // Can't test equality for multipart/form-data as it will have the form:
522             // multipart/form-data; boundary=---------------------------42937861433140731107235900
523             headerValue = StringUtils.substringBefore(headerValue, ";");
524             assertEquals(getExpectedAlerts()[2], headerValue);
525         }
526         else {
527             assertEquals(getExpectedAlerts()[2], headerValue);
528         }
529     }
530 
531     /**
532      * @throws Exception if the test fails
533      */
534     @Test
535     @Alerts({"multipart/form-data", "application/x-www-form-urlencoded", "application/x-www-form-urlencoded"})
536     public void encodingProperty() throws Exception {
537         doTestProperty("encoding", "enctype", "multipart/form-data", "application/x-www-form-urlencoded");
538     }
539 
540     /**
541      * @throws Exception if the test fails
542      */
543     @Test
544     @Alerts({"text/plain", "application/x-www-form-urlencoded", "newEncoding"})
545     public void encodingProperty_textPlain() throws Exception {
546         doTestProperty("encoding", "enctype", MimeType.TEXT_PLAIN, "newEncoding");
547     }
548 
549     /**
550      * @throws Exception if the test fails
551      */
552     @Test
553     @Alerts({"application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "newEncoding"})
554     public void encodingProperty_dummyValues() throws Exception {
555         doTestProperty("encoding", "enctype", "myEncoding", "newEncoding");
556     }
557 
558     /**
559      * @throws Exception if the test fails
560      */
561     @Test
562     @Alerts({"get", "post", "post"})
563     public void methodProperty() throws Exception {
564         doTestProperty("method", "method", "get", "post");
565     }
566 
567     /**
568      * @throws Exception if the test fails
569      */
570     @Test
571     @Alerts({"_top", "_parent", "_parent"})
572     public void targetProperty() throws Exception {
573         doTestProperty("target", "target", "_top", "_parent");
574     }
575 
576     private void doTestProperty(final String jsProperty, final String htmlProperty,
577             final String oldValue, final String newValue) throws Exception {
578 
579         final String html = DOCTYPE_HTML
580             + "<html><head><script>\n"
581             + LOG_TITLE_FUNCTION
582             + "function doTest() {\n"
583             + "  log(document.forms[0]." + jsProperty + ");\n"
584             + "  try {\n"
585             + "    document.forms[0]." + jsProperty + "='" + newValue + "';\n"
586             + "    log(document.forms[0]." + jsProperty + ");\n"
587             + "    log(document.forms[0].getAttribute('" + htmlProperty + "'));\n"
588             + "  } catch(e) { logEx(e); }\n"
589             + "}\n"
590             + "</script></head><body onload='doTest()'>\n"
591             + "<p>hello world</p>\n"
592             + "<form " + htmlProperty + "='" + oldValue + "'>\n"
593             + "  <input type='button' name='button1' />\n"
594             + "</form>\n"
595             + "</body></html>";
596 
597         final WebDriver wd = loadPageVerifyTitle2(html);
598 
599         final WebElement form = wd.findElement(By.xpath("//form"));
600         if (wd instanceof HtmlUnitDriver && getExpectedAlerts().length >= 3) {
601             // form.getAttribute("enctype") returns form.getAttribute("encoding") with the FF driver. Bug or feature?
602             assertEquals(getExpectedAlerts()[2], form.getAttribute(htmlProperty));
603         }
604     }
605 
606     /**
607      * @throws Exception if the test fails
608      */
609     @Test
610     @Alerts({"id2", "foo"})
611     public void inputNamedId() throws Exception {
612         doTestInputWithName("id");
613     }
614 
615     /**
616      * @throws Exception if the test fails
617      */
618     @Test
619     @Alerts({"action2", "foo"})
620     public void inputNamedAction() throws Exception {
621         doTestInputWithName("action");
622     }
623 
624     private void doTestInputWithName(final String name) throws Exception {
625         final String html = DOCTYPE_HTML
626             + "<html><head><script>\n"
627             + LOG_TITLE_FUNCTION
628             + "function go() {\n"
629             + "  log(document.simple_form." + name + ".value);\n"
630             + "  document.simple_form." + name + ".value = 'foo';\n"
631             + "  log(document.simple_form." + name + ".value);\n"
632             + "}</script></head>\n"
633             + "<body onload='go()'>\n"
634             + "<p>hello world</p>\n"
635             + "<form action='login.jsp' name='simple_form'>\n"
636             + "  <input name='" + name + "' type='hidden' value='" + name + "2'>\n"
637             + "</form>\n"
638             + "</body></html>";
639 
640         loadPageVerifyTitle2(html);
641     }
642 
643     /**
644      * Regression test that used to blow up on page load.
645      * @throws Exception if the test fails
646      */
647     @Test
648     @Alerts("value = 2")
649     public void accessingRadioButtonArrayByName_Regression() throws Exception {
650         final String html = DOCTYPE_HTML
651             + "<html><head></head>\n"
652             + "<body><form name='whatsnew'>\n"
653             + "<input type='radio' name='second' value='1'>\n"
654             + "<input type='radio' name='second' value='2' checked>\n"
655             + "</form><script>\n"
656             + LOG_TITLE_FUNCTION
657             + "clickAction();\n"
658             + "function clickAction() {\n"
659             + "  var value = -1;\n"
660             + "  radios = document.forms['whatsnew'].elements['second'];\n"
661             + "  for (var i = 0; i < radios.length; i++){\n"
662             + "    if (radios[i].checked == true) {\n"
663             + "      value = radios[i].value;\n"
664             + "      break;\n"
665             + "    }\n"
666             + "  }\n"
667             + "  log('value = ' + value);\n"
668             + "}\n"
669             + "</script></body></html>";
670 
671         loadPageVerifyTitle2(html);
672     }
673 
674     /**
675      * Test for a bug that appeared when visiting mail.yahoo.com. Setting the value of one input
676      * seems to blow away the other input. Also tests that the form input collection does not get
677      * cached before the document is finished loading.
678      * @throws Exception if the test fails
679      */
680     @Test
681     @Alerts("foo")
682     public void findInputWithoutTypeDefined() throws Exception {
683         final String html = DOCTYPE_HTML
684             + "<html><head>\n"
685             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
686             + "</head>\n"
687             + "<body onload='log(document.simple_form.login.value);'>\n"
688             + "<p>hello world</p><table><tr><td>\n"
689             + "<form action='login.jsp' name='simple_form'>\n"
690             + "  <input name='msg' type='hidden' value='0'>\n"
691             + "  <script>document.simple_form.msg.value = 1</script>\n"
692             + "  <input name='login' size='17' value='foo'>\n"
693             + "</form></td></tr></table>\n"
694             + "</body></html>";
695 
696         loadPageVerifyTitle2(html);
697     }
698 
699     /**
700      * Test form.length - This method does not count the type=image
701      * input tags.
702      * @throws Exception if the test fails
703      */
704     @Test
705     @Alerts("2")
706     public void length() throws Exception {
707         final String html = DOCTYPE_HTML
708             + "<html><head><script>\n"
709             + LOG_TITLE_FUNCTION
710             + "function doTest() {\n"
711             + "  log(document.form1.length);\n"
712             + "}\n"
713             + "</script></head><body onload='doTest()'>\n"
714             + "<form name='form1'>\n"
715             + "  <input type='radio' name='radio1' value='1'/>\n"
716             + "  <input type='image' src='foo' value='1'/>\n"
717             + "  <input type='submit' name='submit1' value='1'/>\n"
718             + "</form>\n"
719             + "</body></html>";
720 
721         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
722 
723         loadPageVerifyTitle2(html);
724     }
725 
726     /**
727      * @throws Exception if the test fails
728      */
729     @Test
730     @Alerts("button1")
731     public void get() throws Exception {
732         final String html = DOCTYPE_HTML
733             + "<html><head><script>\n"
734             + LOG_TITLE_FUNCTION
735             + "function doTest() {\n"
736             + "  log(document.form1[0].name);\n"
737             + "}\n"
738             + "</script></head><body onload='doTest()'>\n"
739             + "<p>hello world</p>\n"
740             + "<form name='form1'>\n"
741             + "  <input type='button' name='button1' />\n"
742             + "</form>\n"
743             + "</body></html>";
744 
745         loadPageVerifyTitle2(html);
746     }
747 
748     /**
749      * Test that the elements collection is live.
750      * @throws Exception if the test fails
751      */
752     @Test
753     @Alerts({"0", "1", "1", "true"})
754     public void elementsLive() throws Exception {
755         final String html = DOCTYPE_HTML
756             + "<html>\n"
757             + "<body>\n"
758             + "<form name='myForm'>\n"
759             + "<script>\n"
760             + LOG_TITLE_FUNCTION
761             + "var oElements = document.myForm.elements;\n"
762             + "log(oElements.length);\n"
763             + "</script>\n"
764             + "<input type='text' name='foo'/>\n"
765             + "<script>\n"
766             + "log(oElements.length);\n"
767             + "log(document.myForm.elements.length);\n"
768             + "log(oElements == document.myForm.elements);\n"
769             + "</script>\n"
770             + "</form>\n"
771             + "</body>\n"
772             + "</html>";
773 
774         loadPageVerifyTitle2(html);
775     }
776 
777     /**
778      * @throws Exception if the test fails
779      */
780     @Test
781     @Alerts({"1", "[object HTMLInputElement]/txt"})
782     public void elementsInputImage() throws Exception {
783         final String html = DOCTYPE_HTML
784             + "<html>\n"
785             + "<body>\n"
786             + "<form name='myForm'>\n"
787             + "  <input type='text' name='foo' id='txt'/>\n"
788             + "  <input type='image' name='fooo' id='img'/>\n"
789             + "</form>\n"
790 
791             + "<script>\n"
792             + LOG_TITLE_FUNCTION
793             + "var oElements = document.myForm.elements;\n"
794             + "log(oElements.length);\n"
795             + "log(oElements[0] + '/' + oElements[0].id);\n"
796             + "</script>\n"
797             + "</body>\n"
798             + "</html>";
799 
800         loadPageVerifyTitle2(html);
801     }
802 
803     /**
804      * @throws Exception if the test fails
805      */
806     @Test
807     @Alerts("0")
808     public void elementsImage() throws Exception {
809         final String html = DOCTYPE_HTML
810             + "<html>\n"
811             + "<body>\n"
812             + "<form name='myForm'>\n"
813             + "  <img name='foo' id='txt'>\n"
814             + "</form>\n"
815 
816             + "<script>\n"
817             + LOG_TITLE_FUNCTION
818             + "var oElements = document.myForm.elements;\n"
819             + "log(oElements.length);\n"
820             + "</script>\n"
821             + "</body>\n"
822             + "</html>";
823 
824         loadPageVerifyTitle2(html);
825     }
826 
827     /**
828      * @throws Exception if the test fails
829      */
830     @Test
831     @Alerts({"1", "[object HTMLOutputElement]"})
832     public void elementsOutput() throws Exception {
833         final String html = DOCTYPE_HTML
834             + "<html>\n"
835             + "<body>\n"
836             + "<form name='myForm'>\n"
837             + "  <output name='result'>60</output>\n"
838             + "</form>\n"
839 
840             + "<script>\n"
841             + LOG_TITLE_FUNCTION
842             + "var oElements = document.myForm.elements;\n"
843             + "log(oElements.length);\n"
844             + "log(oElements[0]);\n"
845             + "</script>\n"
846             + "</body>\n"
847             + "</html>";
848 
849         loadPageVerifyTitle2(html);
850     }
851 
852     /**
853      * @throws Exception if the test fails
854      */
855     @Test
856     @Alerts({"2", "[object HTMLFieldSetElement]", "[object HTMLInputElement]"})
857     public void elementsFieldSet() throws Exception {
858         final String html = DOCTYPE_HTML
859             + "<html>\n"
860             + "<body>\n"
861             + "<form name='myForm'>\n"
862             + "  <fieldset id='fs'>\n"
863             + "    <legend>Legend</legend>\n"
864             + "    <input type='text' name='foo'/>\n"
865             + "  </fieldset>\n"
866             + "</form>\n"
867 
868             + "<script>\n"
869             + LOG_TITLE_FUNCTION
870             + "var oElements = document.myForm.elements;\n"
871             + "log(oElements.length);\n"
872             + "log(oElements[0]);\n"
873             + "log(oElements[1]);\n"
874             + "</script>\n"
875             + "</body>\n"
876             + "</html>";
877 
878         loadPageVerifyTitle2(html);
879     }
880 
881     /**
882      * @throws Exception if the test fails
883      */
884     @Test
885     @Alerts({"2", "[object HTMLFieldSetElement]", "[object HTMLInputElement]"})
886     public void elementsFieldSetEmpty() throws Exception {
887         final String html = DOCTYPE_HTML
888             + "<html>\n"
889             + "<body>\n"
890             + "<form name='myForm'>\n"
891             + "  <fieldset id='fs'>\n"
892             + "  </fieldset>\n"
893             + "  <input type='text' name='foo'/>\n"
894             + "</form>\n"
895 
896             + "<script>\n"
897             + LOG_TITLE_FUNCTION
898             + "var oElements = document.myForm.elements;\n"
899             + "log(oElements.length);\n"
900             + "log(oElements[0]);\n"
901             + "log(oElements[1]);\n"
902             + "</script>\n"
903             + "</body>\n"
904             + "</html>";
905 
906         loadPageVerifyTitle2(html);
907     }
908 
909     /**
910      * @throws Exception if the test fails
911      */
912     @Test
913     @Alerts({"4", "[object HTMLFieldSetElement]/fs_outer",
914              "[object HTMLInputElement]/foo",
915              "[object HTMLFieldSetElement]/fs_inner",
916              "[object HTMLInputElement]/fooo"})
917     public void elementsFieldSetInsideFieldSet() throws Exception {
918         final String html = DOCTYPE_HTML
919             + "<html>\n"
920             + "<body>\n"
921             + "<form name='myForm'>\n"
922             + "  <fieldset id='fs_outer'>\n"
923             + "    <legend>Legend</legend>\n"
924             + "    <input type='text' name='foo' id='foo'/>\n"
925 
926             + "    <fieldset id='fs_inner'>\n"
927             + "      <input type='text' name='fooo' id='fooo'/>\n"
928             + "    </fieldset>\n"
929             + "  </fieldset>\n"
930             + "</form>\n"
931 
932             + "<script>\n"
933             + LOG_TITLE_FUNCTION
934             + "var oElements = document.myForm.elements;\n"
935             + "log(oElements.length);\n"
936             + "log(oElements[0] + '/' + oElements[0].id);\n"
937             + "log(oElements[1] + '/' + oElements[1].id);\n"
938             + "log(oElements[2] + '/' + oElements[2].id);\n"
939             + "log(oElements[3] + '/' + oElements[3].id);\n"
940             + "</script>\n"
941             + "</body>\n"
942             + "</html>";
943 
944         loadPageVerifyTitle2(html);
945     }
946 
947     /**
948      * @throws Exception if the test fails
949      */
950     @Test
951     @Alerts("§§URL§§foo.html")
952     public void getFormFromFormsById() throws Exception {
953         final String html = DOCTYPE_HTML
954             + "<html>\n"
955             + "<head>\n"
956             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
957             + "</head>\n"
958             + "<body onload=\"log(document.forms['myForm'].action)\">\n"
959             + "<form id='myForm' action='foo.html'>\n"
960             + "</form>\n"
961             + "</body>\n"
962             + "</html>";
963 
964         expandExpectedAlertsVariables(URL_FIRST);
965         loadPageVerifyTitle2(html);
966     }
967 
968     /**
969      * @throws Exception if the test fails
970      */
971     @Test
972     @Alerts("§§URL§§")
973     public void action() throws Exception {
974         final String html = DOCTYPE_HTML
975             + "<html>\n"
976             + "<head>\n"
977             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
978             + "</head>\n"
979             + "<body onload=\"log(document.forms['myForm'].action)\">\n"
980             + "<form id='myForm'>\n"
981             + "</form>\n"
982             + "</body>\n"
983             + "</html>";
984 
985         expandExpectedAlertsVariables(URL_FIRST);
986         loadPageVerifyTitle2(html);
987     }
988 
989     /**
990      * @throws Exception if the test fails
991      */
992     @Test
993     @Alerts("§§URL§§")
994     public void actionEmpty() throws Exception {
995         final String html = DOCTYPE_HTML
996             + "<html>\n"
997             + "<head>\n"
998             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
999             + "</head>\n"
1000             + "<body onload=\"log(document.forms['myForm'].action)\">\n"
1001             + "<form id='myForm' action=''>\n"
1002             + "</form>\n"
1003             + "</body>\n"
1004             + "</html>";
1005 
1006         expandExpectedAlertsVariables(URL_FIRST);
1007         loadPageVerifyTitle2(html);
1008     }
1009 
1010     /**
1011      * @throws Exception if the test fails
1012      */
1013     @Test
1014     @Alerts("§§URL§§")
1015     public void actionBlank() throws Exception {
1016         final String html = DOCTYPE_HTML
1017             + "<html>\n"
1018             + "<head>\n"
1019             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
1020             + "</head>\n"
1021             + "<body onload=\"log(document.forms['myForm'].action)\">\n"
1022             + "<form id='myForm' action='  '>\n"
1023             + "</form>\n"
1024             + "</body>\n"
1025             + "</html>";
1026 
1027         expandExpectedAlertsVariables(URL_FIRST);
1028         loadPageVerifyTitle2(html);
1029     }
1030 
1031     /**
1032      * @throws Exception if the test fails
1033      */
1034     @Test
1035     @Alerts("text")
1036     public void getFieldNamedLikeForm() throws Exception {
1037         final String html = DOCTYPE_HTML
1038             + "<html>\n"
1039             + "<head>\n"
1040             + "<script>" + LOG_TITLE_FUNCTION + "</script>\n"
1041             + "</head>\n"
1042             + "<body onload='log(document.login.login.type)'>\n"
1043             + "<form name='login' action='foo.html'>\n"
1044             + "<input name='login' type='text'>\n"
1045             + "</form>\n"
1046             + "</body>\n"
1047             + "</html>";
1048 
1049         loadPageVerifyTitle2(html);
1050     }
1051 
1052     /**
1053      * Verifies that document.myForm.submit returns a field name submit or the submit function
1054      * depending on the sort of the field named submit.
1055      * @throws Exception if the test fails
1056      */
1057     @Test
1058     public void fieldNamedSubmit() throws Exception {
1059         fieldNamedSubmit("<input type='text' name='submit'>\n", "INPUT");
1060         fieldNamedSubmit("<input type='password' name='submit'>\n", "INPUT");
1061         fieldNamedSubmit("<input type='submit' name='submit'>\n", "INPUT");
1062         fieldNamedSubmit("<input type='radio' name='submit'>\n", "INPUT");
1063         fieldNamedSubmit("<input type='checkbox' name='submit'>\n", "INPUT");
1064         fieldNamedSubmit("<input type='button' name='submit'>\n", "INPUT");
1065         fieldNamedSubmit("<button type='submit' name='submit'>\n", "BUTTON");
1066         fieldNamedSubmit("<textarea name='submit'></textarea>\n", "TEXTAREA");
1067         fieldNamedSubmit("<select name='submit'></select>\n", "SELECT");
1068 
1069         fieldNamedSubmit("<input type='image' name='submit'>\n", "function");
1070         fieldNamedSubmit("<input type='IMAGE' name='submit'>\n", "function");
1071         fieldNamedSubmit("<input type='IMAGE' name='submit'>\n", "function");
1072 
1073         fieldNamedSubmit("<fieldset name='submit'><legend>Legend</legend></fieldset>\n", "FIELDSET");
1074 
1075         fieldNamedSubmit("<object name='submit'></object>\n", "OBJECT");
1076 
1077         fieldNamedSubmit("<output name='submit'></output>\n", "OUTPUT");
1078 
1079         fieldNamedSubmit("<img name='submit'>\n", "IMG");
1080     }
1081 
1082     /**
1083      * @param htmlSnippet the HTML to embed in the test
1084      * @param expected the expected alert
1085      * @throws Exception if the test fails
1086      */
1087     private void fieldNamedSubmit(final String htmlSnippet, final String expected) throws Exception {
1088         final String html = DOCTYPE_HTML
1089             + "<html>\n"
1090             + "<head>\n"
1091             + "<script>\n"
1092             + LOG_TITLE_FUNCTION
1093             + "function test() {\n"
1094             + "  if (document.login.submit.tagName)\n"
1095             + "    log(document.login.submit.tagName);\n"
1096             + "  else"
1097             + "    log('function');\n"
1098             + "}\n"
1099             + "</script>\n"
1100             + "</head>\n"
1101             + "<body onload='test()'>\n"
1102             + "<form name='login' action='foo.html'>\n"
1103             + htmlSnippet
1104             + "</form>\n"
1105             + "</body>\n"
1106             + "</html>";
1107 
1108         setExpectedAlerts(expected);
1109         loadPageVerifyTitle2(html);
1110     }
1111 
1112     /**
1113      * @throws Exception if the test fails
1114      */
1115     @Test
1116     @Alerts({"before", "2", "undefined"})
1117     public void fieldFoundWithId() throws Exception {
1118         final String html = DOCTYPE_HTML
1119             + "<html><head>\n"
1120             + "<script>\n"
1121             + LOG_TITLE_FUNCTION
1122             + "function test() {\n"
1123             + "  log(IRForm.IRText.value);\n"
1124             + "  log(IRForm.myField.length);\n"
1125             + "  log(IRForm.myDiv);\n"
1126             + "}\n"
1127             + "</script>\n"
1128             + "</head>\n"
1129             + "<body onload='test()'>\n"
1130             + "  <form name='IRForm' action='#'>\n"
1131             + "    <input type='text' id='IRText' value='before'/>\n"
1132             + "    <input type='image' name='myField' src='foo.gif'/>\n"
1133             + "    <input type='image' id='myField' src='foo.gif'/>\n"
1134             + "    <input type='text' name='myField'/>\n"
1135             + "    <input type='text' id='myField'/>\n"
1136             + "    <div id='myDiv'>oooo</div>\n"
1137             + "  </form>\n"
1138             + "</body>\n"
1139             + "</html>";
1140 
1141         loadPageVerifyTitle2(html);
1142     }
1143 
1144     /**
1145      * @throws Exception if the test fails
1146      */
1147     @Test
1148     @Alerts({"[object HTMLInputElement]", "[object HTMLInputElement]"})
1149     public void fieldFoundWithIdByReference() throws Exception {
1150         final String html = DOCTYPE_HTML
1151             + "<html><head>\n"
1152             + "<script>\n"
1153             + LOG_TITLE_FUNCTION
1154             + "function test() {\n"
1155             + "  log(IRForm.IRText);\n"
1156             + "  log(IRForm.myField);\n"
1157             + "}\n"
1158             + "</script>\n"
1159             + "</head>\n"
1160             + "<body onload='test()'>\n"
1161             + "  <form name='IRForm' id='testForm' action='#'>\n"
1162             + "  </form>\n"
1163             + "  <input type='text' id='IRText' value='abc' form='testForm' />\n"
1164             + "  <input type='text' id='myField' value='xy' form='testForm'/>\n"
1165             + "</body>\n"
1166             + "</html>";
1167 
1168         loadPageVerifyTitle2(html);
1169     }
1170 
1171     /**
1172      * @throws Exception if the test fails
1173      */
1174     @Test
1175     @Alerts({"INPUT", "idImg1", "img2", "true"})
1176     public void nonFieldChildFound() throws Exception {
1177         final String html = DOCTYPE_HTML
1178             + "<html><head>\n"
1179             + "<script>\n"
1180             + LOG_TITLE_FUNCTION
1181             + "function test() {\n"
1182             + "  var oForm = document.testForm;\n"
1183             + "  log(oForm.img.tagName);\n"
1184             + "  log(oForm.img1.id);\n"
1185             + "  log(oForm.img2.id);\n"
1186             + "  log(oForm.testSpan == undefined);\n"
1187             + "}\n"
1188             + "</script>\n"
1189             + "</head>\n"
1190             + "<body onload='test()'>\n"
1191             + "  <form name='testForm' action='foo'>\n"
1192             + "    <input type='text' id='img' value='before'/>\n"
1193             + "    <img name='img' id='idImg' src='foo.png'/>\n"
1194             + "    <img name='img1' id='idImg1' src='foo.png'/>\n"
1195             + "    <img id='img2' src='foo.png'/>\n"
1196             + "    <span id='testSpan'>foo</span>\n"
1197             + "  </form>\n"
1198             + "</body>\n"
1199             + "</html>";
1200 
1201         getMockWebConnection().setDefaultResponse("Error: not found", 404, "Not Found", MimeType.TEXT_HTML);
1202 
1203         loadPageVerifyTitle2(html);
1204     }
1205 
1206     /**
1207      * @throws Exception if the test fails
1208      */
1209     @Test
1210     @Alerts({"[object HTMLImageElement]", "[object HTMLImageElement]"})
1211     public void findImageWhenNotDirectChild() throws Exception {
1212         final String html = DOCTYPE_HTML
1213             + "<html>\n"
1214             + "<head>\n"
1215             + "<script>\n"
1216             + LOG_TITLE_FUNCTION
1217             + "function doTest() {\n"
1218             + "  log(document.fmLogin.myImgName);\n"
1219             + "  log(document.fmLogin.myImgId);\n"
1220             + "}\n"
1221             + "</script>\n"
1222             + "</head>\n"
1223             + "<body onload='doTest()'>\n"
1224             + "  <form name='fmLogin' action='doLogin' method='POST'>\n"
1225             + "    <div>\n"
1226             + "      <img name='myImgName' src='somewhere'>\n"
1227             + "      <img id='myImgId' src='somewhere'>\n"
1228             + "    <div/>\n"
1229             + "  </form>\n"
1230             + "</body></html>";
1231 
1232         loadPageVerifyTitle2(html);
1233     }
1234 
1235     /**
1236      * This test shows a problem in current implementation of host object with visible constructors
1237      * used to retrieve JS object associated to a particular DOM node. The general problem needs
1238      * later.
1239      * @throws Exception if the test fails
1240      */
1241     @Test
1242     public void formIsNotAConstructor() throws Exception {
1243         final String html = DOCTYPE_HTML
1244             + "<html><head>\n"
1245             + "<script>\n"
1246             + "var Form = {};\n"
1247             + "function test() {\n"
1248             + "  document.getElementById('formId');\n"
1249             + "}\n"
1250             + "</script></head>\n"
1251             + "<body onload='test()'>\n"
1252             + "  <form id='formId' name='formName'>\n"
1253             + "    <input type='text' name='field1' value='barney'>\n"
1254             + "    <input type='submit'>\n"
1255             + "</body>\n"
1256             + "</html>";
1257         loadPageWithAlerts2(html);
1258     }
1259 
1260     /**
1261      * Test that the form from the right page is returned after browsing.
1262      * Regression test for
1263      * http://sourceforge.net/p/htmlunit/bugs/417/
1264      * @throws Exception if the test fails
1265      */
1266     @Test
1267     @Alerts({"page 1: formPage1", "page 2: formPage2"})
1268     public void formAccessAfterBrowsing() throws Exception {
1269         final String html = DOCTYPE_HTML
1270             + "<html><head>\n"
1271             + "<script>\n"
1272             + "function test() {\n"
1273             + "  window.name = 'page 1: ' + document.forms[0].name;\n"
1274             + "  document.location = 'page2.html';\n"
1275             + "}\n"
1276             + "</script>\n"
1277             + "</head><body onload='test()'>\n"
1278             + "<form name='formPage1' action='foo'>\n"
1279             + "</form>\n"
1280             + "</body></html>";
1281         final String secondContent = DOCTYPE_HTML
1282             + "<html><head>\n"
1283             + "<script>\n"
1284             + LOG_TITLE_FUNCTION
1285             + "function test() {\n"
1286             + "  log(window.name);\n"
1287             + "  log('page 2: ' + document.forms[0].name);\n"
1288             + "}\n"
1289             + "</script>\n"
1290             + "</head><body onload='test()'>\n"
1291             + "<form name='formPage2' action='foo'>\n"
1292             + "</form>\n"
1293             + "</body></html>";
1294 
1295         getMockWebConnection().setDefaultResponse(secondContent);
1296         loadPageVerifyTitle2(html);
1297     }
1298 
1299     /**
1300      * @throws Exception if the test fails
1301      */
1302     @Test
1303     @Alerts({"function handler() {}", "null", "null"})
1304     public void onsubmitNull() throws Exception {
1305         final String html = DOCTYPE_HTML
1306             + "<html><head>\n"
1307             + "<script>\n"
1308             + LOG_TITLE_FUNCTION
1309             + "  function handler() {}\n"
1310             + "  function test() {\n"
1311             + "    var form = document.getElementById('myForm');\n"
1312             + "    form.onsubmit = handler;\n"
1313             + "    log(String(form.onsubmit).replace(/\\n/g, ''));\n"
1314             + "    form.onsubmit = null;\n"
1315             + "    log(form.onsubmit);\n"
1316             + "    try {\n"
1317             + "      form.onsubmit = undefined;\n"
1318             + "      log(form.onsubmit);\n"
1319             + "    } catch(e) { logEx(e); }\n"
1320             + "  }\n"
1321             + "</script>\n"
1322             + "<body onload=test()>\n"
1323             + "  <form id='myForm'></form>\n"
1324             + "</body></html>";
1325 
1326         loadPageVerifyTitle2(html);
1327     }
1328 
1329     /**
1330      * @throws Exception if the test fails
1331      */
1332     @Test
1333     @Alerts({"page1.html", "page2.html", "page1.html", "page1.html"})
1334     public void changeFormActionAfterSubmit() throws Exception {
1335         final String[] expectedFiles = getExpectedAlerts();
1336         setExpectedAlerts();
1337 
1338         changeFormActionAfterSubmit("input type='button' value='Test'", expectedFiles[0]);
1339         changeFormActionAfterSubmit("input type='submit' value='Test'", expectedFiles[1]);
1340         changeFormActionAfterSubmit("input type='text' value='Test'", expectedFiles[2]);
1341         changeFormActionAfterSubmit("div", expectedFiles[3]);
1342     }
1343 
1344     private void changeFormActionAfterSubmit(final String clickable, final String expectedFile) throws Exception {
1345         final String html = DOCTYPE_HTML
1346             + "<html>\n"
1347             + "<head>\n"
1348             + "  <script type='text/javascript'>\n"
1349             + "    function submitForm() {\n"
1350             + "      document.myForm.submit();\n"
1351             + "      document.myForm.action = 'page2.html';\n"
1352             + "    }\n"
1353             + "  </script>\n"
1354             + "</head>\n"
1355             + "<body>\n"
1356             + "  <form action='page1.html' name='myForm'>\n"
1357             + "    <" + clickable + " id='x' onclick='submitForm();'>foo\n"
1358             + "  </form>\n"
1359             + "</body>\n"
1360             + "</html>";
1361 
1362         getMockWebConnection().setDefaultResponse("");
1363         final WebDriver driver = loadPageWithAlerts2(html);
1364         driver.findElement(By.id("x")).click();
1365         if (useRealBrowser()) {
1366             Thread.sleep(400);
1367         }
1368         assertEquals(URL_FIRST + expectedFile, driver.getCurrentUrl().replaceAll("\\?", ""));
1369     }
1370 
1371     /**
1372      * @throws Exception if the test fails
1373      */
1374     @Test
1375     @Alerts("TypeError")
1376     public void item() throws Exception {
1377         final String html = DOCTYPE_HTML
1378             + "<html>\n"
1379             + "<head>\n"
1380             + "  <script>\n"
1381             + LOG_TITLE_FUNCTION
1382             + "    function test() {\n"
1383             + "      try {\n"
1384             + "        log(document.forms['myForm'].item('myRadio').type);\n"
1385             + "      } catch(e) { logEx(e) }\n"
1386             + "    }\n"
1387             + "  </script>\n"
1388             + "</head>\n"
1389             + "<body onload='test()'>\n"
1390             + "  <form action='page1.html' name='myForm'>\n"
1391             + "    <input type='radio' name='myRadio'>\n"
1392             + "  </form>\n"
1393             + "</body>\n"
1394             + "</html>";
1395 
1396         loadPageVerifyTitle2(html);
1397     }
1398 
1399     /**
1400      * @throws Exception if the test fails
1401      */
1402     @Test
1403     @Alerts("TypeError")
1404     public void item_many() throws Exception {
1405         final String html = DOCTYPE_HTML
1406             + "<html>\n"
1407             + "<head>\n"
1408             + "  <script>\n"
1409             + LOG_TITLE_FUNCTION
1410             + "    function test() {\n"
1411             + "      try {\n"
1412             + "        log(document.forms['myForm'].item('myRadio').length);\n"
1413             + "      } catch(e) { logEx(e) }\n"
1414             + "    }\n"
1415             + "  </script>\n"
1416             + "</head>\n"
1417             + "<body onload='test()'>\n"
1418             + "  <form action='page1.html' name='myForm'>\n"
1419             + "    <input type='radio' name='myRadio'>\n"
1420             + "    <input type='radio' name='myRadio'>\n"
1421             + "  </form>\n"
1422             + "</body>\n"
1423             + "</html>";
1424 
1425         loadPageVerifyTitle2(html);
1426     }
1427 
1428     /**
1429      * @throws Exception if the test fails
1430      */
1431     @Test
1432     @Alerts("TypeError")
1433     public void item_many_subindex() throws Exception {
1434         final String html = DOCTYPE_HTML
1435             + "<html>\n"
1436             + "<head>\n"
1437             + "  <script>\n"
1438             + LOG_TITLE_FUNCTION
1439             + "    function test() {\n"
1440             + "      try {\n"
1441             + "        log(document.forms['myForm'].item('myRadio', 1).id);\n"
1442             + "      } catch(e) { logEx(e) }\n"
1443             + "    }\n"
1444             + "  </script>\n"
1445             + "</head>\n"
1446             + "<body onload='test()'>\n"
1447             + "  <form action='page1.html' name='myForm'>\n"
1448             + "    <input type='radio' name='myRadio' id='radio1'>\n"
1449             + "    <input type='radio' name='myRadio' id='radio2'>\n"
1450             + "  </form>\n"
1451             + "</body>\n"
1452             + "</html>";
1453 
1454         loadPageVerifyTitle2(html);
1455     }
1456 
1457     /**
1458      * @throws Exception if the test fails
1459      */
1460     @Test
1461     @Alerts("TypeError")
1462     public void item_integer() throws Exception {
1463         final String html = DOCTYPE_HTML
1464             + "<html>\n"
1465             + "<head>\n"
1466             + "  <script>\n"
1467             + LOG_TITLE_FUNCTION
1468             + "    function test() {\n"
1469             + "      try {\n"
1470             + "        log(document.forms['myForm'].item(1).id);\n"
1471             + "      } catch(e) { logEx(e) }\n"
1472             + "    }\n"
1473             + "  </script>\n"
1474             + "</head>\n"
1475             + "<body onload='test()'>\n"
1476             + "  <form action='page1.html' name='myForm'>\n"
1477             + "    <input type='radio' name='myRadio' id='radio1'>\n"
1478             + "    <input type='radio' name='myRadio' id='radio2'>\n"
1479             + "  </form>\n"
1480             + "</body>\n"
1481             + "</html>";
1482 
1483         loadPageVerifyTitle2(html);
1484     }
1485 
1486     /**
1487      * Call to form.submit() should capture the request to be done but the request itself should
1488      * be first done after the script execution... and only if it is still valid.
1489      * @throws Exception if the test fails
1490      */
1491     @Test
1492     @Alerts({"page4.html?f1=v1&f2=v2", "page4.html?f1=v1&f2=v2", "page3.html?f1=v1", "page3.html?f1=v1"})
1493     public void changesAfterCallToSubmit() throws Exception {
1494         final String[] expectedUrlSuffixes = getExpectedAlerts();
1495         setExpectedAlerts();
1496 
1497         changesAfterCallToSubmit("inputSubmitReturnTrue", expectedUrlSuffixes[0]);
1498         changesAfterCallToSubmit("inputSubmitVoid", expectedUrlSuffixes[1]);
1499 
1500         changesAfterCallToSubmit("inputSubmitReturnFalse", expectedUrlSuffixes[2]);
1501         changesAfterCallToSubmit("link", expectedUrlSuffixes[3]);
1502     }
1503 
1504     private void changesAfterCallToSubmit(final String id, final String expectedUrlSuffix) throws Exception {
1505         final String html = DOCTYPE_HTML
1506             + "<html><head><script>\n"
1507             + "function submitForm() {\n"
1508             + "  var f = document.forms[0];\n"
1509             + "  f.action = 'page3.html';\n"
1510             + "\n"
1511             + "  var h = document.createElement('input');\n"
1512             + "  h.name = 'f1';\n"
1513             + "  h.value = 'v1';\n"
1514             + "  f.appendChild(h);\n"
1515             + "\n"
1516             + "  f.submit();\n"
1517             + "\n"
1518             + "  f.action = 'page4.html';\n"
1519             + "  var h = document.createElement('input');\n"
1520             + "  h.name = 'f2';\n"
1521             + "  h.value = 'v2';\n"
1522             + "  f.appendChild(h);\n"
1523             + "  return false;\n"
1524             + "}\n"
1525             + "</script></head><body>\n"
1526             + "<form action='page1.html' name='myForm'>\n"
1527             + "  <input type='submit' id='inputSubmitReturnTrue' value='With on click on the button, return true' "
1528             + "onclick='submitForm(); return true'>\n"
1529             + "  <input type='submit' id='inputSubmitReturnFalse' value='With on click on the button, return false' "
1530             + "onclick='submitForm(); return false'>\n"
1531             + "  <input type='submit' id='inputSubmitVoid' value='With on click on the button, no return' "
1532             + "onclick='submitForm();'>\n"
1533             + "  <a id='link' href='#'  onclick='return submitForm()'><input type='submit' "
1534             + "value='With on click on the link'></a>\n"
1535             + "</form></body></html>";
1536 
1537         getMockWebConnection().setDefaultResponse("");
1538         final WebDriver wd = loadPageWithAlerts2(html);
1539         wd.findElement(By.id(id)).click();
1540         if (useRealBrowser()) {
1541             Thread.sleep(400);
1542         }
1543         assertEquals(URL_FIRST + expectedUrlSuffix, wd.getCurrentUrl());
1544     }
1545 
1546     /**
1547      * @throws Exception if the test fails
1548      */
1549     @Test
1550     @Alerts("2")
1551     public void submit_twice() throws Exception {
1552         final String html = DOCTYPE_HTML
1553             + "<html>\n"
1554             + "<head>\n"
1555             + "<script>\n"
1556             + "  function test() {\n"
1557             + "    var f = document.forms[0];\n"
1558             + "    f.submit();\n"
1559             + "    f.submit();\n"
1560             + "  }\n"
1561             + "</script></head>\n"
1562             + "<body onload='test()'>\n"
1563             + "  <form action='page1.html' name='myForm'>\n"
1564             + "    <input name='myField' value='some value'>\n"
1565             + "  </form>\n"
1566             + "</body></html>";
1567 
1568         getMockWebConnection().setDefaultResponse("");
1569         loadPage2(html);
1570         Thread.sleep(100);
1571 
1572         assertEquals(Integer.parseInt(getExpectedAlerts()[0]), getMockWebConnection().getRequestCount());
1573     }
1574 
1575     /**
1576      * @throws Exception if the test fails
1577      */
1578     @Test
1579     public void targetChangedAfterSubmitCall() throws Exception {
1580         final String html = DOCTYPE_HTML
1581             + "<html><head><script>\n"
1582             + "function test() {\n"
1583             + "  var f = document.forms[0];\n"
1584             + "  f.submit();\n"
1585             + "  f.target = 'foo2';\n"
1586             + "}\n"
1587             + "</script></head><body>\n"
1588             + "<form action='page1.html' name='myForm' target='foo1'>\n"
1589             + "  <input name='myField' value='some value'>\n"
1590             + "</form>\n"
1591             + "<div id='clickMe' onclick='test()'>click me</div></body></html>";
1592 
1593         getMockWebConnection().setDefaultResponse("<html><head>"
1594                 + "<script>document.title = 'Name: ' + window.name</script></head></html>");
1595         final WebDriver driver = loadPage2(html);
1596         driver.findElement(By.id("clickMe")).click();
1597 
1598         try {
1599             driver.switchTo().window("foo2");
1600             fail("Window foo2 found");
1601         }
1602         catch (final NoSuchWindowException e) {
1603             // ok
1604         }
1605         driver.switchTo().window("foo1");
1606         assertTitle(driver, "Name: foo1");
1607     }
1608 
1609     /**
1610      * Verify Content-Type header sent with form submission.
1611      * @throws Exception if the test fails
1612      */
1613     @Test
1614     public void enctypeGet() throws Exception {
1615         // for GET, no Content-Type header should be sent
1616         enctypeTest(false, null, "get", null);
1617         enctypeTest(false, "", "get", null);
1618         enctypeTest(false, "application/x-www-form-urlencoded", "get", null);
1619         enctypeTest(false, "multipart/form-data", "get", null);
1620         enctypeTest(false, MimeType.TEXT_PLAIN, "get", null);
1621 
1622         enctypeTest(true, null, "get", null);
1623         enctypeTest(true, "", "get", null);
1624         enctypeTest(true, "application/x-www-form-urlencoded", "get", null);
1625         enctypeTest(true, "multipart/form-data", "get", null);
1626         enctypeTest(true, MimeType.TEXT_PLAIN, "get", null);
1627     }
1628 
1629     /**
1630      * Verify Content-Type header sent with form submission.
1631      * @throws Exception if the test fails
1632      */
1633     @Test
1634     @Alerts({"application/x-www-form-urlencoded",
1635                 "application/x-www-form-urlencoded",
1636                 "application/x-www-form-urlencoded",
1637                 "multipart/form-data",
1638                 "text/plain"})
1639     public void enctypePost() throws Exception {
1640         enctypeTest(false, null, "post", getExpectedAlerts()[0]);
1641         enctypeTest(false, "", "post", getExpectedAlerts()[1]);
1642         enctypeTest(false, "application/x-www-form-urlencoded", "post", getExpectedAlerts()[2]);
1643         enctypeTest(false, "multipart/form-data", "post", getExpectedAlerts()[3]);
1644         enctypeTest(false, MimeType.TEXT_PLAIN, "post", getExpectedAlerts()[4]);
1645 
1646         enctypeTest(true, null, "post", getExpectedAlerts()[0]);
1647         enctypeTest(true, "", "post", getExpectedAlerts()[1]);
1648         enctypeTest(true, "application/x-www-form-urlencoded", "post", getExpectedAlerts()[2]);
1649         enctypeTest(true, "multipart/form-data", "post", getExpectedAlerts()[3]);
1650         enctypeTest(true, MimeType.TEXT_PLAIN, "post", getExpectedAlerts()[4]);
1651     }
1652 
1653     /**
1654      * Regression test for bug
1655      * <a href="http://sf.net/suppor/tracker.php?aid=2860721">2860721</a>: incorrect enctype form attribute
1656      * should be ignored.
1657      * @throws Exception if the test fails
1658      */
1659     @Test
1660     public void enctype_incorrect() throws Exception {
1661         enctypeTest(false, MimeType.TEXT_HTML, "post", "application/x-www-form-urlencoded");
1662         enctypeTest(false, MimeType.TEXT_HTML, "get", null);
1663 
1664         enctypeTest(true, MimeType.TEXT_HTML, "post", "application/x-www-form-urlencoded");
1665         enctypeTest(true, MimeType.TEXT_HTML, "get", null);
1666 
1667         enctypeTest(false, MimeType.TEXT_XML, "post", "application/x-www-form-urlencoded");
1668         enctypeTest(false, MimeType.TEXT_XML, "get", null);
1669 
1670         enctypeTest(true, MimeType.TEXT_XML, "post", "application/x-www-form-urlencoded");
1671         enctypeTest(true, MimeType.TEXT_XML, "get", null);
1672 
1673         enctypeTest(false, MimeType.APPLICATION_JSON, "post", "application/x-www-form-urlencoded");
1674         enctypeTest(false, MimeType.APPLICATION_JSON, "get", null);
1675 
1676         enctypeTest(true, MimeType.APPLICATION_JSON, "post", "application/x-www-form-urlencoded");
1677         enctypeTest(true, MimeType.APPLICATION_JSON, "get", null);
1678     }
1679 
1680     private void enctypeTest(final boolean html5, final String enctype,
1681                     final String method, final String expectedCntType) throws Exception {
1682         String html = "";
1683         if (html5) {
1684             html += DOCTYPE_HTML;
1685         }
1686         html += "<html><head><script>\n"
1687             + "function test() {\n"
1688             + "  var f = document.forms[0];\n"
1689             + "  f.submit();\n"
1690             + "}\n"
1691             + "</script></head><body onload='test()'>\n"
1692             + "<form action='foo.html' ";
1693         if (enctype != null) {
1694             html += "enctype='" + enctype + "' ";
1695         }
1696         html += "method='" + method + "'>\n"
1697             + "  <input name='myField' value='some value'>\n"
1698             + "</form></body></html>";
1699 
1700         getMockWebConnection().setDefaultResponse("<html><title>Response</title></html>");
1701         final WebDriver driver = loadPage2(html);
1702         assertTitle(driver, "Response");
1703         String headerValue = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1704             .get(HttpHeader.CONTENT_TYPE);
1705         if (headerValue != null && headerValue.startsWith(FormEncodingType.MULTIPART.getName())) {
1706             // Can't test equality for multipart/form-data as it will have the form:
1707             // multipart/form-data; boundary=---------------------------42937861433140731107235900
1708             headerValue = StringUtils.substringBefore(headerValue, ";");
1709             assertEquals(expectedCntType, headerValue);
1710         }
1711         else {
1712             assertEquals(expectedCntType, headerValue);
1713         }
1714     }
1715 
1716     /**
1717      * Verify the default value of enctype for a newly created form element.
1718      * A similar test is used by jQuery-1.9.1 in its "feature support" detection.
1719      * @throws Exception if the test fails
1720      */
1721     @Test
1722     @Alerts("application/x-www-form-urlencoded")
1723     public void enctype_defaultValue_html5() throws Exception {
1724         final String html = DOCTYPE_HTML
1725             + "<html><body><script>\n"
1726             + LOG_TITLE_FUNCTION
1727             + "log(document.createElement('form').enctype);\n"
1728             + "</script></body></html>";
1729 
1730         loadPageVerifyTitle2(html);
1731     }
1732 
1733     /**
1734      * @throws Exception in case of error
1735      */
1736     @Test
1737     @Alerts("application/x-www-form-urlencoded")
1738     public void enctype_defaultValue() throws Exception {
1739         final String html = DOCTYPE_HTML
1740             + "<html><body><script>\n"
1741             + LOG_TITLE_FUNCTION
1742             + "log(document.createElement('form').enctype);\n"
1743             + "</script></body></html>";
1744 
1745         loadPageVerifyTitle2(html);
1746     }
1747 
1748     /**
1749      * Ensure that Multipart form text fields are correctly encoded.
1750      * @throws Exception if the test fails
1751      */
1752     @Test
1753     public void submitMultipartTextFieldWithRightEncoding() throws Exception {
1754         final String html = DOCTYPE_HTML
1755             + "<html><body onload='document.forms[0].submit()'>\n"
1756             + "<form action='foo.html' enctype='multipart/form-data' method='post'>\n"
1757             + "  <input name='myField' value='éèê\u00e4\u00f6\u00fc'>\n"
1758             + "</form></body></html>";
1759 
1760         getMockWebConnection().setDefaultResponse("");
1761         loadPage2(html);
1762         Thread.sleep(100);
1763 
1764         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
1765         final String expected = "Content-Disposition: form-data; name=\"myField\"\r\n"
1766             + "\r\n"
1767             + "éèê\u00e4\u00f6\u00fc";
1768 
1769         assertTrue("Body: " + body, body.contains(expected));
1770     }
1771 
1772     /**
1773      * Ensure that text/plain form parameters are correctly encoded.
1774      * @throws Exception if the test fails
1775      */
1776     @Test
1777     @Alerts("application/x-www-form-urlencoded")
1778     public void submitUrlEncodedEmptyForm() throws Exception {
1779         final String html = DOCTYPE_HTML
1780                 + "<html>\n"
1781                 + "<body onload='document.forms[0].submit()'>\n"
1782                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1783                 + "  </form>\n"
1784                 + "</body>\n"
1785                 + "</html>";
1786 
1787         getMockWebConnection().setDefaultResponse("");
1788         loadPage2(html);
1789         Thread.sleep(100);
1790 
1791         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1792                 .get(HttpHeader.CONTENT_TYPE);
1793         assertEquals(getExpectedAlerts()[0], headerContentType);
1794 
1795         assertEquals(0, getMockWebConnection().getLastWebRequest()
1796                 .getRequestParameters().size());
1797         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1798     }
1799 
1800     /**
1801      * Ensure that text/plain form parameters are correctly encoded.
1802      * @throws Exception if the test fails
1803      */
1804     @Test
1805     @Alerts({"application/x-www-form-urlencoded", "myField=abcDEF"})
1806     public void submitUrlEncodedAsciiText() throws Exception {
1807         final String html = DOCTYPE_HTML
1808                 + "<html>\n"
1809                 + "<body onload='document.forms[0].submit()'>\n"
1810                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1811                 + "    <input name='myField' value='abcDEF'>\n"
1812                 + "  </form>\n"
1813                 + "</body>\n"
1814                 + "</html>";
1815 
1816         getMockWebConnection().setDefaultResponse("");
1817         loadPage2(html);
1818         Thread.sleep(100);
1819 
1820         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1821                 .get(HttpHeader.CONTENT_TYPE);
1822         assertEquals(getExpectedAlerts()[0], headerContentType);
1823 
1824         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1825                 .getRequestParameters().get(0).toString());
1826         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1827     }
1828 
1829     /**
1830      * Ensure that text/plain form parameters are correctly encoded.
1831      * @throws Exception if the test fails
1832      */
1833     @Test
1834     @Alerts({"application/x-www-form-urlencoded", "my\tFie ld = a b\tc \t"})
1835     public void submitUrlEncodedSpecialChars() throws Exception {
1836         final String html = DOCTYPE_HTML
1837                 + "<html>\n"
1838                 + "<body onload='document.forms[0].submit()'>\n"
1839                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1840                 + "    <input name='my\tFie ld ' value=' a b\tc \t'>\n"
1841                 + "  </form>\n"
1842                 + "</body>\n"
1843                 + "</html>";
1844 
1845         getMockWebConnection().setDefaultResponse("");
1846         loadPage2(html);
1847         Thread.sleep(100);
1848 
1849         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1850                 .get(HttpHeader.CONTENT_TYPE);
1851         assertEquals(getExpectedAlerts()[0], headerContentType);
1852 
1853         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1854                 .getRequestParameters().get(0).toString());
1855         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1856     }
1857 
1858     /**
1859      * Ensure that text/plain form parameters are correctly encoded.
1860      * @throws Exception if the test fails
1861      */
1862     @Test
1863     @Alerts({"application/x-www-form-urlencoded", "myField=éèê\u00e4\u00f6\u00fc"})
1864     public void submitUrlEncodedUnicode() throws Exception {
1865         final String html = DOCTYPE_HTML
1866                 + "<html>\n"
1867                 + "<body onload='document.forms[0].submit()'>\n"
1868                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1869                 + "    <input name='myField' value='éèê\u00e4\u00f6\u00fc'>\n"
1870                 + "  </form>\n"
1871                 + "</body>\n"
1872                 + "</html>";
1873 
1874         getMockWebConnection().setDefaultResponse("");
1875         loadPage2(html, URL_FIRST, "text/html;charset=UTF-8", UTF_8, null);
1876         Thread.sleep(100);
1877 
1878         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1879                 .get(HttpHeader.CONTENT_TYPE);
1880         assertEquals(getExpectedAlerts()[0], headerContentType);
1881 
1882         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1883                 .getRequestParameters().get(0).toString());
1884         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1885     }
1886 
1887     /**
1888      * Ensure that text/plain form parameters are correctly encoded.
1889      * @throws Exception if the test fails
1890      */
1891     @Test
1892     @Alerts({"application/x-www-form-urlencoded", "myField=HtmlUnit \u043B\u0189"})
1893     public void submitUrlEncodedUnicodeUTF8() throws Exception {
1894         final String html = DOCTYPE_HTML
1895                 + "<html>\n"
1896                 + "<body onload='document.forms[0].submit()'>\n"
1897                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1898                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
1899                 + "  </form>\n"
1900                 + "</body>\n"
1901                 + "</html>";
1902 
1903         getMockWebConnection().setDefaultResponse("");
1904         loadPage2(html, URL_FIRST, "text/html;charset=UTF-8", UTF_8, null);
1905         Thread.sleep(100);
1906 
1907         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1908                 .get(HttpHeader.CONTENT_TYPE);
1909         assertEquals(getExpectedAlerts()[0], headerContentType);
1910 
1911         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1912                 .getRequestParameters().get(0).toString());
1913         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1914     }
1915 
1916     /**
1917      * Ensure that text/plain form parameters are correctly encoded.
1918      * @throws Exception if the test fails
1919      */
1920     @Test
1921     @Alerts({"application/x-www-form-urlencoded", "myField=HtmlUnit \u043B\u0189"})
1922     public void submitUrlEncodedUnicodeUTF16() throws Exception {
1923         final String html = DOCTYPE_HTML
1924                 + "<html>\n"
1925                 + "<body onload='document.forms[0].submit()'>\n"
1926                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1927                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
1928                 + "  </form>\n"
1929                 + "</body>\n"
1930                 + "</html>";
1931 
1932         getMockWebConnection().setDefaultResponse("");
1933         loadPage2(html, URL_FIRST, "text/html;charset=UTF-16", UTF_16, null);
1934         Thread.sleep(100);
1935 
1936         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1937                 .get(HttpHeader.CONTENT_TYPE);
1938         assertEquals(getExpectedAlerts()[0], headerContentType);
1939 
1940         assertEquals(getExpectedAlerts()[1], getMockWebConnection().getLastWebRequest()
1941                 .getRequestParameters().get(0).toString());
1942         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1943     }
1944 
1945     /**
1946      * Ensure that text/plain form parameters are correctly encoded.
1947      * @throws Exception if the test fails
1948      */
1949     @Test
1950     @Alerts({"application/x-www-form-urlencoded", "myFile=htmlunit-test", ".txt"})
1951     public void submitUrlEncodedFile() throws Exception {
1952         final String html = DOCTYPE_HTML
1953                 + "<html>\n"
1954                 + "<body>\n"
1955                 + "  <form action='foo.html' enctype='application/x-www-form-urlencoded' method='post'>\n"
1956                 + "    <input type='file' id='f' name='myFile'>\n"
1957                 + "    <input id='clickMe' type='submit' value='Click Me'>\n"
1958                 + "  </form>\n"
1959                 + "</body>\n"
1960                 + "</html>";
1961 
1962         getMockWebConnection().setDefaultResponse("");
1963 
1964         final WebDriver driver = loadPage2(html);
1965 
1966         final File tmpFile = File.createTempFile("htmlunit-test", ".txt");
1967         try {
1968             final String path = tmpFile.getAbsolutePath();
1969             driver.findElement(By.id("f")).sendKeys(path);
1970             driver.findElement(By.id("clickMe")).click();
1971             if (useRealBrowser()) {
1972                 Thread.sleep(400);
1973             }
1974         }
1975         finally {
1976             assertTrue(tmpFile.delete());
1977         }
1978 
1979         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
1980                 .get(HttpHeader.CONTENT_TYPE);
1981         assertEquals(getExpectedAlerts()[0], headerContentType);
1982 
1983         final String body = getMockWebConnection().getLastWebRequest()
1984                 .getRequestParameters().get(0).toString();
1985         assertTrue(body, body.startsWith(getExpectedAlerts()[1]));
1986         assertTrue(body, body.endsWith(getExpectedAlerts()[2]));
1987         assertNull(getMockWebConnection().getLastWebRequest().getRequestBody());
1988     }
1989 
1990     /**
1991      * Ensure that text/plain form parameters are correctly encoded.
1992      * @throws Exception if the test fails
1993      */
1994     @Test
1995     @Alerts("text/plain")
1996     public void submitPlainTextEmptyForm() throws Exception {
1997         final String html = DOCTYPE_HTML
1998                 + "<html>\n"
1999                 + "<body onload='document.forms[0].submit()'>\n"
2000                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2001                 + "  </form>\n"
2002                 + "</body>\n"
2003                 + "</html>";
2004 
2005         getMockWebConnection().setDefaultResponse("");
2006         loadPage2(html);
2007         Thread.sleep(100);
2008 
2009         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2010                 .get(HttpHeader.CONTENT_TYPE);
2011         assertEquals(getExpectedAlerts()[0], headerContentType);
2012 
2013         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2014         assertNull(body);
2015     }
2016 
2017     /**
2018      * Ensure that text/plain form parameters are correctly encoded.
2019      * @throws Exception if the test fails
2020      */
2021     @Test
2022     @Alerts({"text/plain", "myField=abcDEF\r\n"})
2023     public void submitPlainTextAsciiText() throws Exception {
2024         final String html = DOCTYPE_HTML
2025                 + "<html>\n"
2026                 + "<body onload='document.forms[0].submit()'>\n"
2027                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2028                 + "    <input name='myField' value='abcDEF'>\n"
2029                 + "  </form>\n"
2030                 + "</body>\n"
2031                 + "</html>";
2032 
2033         getMockWebConnection().setDefaultResponse("");
2034         loadPage2(html);
2035         Thread.sleep(100);
2036 
2037         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2038                 .get(HttpHeader.CONTENT_TYPE);
2039         assertEquals(getExpectedAlerts()[0], headerContentType);
2040 
2041         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2042         assertEquals(getExpectedAlerts()[1], body);
2043     }
2044 
2045     /**
2046      * Ensure that text/plain form parameters are correctly encoded.
2047      * @throws Exception if the test fails
2048      */
2049     @Test
2050     @Alerts({"text/plain", "my\tField = abcDEF \t\r\n"})
2051     public void submitPlainTextSpecialChars() throws Exception {
2052         final String html = DOCTYPE_HTML
2053                 + "<html>\n"
2054                 + "<body onload='document.forms[0].submit()'>\n"
2055                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2056                 + "    <input name='my\tField ' value=' ab\rcD\nEF \t'>\n"
2057                 + "  </form>\n"
2058                 + "</body>\n"
2059                 + "</html>";
2060 
2061         getMockWebConnection().setDefaultResponse("");
2062         loadPage2(html);
2063         Thread.sleep(100);
2064 
2065         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2066                 .get(HttpHeader.CONTENT_TYPE);
2067         assertEquals(getExpectedAlerts()[0], headerContentType);
2068 
2069         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2070         assertEquals(getExpectedAlerts()[1], body);
2071     }
2072 
2073     /**
2074      * Ensure that text/plain form parameters are correctly encoded.
2075      * @throws Exception if the test fails
2076      */
2077     @Test
2078     @Alerts({"text/plain", "myField=éèê\u00e4\u00f6\u00fc\u00a9\r\n"})
2079     public void submitPlainTextUnicode() throws Exception {
2080         final String html = DOCTYPE_HTML
2081                 + "<html>\n"
2082                 + "<body onload='document.forms[0].submit()'>\n"
2083                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2084                 + "    <input name='myField' value='éèê\u00e4\u00f6\u00fc\u00a9'>\n"
2085                 + "  </form>\n"
2086                 + "</body>\n"
2087                 + "</html>";
2088 
2089         getMockWebConnection().setDefaultResponse("");
2090         loadPage2(html);
2091         Thread.sleep(100);
2092 
2093         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2094                 .get(HttpHeader.CONTENT_TYPE);
2095         assertEquals(getExpectedAlerts()[0], headerContentType);
2096 
2097         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2098         assertEquals(getExpectedAlerts()[1], body);
2099     }
2100 
2101     /**
2102      * Ensure that text/plain form parameters are correctly encoded.
2103      * @throws Exception if the test fails
2104      */
2105     @Test
2106     @Alerts({"text/plain", "myField=éèê\u00e4\u00f6\u00fc\u00a9?\r\n"})
2107     public void submitPlainTextISO_8859_1() throws Exception {
2108         final String html = DOCTYPE_HTML
2109                 + "<html>\n"
2110                 + "<body onload='document.forms[0].submit()'>\n"
2111                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2112                 + "    <input name='myField' value='éèê\u00e4\u00f6\u00fc\u00a9\u05d4'>\n"
2113                 + "  </form>\n"
2114                 + "</body>\n"
2115                 + "</html>";
2116 
2117         getMockWebConnection().setDefaultResponse("");
2118         loadPage2(html, URL_FIRST, "text/html;charset=ISO-8859-1", ISO_8859_1, null);
2119         Thread.sleep(100);
2120 
2121         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2122                 .get(HttpHeader.CONTENT_TYPE);
2123         assertEquals(getExpectedAlerts()[0], headerContentType);
2124 
2125         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2126         assertEquals(getExpectedAlerts()[1], body);
2127         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2128     }
2129 
2130 
2131     /**
2132      * Ensure that text/plain form parameters are correctly encoded.
2133      * @throws Exception if the test fails
2134      */
2135     @Test
2136     @Alerts({"text/plain", "myField=éèêäöü©?\r\n"})
2137     public void submitPlainTextISO_8859_1_AcceptCharsetUtf8() throws Exception {
2138         final String html = DOCTYPE_HTML
2139                 + "<html>\n"
2140                 + "<body onload='document.forms[0].submit()'>\n"
2141                 + "  <form action='foo.html' enctype='text/plain' accept-charset='utf8' method='post'>\n"
2142                 + "    <input name='myField' value='éèê\u00e4\u00f6\u00fc\u00a9\u05d4'>\n"
2143                 + "  </form>\n"
2144                 + "</body>\n"
2145                 + "</html>";
2146 
2147         getMockWebConnection().setDefaultResponse("");
2148         loadPage2(html, URL_FIRST, "text/html;charset=ISO-8859-1", ISO_8859_1, null);
2149         Thread.sleep(100);
2150 
2151         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2152                 .get(HttpHeader.CONTENT_TYPE);
2153         assertEquals(getExpectedAlerts()[0], headerContentType);
2154 
2155         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2156         assertEquals(getExpectedAlerts()[1], body);
2157         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2158     }
2159 
2160     /**
2161      * Ensure that text/plain form parameters are correctly encoded.
2162      * @throws Exception if the test fails
2163      */
2164     @Test
2165     @Alerts({"text/plain", "myField=HtmlUnit \u00D0\u00BB\u00C6\u0089\r\n"})
2166     public void submitPlainTextUnicodeUTF8() throws Exception {
2167         final String html = DOCTYPE_HTML
2168                 + "<html>\n"
2169                 + "<body onload='document.forms[0].submit()'>\n"
2170                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2171                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
2172                 + "  </form>\n"
2173                 + "</body>\n"
2174                 + "</html>";
2175 
2176         getMockWebConnection().setDefaultResponse("");
2177         loadPage2(html, URL_FIRST, "text/html;charset=UTF-8", UTF_8, null);
2178         Thread.sleep(100);
2179 
2180         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2181                 .get(HttpHeader.CONTENT_TYPE);
2182         assertEquals(getExpectedAlerts()[0], headerContentType);
2183 
2184         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2185         assertEquals(getExpectedAlerts()[1], body);
2186         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2187     }
2188 
2189     /**
2190      * Ensure that text/plain form parameters are correctly encoded.
2191      * @throws Exception if the test fails
2192      */
2193     @Test
2194     @Alerts({"text/plain", "myField=HtmlUnit \u00D0\u00BB\u00C6\u0089\r\n"})
2195     public void submitPlainTextUnicodeUTF16() throws Exception {
2196         final String html = DOCTYPE_HTML
2197                 + "<html>\n"
2198                 + "<body onload='document.forms[0].submit()'>\n"
2199                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2200                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
2201                 + "  </form>\n"
2202                 + "</body>\n"
2203                 + "</html>";
2204 
2205         getMockWebConnection().setDefaultResponse("");
2206         loadPage2(html, URL_FIRST, "text/html;charset=UTF-16", UTF_16, null);
2207         Thread.sleep(100);
2208 
2209         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2210                 .get(HttpHeader.CONTENT_TYPE);
2211         assertEquals(getExpectedAlerts()[0], headerContentType);
2212 
2213         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2214         assertEquals(getExpectedAlerts()[1], body);
2215         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2216     }
2217 
2218     /**
2219      * Ensure that text/plain form parameters are correctly encoded.
2220      * @throws Exception if the test fails
2221      */
2222     @Test
2223     @Alerts({"text/plain", "myField=HtmlUnit \u00D0\u00BB\u00C6\u0089\r\n"})
2224     public void submitPlainTextUnicodeUTF16AcceptCharsetUtf8() throws Exception {
2225         final String html = DOCTYPE_HTML
2226                 + "<html>\n"
2227                 + "<body onload='document.forms[0].submit()'>\n"
2228                 + "  <form action='foo.html' enctype='text/plain' accept-charset='utf8' method='post'>\n"
2229                 + "    <input name='myField' value='HtmlUnit \u043B\u0189'>\n"
2230                 + "  </form>\n"
2231                 + "</body>\n"
2232                 + "</html>";
2233 
2234         getMockWebConnection().setDefaultResponse("");
2235         loadPage2(html, URL_FIRST, "text/html;charset=UTF-16", UTF_16, null);
2236         Thread.sleep(100);
2237 
2238         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2239                 .get(HttpHeader.CONTENT_TYPE);
2240         assertEquals(getExpectedAlerts()[0], headerContentType);
2241 
2242         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2243         assertEquals(getExpectedAlerts()[1], body);
2244         assertNull(getMockWebConnection().getLastWebRequest().getCharset());
2245     }
2246 
2247     /**
2248      * Ensure that text/plain form parameters are correctly encoded.
2249      * @throws Exception if the test fails
2250      */
2251     @Test
2252     @Alerts({"text/plain", "myFile=htmlunit-test", ".txt\r\n"})
2253     public void submitPlainTextFile() throws Exception {
2254         final String html = DOCTYPE_HTML
2255                 + "<html>\n"
2256                 + "<body>\n"
2257                 + "  <form action='foo.html' enctype='text/plain' method='post'>\n"
2258                 + "    <input type='file' id='f' name='myFile'>\n"
2259                 + "    <input id='clickMe' type='submit' value='Click Me'>\n"
2260                 + "  </form>\n"
2261                 + "</body>\n"
2262                 + "</html>";
2263 
2264         getMockWebConnection().setDefaultResponse("");
2265 
2266         final WebDriver driver = loadPage2(html);
2267 
2268         final File tmpFile = File.createTempFile("htmlunit-test", ".txt");
2269         try {
2270             final String path = tmpFile.getAbsolutePath();
2271             driver.findElement(By.id("f")).sendKeys(path);
2272             driver.findElement(By.id("clickMe")).click();
2273             if (useRealBrowser()) {
2274                 Thread.sleep(400);
2275             }
2276         }
2277         finally {
2278             assertTrue(tmpFile.delete());
2279         }
2280 
2281         final String headerContentType = getMockWebConnection().getLastWebRequest().getAdditionalHeaders()
2282                 .get(HttpHeader.CONTENT_TYPE);
2283         assertEquals(getExpectedAlerts()[0], headerContentType);
2284 
2285         final String body = getMockWebConnection().getLastWebRequest().getRequestBody();
2286         assertTrue(body, body.startsWith(getExpectedAlerts()[1]));
2287         assertTrue(body, body.endsWith(getExpectedAlerts()[2]));
2288     }
2289 
2290     /**
2291      * Failed as of HtmlUnit-2.7-SNAPSHOT 01.12.2009 as the '#' from the
2292      * link together with the fact that submission occurs to the same url
2293      * let HtmlUnit think that it as just navigation to an anchor.
2294      * @throws Exception if the test fails
2295      */
2296     @Test
2297     public void submitToSameUrlFromLinkOnclick_post() throws Exception {
2298         submitToSameUrlFromLinkOnclick("post");
2299     }
2300 
2301     /**
2302      * @throws Exception if the test fails
2303      */
2304     @Test
2305     public void submitToSameUrlFromLinkOnclick_get() throws Exception {
2306         submitToSameUrlFromLinkOnclick("get");
2307     }
2308 
2309     private void submitToSameUrlFromLinkOnclick(final String method) throws Exception {
2310         final String html = DOCTYPE_HTML
2311             + "<html><head><title>foo</title></head><body>\n"
2312             + "<form id='form1' method='" + method + "'>\n"
2313             + "<input name='foo'>\n"
2314             + "<a href='#' onclick='document.forms[0].submit()' id='clickMe'>submit it</a>\n"
2315             + "</form></body></html>";
2316 
2317         final WebDriver driver = loadPage2(html);
2318         driver.findElement(By.id("clickMe")).click();
2319         driver.findElement(By.id("clickMe")).click(); // a second time to be sure to have same resulting Url
2320         if (useRealBrowser()) {
2321             Thread.sleep(400);
2322         }
2323 
2324         assertEquals(3, getMockWebConnection().getRequestCount());
2325     }
2326 
2327     /**
2328      * @throws Exception if the test fails
2329      */
2330     @Test
2331     @Alerts({"", "foo4?foo=", "script4.js"})
2332     @NotYetImplemented
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 }