Upgrade to HtmUnit 3.11.0

This commit upgrades to a major new release of HtmlUnit. This is a
breaking change as HtmlUnit 3 moves to a `org.htmlunit` package and
calling code needs to be restructured.

Our use of Selenium has been adapted accordingly, moving to Selenium
3, using the new org.seleniumhq.selenium:htmlunit3-driver integration.

Closes gh-30392
This commit is contained in:
Stéphane Nicoll 2024-03-11 10:51:57 +01:00
parent 71245f9655
commit 92d1ebefbb
25 changed files with 103 additions and 96 deletions

View File

@ -8,8 +8,7 @@ to use the raw HtmlUnit libraries.
== MockMvc and HtmlUnit Setup
First, make sure that you have included a test dependency on
`net.sourceforge.htmlunit:htmlunit`. In order to use HtmlUnit with Apache HttpComponents
4.5+, you need to use HtmlUnit 2.18 or higher.
`org.htmlunit:htmlunit`.
We can easily create an HtmlUnit `WebClient` that integrates with MockMvc by using the
`MockMvcWebClientBuilder`, as follows:

View File

@ -166,7 +166,7 @@ following sections to make this pattern much easier to implement.
== MockMvc and WebDriver Setup
To use Selenium WebDriver with the Spring MVC Test framework, make sure that your project
includes a test dependency on `org.seleniumhq.selenium:selenium-htmlunit-driver`.
includes a test dependency on `org.seleniumhq.selenium:selenium-htmlunit3-driver`.
We can easily create a Selenium WebDriver that integrates with MockMvc by using the
`MockMvcHtmlUnitDriverBuilder` as the following example shows:

View File

@ -87,7 +87,7 @@ Kotlin::
This test has some obvious drawbacks. If we update our controller to use the parameter
`message` instead of `text`, our form test continues to pass, even though the HTML form
is out of synch with the controller. To resolve this we can combine our two tests, as
is out of sync with the controller. To resolve this we can combine our two tests, as
follows:
[tabs]

View File

