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 java.util.ArrayList;
18  import java.util.List;
19  
20  import org.htmlunit.Page;
21  import org.htmlunit.SimpleWebTestCase;
22  import org.htmlunit.html.HtmlAnchor;
23  import org.htmlunit.html.HtmlButton;
24  import org.htmlunit.html.HtmlFileInput;
25  import org.htmlunit.html.HtmlPage;
26  import org.htmlunit.html.HtmlSubmitInput;
27  import org.htmlunit.junit.BrowserRunner;
28  import org.htmlunit.junit.annotation.Alerts;
29  import org.junit.Test;
30  import org.junit.runner.RunWith;
31  
32  /**
33   * Tests for {@link HTMLFormElement}.
34   *
35   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
36   * @author David K. Taylor
37   * @author Marc Guillemot
38   * @author Chris Erskine
39   * @author Ahmed Ashour
40   * @author Frank Danek
41   */
42  @RunWith(BrowserRunner.class)
43  public class HTMLFormElement2Test extends SimpleWebTestCase {
44  
45      /**
46       * @throws Exception if the test fails
47       */
48      @Test
49      public void formSubmit() throws Exception {
50          final String html = DOCTYPE_HTML
51              + "<html><head><title>first</title></head><body>\n"
52              + "<p>hello world</p>\n"
53              + "<form name='form1' method='get' action='" + URL_SECOND + "'>\n"
54              + "  <input type='button' name='button1' />\n"
55              + "  <input type='button' name='button2' />\n"
56              + "</form>\n"
57              + "</body></html>";
58          final String secondContent = DOCTYPE_HTML
59              + "<html><head><title>second</title></head><body>\n"
60              + "<p>hello world</p>\n"
61              + "</body></html>";
62  
63          getMockWebConnection().setDefaultResponse(secondContent);
64          final HtmlPage page = loadPageWithAlerts(html);
65  
66          page.executeJavaScript("document.form1.submit()");
67          final HtmlPage secondPage = (HtmlPage) getWebClient().getCurrentWindow().getEnclosedPage();
68          assertEquals("second", secondPage.getTitleText());
69      }
70  
71      /**
72       * @throws Exception if the test fails
73       */
74      @Test
75      @Alerts("javaScript")
76      public void formSubmitWithJavascript() throws Exception {
77          final String html = DOCTYPE_HTML
78              + "<html><head><title>first</title></head><body>\n"
79              + "<p>hello world</p>\n"
80              + "<form name='form1' method='get' action='javascript:alert(\"javaScript\")'>\n"
81              + "  <input type='button' name='button1' />\n"
82              + "  <input type='button' name='button2' />\n"
83              + "</form>\n"
84              + "</body></html>";
85  
86          final List<String> collectedAlerts = new ArrayList<>();
87  
88          final HtmlPage page1 = loadPage(html, collectedAlerts);
89          page1.executeJavaScript("document.form1.submit()");
90          final HtmlPage page2 = (HtmlPage) getWebClient().getCurrentWindow().getEnclosedPage();
91  
92          assertEquals(page1, page2);
93          assertEquals(getExpectedAlerts(), collectedAlerts);
94      }
95  
96      /**
97       * @throws Exception if the test fails
98       */
99      @Test
100     @Alerts("javaScript")
101     public void formSubmitWithJavascriptLeadingWhitespace() throws Exception {
102         final String html = DOCTYPE_HTML
103             + "<html><head><title>first</title></head><body>\n"
104             + "<p>hello world</p>\n"
105             + "<form name='form1' method='get' action='  javascript:alert(\"javaScript\")'>\n"
106             + "  <input type='button' name='button1' />\n"
107             + "  <input type='button' name='button2' />\n"
108             + "</form>\n"
109             + "</body></html>";
110 
111         final List<String> collectedAlerts = new ArrayList<>();
112 
113         final HtmlPage page1 = loadPage(html, collectedAlerts);
114         page1.executeJavaScript("document.form1.submit()");
115         final HtmlPage page2 = (HtmlPage) getWebClient().getCurrentWindow().getEnclosedPage();
116 
117         assertEquals(page1, page2);
118         assertEquals(getExpectedAlerts(), collectedAlerts);
119     }
120 
121     /**
122      * @throws Exception if the test fails
123      */
124     @Test
125     @Alerts("javaScript")
126     public void formSubmitWithJavascriptMixedCase() throws Exception {
127         final String html = DOCTYPE_HTML
128             + "<html><head><title>first</title></head><body>\n"
129             + "<p>hello world</p>\n"
130             + "<form name='form1' method='get' action='javaSCript:alert(\"javaScript\")'>\n"
131             + "  <input type='button' name='button1' />\n"
132             + "  <input type='button' name='button2' />\n"
133             + "</form>\n"
134             + "</body></html>";
135 
136         final List<String> collectedAlerts = new ArrayList<>();
137 
138         final HtmlPage page1 = loadPage(html, collectedAlerts);
139         page1.executeJavaScript("document.form1.submit()");
140         final HtmlPage page2 = (HtmlPage) getWebClient().getCurrentWindow().getEnclosedPage();
141 
142         assertEquals(page1, page2);
143         assertEquals(getExpectedAlerts(), collectedAlerts);
144     }
145 
146     /**
147      * @throws Exception if the test fails
148      */
149     @Test
150     public void onSubmitChangesAction() throws Exception {
151         final String html = DOCTYPE_HTML
152             + "<html><body>\n"
153             + "<form name='form1' action='" + URL_SECOND + "' onsubmit='this.action=\"" + URL_THIRD + "\"' "
154             + "method='post'>\n"
155             + "    <input type='submit' id='button1' />\n"
156             + "</form>\n"
157             + "</body></html>";
158 
159         getMockWebConnection().setDefaultResponse("<html></html>");
160 
161         final HtmlPage page = loadPageWithAlerts(html);
162         final Page page2 = page.getHtmlElementById("button1").click();
163 
164         assertEquals(URL_THIRD.toExternalForm(), page2.getUrl());
165     }
166 
167     /**
168      * @throws Exception if the test fails
169      */
170     @Test
171     public void formSubmit_target() throws Exception {
172         final String html = DOCTYPE_HTML
173             + "<html><head><title>first</title></head><body>\n"
174             + "<p>hello world</p>\n"
175             + "<form name='form1' method='get' action='" + URL_SECOND + "' target='MyNewWindow'>\n"
176             + "  <input type='button' name='button1' />\n"
177             + "</form>\n"
178             + "</body></html>";
179         final String secondContent = DOCTYPE_HTML
180             + "<html><head><title>second</title></head><body>\n"
181             + "<p>hello world</p>\n"
182             + "</body></html>";
183 
184         getMockWebConnection().setDefaultResponse(secondContent);
185 
186         final HtmlPage page = loadPageWithAlerts(html);
187 
188         page.executeJavaScript("document.form1.submit()");
189         final HtmlPage secondPage = (HtmlPage) getWebClient().getCurrentWindow().getEnclosedPage();
190 
191         assertEquals("second", secondPage.getTitleText());
192         assertEquals("MyNewWindow", secondPage.getEnclosingWindow().getName());
193     }
194 
195     /**
196      * @throws Exception if the test fails
197      */
198     @Test
199     public void formSubmitDoesntCallOnSubmit() throws Exception {
200         final String html = DOCTYPE_HTML
201             + "<html><head><title>first</title></head><body>\n"
202             + "<form name='form1' method='get' action='" + URL_SECOND + "' onsubmit=\"this.action = 'foo.html'\">\n"
203             + "  <input type='submit' />\n"
204             + "</form>\n"
205             + "<a href='javascript:document.form1.submit()' id='link1'>Click me</a>\n"
206             + "</body></html>";
207         final String secondContent = DOCTYPE_HTML
208             + "<html><head><title>second</title></head><body>\n"
209             + "<p>hello world</p>\n"
210             + "</body></html>";
211 
212         getMockWebConnection().setDefaultResponse(secondContent);
213 
214         final HtmlPage page = loadPageWithAlerts(html);
215         final HtmlAnchor link = page.getHtmlElementById("link1");
216         final HtmlPage page2 = link.click();
217         assertEquals("second", page2.getTitleText());
218     }
219 
220     /**
221      * @throws Exception if the test fails
222      */
223     @Test
224     public void formSubmit_MultipleButtons() throws Exception {
225         final String html = DOCTYPE_HTML
226             + "<html><head><title>first</title></head><body>\n"
227             + "<p>hello world</p>\n"
228             + "<form name='form1' method='get' action='" + URL_SECOND + "'>\n"
229             + "  <button type='submit' name='button1' id='button1'/>\n"
230             + "  <button type='submit' name='button2' />\n"
231             + "</form>\n"
232             + "</body></html>";
233         final String secondContent = DOCTYPE_HTML
234             + "<html><head><title>second</title></head><body>\n"
235             + "<p>hello world</p>\n"
236             + "</body></html>";
237 
238         getMockWebConnection().setDefaultResponse(secondContent);
239 
240         final HtmlPage page = loadPageWithAlerts(html);
241         assertEquals("first", page.getTitleText());
242 
243         final HtmlButton button = page.getHtmlElementById("button1");
244         final HtmlPage secondPage = button.click();
245         assertEquals("second", secondPage.getTitleText());
246         assertEquals(URL_SECOND + "?button1=", secondPage.getUrl());
247     }
248 
249     /**
250      * @throws Exception if the test fails
251      */
252     @Test
253     @Alerts("hi!")
254     public void lostFunction() throws Exception {
255         final String content = DOCTYPE_HTML
256             + "<html><head><title>foo</title><script>\n"
257             + " function onSubmit() { alert('hi!'); return false; }\n"
258             + "</script></head><body>\n"
259             + "<form onsubmit='return onSubmit();'>\n"
260             + "  <input type='submit' id='clickMe' />\n"
261             + "</form>\n"
262             + "</body></html>";
263 
264         final List<String> collectedAlerts = new ArrayList<>();
265         final HtmlPage page = loadPage(content, collectedAlerts);
266         final HtmlSubmitInput button = page.getHtmlElementById("clickMe");
267         button.click();
268         assertEquals(getExpectedAlerts(), collectedAlerts);
269     }
270 
271     /**
272      * @throws Exception if the test fails
273      */
274     @Test
275     @Alerts("hi!")
276     public void assignedOnsubmit() throws Exception {
277         final String content = DOCTYPE_HTML
278             + "<html><head><title>foo</title><script>\n"
279             + "  function onSubmit() { alert('hi!'); return false; }\n"
280             + "  function init() { document.myForm.onsubmit = onSubmit; }\n"
281             + "  window.onload = init;\n"
282             + "</script></head><body>\n"
283             + "<form name='myForm'>\n"
284             + "  <input type='submit' id='clickMe' />\n"
285             + "</form>\n"
286             + "</body></html>";
287 
288         final List<String> collectedAlerts = new ArrayList<>();
289         final HtmlPage page = loadPage(content, collectedAlerts);
290         final HtmlSubmitInput button = page.getHtmlElementById("clickMe");
291         button.click();
292         assertEquals(getExpectedAlerts(), collectedAlerts);
293     }
294 
295     /**
296      * In action "this" should be the window and not the form.
297      * @throws Exception if the test fails
298      */
299     @Test
300     @Alerts("true")
301     public void thisInJavascriptAction() throws Exception {
302         final String content = DOCTYPE_HTML
303             + "<html>\n"
304             + "<body>\n"
305             + "<form action='javascript:alert(this == window)'>\n"
306             + "<input type='submit' id='theButton'>\n"
307             + "</form>\n"
308             + "</body></html>";
309 
310         final List<String> collectedAlerts = new ArrayList<>();
311         final HtmlPage page1 = loadPage(content, collectedAlerts);
312         final Page page2 = page1.getHtmlElementById("theButton").click();
313 
314         assertEquals(getExpectedAlerts(), collectedAlerts);
315         assertSame(page1, page2);
316     }
317 
318     /**
319      * @throws Exception if the test fails
320      */
321     @Test
322     @Alerts("onchange")
323     public void fileInput_fireOnChange() throws Exception {
324         final String html = DOCTYPE_HTML
325             + "<html><body>\n"
326             + "<form>\n"
327             + "  <input type='file' name='myFile' id='myFile' onchange='alert(\"onchange\")'/>\n"
328             + "</form>\n"
329             + "</body></html>";
330 
331         final List<String> collectedAlerts = new ArrayList<>();
332         final HtmlPage page = loadPage(html, collectedAlerts);
333         final HtmlFileInput fileInput = page.getHtmlElementById("myFile");
334         fileInput.setValue("dummy.txt");
335         assertEquals(getExpectedAlerts(), collectedAlerts);
336     }
337 }