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