Java tutorial
/* * Copyright (c) 2002-2016 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; import static com.gargoylesoftware.htmlunit.httpclient.HtmlUnitBrowserCompatCookieSpec.EMPTY_COOKIE_NAME; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; import org.apache.commons.lang3.SerializationUtils; import org.apache.commons.lang3.time.DateUtils; import org.junit.Test; import org.junit.runner.RunWith; import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts; import com.gargoylesoftware.htmlunit.BrowserRunner.NotYetImplemented; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.util.Cookie; /** * Tests for {@link WebClient} that run with BrowserRunner. * * @author Ahmed Ashour */ @RunWith(BrowserRunner.class) public class WebClient2Test extends SimpleWebTestCase { /** * @throws Exception if an error occurs */ @Test @Alerts(DEFAULT = "http://first/?param=%A3", IE = "http://first/?param=\u00A3") public void encodeURL() throws Exception { final String html = "<body onload='alert(window.location.href)'></body>"; getMockWebConnection().setDefaultResponse(html); loadPageWithAlerts(html, new URL("http://first/?param=\u00A3"), -1); } /** * Test that the path and query string are encoded to be valid. * @throws Exception if something goes wrong */ @Test public void loadPage_EncodeRequest() throws Exception { final String htmlContent = "<html><head><title>foo</title></head><body>\n" + "</body></html>"; final WebClient client = getWebClient(); final MockWebConnection webConnection = new MockWebConnection(); webConnection.setDefaultResponse(htmlContent); client.setWebConnection(webConnection); // with query string not encoded HtmlPage page = client.getPage("http://first?a=b c&d=\u00E9\u00E8"); String expected; final boolean ie = getBrowserVersion().isIE(); if (ie) { expected = "?a=b%20c&d=\u00E9\u00E8"; } else { expected = "?a=b%20c&d=%E9%E8"; } assertEquals("http://first/" + expected, page.getUrl()); // with query string already encoded page = client.getPage("http://first?a=b%20c&d=%C3%A9%C3%A8"); assertEquals("http://first/?a=b%20c&d=%C3%A9%C3%A8", page.getUrl()); // with query string partially encoded page = client.getPage("http://first?a=b%20c&d=e f"); assertEquals("http://first/?a=b%20c&d=e%20f", page.getUrl()); // with anchor page = client.getPage("http://first?a=b c#myAnchor"); assertEquals("http://first/?a=b%20c#myAnchor", page.getUrl()); // with query string containing encoded "&", "=", "+", ",", and "$" page = client.getPage("http://first?a=%26%3D%20%2C%24"); assertEquals("http://first/?a=%26%3D%20%2C%24", page.getUrl()); // with character to encode in path page = client.getPage("http://first/page 1.html"); assertEquals("http://first/page%201.html", page.getUrl()); // with character to encode in path page = client.getPage("http://first/page 1.html"); assertEquals("http://first/page%201.html", page.getUrl()); } /** * Test for 3151939. The Browser removes leading '/..' from the path. * @throws Exception if something goes wrong */ @Test public void loadPage_HandleDoubleDotsAtRoot() throws Exception { final String htmlContent = "<html><head><title>foo</title></head><body>\n" + "</body></html>"; final WebClient client = getWebClient(); final MockWebConnection webConnection = new MockWebConnection(); webConnection.setDefaultResponse(htmlContent); client.setWebConnection(webConnection); HtmlPage page = client.getPage("http://www.somewhere.org/.."); assertEquals("http://www.somewhere.org/", page.getUrl()); page = client.getPage("http://www.somewhere.org/../test"); assertEquals("http://www.somewhere.org/test", page.getUrl()); // many page = client.getPage("http://www.somewhere.org/../../.."); assertEquals("http://www.somewhere.org/", page.getUrl()); } /** * Verifies that a WebClient can be serialized and deserialized before it has been used. * @throws Exception if an error occurs */ @Test public void serialization_beforeUse() throws Exception { final WebClient client = getWebClient(); final WebClient copy = clone(client); assertNotNull(copy); } /** * Regression test for bug 2833433. * @throws Exception if an error occurs */ @Test public void serialization_pageLoad() throws Exception { final String page1Content = "<html><body>hello 1</body></html>"; try (final WebClient client = getWebClient()) { final HtmlPage page1 = loadPage(client, page1Content, null, URL_FIRST); assertEquals("hello 1", page1.asText()); final String page2Content = "<html><body>hello 2</body></html>"; try (final WebClient copy = clone(client)) { final HtmlPage page2 = loadPage(copy, page2Content, null, URL_SECOND); assertEquals("hello 2", page2.asText()); } } } /** * Regression test for bug 2836355. * @throws Exception if an error occurs */ @Test public void serialization_withClickAfterwards() throws Exception { final String html = "<html><head>\n" + "<script>\n" + " function foo() {\n" + " document.getElementById('mybox').innerHTML='hello world';\n" + " return false;\n" + " }\n" + "</script></head>\n" + "<body><div id='mybox'></div>\n" + "<a href='#' onclick='foo()' id='clicklink'>say hello world</a>\n" + "</body></html>"; final HtmlPage page = loadPageWithAlerts(html); assertEquals("", page.getElementById("mybox").getTextContent()); final WebClient clientCopy = clone(page.getWebClient()); final HtmlPage pageCopy = (HtmlPage) clientCopy.getCurrentWindow().getTopWindow().getEnclosedPage(); pageCopy.getHtmlElementById("clicklink").click(); assertEquals("hello world", pageCopy.getElementById("mybox").getTextContent()); } /** * Background tasks that have been registered before the serialization should * wake up and run normally after the deserialization. * Until now (2.7-SNAPSHOT 17.09.09) HtmlUnit has probably never supported it. * This is currently not requested and this test is just to document the current status. * @throws Exception if an error occurs */ @Test @NotYetImplemented public void serialization_withJSBackgroundTasks() throws Exception { final String html = "<html><head>\n" + "<script>\n" + " function foo() {\n" + " if (window.name == 'hello') {\n" + " alert('exiting');\n" + " clearInterval(intervalId);\n" + " }\n" + " }\n" + " var intervalId = setInterval(foo, 10);\n" + "</script></head>\n" + "<body></body></html>"; final HtmlPage page = loadPageWithAlerts(html); // verify that 1 background job exists assertEquals(1, page.getEnclosingWindow().getJobManager().getJobCount()); final byte[] bytes = SerializationUtils.serialize(page); page.getWebClient().close(); // deserialize page and verify that 1 background job exists final HtmlPage clonedPage = (HtmlPage) SerializationUtils.deserialize(bytes); assertEquals(1, clonedPage.getEnclosingWindow().getJobManager().getJobCount()); // configure a new CollectingAlertHandler (in fact it has surely already one and we could get and cast it) final List<String> collectedAlerts = Collections.synchronizedList(new ArrayList<String>()); final AlertHandler alertHandler = new CollectingAlertHandler(collectedAlerts); clonedPage.getWebClient().setAlertHandler(alertHandler); // make some change in the page on which background script reacts clonedPage.getEnclosingWindow().setName("hello"); clonedPage.getWebClient().waitForBackgroundJavaScriptStartingBefore(100); assertEquals(0, clonedPage.getEnclosingWindow().getJobManager().getJobCount()); final String[] expectedAlerts = { "exiting" }; assertEquals(expectedAlerts, collectedAlerts); } /** * Regression test for bug 2812769. * @throws Exception if an error occurs */ @Test public void acceptLanguage() throws Exception { final String html = "<html><body></body></html>"; final HtmlPage p = loadPageWithAlerts(html); // browsers are using different casing, but this is not relevant for this test assertEquals("en-us", getMockWebConnection().getLastAdditionalHeaders().get("Accept-Language").toLowerCase(Locale.ROOT)); final WebClient client = p.getWebClient(); final String lang = client.getBrowserVersion().getBrowserLanguage(); try { client.getBrowserVersion().setBrowserLanguage("fr"); client.getPage(getDefaultUrl()); assertEquals("fr", getMockWebConnection().getLastAdditionalHeaders().get("Accept-Language")); } finally { // Restore original language. client.getBrowserVersion().setBrowserLanguage(lang); } } /** * As of HtmlUnit-2.7-SNAPSHOT from 24.09.09, loading about:blank in a page didn't * reinitialized the window host object. * @throws Exception if an error occurs */ @Test public void newWindowScopeForAboutBlank() throws Exception { final HtmlPage p = loadPage("<html><body></body></html>"); p.executeJavaScript("top.foo = 'hello';"); final ScriptResult result = p.executeJavaScript("top.foo"); assertEquals("hello", result.getJavaScriptResult()); final HtmlPage page2 = p.getWebClient().getPage("about:blank"); final ScriptResult result2 = page2.executeJavaScript("String(top.foo)"); assertEquals("undefined", result2.getJavaScriptResult()); } /** * @throws Exception if the test fails */ @Test public void buildCookie() throws Exception { checkCookie("", EMPTY_COOKIE_NAME, "", "/", false, null); checkCookie("toto", EMPTY_COOKIE_NAME, "toto", "/", false, null); checkCookie("toto=", "toto", "", "/", false, null); checkCookie("toto=foo", "toto", "foo", "/", false, null); checkCookie("toto=foo;secure", "toto", "foo", "/", true, null); checkCookie("toto=foo;path=/myPath;secure", "toto", "foo", "/myPath", true, null); // Check that leading and trailing whitespaces are ignored checkCookie(" toto", EMPTY_COOKIE_NAME, "toto", "/", false, null); checkCookie(" = toto", EMPTY_COOKIE_NAME, "toto", "/", false, null); checkCookie(" toto=foo; path=/myPath ; secure ", "toto", "foo", "/myPath", true, null); // Check that we accept reserved attribute names (e.g expires, domain) in any case checkCookie("toto=foo; PATH=/myPath; SeCURE", "toto", "foo", "/myPath", true, null); // Check that we are able to parse and set the expiration date correctly final String dateString = "Fri, 21 Jul 2017 20:47:11 UTC"; final Date date = DateUtils.parseDate(dateString, "EEE, dd MMM yyyy HH:mm:ss z"); checkCookie("toto=foo; expires=" + dateString, "toto", "foo", "/", false, date); } private void checkCookie(final String cookieString, final String name, final String value, final String path, final boolean secure, final Date date) { final String domain = URL_FIRST.getHost(); getWebClient().getCookieManager().clearCookies(); getWebClient().addCookie(cookieString, URL_FIRST, this); final Cookie cookie = getWebClient().getCookieManager().getCookies().iterator().next(); assertEquals(name, cookie.getName()); assertEquals(value, cookie.getValue()); assertEquals(path, cookie.getPath()); assertEquals(domain, cookie.getDomain()); assertEquals(secure, cookie.isSecure()); assertEquals(date, cookie.getExpires()); } }