@ -89,7 +89,6 @@ dependencies {
api("jaxen:jaxen:1.2.0")
api("junit:junit:4.13.2")
api("net.sf.jopt-simple:jopt-simple:5.0.4")
api("net.sourceforge.htmlunit:htmlunit:2.70.0")
api("org.apache-extras.beanshell:bsh:2.0b6")
api("org.apache.activemq:activemq-broker:5.17.6")
api("org.apache.activemq:activemq-kahadb-store:5.17.6")
@ -129,6 +128,7 @@ dependencies {
api("org.hibernate:hibernate-core-jakarta:5.6.15.Final")
api("org.hibernate:hibernate-validator:7.0.5.Final")
api("org.hsqldb:hsqldb:2.7.2")
api("org.htmlunit:htmlunit:3.11.0")
api("org.javamoney:moneta:1.4.2")
api("org.jruby:jruby:9.4.6.0")
api("org.junit.support:testng-engine:1.0.5")
@ -136,8 +136,8 @@ dependencies {
api("org.ogce:xpp3:1.1.6")
api("org.python:jython-standalone:2.7.3")
api("org.quartz-scheduler:quartz:2.3.2")
api("org.seleniumhq.selenium:htmlunit-driver:2.70.0")
api("org.seleniumhq.selenium:selenium-java:3.141.59")
api("org.seleniumhq.selenium:htmlunit3-driver:4.18.1")
api("org.seleniumhq.selenium:selenium-java:4.18.1")
api("org.skyscreamer:jsonassert:1.5.1")
api("org.slf4j:slf4j-api:2.0.12")
api("org.testng:testng:7.9.0")

View File

@ -29,13 +29,13 @@ dependencies {
optional("jakarta.xml.bind:jakarta.xml.bind-api")
optional("javax.inject:javax.inject")
optional("junit:junit")
optional("net.sourceforge.htmlunit:htmlunit") {
exclude group: "commons-logging", module: "commons-logging"
}
optional("org.apache.groovy:groovy")
optional("org.apache.tomcat.embed:tomcat-embed-core")
optional("org.aspectj:aspectjweaver")
optional("org.hamcrest:hamcrest")
optional("org.htmlunit:htmlunit") {
exclude group: "commons-logging", module: "commons-logging"
}
optional("org.jetbrains.kotlin:kotlin-reflect")
optional("org.jetbrains.kotlin:kotlin-stdlib")
optional("org.jetbrains.kotlinx:kotlinx-coroutines-core")
@ -43,7 +43,7 @@ dependencies {
optional("org.junit.jupiter:junit-jupiter-api")
optional("org.junit.platform:junit-platform-launcher") // for AOT processing
optional("org.mockito:mockito-core")
optional("org.seleniumhq.selenium:htmlunit-driver") {
optional("org.seleniumhq.selenium:htmlunit3-driver") {
exclude group: "commons-logging", module: "commons-logging"
exclude group: "net.bytebuddy", module: "byte-buddy"
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,9 +20,9 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import org.htmlunit.WebConnection;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.springframework.util.Assert;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,7 +21,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import com.gargoylesoftware.htmlunit.WebRequest;
import org.htmlunit.WebRequest;
/**
* A {@link WebRequestMatcher} that allows matching on the host and optionally

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,15 +30,15 @@ import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import com.gargoylesoftware.htmlunit.FormEncodingType;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.util.KeyDataPair;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.htmlunit.FormEncodingType;
import org.htmlunit.WebClient;
import org.htmlunit.WebRequest;
import org.htmlunit.util.KeyDataPair;
import org.htmlunit.util.NameValuePair;
import org.springframework.beans.Mergeable;
import org.springframework.http.MediaType;
@ -301,8 +301,8 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
}
}
Set<com.gargoylesoftware.htmlunit.util.Cookie> managedCookies = this.webClient.getCookies(this.webRequest.getUrl());
for (com.gargoylesoftware.htmlunit.util.Cookie cookie : managedCookies) {
Set<org.htmlunit.util.Cookie> managedCookies = this.webClient.getCookies(this.webRequest.getUrl());
for (org.htmlunit.util.Cookie cookie : managedCookies) {
processCookie(request, cookies, new Cookie(cookie.getName(), cookie.getValue()));
}
@ -351,8 +351,8 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
this.webClient.getCookieManager().removeCookie(createCookie(request, sessionid));
}
private com.gargoylesoftware.htmlunit.util.Cookie createCookie(MockHttpServletRequest request, String sessionid) {
return new com.gargoylesoftware.htmlunit.util.Cookie(request.getServerName(), "JSESSIONID", sessionid,
private org.htmlunit.util.Cookie createCookie(MockHttpServletRequest request, String sessionid) {
return new org.htmlunit.util.Cookie(request.getServerName(), "JSESSIONID", sessionid,
request.getContextPath() + "/", null, request.isSecure(), true);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
package org.springframework.test.web.servlet.htmlunit;
import com.gargoylesoftware.htmlunit.WebClient;
import org.htmlunit.WebClient;
import org.springframework.lang.Nullable;
import org.springframework.test.web.servlet.MockMvc;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,13 +21,13 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.gargoylesoftware.htmlunit.CookieManager;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.util.Cookie;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.htmlunit.CookieManager;
import org.htmlunit.WebClient;
import org.htmlunit.WebConnection;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.htmlunit.util.Cookie;
import org.springframework.lang.Nullable;
import org.springframework.mock.web.MockHttpServletResponse;
@ -181,7 +181,7 @@ public final class MockMvcWebConnection implements WebConnection {
}
@SuppressWarnings("removal")
private static com.gargoylesoftware.htmlunit.util.Cookie createCookie(jakarta.servlet.http.Cookie cookie) {
private static Cookie createCookie(jakarta.servlet.http.Cookie cookie) {
Date expires = null;
if (cookie.getMaxAge() > -1) {
expires = new Date(System.currentTimeMillis() + cookie.getMaxAge() * 1000);
@ -195,7 +195,7 @@ public final class MockMvcWebConnection implements WebConnection {
if (cookie.isHttpOnly()) {
result.setAttribute("httponly", "true");
}
return new com.gargoylesoftware.htmlunit.util.Cookie(result);
return new Cookie(result);
}
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,8 +20,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebConnection;
import org.htmlunit.WebClient;
import org.htmlunit.WebConnection;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.htmlunit.DelegatingWebConnection.DelegateWebConnection;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,10 +21,10 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.WebResponseData;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.htmlunit.WebResponseData;
import org.htmlunit.util.NameValuePair;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletResponse;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,7 +18,7 @@ package org.springframework.test.web.servlet.htmlunit;
import java.util.regex.Pattern;
import com.gargoylesoftware.htmlunit.WebRequest;
import org.htmlunit.WebRequest;
/**
* A {@link WebRequestMatcher} that allows matching on

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
package org.springframework.test.web.servlet.htmlunit;
import com.gargoylesoftware.htmlunit.WebRequest;
import org.htmlunit.WebRequest;
/**
* Strategy for matching on a {@link WebRequest}.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,8 +16,8 @@
package org.springframework.test.web.servlet.htmlunit.webdriver;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import org.htmlunit.BrowserVersion;
import org.htmlunit.WebClient;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.springframework.lang.Nullable;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,9 +16,9 @@
package org.springframework.test.web.servlet.htmlunit.webdriver;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebConnection;
import org.htmlunit.BrowserVersion;
import org.htmlunit.WebClient;
import org.htmlunit.WebConnection;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,7 +19,7 @@ package org.springframework.test.web.servlet.htmlunit;
import java.net.MalformedURLException;
import java.net.URL;
import com.gargoylesoftware.htmlunit.WebRequest;
import org.htmlunit.WebRequest;
import static org.assertj.core.api.Assertions.assertThat;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,13 +19,13 @@ package org.springframework.test.web.servlet.htmlunit;
import java.net.URL;
import java.util.Collections;
import com.gargoylesoftware.htmlunit.HttpWebConnection;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.WebResponseData;
import org.htmlunit.HttpWebConnection;
import org.htmlunit.Page;
import org.htmlunit.WebClient;
import org.htmlunit.WebConnection;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.htmlunit.WebResponseData;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

View File

@ -24,15 +24,15 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import com.gargoylesoftware.htmlunit.FormEncodingType;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpSession;
import org.apache.commons.io.IOUtils;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.htmlunit.FormEncodingType;
import org.htmlunit.HttpMethod;
import org.htmlunit.WebClient;
import org.htmlunit.WebRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -340,11 +340,11 @@ public class HtmlUnitRequestBuilderTests {
}
@Test
void buildRequestLocalPort() throws Exception {
void buildRequestLocalPortMatchingDefault() throws Exception {
webRequest.setUrl(new URL("http://localhost:80/test/this/here"));
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext);
assertThat(actualRequest.getLocalPort()).isEqualTo(80);
assertThat(actualRequest.getLocalPort()).isEqualTo(-1);
}
@Test
@ -626,10 +626,18 @@ public class HtmlUnitRequestBuilderTests {
@Test
void buildRequestServerPort() throws Exception {
webRequest.setUrl(new URL("http://localhost:80/test/this/here"));
webRequest.setUrl(new URL("http://localhost:8080/test/this/here"));
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext);
assertThat(actualRequest.getServerPort()).isEqualTo(80);
assertThat(actualRequest.getServerPort()).isEqualTo(8080);
}
@Test
void buildRequestServerPortMatchingDefault() throws Exception {
webRequest.setUrl(new URL("http://localhost/test/this/here"));
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext);
assertThat(actualRequest.getServerPort()).isEqualTo(-1);
}
@Test
@ -890,7 +898,7 @@ public class HtmlUnitRequestBuilderTests {
private void assertSingleSessionCookie(String expected) {
com.gargoylesoftware.htmlunit.util.Cookie jsessionidCookie = webClient.getCookieManager().getCookie("JSESSIONID");
org.htmlunit.util.Cookie jsessionidCookie = webClient.getCookieManager().getCookie("JSESSIONID");
if (expected == null || expected.contains("Expires=Thu, 01-Jan-1970 00:00:01 GMT")) {
assertThat(jsessionidCookie).isNull();
return;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,11 +19,11 @@ package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import java.net.URL;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import jakarta.servlet.http.HttpServletRequest;
import org.htmlunit.WebClient;
import org.htmlunit.WebConnection;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,13 +19,13 @@ package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import java.net.URL;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.util.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.htmlunit.HttpMethod;
import org.htmlunit.WebClient;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.htmlunit.util.Cookie;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Configuration;

View File

@ -18,9 +18,9 @@ package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import org.htmlunit.FailingHttpStatusCodeException;
import org.htmlunit.Page;
import org.htmlunit.WebClient;
import org.junit.jupiter.api.Test;
import org.springframework.test.web.servlet.MockMvc;

View File

@ -20,10 +20,10 @@ import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import jakarta.servlet.http.Cookie;
import org.htmlunit.WebRequest;
import org.htmlunit.WebResponse;
import org.htmlunit.util.NameValuePair;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -16,8 +16,8 @@
package org.springframework.test.web.servlet.htmlunit.webdriver;
import com.gargoylesoftware.htmlunit.util.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import org.htmlunit.util.Cookie;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;

View File

@ -18,8 +18,8 @@ package org.springframework.test.web.servlet.htmlunit.webdriver;
import java.io.IOException;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import org.htmlunit.WebConnection;
import org.htmlunit.WebRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;