View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.html;
16  
17  import java.net.URL;
18  import java.util.ArrayList;
19  import java.util.Arrays;
20  import java.util.Collections;
21  import java.util.List;
22  
23  import org.htmlunit.CollectingAlertHandler;
24  import org.htmlunit.ElementNotFoundException;
25  import org.htmlunit.HttpMethod;
26  import org.htmlunit.MockWebConnection;
27  import org.htmlunit.Page;
28  import org.htmlunit.SimpleWebTestCase;
29  import org.htmlunit.WebClient;
30  import org.htmlunit.WebRequest;
31  import org.htmlunit.WebWindow;
32  import org.htmlunit.junit.annotation.Alerts;
33  import org.htmlunit.util.MimeType;
34  import org.htmlunit.util.NameValuePair;
35  import org.junit.jupiter.api.Assertions;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   * Tests for {@link HtmlForm}.
40   *
41   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
42   * @author <a href="mailto:chen_jun@users.sourceforge.net">Jun Chen</a>
43   * @author George Murnock
44   * @author Marc Guillemot
45   * @author Ahmed Ashour
46   * @author Philip Graf
47   * @author Ronald Brill
48   */
49  public class HtmlFormTest extends SimpleWebTestCase {
50  
51      /**
52       * Tests the good case for setCheckedRatdioButton().
53       * @exception Exception If the test fails
54       */
55      @Test
56      public void setSelectedRadioButton_ValueExists() throws Exception {
57          final String html = DOCTYPE_HTML
58              + "<html><head><title>foo</title></head><body>\n"
59              + "<form id='form1'>\n"
60              + "<input type='radio' name='foo' value='1' selected='selected' id='input1'/>\n"
61              + "<input type='radio' name='foo' value='2' id='input2'/>\n"
62              + "<input type='radio' name='foo' value='3'/>\n"
63              + "<input type='submit' name='button' value='foo'/>\n"
64              + "</form></body></html>";
65          final HtmlPage page = loadPage(html);
66          final MockWebConnection webConnection = getMockConnection(page);
67  
68          final HtmlForm form = page.getHtmlElementById("form1");
69  
70          final HtmlSubmitInput pushButton = form.getInputByName("button");
71  
72          form.<HtmlRadioButtonInput>getFirstByXPath(
73                  "//input[@type='radio' and @name='foo' and @value='2']").setChecked(true);
74  
75          assertFalse(page.<HtmlRadioButtonInput>getHtmlElementById("input1").isChecked());
76          assertTrue(page.<HtmlRadioButtonInput>getHtmlElementById("input2").isChecked());
77  
78          // Test that only one value for the radio button is being passed back to the server
79          final HtmlPage secondPage = (HtmlPage) pushButton.click();
80  
81          assertEquals("url", URL_FIRST + "?foo=2&button=foo", secondPage.getUrl());
82          assertSame("method", HttpMethod.GET, webConnection.getLastMethod());
83      }
84  
85      /**
86       * Tests setCheckedRadioButton() with a value that doesn't exist.
87       * @exception Exception If the test fails
88       */
89      @Test
90      public void setSelectedRadioButton_ValueDoesNotExist_DoNotForceSelection() throws Exception {
91          final String html = DOCTYPE_HTML
92              + "<html><head><title>foo</title></head><body>\n"
93              + "<form id='form1'>\n"
94              + "<input type='radio' name='foo' value='1' selected='selected'/>\n"
95              + "<input type='radio' name='foo' value='2'/>\n"
96              + "<input type='radio' name='foo' value='3'/>\n"
97              + "<input type='submit' name='button' value='foo'/>\n"
98              + "</form></body></html>";
99          final HtmlPage page = loadPage(html);
100 
101         final HtmlForm form = page.getHtmlElementById("form1");
102 
103         final HtmlInput pushButton = form.getInputByName("button");
104         assertNotNull(pushButton);
105 
106         assertNull(form.getFirstByXPath("//input[@type='radio' and @name='foo' and @value='4']"));
107     }
108 
109     /**
110      * @throws Exception if the test fails
111      */
112     @Test
113     public void submit_String() throws Exception {
114         final String html = DOCTYPE_HTML
115             + "<html><head><title>foo</title></head><body>\n"
116             + "<form id='form1'>\n"
117             + "<input id='submitButton' type='submit' name='button' value='foo'/>\n"
118             + "</form></body></html>";
119         final HtmlPage page = loadPage(html);
120 
121         final HtmlForm form = page.getHtmlElementById("form1");
122 
123         // Regression test: this used to blow up
124         form.submit((HtmlSubmitInput) page.getHtmlElementById("submitButton"));
125     }
126 
127     /**
128      * @throws Exception if the test fails
129      */
130     @Test
131     public void submit_ExtraParameters() throws Exception {
132         final String html = DOCTYPE_HTML
133             + "<html><head><title>foo</title></head><body>\n"
134             + "<form id='form1' method='post'>\n"
135             + "  <input type='text' name='textfield' value='*'/>\n"
136             + "  <input type='submit' name='button' value='foo'/>\n"
137             + "</form></body></html>";
138         final HtmlPage page = loadPage(html);
139         final MockWebConnection webConnection = getMockConnection(page);
140 
141         final HtmlForm form = page.getHtmlElementById("form1");
142 
143         final HtmlSubmitInput button = form.getInputByName("button");
144         button.click();
145 
146         final List<NameValuePair> expectedParameters = Arrays.asList(new NameValuePair[]{
147             new NameValuePair("textfield", "*"), new NameValuePair("button", "foo")
148         });
149         final List<NameValuePair> collectedParameters = webConnection.getLastParameters();
150 
151         assertEquals(expectedParameters, collectedParameters);
152     }
153 
154     /**
155      * @throws Exception if the test fails
156      */
157     @Test
158     public void submit_BadSubmitMethod() throws Exception {
159         final String html = DOCTYPE_HTML
160             + "<html><head><title>foo</title></head><body>\n"
161             + "<form id='form1' method='put'>\n"
162             + "  <input type='text' name='textfield' value='*'/>\n"
163             + "  <input type='submit' name='button' id='button' value='foo'/>\n"
164             + "</form></body></html>";
165         final HtmlPage page = loadPage(html);
166         final MockWebConnection webConnection = getMockConnection(page);
167         page.getHtmlElementById("button").click();
168         assertSame(HttpMethod.GET, webConnection.getLastMethod());
169     }
170 
171     /**
172      * @throws Exception if the test fails
173      */
174     @Test
175     public void submit_onSubmitHandler() throws Exception {
176         final String firstHtml = DOCTYPE_HTML
177             + "<html><head><title>First</title></head><body>\n"
178             + "<form method='get' action='" + URL_SECOND + "' onSubmit='alert(\"clicked\")'>\n"
179             + "<input name='button' type='submit' value='PushMe' id='button'/></form>\n"
180             + "</body></html>";
181         final String secondHtml = DOCTYPE_HTML + "<html><head><title>Second</title></head><body></body></html>";
182 
183         final WebClient client = getWebClientWithMockWebConnection();
184         final List<String> collectedAlerts = new ArrayList<>();
185         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
186 
187         final MockWebConnection webConnection = getMockWebConnection();
188         webConnection.setResponse(URL_FIRST, firstHtml);
189         webConnection.setDefaultResponse(secondHtml);
190 
191         final HtmlPage firstPage = client.getPage(URL_FIRST);
192         final HtmlSubmitInput button = firstPage.getHtmlElementById("button");
193 
194         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
195         final HtmlPage secondPage = button.click();
196         assertEquals("Second", secondPage.getTitleText());
197 
198         assertEquals(new String[] {"clicked"}, collectedAlerts);
199     }
200 
201     /**
202      * @throws Exception if the test fails
203      */
204     @Test
205     public void submit_onSubmitHandler_returnFalse() throws Exception {
206         final String firstHtml = DOCTYPE_HTML
207             + "<html><head><title>First</title></head><body>\n"
208             + "<form method='get' action='" + URL_SECOND + "' "
209             + "onSubmit='alert(\"clicked\");return false;'>\n"
210             + "<input name='button' type='submit' value='PushMe' id='button'/></form>\n"
211             + "</body></html>";
212         final String secondHtml = DOCTYPE_HTML + "<html><head><title>Second</title></head><body></body></html>";
213 
214         final WebClient client = getWebClientWithMockWebConnection();
215         final List<String> collectedAlerts = new ArrayList<>();
216         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
217 
218         final MockWebConnection webConnection = getMockWebConnection();
219         webConnection.setResponse(URL_FIRST, firstHtml);
220         webConnection.setResponse(URL_SECOND, secondHtml);
221 
222         final HtmlPage firstPage = client.getPage(URL_FIRST);
223         final HtmlSubmitInput button = firstPage.getHtmlElementById("button");
224 
225         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
226         final HtmlPage secondPage = button.click();
227         assertEquals(firstPage.getTitleText(), secondPage.getTitleText());
228 
229         assertEquals(new String[] {"clicked"}, collectedAlerts);
230     }
231 
232     /**
233      * Testcase for 3072010.
234      *
235      * @throws Exception if the test fails
236      */
237     @Test
238     @Alerts("clicked")
239     public void submit_onSubmitHandler_preventDefaultOnly() throws Exception {
240         final String firstHtml = DOCTYPE_HTML
241             + "<html><body>\n"
242             + "<form method='post' action='/foo' >\n"
243             + "<input type='submit' id='button'/>\n"
244             + "</form>\n"
245             + "<script>\n"
246             + "function foo(e) {\n"
247             + "  alert('clicked');\n"
248             + "  e.returnValue = false;\n"
249             + "  if (e.preventDefault) {\n"
250             + "    e.preventDefault();\n"
251             + "  }\n"
252             + "}\n"
253             + "var oForm = document.forms[0];\n"
254             + "oForm.addEventListener('submit', foo, false);\n"
255             + "</script>\n"
256             + "</body></html>";
257 
258         final WebClient client = getWebClientWithMockWebConnection();
259         final List<String> collectedAlerts = new ArrayList<>();
260         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
261 
262         getMockWebConnection().setResponse(URL_FIRST, firstHtml);
263         getMockWebConnection().setDefaultResponse("");
264 
265         final HtmlPage firstPage = client.getPage(URL_FIRST);
266         final HtmlSubmitInput button = firstPage.getHtmlElementById("button");
267 
268         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
269         final HtmlPage secondPage = button.click();
270         assertSame(firstPage, secondPage);
271 
272         assertEquals(getExpectedAlerts(), collectedAlerts);
273     }
274 
275     /**
276      * Regression test for NullPointerException when submitting forms.
277      * @throws Exception if the test fails
278      */
279     @Test
280     public void submit_onSubmitHandler_fails() throws Exception {
281         final String firstHtml = DOCTYPE_HTML
282             + "<html><head><title>First</title></head><body>\n"
283             + "<form method='get' action='" + URL_SECOND + "' onSubmit='return null'>\n"
284             + "<input name='button' type='submit' value='PushMe' id='button'/></form>\n"
285             + "</body></html>";
286         final String secondHtml = DOCTYPE_HTML + "<html><head><title>Second</title></head><body></body></html>";
287 
288         final WebClient client = getWebClientWithMockWebConnection();
289         final MockWebConnection webConnection = getMockWebConnection();
290         webConnection.setResponse(URL_FIRST, firstHtml);
291         webConnection.setDefaultResponse(secondHtml);
292 
293         final HtmlPage firstPage = client.getPage(URL_FIRST);
294         final HtmlSubmitInput button = firstPage.getHtmlElementById("button");
295         final HtmlPage secondPage = button.click();
296         assertEquals("Second", secondPage.getTitleText());
297     }
298 
299     /**
300      * @throws Exception if the test fails
301      */
302     @Test
303     public void submit_onSubmitHandler_javascriptDisabled() throws Exception {
304         final String firstHtml = DOCTYPE_HTML
305             + "<html><head><title>First</title></head><body>\n"
306             + "<form method='get' action='" + URL_SECOND + "' onSubmit='alert(\"clicked\")'>\n"
307             + "<input name='button' type='submit' value='PushMe' id='button'/></form>\n"
308             + "</body></html>";
309         final String secondHtml = DOCTYPE_HTML + "<html><head><title>Second</title></head><body></body></html>";
310 
311         final WebClient client = getWebClientWithMockWebConnection();
312         client.getOptions().setJavaScriptEnabled(false);
313 
314         final List<String> collectedAlerts = new ArrayList<>();
315         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
316 
317         final MockWebConnection webConnection = getMockWebConnection();
318         webConnection.setResponse(URL_FIRST, firstHtml);
319         webConnection.setDefaultResponse(secondHtml);
320 
321         final HtmlPage firstPage = client.getPage(URL_FIRST);
322         final HtmlSubmitInput button = firstPage.getHtmlElementById("button");
323 
324         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
325         final HtmlPage secondPage = button.click();
326         assertEquals("First", firstPage.getTitleText());
327         assertEquals("Second", secondPage.getTitleText());
328 
329         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
330     }
331 
332     /**
333      * @throws Exception if the test fails
334      */
335     @Test
336     public void submit_javascriptAction() throws Exception {
337         final String firstHtml = DOCTYPE_HTML
338             + "<html><head><title>First</title></head><body>\n"
339             + "<form method='get' action='javascript:alert(\"clicked\")'>\n"
340             + "<input name='button' type='submit' value='PushMe' id='button'/></form>\n"
341             + "</body></html>";
342         final String secondHtml = DOCTYPE_HTML + "<html><head><title>Second</title></head><body></body></html>";
343 
344         final WebClient client = getWebClientWithMockWebConnection();
345         final List<String> collectedAlerts = new ArrayList<>();
346         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
347 
348         final MockWebConnection webConnection = getMockWebConnection();
349         webConnection.setResponse(URL_FIRST, firstHtml);
350         webConnection.setResponse(URL_SECOND, secondHtml);
351 
352         final HtmlPage firstPage = client.getPage(URL_FIRST);
353         final HtmlSubmitInput button = firstPage.getHtmlElementById("button");
354 
355         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
356         final HtmlPage secondPage = button.click();
357         assertEquals(firstPage.getTitleText(), secondPage.getTitleText());
358 
359         assertEquals(new String[] {"clicked"}, collectedAlerts);
360     }
361 
362     /**
363      * @throws Exception if the test fails
364      */
365     @Test
366     public void submit_javascriptActionMixedCase() throws Exception {
367         final String firstHtml = DOCTYPE_HTML
368             + "<html><head><title>First</title></head><body>\n"
369             + "<form method='get' action='jaVAscrIpt:alert(\"clicked\")'>\n"
370             + "<input name='button' type='submit' value='PushMe' id='button'/></form>\n"
371             + "</body></html>";
372         final String secondHtml = DOCTYPE_HTML + "<html><head><title>Second</title></head><body></body></html>";
373 
374         final WebClient client = getWebClientWithMockWebConnection();
375         final List<String> collectedAlerts = new ArrayList<>();
376         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
377 
378         final MockWebConnection webConnection = getMockWebConnection();
379         webConnection.setResponse(URL_FIRST, firstHtml);
380         webConnection.setResponse(URL_SECOND, secondHtml);
381 
382         final HtmlPage firstPage = client.getPage(URL_FIRST);
383         final HtmlSubmitInput button = firstPage.getHtmlElementById("button");
384 
385         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
386         final HtmlPage secondPage = button.click();
387         assertEquals(firstPage.getTitleText(), secondPage.getTitleText());
388 
389         assertEquals(new String[] {"clicked"}, collectedAlerts);
390     }
391 
392     /**
393      * @throws Exception if the test fails
394      */
395     @Test
396     public void submit_javascriptActionLeadingWhitespace() throws Exception {
397         final String firstHtml = DOCTYPE_HTML
398             + "<html><head><title>First</title></head><body>\n"
399             + "<form method='get' action=' javascript:alert(\"clicked\")'>\n"
400             + "<input name='button' type='submit' value='PushMe' id='button'/></form>\n"
401             + "</body></html>";
402         final String secondHtml = DOCTYPE_HTML + "<html><head><title>Second</title></head><body></body></html>";
403 
404         final WebClient client = getWebClientWithMockWebConnection();
405         final List<String> collectedAlerts = new ArrayList<>();
406         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
407 
408         final MockWebConnection webConnection = getMockWebConnection();
409         webConnection.setResponse(URL_FIRST, firstHtml);
410         webConnection.setResponse(URL_SECOND, secondHtml);
411 
412         final HtmlPage firstPage = client.getPage(URL_FIRST);
413         final HtmlSubmitInput button = firstPage.getHtmlElementById("button");
414 
415         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
416         final HtmlPage secondPage = button.click();
417         assertEquals(firstPage.getTitleText(), secondPage.getTitleText());
418 
419         assertEquals(new String[] {"clicked"}, collectedAlerts);
420     }
421 
422     /**
423      * @throws Exception if the test fails
424      */
425     @Test
426     public void submit_javascriptAction_javascriptDisabled() throws Exception {
427         final String html = DOCTYPE_HTML
428             + "<html><head><title>First</title></head><body>\n"
429             + "<form method='get' action='javascript:alert(\"clicked\")'>\n"
430             + "<input name='button' type='submit' value='PushMe' id='button'/></form>\n"
431             + "</body></html>";
432 
433         final WebClient client = getWebClientWithMockWebConnection();
434         client.getOptions().setJavaScriptEnabled(false);
435 
436         final List<String> collectedAlerts = new ArrayList<>();
437         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
438 
439         final MockWebConnection webConnection = getMockWebConnection();
440         webConnection.setResponse(URL_FIRST, html);
441 
442         final HtmlPage firstPage = client.getPage(URL_FIRST);
443         final HtmlSubmitInput button = firstPage.getHtmlElementById("button");
444 
445         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
446         final HtmlPage secondPage = button.click();
447         assertSame(firstPage, secondPage);
448     }
449 
450     /**
451      * Regression test for a bug that caused a NullPointer exception to be thrown during submit.
452      * @throws Exception if the test fails
453      */
454     @Test
455     public void submitRadioButton() throws Exception {
456         final String html = DOCTYPE_HTML
457             + "<html><body><form method='POST' action='" + URL_FIRST + "'>\n"
458             + "<table><tr> <td ><input type='radio' name='name1' value='foo'> "
459             + "Option 1</td> </tr>\n"
460             + "<tr> <td ><input type='radio' name='name1' value='bar' checked >\n"
461             + "Option 2</td> </tr>\n"
462             + "<tr> <td ><input type='radio' name='name1' value='baz'> Option 3</td> </tr>\n"
463             + "</table><input type='submit' value='Login' name='loginButton1'></form>\n"
464             + "</body></html>";
465 
466         final HtmlPage page = loadPage(html);
467         final HtmlSubmitInput loginButton
468             = page.getDocumentElement().getOneHtmlElementByAttribute("input", "value", "Login");
469         loginButton.click();
470     }
471 
472     /**
473      * @throws Exception if the test fails
474      */
475     @Test
476     public void reset_onResetHandler() throws Exception {
477         final String html = DOCTYPE_HTML
478             + "<html><head><title>First</title></head><body>\n"
479             + "<form method='get' action='" + URL_SECOND + "' "
480             + "onReset='alert(\"clicked\");alert(event.type)'>\n"
481             + "<input name='button' type='reset' value='PushMe' id='button'/></form>\n"
482             + "</body></html>";
483 
484         final List<String> collectedAlerts = new ArrayList<>();
485 
486         final HtmlPage firstPage = loadPage(html, collectedAlerts);
487         final HtmlResetInput button = (HtmlResetInput) firstPage.getHtmlElementById("button");
488 
489         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
490         final HtmlPage secondPage = button.click();
491         assertSame(firstPage, secondPage);
492 
493         final String[] expectedAlerts = {"clicked", "reset"};
494         assertEquals(expectedAlerts, collectedAlerts);
495     }
496 
497     /**
498      * <p>Simulate a bug report where an anchor contained JavaScript that caused a form submit.
499      * According to the bug report, the form would be submitted even though the onsubmit
500      * handler would return false. This wasn't reproducible but I added a test for it anyway.</p>
501      *
502      * <p>UPDATE: If the form submit is triggered by JavaScript then the onsubmit handler is not
503      * supposed to be called so it doesn't matter what value it returns.</p>
504      * @throws Exception if the test fails
505      */
506     @Test
507     public void submit_AnchorCausesSubmit_onSubmitHandler_returnFalse() throws Exception {
508         final String firstHtml = DOCTYPE_HTML
509             + "<html><head><title>First</title></head>\n"
510             + "<script>function doalert(message){alert(message);}</script>\n"
511             + "<body><form name='form1' method='get' action='" + URL_SECOND + "' "
512             + "onSubmit='doalert(\"clicked\");return false;'>\n"
513             + "<input name='button' type='submit' value='PushMe' id='button'/></form>\n"
514             + "<a id='link1' href='javascript:document.form1.submit()'>Click me</a>\n"
515             + "</body></html>";
516         final String secondHtml = DOCTYPE_HTML + "<html><head><title>Second</title></head><body></body></html>";
517 
518         final WebClient client = getWebClientWithMockWebConnection();
519         final List<String> collectedAlerts = new ArrayList<>();
520         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
521 
522         final MockWebConnection webConnection = getMockWebConnection();
523         webConnection.setResponse(URL_FIRST, firstHtml);
524         webConnection.setDefaultResponse(secondHtml);
525 
526         final HtmlPage firstPage = client.getPage(URL_FIRST);
527         final HtmlAnchor anchor = firstPage.getHtmlElementById("link1");
528 
529         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
530         final HtmlPage secondPage = anchor.click();
531         assertEquals("Second", secondPage.getTitleText());
532 
533         assertEquals(Collections.EMPTY_LIST, collectedAlerts);
534     }
535 
536     /**
537      * @throws Exception if the test fails
538      */
539     @Test
540     public void submit_CheckboxClicked() throws Exception {
541         final String html = DOCTYPE_HTML
542             + "<html><head><title>foo</title>\n"
543             + "<script language='javascript'>\n"
544             + "function setFormat() {\n"
545             + "  if (document.form1.Format.checked) {\n"
546             + "    document.form1.Format.value = 'html';\n"
547             + "  } else {\n"
548             + "    document.form1.Format.value = 'plain';\n"
549             + "  }\n"
550             + "}\n"
551             + "</script>\n"
552             + "</head><body>\n"
553             + "<form name='form1' id='form1' method='post'>\n"
554             + "  <input type=checkbox name=Format value='' onclick='setFormat()'>\n"
555             + "  <input type='submit' name='button' value='foo'/>\n"
556             + "</form></body></html>";
557 
558         final HtmlPage page1 = loadPage(html);
559         final MockWebConnection webConnection1 = getMockConnection(page1);
560         final HtmlForm form1 = page1.getHtmlElementById("form1");
561         final HtmlSubmitInput button1 = form1.getInputByName("button");
562 
563         final HtmlPage page2 = button1.click();
564         final List<NameValuePair> collectedParameters1 = webConnection1.getLastParameters();
565         final List<NameValuePair> expectedParameters1 =
566             Arrays.asList(new NameValuePair[] {new NameValuePair("button", "foo")});
567 
568         final MockWebConnection webConnection2 = getMockConnection(page2);
569         final HtmlForm form2 = page2.getHtmlElementById("form1");
570         final HtmlCheckBoxInput checkBox2 = form2.getInputByName("Format");
571         final HtmlSubmitInput button2 = form2.getInputByName("button");
572 
573         checkBox2.click();
574         button2.click();
575         final List<NameValuePair> collectedParameters2 = webConnection2.getLastParameters();
576         final List<NameValuePair> expectedParameters2 = Arrays.asList(new NameValuePair[] {
577             new NameValuePair("Format", "html"),
578             new NameValuePair("button", "foo")
579         });
580 
581         assertEquals(expectedParameters1, collectedParameters1);
582         assertEquals(expectedParameters2, collectedParameters2);
583     }
584 
585     /**
586      * @throws Exception if the test fails
587      */
588     @Test
589     public void getInputByValue() throws Exception {
590         final String html = DOCTYPE_HTML
591             + "<html><head><title>foo</title></head><body>\n"
592             + "<form id='form1'>\n"
593             + "  <input type='submit' name='button' value='xxx'/>\n"
594             + "  <input type='text' name='textfield' value='foo'/>\n"
595             + "  <input type='submit' name='button1' value='foo'/>\n"
596             + "  <input type='reset' name='button2' value='foo'/>\n"
597             + "  <input type='submit' name='button' value='bar'/>\n"
598             + "</form></body></html>";
599         final HtmlPage page = loadPage(html);
600 
601         final HtmlForm form = page.getHtmlElementById("form1");
602 
603         final List<String> actualInputs = new ArrayList<>();
604         for (final HtmlInput input : form.getInputsByValue("foo")) {
605             actualInputs.add(input.getNameAttribute());
606         }
607 
608         final String[] expectedInputs = {"textfield", "button1", "button2"};
609         assertEquals("Get all", expectedInputs, actualInputs);
610         assertEquals(Collections.EMPTY_LIST, form.getInputsByValue("none-matching"));
611 
612         assertEquals("Get first", "button", form.getInputByValue("bar").getNameAttribute());
613         try {
614             form.getInputByValue("none-matching");
615             Assertions.fail("Expected ElementNotFoundException");
616         }
617         catch (final ElementNotFoundException e) {
618             // Expected path.
619         }
620     }
621 
622 
623     /**
624      * @throws Exception if the test fails
625      */
626     @Test
627     public void getInputByValueValueChanged() throws Exception {
628         final String html = DOCTYPE_HTML
629             + "<html><head><title>foo</title></head><body>\n"
630             + "<form id='form1'>\n"
631             + "  <input type='submit' name='button' value='xxx'/>\n"
632             + "  <input type='text' name='textfield' value='foo'/>\n"
633             + "  <input type='submit' name='button1' value='foo'/>\n"
634             + "  <input type='reset' name='button2' value='foo'/>\n"
635             + "  <input type='button' name='button3' value='foo'/>\n"
636             + "  <input type='image' name='img' value='foo'/>\n"
637             + "  <input type='submit' name='button' value='bar'/>\n"
638             + "</form></body></html>";
639         final HtmlPage page = loadPage(html);
640 
641         final HtmlForm form = page.getHtmlElementById("form1");
642 
643         HtmlInput input = form.getInputByValue("xxx");
644         input.setValue("yyy");
645         HtmlElement elem = form.getInputByValue("yyy");
646         assertEquals(input, elem);
647 
648         input = form.getInputByValue("foo");
649         input.setValue("text");
650         elem = form.getInputByValue("text");
651         assertEquals(input, elem);
652 
653         input = form.getInputByValue("foo");
654         input.setValue("suBmit");
655         elem = form.getInputByValue("suBmit");
656         assertEquals(input, elem);
657 
658         input = form.getInputByValue("foo");
659         input.setValue("RESET");
660         elem = form.getInputByValue("RESET");
661         assertEquals(input, elem);
662 
663         input = form.getInputByValue("foo");
664         input.setValue("button");
665         elem = form.getInputByValue("button");
666         assertEquals(input, elem);
667 
668         input = form.getInputByValue("foo");
669         input.setValue("Image");
670         elem = form.getInputByValue("Image");
671         assertEquals(input, elem);
672 
673         input = form.getInputByValue("bar");
674         input.setValue("1234");
675         elem = form.getInputByValue("1234");
676         assertEquals(input, elem);
677     }
678 
679     /**
680      * Test that {@link HtmlForm#getTextAreaByName(String)} returns
681      * the first textarea with the given name.
682      *
683      * @throws Exception if the test page can't be loaded
684      */
685     @Test
686     public void getTextAreaByName() throws Exception {
687         final String html = DOCTYPE_HTML
688             + "<html><head><title>foo</title></head><body>\n"
689             + "<form id='form1'>\n"
690             + "  <textarea id='ta1_1' name='ta1'>hello</textarea>\n"
691             + "  <textarea id='ta1_2' name='ta1'>world</textarea>\n"
692             + "  <textarea id='ta2_1' name='ta2'>!</textarea>\n"
693             + "</form></body></html>";
694         final HtmlPage page = loadPage(html);
695 
696         final HtmlForm form = page.getHtmlElementById("form1");
697 
698         assertEquals("First textarea with name 'ta1'", page.getElementById("ta1_1"),
699             form.getTextAreaByName("ta1"));
700         assertEquals("First textarea with name 'ta2'", page.getElementById("ta2_1"),
701             form.getTextAreaByName("ta2"));
702 
703         try {
704             form.getTextAreaByName("ta3");
705             Assertions.fail("Expected ElementNotFoundException as there is no textarea with name 'ta3'");
706         }
707         catch (final ElementNotFoundException e) {
708             // pass: exception is expected
709         }
710     }
711 
712     /**
713      * Test that {@link HtmlForm#getButtonByName(String)} returns
714      * the first button with the given name.
715      *
716      * @throws Exception if the test page can't be loaded
717      */
718     @Test
719     public void getButtonByName() throws Exception {
720         final String html = DOCTYPE_HTML
721             + "<html><head><title>foo</title></head><body>\n"
722             + "<form id='form1'>\n"
723             + "  <button id='b1_1' name='b1' value='hello' type='button'/>\n"
724             + "  <button id='b1_2' name='b1' value='world' type='button'/>\n"
725             + "  <button id='b2_1' name='b2' value='!' type='button'/>\n"
726             + "</form></body></html>";
727         final HtmlPage page = loadPage(html);
728 
729         final HtmlForm form = page.getHtmlElementById("form1");
730 
731         assertEquals("First button with name 'b1'", page.getElementById("b1_1"),
732             form.getButtonByName("b1"));
733         assertEquals("First button with name 'b2'", page.getElementById("b2_1"),
734             form.getButtonByName("b2"));
735 
736         try {
737             form.getTextAreaByName("b3");
738             Assertions.fail("Expected ElementNotFoundException as there is no button with name 'b3'");
739         }
740         catch (final ElementNotFoundException e) {
741             // pass: exception is expected
742         }
743     }
744 
745     /**
746      * Tests that the result of the form will get loaded into the window specified by "target".
747      * @throws Exception if the test fails
748      */
749     @Test
750     public void submitToTargetWindow() throws Exception {
751         final String html = DOCTYPE_HTML
752             + "<html><head><title>first</title></head><body>\n"
753             + "<form id='form1' target='window2' action='" + URL_SECOND + "' method='post'>\n"
754             + "  <input type='submit' name='button' value='push me'/>\n"
755             + "</form></body></html>";
756         final WebClient client = getWebClientWithMockWebConnection();
757 
758         final MockWebConnection webConnection = getMockWebConnection();
759         webConnection.setResponse(URL_FIRST, html);
760         webConnection.setResponseAsGenericHtml(URL_SECOND, "second");
761 
762         final HtmlPage page = client.getPage(URL_FIRST);
763         final WebWindow firstWindow = client.getCurrentWindow();
764         assertEquals("first window name", "", firstWindow.getName());
765         assertSame(page, firstWindow.getEnclosedPage());
766 
767         final HtmlForm form = page.getHtmlElementById("form1");
768 
769         final HtmlSubmitInput button = form.getInputByName("button");
770         final HtmlPage secondPage = button.click();
771         assertEquals("window2", secondPage.getEnclosingWindow().getName());
772         assertSame(secondPage.getEnclosingWindow(), client.getCurrentWindow());
773     }
774 
775     /**
776      * @throws Exception if the test fails
777      */
778     @Test
779     public void submit_SelectHasNoOptions() throws Exception {
780         final String html = DOCTYPE_HTML
781             + "<html><body><form name='form' method='GET' action='action.html'>\n"
782             + "  <select name='select'>\n"
783             + "  </select>\n"
784             + "  <input type='submit' id='clickMe'>\n"
785             + "</form></body></html>";
786         final HtmlPage page = loadPage(html);
787         final MockWebConnection webConnection = getMockConnection(page);
788 
789         final HtmlPage secondPage = page.getHtmlElementById("clickMe").click();
790 
791         assertNotNull(secondPage);
792         assertEquals("parameters", Collections.EMPTY_LIST, webConnection.getLastParameters());
793     }
794 
795     /**
796      * @throws Exception if the test fails
797      */
798     @Test
799     public void submit_SelectOptionWithoutValueAttribute() throws Exception {
800         final String html = DOCTYPE_HTML
801             + "<html><body><form name='form' action='action.html'>\n"
802             + "<select name='select'>\n"
803             + "  <option>first value</option>\n"
804             + "  <option selected>second value</option>\n"
805             + "</select>\n"
806             + "<input type='submit' id='mySubmit'>\n"
807             + "</form></body></html>";
808         final HtmlPage page = loadPage(html);
809         final HtmlPage secondPage = page.getHtmlElementById("mySubmit").click();
810 
811         assertNotNull(secondPage);
812         assertEquals(page.getUrl() + "action.html?select=second+value", secondPage.getUrl());
813     }
814 
815     /**
816      * At one point this test was failing because deeply nested inputs weren't getting picked up.
817      * @throws Exception if the test fails
818      */
819     @Test
820     public void submit_DeepInputs() throws Exception {
821         final String html = DOCTYPE_HTML
822             + "<html><form method='post' action=''>\n"
823             + "<table><tr><td>\n"
824             + "<input value='NOT_SUBMITTED' name='data' type='text'/>\n"
825             + "</td></tr></table>\n"
826             + "<input id='submitButton' name='submit' type='submit'/>\n"
827             + "</form></html>";
828         final HtmlPage page = loadPage(html);
829         final MockWebConnection webConnection = getMockConnection(page);
830 
831         final HtmlInput submitButton = page.getHtmlElementById("submitButton");
832         submitButton.click();
833 
834         final List<NameValuePair> collectedParameters = webConnection.getLastParameters();
835         final List<NameValuePair> expectedParameters = Arrays.asList(new NameValuePair[] {
836             new NameValuePair("data", "NOT_SUBMITTED"),
837             new NameValuePair("submit", "Submit Query")
838         });
839         assertEquals(expectedParameters, collectedParameters);
840     }
841 
842     /**
843      * Test order of submitted parameters matches order of elements in form.
844      * @throws Exception if the test fails
845      */
846     @Test
847     public void submit_FormElementOrder() throws Exception {
848         final String html = DOCTYPE_HTML
849             + "<html><head></head><body><form method='post' action=''>\n"
850             + "<input type='submit' name='dispatch' value='Save' id='submitButton'>\n"
851             + "<input type='hidden' name='dispatch' value='TAB'>\n"
852             + "</form></body></html>";
853         final WebClient client = getWebClientWithMockWebConnection();
854 
855         final MockWebConnection webConnection = getMockWebConnection();
856         webConnection.setDefaultResponse(html);
857 
858         final WebRequest request = new WebRequest(URL_FIRST, HttpMethod.POST);
859 
860         final HtmlPage page = client.getPage(request);
861         final HtmlInput submitButton = page.getHtmlElementById("submitButton");
862         submitButton.click();
863 
864         final List<NameValuePair> collectedParameters = webConnection.getLastParameters();
865         final List<NameValuePair> expectedParameters = Arrays.asList(new NameValuePair[] {
866             new NameValuePair("dispatch", "Save"),
867             new NameValuePair("dispatch", "TAB"),
868         });
869         assertEquals(expectedParameters, collectedParameters);
870     }
871 
872     /**
873      * @throws Exception if the test fails
874      */
875     @Test
876     public void urlAfterSubmit()
877         throws Exception {
878         urlAfterSubmit("get", "foo", "foo?textField=foo&nonAscii=Flo%DFfahrt&button=foo");
879         // for a get submit, query parameters in action are lost in browsers
880         urlAfterSubmit("get", "foo?foo=12", "foo?textField=foo&nonAscii=Flo%DFfahrt&button=foo");
881         urlAfterSubmit("post", "foo", "foo");
882         urlAfterSubmit("post", "foo?foo=12", "foo?foo=12");
883         urlAfterSubmit("post", "", "");
884         urlAfterSubmit("post", "?a=1&b=2", "?a=1&b=2");
885         final URL url = new URL(URL_FIRST + "?a=1&b=2");
886         urlAfterSubmit(url, "post", "", url.toExternalForm());
887     }
888 
889     /**
890      * @throws Exception if the test fails
891      */
892     @Test
893     @Alerts({"foo?textField=foo&nonAscii=Flo%DFfahrt&button=foo#anchor",
894              "foo?textField=foo&nonAscii=Flo%DFfahrt&button=foo#anchor",
895              "foo#anchor",
896              "foo?foo=12#anchor"})
897     public void urlAfterSubmitWithAnchor() throws Exception {
898         urlAfterSubmit("get", "foo#anchor", getExpectedAlerts()[0]);
899         urlAfterSubmit("get", "foo?foo=12#anchor", getExpectedAlerts()[1]);
900         urlAfterSubmit("post", "foo#anchor", getExpectedAlerts()[2]);
901         urlAfterSubmit("post", "foo?foo=12#anchor", getExpectedAlerts()[3]);
902     }
903 
904     /**
905      * Utility for {@link #testUrlAfterSubmit()}
906      * @param method the form method to use
907      * @param action the form action to use
908      * @param expectedUrl the expected URL
909      * @throws Exception if the test fails
910      */
911     private void urlAfterSubmit(final URL url, final String method, final String action,
912             final String expectedUrl) throws Exception {
913         final String html = DOCTYPE_HTML
914             + "<html><head><title>foo</title></head><body>\n"
915             + "<form id='form1' method='" + method + "' action='" + action + "'>\n"
916             + "<input type='text' name='textField' value='foo'/>\n"
917             + "<input type='text' name='nonAscii' value='Flo\u00DFfahrt'/>\n"
918             + "<input id='submitButton' type='submit' name='button' value='foo'/>\n"
919             + "<input type='button' name='inputButton' value='foo'/>\n"
920             + "<button type='button' name='buttonButton' value='foo'/>\n"
921             + "</form></body></html>";
922         final HtmlPage page = loadPage(getBrowserVersion(), html, null, url);
923         final Page page2 = page.getHtmlElementById("submitButton").click();
924 
925         assertEquals(expectedUrl, page2.getUrl());
926     }
927 
928     /**
929      * Utility for {@link #testUrlAfterSubmit()}. Calls {@link #urlAfterSubmit(URL, String, String, String)} with
930      * the default url.
931      * @param method the form method to use
932      * @param action the form action to use
933      * @param expectedUrlEnd the expected URL
934      * @throws Exception if the test fails
935      */
936     private void urlAfterSubmit(final String method, final String action, final String expectedUrlEnd)
937         throws Exception {
938         urlAfterSubmit(URL_FIRST, method, action, URL_FIRST + expectedUrlEnd);
939     }
940 
941     /**
942      * @throws Exception if the test fails
943      */
944     @Test
945     public void submitRequestCharset() throws Exception {
946         pageCharset("utf-8", null, null, "UTF-8");
947         pageCharset(null, "utf-8", null, "UTF-8");
948         pageCharset("iso-8859-1", null, "utf-8", "windows-1252");
949         pageCharset("iso-8859-1", null, "utf-8, iso-8859-1", "windows-1252");
950         pageCharset("utf-8", null, "iso-8859-1 utf-8", "UTF-8");
951         pageCharset("iso-8859-1", null, "utf-8, iso-8859-1", "windows-1252");
952     }
953 
954     /**
955      * Utility for {@link #submitRequestCharset()}
956      * @param headerCharset the charset for the content type header if not null
957      * @param metaCharset the charset for the meta http-equiv content type tag if not null
958      * @param formCharset the charset for the form's accept-charset attribute if not null
959      * @throws Exception if the test fails
960      */
961     private void pageCharset(final String headerCharset,
962             final String metaCharset, final String formCharset,
963             final String expectedRequestCharset) throws Exception {
964 
965         final String formAcceptCharset;
966         if (formCharset == null) {
967             formAcceptCharset = "";
968         }
969         else {
970             formAcceptCharset = " accept-charset='" + formCharset + "'";
971         }
972 
973         final String metaContentType;
974         if (metaCharset == null) {
975             metaContentType = "";
976         }
977         else {
978             metaContentType = "<meta http-equiv='Content-Type' content='text/html; charset="
979                 + metaCharset + "'>\n";
980         }
981 
982         final String html = DOCTYPE_HTML
983             + "<html><head><title>foo</title>\n"
984             + metaContentType
985             + "</head><body>\n"
986             + "<form name='form1' method='post' action='foo'"
987             + formAcceptCharset + ">\n"
988             + "<input type='text' name='textField' value='foo'/>\n"
989             + "<input type='text' name='nonAscii' value='Flo\u00DFfahrt'/>\n"
990             + "<input type='submit' name='button' value='foo'/>\n"
991             + "</form></body></html>";
992         final WebClient client = getWebClientWithMockWebConnection();
993         final MockWebConnection webConnection = getMockWebConnection();
994 
995         String contentType = MimeType.TEXT_HTML;
996         if (headerCharset != null) {
997             contentType += ";charset=" + headerCharset;
998         }
999         webConnection.setDefaultResponse(html, 200, "ok", contentType);
1000         final HtmlPage page = client.getPage(URL_FIRST);
1001 
1002         assertEquals(expectedRequestCharset, page.getCharset().name());
1003     }
1004 
1005     /**
1006      * @throws Exception if the test fails
1007      */
1008     @Test
1009     public void sumbit_submitInputValue() throws Exception {
1010         final String html = DOCTYPE_HTML
1011             + "<html><head>\n"
1012             + "</head>\n"
1013             + "<body>\n"
1014             + "<form action='" + URL_SECOND + "'>\n"
1015             + "  <input id='myButton' type='submit' name='Save'>\n"
1016             + "</form>\n"
1017             + "</body></html>";
1018 
1019         final HtmlPage firstPage = loadPage(html);
1020         final HtmlSubmitInput submitInput = firstPage.getHtmlElementById("myButton");
1021         final HtmlPage secondPage = submitInput.click();
1022         assertEquals(URL_SECOND + "?Save=Submit+Query", secondPage.getUrl());
1023     }
1024 
1025     /**
1026      * Regression test for bug #536.
1027      * @throws Exception if the test fails
1028      */
1029     @Test
1030     public void submitWithOnClickThatReturnsFalse() throws Exception {
1031         final String firstHtml = DOCTYPE_HTML
1032             + "<html><head><title>foo</title></head><body>\n"
1033             + "<form action='" + URL_SECOND + "' method='post'>\n"
1034             + "  <input type='submit' name='mySubmit' onClick='document.forms[0].submit(); return false;'>\n"
1035             + "</form></body></html>";
1036 
1037         final String secondHtml = DOCTYPE_HTML
1038             + "<html><head><title>foo</title><script>\n"
1039             + "  Number.prototype.gn = false;\n"
1040             + "  function test() {\n"
1041             + "    var v = 0;\n"
1042             + "    alert(typeof v);\n"
1043             + "    alert(v.gn);\n"
1044             + "  }\n"
1045             + "</script></head><body onload='test()'>\n"
1046             + "</body></html>";
1047 
1048         final String[] expectedAlerts = {"number", "false"};
1049         final List<String> collectedAlerts = new ArrayList<>();
1050         final WebClient client = getWebClientWithMockWebConnection();
1051         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
1052 
1053         final MockWebConnection conn = getMockWebConnection();
1054         conn.setResponse(URL_FIRST, firstHtml);
1055         conn.setResponse(URL_SECOND, secondHtml);
1056 
1057         final HtmlPage page = client.getPage(URL_FIRST);
1058         final HtmlForm form = page.getForms().get(0);
1059         final HtmlSubmitInput submit = form.getInputByName("mySubmit");
1060         submit.click();
1061         assertEquals(expectedAlerts, collectedAlerts);
1062     }
1063 
1064     /**
1065      * Tests that submitting a form without parameters does not trail the URL with a question mark (IE only).
1066      *
1067      * @throws Exception if the test fails
1068      */
1069     @Test
1070     public void submitURLWithoutParameters() throws Exception {
1071         final String firstHtml = DOCTYPE_HTML
1072             + "<html><head><title>foo</title></head><body>\n"
1073             + "<form action='" + URL_SECOND + "'>\n"
1074             + "  <input type='submit' name='mySubmit' onClick='document.forms[0].submit(); return false;'>\n"
1075             + "</form></body></html>";
1076 
1077         final String secondHtml = DOCTYPE_HTML + "<html><head><title>second</title></head></html>";
1078 
1079         final List<String> collectedAlerts = new ArrayList<>();
1080         final WebClient client = getWebClientWithMockWebConnection();
1081         client.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
1082 
1083         final MockWebConnection conn = getMockWebConnection();
1084         conn.setResponse(URL_FIRST, firstHtml);
1085         conn.setDefaultResponse(secondHtml);
1086 
1087         final HtmlPage page = client.getPage(URL_FIRST);
1088         final HtmlForm form = page.getForms().get(0);
1089         final HtmlSubmitInput submit = form.getInputByName("mySubmit");
1090         final HtmlPage secondPage = submit.click();
1091 
1092         final String expectedURL = URL_SECOND.toString();
1093         assertEquals(expectedURL, secondPage.getUrl());
1094     }
1095 
1096     /**
1097      * @throws Exception if the test page can't be loaded
1098      */
1099     @Test
1100     public void malformedHtml_fieldGetters() throws Exception {
1101         final String html = DOCTYPE_HTML
1102             + "<html><head><title>foo</title></head><body>\n"
1103             + "<div>\n"
1104             + "<form id='form1' method='get' action='foo'>\n"
1105             + "  <input name='field1' value='val1'/>\n"
1106             + "  <input name='field2' value='val2'/>\n"
1107             + "  <input type='radio' name='radio1' value='val2'/>\n"
1108             + "  <input type='submit' id='submitButton'/>\n"
1109             + "</div>\n"
1110             + "  <input name='field3' value='val1'/>\n"
1111             + "  <input name='field4' value='val2'/>\n"
1112             + "  <input type='radio' name='radio1' value='val3'/>\n"
1113             + "  <input type='submit' id='submitButton'/>\n"
1114             + "</form></body></html>";
1115 
1116         final HtmlPage page = loadPage(html);
1117         final HtmlForm form = page.getForms().get(0);
1118 
1119         assertEquals("val1", form.getInputByName("field3").getValueAttribute());
1120         assertEquals("val1", form.getInputByName("field3").getValue());
1121         assertEquals(2, form.getInputsByName("radio1").size());
1122 
1123         assertEquals(3, form.getInputsByValue("val2").size());
1124         assertEquals("radio1", form.getInputByValue("val3").getNameAttribute());
1125 
1126         assertEquals(2, form.getRadioButtonsByName("radio1").size());
1127     }
1128 
1129     /**
1130      * Regression test for bug #784 (form lost children breakage when there is more than one
1131      * form element with the same name).
1132      * @throws Exception if an error occurs
1133      */
1134     @Test
1135     public void malformedHtml_formAndTables() throws Exception {
1136         final String html = DOCTYPE_HTML
1137             + "<html><body>\n"
1138             + "\n"
1139             + "<table id='table1'>\n"
1140             + "<tr>\n"
1141             + "<td>this is table1</td>\n"
1142             + "\n"
1143             + "<form name='cb_form' method='post' onSubmit='return formsubmit(\"submit\");'>\n"
1144             + "<input type='hidden' name='ls' value='0'>\n"
1145             + "<input type='hidden' name='seller' value='OTTO'>\n"
1146             + "<input type='hidden' name='getLA' value='true'>\n"
1147             + "<input type='hidden' name='li_count' value='10'>\n"
1148             + "<input type='hidden' name='EmailTo' value=''>\n"
1149             + "\n"
1150             + "</tr>\n"
1151             + "</table>\n"
1152             + "\n"
1153             + "<table id='table2'>\n"
1154             + "\n"
1155             + "<tr>\n"
1156             + "<td><input type='text' value='' name='OrderNr'></td>\n"
1157             + "<td><input type='text' value='' name='Size'></td>\n"
1158             + "<td><input type='text' value='' name='Quantity'></td>\n"
1159             + "</tr>\n"
1160             + "\n"
1161             + "<tr>\n"
1162             + "<td><input type='text' value='' name='OrderNr'></td>\n"
1163             + "<td><input type='text' value='' name='Size'></td>\n"
1164             + "<td><input type='text' value='' name='Quantity'></td>\n"
1165             + "</tr>\n"
1166             + "\n"
1167             + "<tr>\n"
1168             + "<td><input type='text' value='' name='OrderNr'></td>\n"
1169             + "<td><input type='text' value='' name='Size'></td>\n"
1170             + "<td><input type='text' value='' name='Quantity'></td>\n"
1171             + "</tr>\n"
1172             + "\n"
1173             + "</form>\n"
1174             + "</table>\n"
1175             + "\n"
1176             + "<script>\n"
1177             + "var i = 0;\n"
1178             + "while (document.cb_form.Quantity[i]) {\n"
1179             + "  document.cb_form.Quantity[i].value = document.cb_form.Quantity[i].value.replace(/[^0-9]/g, '');\n"
1180             + "  if ((document.cb_form.Quantity[i].value.length == 0)) {\n"
1181             + "    document.cb_form.Quantity[i].value = '1';\n"
1182             + "  }\n"
1183             + "  i++;\n"
1184             + "}\n"
1185             + "</script>\n"
1186             + "\n"
1187             + "</body></html>";
1188         final HtmlPage page = loadPage(html);
1189         final List<DomElement> quantities = page.getElementsByName("Quantity");
1190         assertEquals(3, quantities.size());
1191         for (final DomElement quantity : quantities) {
1192             assertEquals("1", ((HtmlInput) quantity).getValue());
1193         }
1194     }
1195 
1196     /**
1197      * @throws Exception if the test fails
1198      */
1199     @Test
1200     public void urlAfterSubmit2() throws Exception {
1201         final URL url = new URL(URL_FIRST, "test.html");
1202         urlAfterSubmit(url, "post", "?hi", url + "?hi");
1203         urlAfterSubmit(new URL(URL_FIRST, "test.html?there"), "post", "?hi",
1204                 URL_FIRST + "test.html?hi");
1205     }
1206 
1207     /**
1208      * @throws Exception if the test fails
1209      */
1210     @Test
1211     public void asXml_emptyTag() throws Exception {
1212         final String html = DOCTYPE_HTML
1213             + "<html><body>\n"
1214             + "<form></form>\n"
1215             + "<div>test</div>\n"
1216             + "</body></html>";
1217 
1218         final String xml =
1219             "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\r\n"
1220             + "<html>\r\n"
1221             + "  <head/>\r\n"
1222             + "  <body>\r\n"
1223             + "    <form></form>\r\n"
1224             + "    <div>test</div>\r\n"
1225             + "  </body>\r\n"
1226             + "</html>";
1227 
1228         final HtmlPage page = loadPage(html);
1229         assertEquals(xml, page.asXml());
1230     }
1231 
1232     /**
1233      * @throws Exception if the test fails
1234      */
1235     @Test
1236     @Alerts("second/?hiddenName=hiddenValue")
1237     public void inputHiddenAdded() throws Exception {
1238         final String html = DOCTYPE_HTML
1239             + "<html><head></head>\n"
1240             + "<body>\n"
1241             + "  <p>hello world</p>\n"
1242             + "  <form id='myForm' method='GET' action='" + URL_SECOND + "'>\n"
1243             + "    <input id='myButton' type='submit' />\n"
1244             + "  </form>\n"
1245             + "</body></html>";
1246 
1247         final String secondContent = "second content";
1248         getMockWebConnection().setResponse(URL_SECOND, secondContent);
1249 
1250         final HtmlPage page = loadPage(html);
1251         final HtmlForm form = (HtmlForm) page.getElementById("myForm");
1252 
1253         final DomElement input = page.createElement("input");
1254         input.setAttribute("type", "hidden");
1255         input.setAttribute("id", "hiddenId");
1256         input.setAttribute("name", "hiddenName");
1257         input.setAttribute("value", "hiddenValue");
1258 
1259         form.appendChild(input);
1260 
1261         page.getElementById("myButton").click();
1262 
1263         final String url = getMockWebConnection().getLastWebRequest().getUrl().toExternalForm();
1264         assertTrue(url.endsWith(getExpectedAlerts()[0]));
1265     }
1266 }