Add `BaseUrl` backed HTTP Unit support classes
Add new HTML Unit support classes that use `BaseUrlProviders` to find the `BaseUrl`. See gh-46356
This commit is contained in:
parent
bba56ffc8b
commit
ef37765625
|
@ -38,6 +38,10 @@ dependencies {
|
|||
optional("org.hamcrest:hamcrest-library")
|
||||
optional("org.junit.jupiter:junit-jupiter-api")
|
||||
optional("org.mockito:mockito-core")
|
||||
optional("org.seleniumhq.selenium:htmlunit3-driver") {
|
||||
exclude(group: "com.sun.activation", module: "jakarta.activation")
|
||||
}
|
||||
optional("org.seleniumhq.selenium:selenium-api")
|
||||
optional("org.skyscreamer:jsonassert")
|
||||
optional("org.springframework:spring-web")
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright 2012-present 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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 org.springframework.boot.test.web.htmlunit;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.htmlunit.FailingHttpStatusCodeException;
|
||||
import org.htmlunit.Page;
|
||||
import org.htmlunit.WebClient;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.test.http.server.BaseUrl;
|
||||
import org.springframework.boot.test.http.server.BaseUrlProvider;
|
||||
|
||||
/**
|
||||
* HTML Unit {@link WebClient} that will automatically prefix relative URLs with a
|
||||
* {@link BaseUrlProvider provided} {@link BaseUrl}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class BaseUrlWebClient extends WebClient {
|
||||
|
||||
private @Nullable BaseUrl baseUrl;
|
||||
|
||||
public BaseUrlWebClient(@Nullable BaseUrl baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <P extends Page> P getPage(String url) throws IOException, FailingHttpStatusCodeException {
|
||||
if (this.baseUrl != null && url.startsWith("/")) {
|
||||
url = this.baseUrl.resolve(url);
|
||||
}
|
||||
return super.getPage(url);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 2012-present 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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 org.springframework.boot.test.web.htmlunit;
|
||||
|
||||
import org.htmlunit.BrowserVersion;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.openqa.selenium.Capabilities;
|
||||
|
||||
import org.springframework.boot.test.http.server.BaseUrl;
|
||||
import org.springframework.boot.test.http.server.BaseUrlProvider;
|
||||
import org.springframework.test.web.servlet.htmlunit.webdriver.WebConnectionHtmlUnitDriver;
|
||||
|
||||
/**
|
||||
* HTML Unit {@link WebConnectionHtmlUnitDriver} that will automatically prefix relative
|
||||
* URLs with a {@link BaseUrlProvider provided} {@link BaseUrl}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class BaseUrlWebConnectionHtmlUnitDriver extends WebConnectionHtmlUnitDriver {
|
||||
|
||||
private @Nullable BaseUrl baseUrl;
|
||||
|
||||
public BaseUrlWebConnectionHtmlUnitDriver(@Nullable BaseUrl baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public BaseUrlWebConnectionHtmlUnitDriver(@Nullable BaseUrl baseUrl, boolean enableJavascript) {
|
||||
super(enableJavascript);
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public BaseUrlWebConnectionHtmlUnitDriver(@Nullable BaseUrl baseUrl, BrowserVersion browserVersion) {
|
||||
super(browserVersion);
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public BaseUrlWebConnectionHtmlUnitDriver(@Nullable BaseUrl baseUrl, Capabilities capabilities) {
|
||||
super(capabilities);
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void get(String url) {
|
||||
if (this.baseUrl != null && url.startsWith("/")) {
|
||||
url = this.baseUrl.resolve(url);
|
||||
}
|
||||
super.get(url);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2012-present 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* HtmlUnit support classes.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.test.web.htmlunit;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2012-present 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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 org.springframework.boot.test.web.htmlunit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.htmlunit.StringWebResponse;
|
||||
import org.htmlunit.WebClient;
|
||||
import org.htmlunit.WebConnection;
|
||||
import org.htmlunit.WebResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.test.http.server.BaseUrl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.assertArg;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link BaseUrlWebClient}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
class BaseUrlWebClientTests {
|
||||
|
||||
@Test
|
||||
void createWhenBaseUrlIsNull() throws Exception {
|
||||
BaseUrlWebClient client = new BaseUrlWebClient(null);
|
||||
WebConnection connection = mockConnection();
|
||||
client.setWebConnection(connection);
|
||||
assertThatExceptionOfType(MalformedURLException.class).isThrownBy(() -> client.getPage("/test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPageWhenUrlIsRelativeUsesBaseUrl() throws Exception {
|
||||
WebClient client = new BaseUrlWebClient(BaseUrl.of("https://example.com:8080"));
|
||||
WebConnection connection = mockConnection();
|
||||
client.setWebConnection(connection);
|
||||
client.getPage("/test");
|
||||
thenConnectionRequests(connection, new URL("https://example.com:8080/test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPageWhenUrlIsNotRelativeUsesUrl() throws Exception {
|
||||
WebClient client = new BaseUrlWebClient(BaseUrl.of("https://example.com:8080"));
|
||||
WebConnection connection = mockConnection();
|
||||
client.setWebConnection(connection);
|
||||
client.getPage("https://example.com:9000/test");
|
||||
thenConnectionRequests(connection, new URL("https://example.com:9000/test"));
|
||||
}
|
||||
|
||||
private void thenConnectionRequests(WebConnection connection, URL url) throws IOException {
|
||||
then(connection).should().getResponse(assertArg((request) -> assertThat(request.getUrl()).isEqualTo(url)));
|
||||
}
|
||||
|
||||
private WebConnection mockConnection() throws IOException {
|
||||
WebConnection connection = mock(WebConnection.class);
|
||||
WebResponse response = new StringWebResponse("test", new URL("http://localhost"));
|
||||
given(connection.getResponse(any())).willReturn(response);
|
||||
return connection;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2012-present 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://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 org.springframework.boot.test.web.htmlunit;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.htmlunit.TopLevelWindow;
|
||||
import org.htmlunit.WebClient;
|
||||
import org.htmlunit.WebClientOptions;
|
||||
import org.htmlunit.WebConsole;
|
||||
import org.htmlunit.WebRequest;
|
||||
import org.htmlunit.WebWindow;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.openqa.selenium.WebDriverException;
|
||||
|
||||
import org.springframework.boot.test.http.server.BaseUrl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link BaseUrlWebConnectionHtmlUnitDriver}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class BaseUrlWebConnectionHtmlUnitDriverTests {
|
||||
|
||||
private final WebClient webClient;
|
||||
|
||||
BaseUrlWebConnectionHtmlUnitDriverTests() {
|
||||
this.webClient = mock();
|
||||
given(this.webClient.getOptions()).willReturn(new WebClientOptions());
|
||||
given(this.webClient.getWebConsole()).willReturn(new WebConsole());
|
||||
WebWindow currentWindow = mock(WebWindow.class);
|
||||
given(currentWindow.isClosed()).willReturn(false);
|
||||
given(this.webClient.getCurrentWindow()).willReturn(currentWindow);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenBaseUrlIsNull() {
|
||||
BaseUrlWebConnectionHtmlUnitDriver driver = new TestBaseUrlWebConnectionHtmlUnitDriver(null);
|
||||
assertThatExceptionOfType(WebDriverException.class).isThrownBy(() -> driver.get("/test"))
|
||||
.withCauseInstanceOf(MalformedURLException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getWhenUrlIsRelativeUsesBaseUrl() throws Exception {
|
||||
BaseUrl baseUrl = BaseUrl.of("https://example.com");
|
||||
BaseUrlWebConnectionHtmlUnitDriver driver = new TestBaseUrlWebConnectionHtmlUnitDriver(baseUrl);
|
||||
driver.get("/test");
|
||||
then(this.webClient).should()
|
||||
.getPage(any(TopLevelWindow.class), requestToUrl(new URL("https://example.com/test")));
|
||||
}
|
||||
|
||||
private WebRequest requestToUrl(URL url) {
|
||||
return argThat(new WebRequestUrlArgumentMatcher(url));
|
||||
}
|
||||
|
||||
public class TestBaseUrlWebConnectionHtmlUnitDriver extends BaseUrlWebConnectionHtmlUnitDriver {
|
||||
|
||||
TestBaseUrlWebConnectionHtmlUnitDriver(@Nullable BaseUrl baseUrl) {
|
||||
super(baseUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebClient getWebClient() {
|
||||
return BaseUrlWebConnectionHtmlUnitDriverTests.this.webClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class WebRequestUrlArgumentMatcher implements ArgumentMatcher<WebRequest> {
|
||||
|
||||
private final URL expectedUrl;
|
||||
|
||||
private WebRequestUrlArgumentMatcher(URL expectedUrl) {
|
||||
this.expectedUrl = expectedUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(WebRequest argument) {
|
||||
return argument.getUrl().equals(this.expectedUrl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -32,7 +32,6 @@ dependencies {
|
|||
|
||||
implementation(project(":module:spring-boot-http-converter"))
|
||||
implementation(project(":module:spring-boot-web-server"))
|
||||
implementation(project(":module:spring-boot-web-server-test"))
|
||||
|
||||
optional(project(":core:spring-boot-autoconfigure"))
|
||||
optional(project(":core:spring-boot-test-autoconfigure"))
|
||||
|
|
|
@ -23,9 +23,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.web.server.test.htmlunit.LocalHostWebClient;
|
||||
import org.springframework.boot.test.http.server.BaseUrl;
|
||||
import org.springframework.boot.test.http.server.BaseUrlProviders;
|
||||
import org.springframework.boot.test.web.htmlunit.BaseUrlWebClient;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.htmlunit.MockMvcWebClientBuilder;
|
||||
|
||||
|
@ -43,8 +45,9 @@ public final class MockMvcWebClientAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean({ WebClient.class, MockMvcWebClientBuilder.class })
|
||||
@ConditionalOnBean(MockMvc.class)
|
||||
MockMvcWebClientBuilder mockMvcWebClientBuilder(MockMvc mockMvc, Environment environment) {
|
||||
return MockMvcWebClientBuilder.mockMvcSetup(mockMvc).withDelegate(new LocalHostWebClient(environment));
|
||||
MockMvcWebClientBuilder mockMvcWebClientBuilder(MockMvc mockMvc, ApplicationContext applicationContext) {
|
||||
BaseUrl baseUrl = new BaseUrlProviders(applicationContext).getBaseUrlOrDefault();
|
||||
return MockMvcWebClientBuilder.mockMvcSetup(mockMvc).withDelegate(new BaseUrlWebClient(baseUrl));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -26,9 +26,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.web.server.test.htmlunit.webdriver.LocalHostWebConnectionHtmlUnitDriver;
|
||||
import org.springframework.boot.test.http.server.BaseUrl;
|
||||
import org.springframework.boot.test.http.server.BaseUrlProviders;
|
||||
import org.springframework.boot.test.web.htmlunit.BaseUrlWebConnectionHtmlUnitDriver;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
|
||||
|
||||
|
@ -46,9 +48,10 @@ public final class MockMvcWebDriverAutoConfiguration {
|
|||
@Bean
|
||||
@ConditionalOnMissingBean({ WebDriver.class, MockMvcHtmlUnitDriverBuilder.class })
|
||||
@ConditionalOnBean(MockMvc.class)
|
||||
MockMvcHtmlUnitDriverBuilder mockMvcHtmlUnitDriverBuilder(MockMvc mockMvc, Environment environment) {
|
||||
MockMvcHtmlUnitDriverBuilder mockMvcHtmlUnitDriverBuilder(MockMvc mockMvc, ApplicationContext applicationContext) {
|
||||
BaseUrl baseUrl = new BaseUrlProviders(applicationContext).getBaseUrlOrDefault();
|
||||
MockMvcHtmlUnitDriverBuilder builder = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(mockMvc)
|
||||
.withDelegate(new LocalHostWebConnectionHtmlUnitDriver(environment, BrowserVersion.CHROME));
|
||||
.withDelegate(new BaseUrlWebConnectionHtmlUnitDriver(baseUrl, BrowserVersion.CHROME));
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue