/* * Copyright (c) 2002-2008 Gargoyle Software Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gargoylesoftware.htmlunit.html; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.lang.StringUtils; import org.junit.Assert; import org.junit.Test; import com.gargoylesoftware.htmlunit.BrowserVersion; import com.gargoylesoftware.htmlunit.CollectingAlertHandler; import com.gargoylesoftware.htmlunit.ElementNotFoundException; import com.gargoylesoftware.htmlunit.HttpMethod; import com.gargoylesoftware.htmlunit.MockWebConnection; import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebRequestSettings; import com.gargoylesoftware.htmlunit.WebTestCase; import com.gargoylesoftware.htmlunit.WebWindow; /** * Tests for {@link HtmlForm}. * * @version $Revision$ * @author Mike Bowler * @author Jun Chen * @author George Murnock * @author Marc Guillemot * @author Ahmed Ashour * @author Philip Graf */ public class HtmlFormTest extends WebTestCase { /** * Tests the good case for setCheckedRatdioButton(). * @exception Exception If the test fails */ @Test public void testSetSelectedRadioButton_ValueExists() throws Exception { final String htmlContent = "foo\n" + "
\n" + "\n" + "\n" + "\n" + "\n" + "
"; final HtmlPage page = loadPage(htmlContent); final MockWebConnection webConnection = getMockConnection(page); final HtmlForm form = (HtmlForm) page.getHtmlElementById("form1"); final HtmlSubmitInput pushButton = (HtmlSubmitInput) form.getInputByName("button"); ((HtmlRadioButtonInput) form.getFirstByXPath( "//input[@type='radio' and @name='foo' and @value='2']")).setChecked(true); assertFalse(((HtmlRadioButtonInput) page.getHtmlElementById("input1")).isChecked()); assertTrue(((HtmlRadioButtonInput) page.getHtmlElementById("input2")).isChecked()); // Test that only one value for the radio button is being passed back to the server final HtmlPage secondPage = (HtmlPage) pushButton.click(); assertEquals("url", URL_GARGOYLE.toExternalForm() + "?foo=2&button=foo", secondPage.getWebResponse().getUrl()); Assert.assertSame("method", HttpMethod.GET, webConnection.getLastMethod()); } /** * Tests setCheckedRadioButton() with a value that doesn't exist. * @exception Exception If the test fails */ @Test public void testSetSelectedRadioButton_ValueDoesNotExist_DoNotForceSelection() throws Exception { final String htmlContent = "foo\n" + "
\n" + "\n" + "\n" + "\n" + "\n" + "
"; final HtmlPage page = loadPage(htmlContent); final HtmlForm form = (HtmlForm) page.getHtmlElementById("form1"); final HtmlInput pushButton = form.getInputByName("button"); assertNotNull(pushButton); assertNull(form.getFirstByXPath("//input[@type='radio' and @name='foo' and @value='4']")); } /** * @throws Exception if the test fails */ @Test public void testSubmit_String() throws Exception { final String htmlContent = "foo\n" + "
\n" + "\n" + "
"; final HtmlPage page = loadPage(htmlContent); final HtmlForm form = (HtmlForm) page.getHtmlElementById("form1"); // Regression test: this used to blow up form.submit((HtmlSubmitInput) page.getHtmlElementById("submitButton")); } /** * @throws Exception if the test fails */ @Test public void testSubmit_ExtraParameters() throws Exception { final String htmlContent = "foo\n" + "
\n" + " \n" + " \n" + "
"; final HtmlPage page = loadPage(htmlContent); final MockWebConnection webConnection = getMockConnection(page); final HtmlForm form = (HtmlForm) page.getHtmlElementById("form1"); final HtmlSubmitInput button = (HtmlSubmitInput) form.getInputByName("button"); button.click(); final List expectedParameters = Arrays.asList(new NameValuePair[]{ new NameValuePair("textfield", "*"), new NameValuePair("button", "foo") }); final List collectedParameters = webConnection.getLastParameters(); assertEquals(expectedParameters, collectedParameters); } /** * @throws Exception if the test fails */ @Test public void testSubmit_BadSubmitMethod() throws Exception { final String htmlContent = "foo\n" + "
\n" + " \n" + " \n" + "
"; final HtmlPage page = loadPage(htmlContent); final MockWebConnection webConnection = getMockConnection(page); ((ClickableElement) page.getHtmlElementById("button")).click(); assertSame(HttpMethod.GET, webConnection.getLastMethod()); } /** * @throws Exception if the test fails */ @Test public void testSubmit_onSubmitHandler() throws Exception { final String firstContent = "First\n" + "
\n" + "
\n" + ""; final String secondContent = "Second"; final WebClient client = new WebClient(); final List collectedAlerts = new ArrayList(); client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); final MockWebConnection webConnection = new MockWebConnection(client); webConnection.setResponse(URL_FIRST, firstContent); webConnection.setDefaultResponse(secondContent); client.setWebConnection(webConnection); final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST); final HtmlSubmitInput button = (HtmlSubmitInput) firstPage.getHtmlElementById("button"); assertEquals(Collections.EMPTY_LIST, collectedAlerts); final HtmlPage secondPage = (HtmlPage) button.click(); assertEquals("Second", secondPage.getTitleText()); assertEquals(new String[] {"clicked"}, collectedAlerts); } /** * @throws Exception if the test fails */ @Test public void testSubmit_onSubmitHandler_returnFalse() throws Exception { final String firstContent = "First\n" + "
\n" + "
\n" + ""; final String secondContent = "Second"; final WebClient client = new WebClient(); final List collectedAlerts = new ArrayList(); client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); final MockWebConnection webConnection = new MockWebConnection(client); webConnection.setResponse(URL_FIRST, firstContent); webConnection.setResponse(URL_SECOND, secondContent); client.setWebConnection(webConnection); final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST); final HtmlSubmitInput button = (HtmlSubmitInput) firstPage.getHtmlElementById("button"); assertEquals(Collections.EMPTY_LIST, collectedAlerts); final HtmlPage secondPage = (HtmlPage) button.click(); assertEquals(firstPage.getTitleText(), secondPage.getTitleText()); assertEquals(new String[] {"clicked"}, collectedAlerts); } /** * Regression test for bug 1628521 (NullPointerException when submitting forms). * @throws Exception if the test fails */ @Test public void testSubmit_onSubmitHandler_fails() throws Exception { final String firstContent = "First\n" + "
\n" + "
\n" + ""; final String secondContent = "Second"; final WebClient client = new WebClient(); final MockWebConnection webConnection = new MockWebConnection(client); webConnection.setResponse(URL_FIRST, firstContent); webConnection.setDefaultResponse(secondContent); client.setWebConnection(webConnection); final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST); final HtmlSubmitInput button = (HtmlSubmitInput) firstPage.getHtmlElementById("button"); final HtmlPage secondPage = (HtmlPage) button.click(); assertEquals("Second", secondPage.getTitleText()); } /** * @throws Exception if the test fails */ @Test public void testSubmit_onSubmitHandler_javascriptDisabled() throws Exception { final String firstContent = "First\n" + "
\n" + "
\n" + ""; final String secondContent = "Second"; final WebClient client = new WebClient(); client.setJavaScriptEnabled(false); final List collectedAlerts = new ArrayList(); client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); final MockWebConnection webConnection = new MockWebConnection(client); webConnection.setResponse(URL_FIRST, firstContent); webConnection.setDefaultResponse(secondContent); client.setWebConnection(webConnection); final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST); final HtmlSubmitInput button = (HtmlSubmitInput) firstPage.getHtmlElementById("button"); assertEquals(Collections.EMPTY_LIST, collectedAlerts); final HtmlPage secondPage = (HtmlPage) button.click(); assertEquals("First", firstPage.getTitleText()); assertEquals("Second", secondPage.getTitleText()); assertEquals(Collections.EMPTY_LIST, collectedAlerts); } /** * @throws Exception if the test fails */ @Test public void testSubmit_javascriptAction() throws Exception { final String firstContent = "First\n" + "
\n" + "
\n" + ""; final String secondContent = "Second"; final WebClient client = new WebClient(); final List collectedAlerts = new ArrayList(); client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); final MockWebConnection webConnection = new MockWebConnection(client); webConnection.setResponse(URL_FIRST, firstContent); webConnection.setResponse(URL_SECOND, secondContent); client.setWebConnection(webConnection); final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST); final HtmlSubmitInput button = (HtmlSubmitInput) firstPage.getHtmlElementById("button"); assertEquals(Collections.EMPTY_LIST, collectedAlerts); final HtmlPage secondPage = (HtmlPage) button.click(); assertEquals(firstPage.getTitleText(), secondPage.getTitleText()); assertEquals(new String[] {"clicked"}, collectedAlerts); } /** * @throws Exception if the test fails */ @Test public void testSubmit_javascriptAction_javascriptDisabled() throws Exception { final String firstContent = "First\n" + "
\n" + "
\n" + ""; final WebClient client = new WebClient(); client.setJavaScriptEnabled(false); final List collectedAlerts = new ArrayList(); client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); final MockWebConnection webConnection = new MockWebConnection(client); webConnection.setResponse(URL_FIRST, firstContent); client.setWebConnection(webConnection); final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST); final HtmlSubmitInput button = (HtmlSubmitInput) firstPage.getHtmlElementById("button"); assertEquals(Collections.EMPTY_LIST, collectedAlerts); final HtmlPage secondPage = (HtmlPage) button.click(); assertSame(firstPage, secondPage); } /** * Regression test for a bug that caused a NullPointer exception to be thrown during submit. * @throws Exception if the test fails */ @Test public void testSubmitRadioButton() throws Exception { final String htmlContent = "
\n" + "\n" + "\n" + "\n" + "
" + "Option 1
\n" + "Option 2
Option 3
\n" + ""; final HtmlPage page = loadPage(htmlContent); final HtmlSubmitInput loginButton = (HtmlSubmitInput) page.getDocumentElement().getOneHtmlElementByAttribute("input", "value", "Login"); loginButton.click(); } /** * @throws Exception if the test fails */ @Test public void testReset_onResetHandler() throws Exception { final String html = "First\n" + "
\n" + "
\n" + ""; final List collectedAlerts = new ArrayList(); final HtmlPage firstPage = loadPage(html, collectedAlerts); final HtmlResetInput button = (HtmlResetInput) firstPage.getHtmlElementById("button"); assertEquals(Collections.EMPTY_LIST, collectedAlerts); final HtmlPage secondPage = (HtmlPage) button.click(); assertSame(firstPage, secondPage); final String[] expectedAlerts = {"clicked", "reset"}; assertEquals(expectedAlerts, collectedAlerts); } /** *

Simulate a bug report where an anchor contained JavaScript that caused a form submit. * According to the bug report, the form would be submitted even though the onsubmit * handler would return false. This wasn't reproducible but I added a test for it anyway.

* *

UPDATE: If the form submit is triggered by JavaScript then the onsubmit handler is not * supposed to be called so it doesn't matter what value it returns.

* @throws Exception if the test fails */ @Test public void testSubmit_AnchorCausesSubmit_onSubmitHandler_returnFalse() throws Exception { final String firstContent = "First\n" + "\n" + "
\n" + "
\n" + "Click me\n" + ""; final String secondContent = "Second"; final WebClient client = new WebClient(); final List collectedAlerts = new ArrayList(); client.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); final MockWebConnection webConnection = new MockWebConnection(client); webConnection.setResponse(URL_FIRST, firstContent); webConnection.setDefaultResponse(secondContent); client.setWebConnection(webConnection); final HtmlPage firstPage = (HtmlPage) client.getPage(URL_FIRST); final HtmlAnchor anchor = (HtmlAnchor) firstPage.getHtmlElementById("link1"); assertEquals(Collections.EMPTY_LIST, collectedAlerts); final HtmlPage secondPage = (HtmlPage) anchor.click(); assertEquals("Second", secondPage.getTitleText()); assertEquals(Collections.EMPTY_LIST, collectedAlerts); } /** * @throws Exception if the test fails */ @Test public void testSubmit_NoDefaultValue() throws Exception { final String htmlContent = "foo\n" + "
\n" + " \n" + " \n" + "
"; final HtmlPage page = loadPage(htmlContent); final MockWebConnection webConnection = getMockConnection(page); final HtmlForm form = (HtmlForm) page.getHtmlElementById("form1"); final HtmlSubmitInput button = (HtmlSubmitInput) form.getInputByName("button"); button.click(); final List expectedParameters = Arrays.asList(new NameValuePair[]{ new NameValuePair("textfield", ""), new NameValuePair("button", "foo") }); final List collectedParameters = webConnection.getLastParameters(); assertEquals(expectedParameters, collectedParameters); } /** * @throws Exception if the test fails */ @Test public void testSubmit_NoNameOnControl() throws Exception { final String htmlContent = "foo\n" + "
\n" + " \n" + " \n" + "
"; final HtmlPage page = loadPage(htmlContent); final MockWebConnection webConnection = getMockConnection(page); final HtmlForm form = (HtmlForm) page.getHtmlElementById("form1"); final HtmlSubmitInput button = (HtmlSubmitInput) form.getInputByName("button"); button.click(); final List expectedParameters = Arrays.asList(new NameValuePair[]{new NameValuePair("button", "foo")}); final List collectedParameters = webConnection.getLastParameters(); assertEquals(expectedParameters, collectedParameters); } /** * @throws Exception if the test fails */ @Test public void testSubmit_NoNameOnButton() throws Exception { final String htmlContent = "foo\n" + "
\n" + " \n" + " \n" + "
"; final HtmlPage page = loadPage(htmlContent); final MockWebConnection webConnection = getMockConnection(page); final HtmlButton button = (HtmlButton) page.getHtmlElementById("button"); button.click(); final List expectedParameters = Arrays.asList(new NameValuePair[]{new NameValuePair("textfield", "blah")}); final List collectedParameters = webConnection.getLastParameters(); assertEquals(expectedParameters, collectedParameters); } /** * @throws Exception if the test fails */ @Test public void testSubmit_NestedInput() throws Exception { final String htmlContent = "foo\n" + "
\n" + " \n" + "
\n" + " \n" + " \n" + " \n" + "
\n" + "
"; final HtmlPage page = loadPage(htmlContent); final MockWebConnection webConnection = getMockConnection(page); final HtmlForm form = (HtmlForm) page.getHtmlElementById("form1"); final HtmlSubmitInput button = (HtmlSubmitInput) form.getInputByName("button"); button.click(); final List expectedParameters = Arrays.asList(new NameValuePair[]{ new NameValuePair("textfield", "blah"), new NameValuePair("button", "foo") }); final List collectedParameters = webConnection.getLastParameters(); assertEquals(expectedParameters, collectedParameters); } /** * @throws Exception if the test fails */ @Test public void testSubmit_IgnoresDisabledControls() throws Exception { final String htmlContent = "foo\n" + "
\n" + " \n" + " \n" + "
"; final HtmlPage page = loadPage(htmlContent); final MockWebConnection webConnection = getMockConnection(page); final HtmlForm form = (HtmlForm) page.getHtmlElementById("form1"); final HtmlSubmitInput button = (HtmlSubmitInput) form.getInputByName("button"); button.click(); final List expectedParameters = Arrays.asList(new NameValuePair[]{new NameValuePair("button", "foo")}); final List collectedParameters = webConnection.getLastParameters(); assertEquals(expectedParameters, collectedParameters); } /** * Reset buttons should not be successful controls. * @see Spec * @throws Exception if the test fails */ @Test public void testSubmit_IgnoresResetControls() throws Exception { final String htmlContent = "foo\n" + "
\n" + "