Polish MockMvc HtmlUnit Support
- formatting - code style - organized imports - precondition assertions - suppressed warnings - Javadoc enhancements Issue: SPR-13158
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,23 +13,27 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebConnection;
|
||||
import com.gargoylesoftware.htmlunit.WebRequest;
|
||||
import com.gargoylesoftware.htmlunit.WebResponse;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Implementation of WebConnection that allows delegating to various WebConnection implementations. For example, if
|
||||
* you host your JavaScript on the domain code.jquery.com, you might want to use the following:</p>
|
||||
* <pre>
|
||||
* Implementation of {@link WebConnection} that allows delegating to various
|
||||
* {@code WebConnection} implementations.
|
||||
*
|
||||
* <p>For example, if you host your JavaScript on the domain {@code code.jquery.com},
|
||||
* you might want to use the following.
|
||||
*
|
||||
* <pre class="code">
|
||||
* WebClient webClient = new WebClient();
|
||||
*
|
||||
* MockMvc mockMvc = ...
|
||||
@@ -45,38 +49,47 @@ import org.springframework.util.Assert;
|
||||
* WebClient webClient = new WebClient();
|
||||
* webClient.setWebConnection(webConnection);
|
||||
* </pre>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public final class DelegatingWebConnection implements WebConnection {
|
||||
|
||||
private final List<DelegateWebConnection> connections;
|
||||
|
||||
private final WebConnection defaultConnection;
|
||||
|
||||
|
||||
public DelegatingWebConnection(WebConnection defaultConnection, List<DelegateWebConnection> connections) {
|
||||
Assert.notNull(defaultConnection, "defaultConnection cannot be null");
|
||||
Assert.notEmpty(connections, "connections cannot be empty");
|
||||
Assert.notNull(defaultConnection, "defaultConnection must not be null");
|
||||
Assert.notEmpty(connections, "connections must not be empty");
|
||||
this.connections = connections;
|
||||
this.defaultConnection = defaultConnection;
|
||||
}
|
||||
|
||||
public DelegatingWebConnection(WebConnection defaultConnection,DelegateWebConnection... connections) {
|
||||
public DelegatingWebConnection(WebConnection defaultConnection, DelegateWebConnection... connections) {
|
||||
this(defaultConnection, Arrays.asList(connections));
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse getResponse(WebRequest request) throws IOException {
|
||||
for(DelegateWebConnection connection : connections) {
|
||||
if(connection.getMatcher().matches(request)) {
|
||||
for (DelegateWebConnection connection : this.connections) {
|
||||
if (connection.getMatcher().matches(request)) {
|
||||
return connection.getDelegate().getResponse(request);
|
||||
}
|
||||
}
|
||||
return defaultConnection.getResponse(request);
|
||||
return this.defaultConnection.getResponse(request);
|
||||
}
|
||||
|
||||
public final static class DelegateWebConnection {
|
||||
|
||||
public static final class DelegateWebConnection {
|
||||
|
||||
private final WebRequestMatcher matcher;
|
||||
|
||||
private final WebConnection delegate;
|
||||
|
||||
|
||||
public DelegateWebConnection(WebRequestMatcher matcher, WebConnection delegate) {
|
||||
this.matcher = matcher;
|
||||
this.delegate = delegate;
|
||||
@@ -90,4 +103,5 @@ public final class DelegatingWebConnection implements WebConnection {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,6 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
@@ -21,19 +22,23 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
final class ForwardRequestPostProcessor implements RequestPostProcessor {
|
||||
|
||||
private final String forwardUrl;
|
||||
|
||||
public ForwardRequestPostProcessor(String url) {
|
||||
Assert.hasText(url, "Forward url must have text");
|
||||
forwardUrl = url;
|
||||
|
||||
public ForwardRequestPostProcessor(String forwardUrl) {
|
||||
Assert.hasText(forwardUrl, "forwardUrl must not be null or empty");
|
||||
this.forwardUrl = forwardUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
|
||||
request.setServletPath(forwardUrl);
|
||||
request.setServletPath(this.forwardUrl);
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,6 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import java.net.URL;
|
||||
@@ -23,50 +24,45 @@ import java.util.Set;
|
||||
import com.gargoylesoftware.htmlunit.WebRequest;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An implementation of WebRequestMatcher that allows matching on the host and optionally
|
||||
* the port of WebRequest#getUrl(). For example, the following would match any request to
|
||||
* the host "code.jquery.com" without regard for the port:
|
||||
* </p>
|
||||
* A {@link WebRequestMatcher} that allows matching on the host and optionally
|
||||
* the port of {@code WebRequest#getUrl()}.
|
||||
*
|
||||
* <pre>
|
||||
* WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com");
|
||||
* </pre>
|
||||
* <p>For example, the following would match any request to the host
|
||||
* {@code "code.jquery.com"} without regard for the port.
|
||||
*
|
||||
* Multiple hosts can also be passed in. For example, the following would match an request
|
||||
* to the host "code.jquery.com" or the host "cdn.com" without regard for the port:
|
||||
* <pre class="code">WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com");</pre>
|
||||
*
|
||||
* <pre>
|
||||
* WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com", "cdn.com");
|
||||
* </pre>
|
||||
* <p>Multiple hosts can also be passed in. For example, the following would
|
||||
* match any request to the host {@code "code.jquery.com"} or the host
|
||||
* {@code "cdn.com"} without regard for the port.
|
||||
*
|
||||
* <p>
|
||||
* Alternatively, one can also specify the port. For example, the following would match
|
||||
* any request to the host "code.jquery.com" with the port of 80.
|
||||
* </p>
|
||||
* <pre class="code">WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com", "cdn.com");</pre>
|
||||
*
|
||||
* <pre>
|
||||
* WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com:80");
|
||||
* </pre>
|
||||
* <p>Alternatively, one can also specify the port. For example, the following would match
|
||||
* any request to the host {@code "code.jquery.com"} with the port of {@code 80}.
|
||||
*
|
||||
* <p>
|
||||
* The above cdnMatcher would match: "http://code.jquery.com/jquery.js" (default port of
|
||||
* 80) and "http://code.jquery.com:80/jquery.js". However, it would not match
|
||||
* "https://code.jquery.com/jquery.js" (default port of 443).
|
||||
* </p>
|
||||
* <pre class="code">WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com:80");</pre>
|
||||
*
|
||||
* <p>The above {@code cdnMatcher} would match {@code "http://code.jquery.com/jquery.js"}
|
||||
* which has a default port of {@code 80} and {@code "http://code.jquery.com:80/jquery.js"}.
|
||||
* However, it would not match {@code "https://code.jquery.com/jquery.js"}
|
||||
* which has a default port of {@code 443}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
* @see UrlRegexRequestMatcher
|
||||
* @see org.springframework.test.web.servlet.htmlunit.DelegatingWebConnection
|
||||
*/
|
||||
public final class HostRequestMatcher implements WebRequestMatcher {
|
||||
|
||||
private final Set<String> hosts = new HashSet<String>();
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param hosts the hosts to match on (i.e. "localhost", "example.com:443")
|
||||
* Create a new {@code HostRequestMatcher} for the given hosts —
|
||||
* for example: {@code "localhost"}, {@code "example.com:443"}, etc.
|
||||
* @param hosts the hosts to match on
|
||||
*/
|
||||
public HostRequestMatcher(String... hosts) {
|
||||
this.hosts.addAll(Arrays.asList(hosts));
|
||||
@@ -77,16 +73,17 @@ public final class HostRequestMatcher implements WebRequestMatcher {
|
||||
URL url = request.getUrl();
|
||||
String host = url.getHost();
|
||||
|
||||
if(hosts.contains(host)) {
|
||||
if (this.hosts.contains(host)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int port = url.getPort();
|
||||
if(port == -1) {
|
||||
if (port == -1) {
|
||||
port = url.getDefaultPort();
|
||||
}
|
||||
String hostAndPort = host + ":" + port;
|
||||
|
||||
return hosts.contains(hostAndPort);
|
||||
return this.hosts.contains(hostAndPort);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,6 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
@@ -33,11 +34,6 @@ import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.CookieManager;
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
import com.gargoylesoftware.htmlunit.WebRequest;
|
||||
import com.gargoylesoftware.htmlunit.util.NameValuePair;
|
||||
|
||||
import org.springframework.beans.Mergeable;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
@@ -49,21 +45,27 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.CookieManager;
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
import com.gargoylesoftware.htmlunit.WebRequest;
|
||||
import com.gargoylesoftware.htmlunit.util.NameValuePair;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Internal class used to allow a {@link WebRequest} into a {@link MockHttpServletRequest} using Spring MVC Test's
|
||||
* {@link RequestBuilder}.
|
||||
* </p>
|
||||
* <p>
|
||||
* By default the first path segment of the URL is used as the contextPath. To override this default see
|
||||
* {@link #setContextPath(String)}.
|
||||
* </p>
|
||||
* Internal class used to transform a {@link WebRequest} into a
|
||||
* {@link MockHttpServletRequest} using Spring MVC Test's {@link RequestBuilder}.
|
||||
*
|
||||
* <p>By default the first path segment of the URL is used as the contextPath.
|
||||
* To override this default see {@link #setContextPath(String)}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
* @see MockMvcWebConnection
|
||||
*/
|
||||
final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
|
||||
private static final Pattern LOCALE_PATTERN = Pattern.compile("^\\s*(\\w{2})(?:-(\\w{2}))?(?:;q=(\\d+\\.\\d+))?$");
|
||||
|
||||
private final Map<String, MockHttpSession> sessions;
|
||||
|
||||
private final WebClient webClient;
|
||||
@@ -78,18 +80,19 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
|
||||
private RequestPostProcessor forwardPostProcessor;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sessions A {@link Map} of the {@link HttpSession#getId()} to currently managed {@link HttpSession}
|
||||
* objects. Cannot be null.
|
||||
* Construct a new {@code HtmlUnitRequestBuilder}.
|
||||
* @param sessions a {@link Map} from session {@linkplain HttpSession#getId() IDs}
|
||||
* to currently managed {@link HttpSession} objects; never {@code null}
|
||||
* @param webClient the WebClient for retrieving cookies
|
||||
* @param webRequest The {@link WebRequest} to transform into a {@link MockHttpServletRequest}. Cannot be null.
|
||||
* @param webRequest the {@link WebRequest} to transform into a
|
||||
* {@link MockHttpServletRequest}; never {@code null}
|
||||
*/
|
||||
public HtmlUnitRequestBuilder(Map<String, MockHttpSession> sessions, WebClient webClient,
|
||||
WebRequest webRequest) {
|
||||
Assert.notNull(sessions, "sessions cannot be null");
|
||||
Assert.notNull(webClient, "webClient cannot be null");
|
||||
Assert.notNull(webRequest, "webRequest cannot be null");
|
||||
public HtmlUnitRequestBuilder(Map<String, MockHttpSession> sessions, WebClient webClient, WebRequest webRequest) {
|
||||
Assert.notNull(sessions, "sessions map must not be null");
|
||||
Assert.notNull(webClient, "webClient must not be null");
|
||||
Assert.notNull(webRequest, "webRequest must not be null");
|
||||
|
||||
this.sessions = sessions;
|
||||
this.webClient = webClient;
|
||||
@@ -98,12 +101,12 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
|
||||
public MockHttpServletRequest buildRequest(ServletContext servletContext) {
|
||||
String charset = getCharset();
|
||||
String httpMethod = webRequest.getHttpMethod().name();
|
||||
String httpMethod = this.webRequest.getHttpMethod().name();
|
||||
UriComponents uriComponents = uriComponents();
|
||||
|
||||
MockHttpServletRequest result = new HtmlUnitMockHttpServletRequest(servletContext, httpMethod,
|
||||
uriComponents.getPath());
|
||||
parent(result, parentBuilder);
|
||||
parent(result, this.parentBuilder);
|
||||
result.setServerName(uriComponents.getHost()); // needs to be first for additional headers
|
||||
authType(result);
|
||||
result.setCharacterEncoding(charset);
|
||||
@@ -125,27 +128,27 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
}
|
||||
|
||||
private MockHttpServletRequest postProcess(MockHttpServletRequest request) {
|
||||
if(parentPostProcessor != null) {
|
||||
request = parentPostProcessor.postProcessRequest(request);
|
||||
if (this.parentPostProcessor != null) {
|
||||
request = this.parentPostProcessor.postProcessRequest(request);
|
||||
}
|
||||
if(forwardPostProcessor != null) {
|
||||
request = forwardPostProcessor.postProcessRequest(request);
|
||||
if (this.forwardPostProcessor != null) {
|
||||
request = this.forwardPostProcessor.postProcessRequest(request);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private void parent(MockHttpServletRequest result, RequestBuilder parent) {
|
||||
if(parent == null) {
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
MockHttpServletRequest parentRequest = parent.buildRequest(result.getServletContext());
|
||||
|
||||
// session
|
||||
HttpSession parentSession = parentRequest.getSession(false);
|
||||
if(parentSession != null) {
|
||||
if (parentSession != null) {
|
||||
Enumeration<String> attrNames = parentSession.getAttributeNames();
|
||||
while(attrNames.hasMoreElements()) {
|
||||
while (attrNames.hasMoreElements()) {
|
||||
String attrName = attrNames.nextElement();
|
||||
Object attrValue = parentSession.getAttribute(attrName);
|
||||
result.getSession().setAttribute(attrName, attrValue);
|
||||
@@ -154,10 +157,10 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
|
||||
// header
|
||||
Enumeration<String> headerNames = parentRequest.getHeaderNames();
|
||||
while(headerNames.hasMoreElements()) {
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String attrName = headerNames.nextElement();
|
||||
Enumeration<String> attrValues = parentRequest.getHeaders(attrName);
|
||||
while(attrValues.hasMoreElements()) {
|
||||
while (attrValues.hasMoreElements()) {
|
||||
String attrValue = attrValues.nextElement();
|
||||
result.addHeader(attrName, attrValue);
|
||||
}
|
||||
@@ -165,7 +168,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
|
||||
// parameter
|
||||
Map<String, String[]> parentParams = parentRequest.getParameterMap();
|
||||
for(Map.Entry<String,String[]> parentParam : parentParams.entrySet()) {
|
||||
for (Map.Entry<String, String[]> parentParam : parentParams.entrySet()) {
|
||||
String paramName = parentParam.getKey();
|
||||
String[] paramValues = parentParam.getValue();
|
||||
result.addParameter(paramName, paramValues);
|
||||
@@ -173,42 +176,34 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
|
||||
// cookie
|
||||
Cookie[] parentCookies = parentRequest.getCookies();
|
||||
if(parentCookies != null) {
|
||||
if (parentCookies != null) {
|
||||
result.setCookies(parentCookies);
|
||||
}
|
||||
|
||||
// request attribute
|
||||
Enumeration<String> parentAttrNames = parentRequest.getAttributeNames();
|
||||
while(parentAttrNames.hasMoreElements()) {
|
||||
while (parentAttrNames.hasMoreElements()) {
|
||||
String parentAttrName = parentAttrNames.nextElement();
|
||||
result.setAttribute(parentAttrName, parentRequest.getAttribute(parentAttrName));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the contextPath to be used. The value may be null in which case the first path segment of the URL is turned
|
||||
* into the contextPath. Otherwise it must conform to {@link HttpServletRequest#getContextPath()} which states it
|
||||
* can be empty string or it must start with a "/" and not end in a "/".
|
||||
*
|
||||
* @param contextPath A valid contextPath
|
||||
* @throws IllegalArgumentException if contextPath is not a valid {@link HttpServletRequest#getContextPath()}.
|
||||
* Set the contextPath to be used.
|
||||
* <p>The value may be null in which case the first path segment of the
|
||||
* URL is turned into the contextPath. Otherwise it must conform to
|
||||
* {@link HttpServletRequest#getContextPath()} which states it can be
|
||||
* an empty string, or it must start with a "/" and not end with a "/".
|
||||
* @param contextPath a valid contextPath
|
||||
* @throws IllegalArgumentException if the contextPath is not a valid {@link HttpServletRequest#getContextPath()}
|
||||
*/
|
||||
public void setContextPath(String contextPath) {
|
||||
if (contextPath == null || "".equals(contextPath)) {
|
||||
this.contextPath = contextPath;
|
||||
return;
|
||||
}
|
||||
if (contextPath.endsWith("/")) {
|
||||
throw new IllegalArgumentException("contextPath cannot end with /. Got '" + contextPath + "'");
|
||||
}
|
||||
if (!contextPath.startsWith("/")) {
|
||||
throw new IllegalArgumentException("contextPath must start with /. Got '" + contextPath + "'");
|
||||
}
|
||||
MockMvcWebConnection.validateContextPath(contextPath);
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
public void setForwardPostProcessor(RequestPostProcessor postProcessor) {
|
||||
this.forwardPostProcessor = postProcessor;
|
||||
public void setForwardPostProcessor(RequestPostProcessor forwardPostProcessor) {
|
||||
this.forwardPostProcessor = forwardPostProcessor;
|
||||
}
|
||||
|
||||
private void authType(MockHttpServletRequest request) {
|
||||
@@ -220,7 +215,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
}
|
||||
|
||||
private void content(MockHttpServletRequest result, String charset) {
|
||||
String requestBody = webRequest.getRequestBody();
|
||||
String requestBody = this.webRequest.getRequestBody();
|
||||
if (requestBody == null) {
|
||||
return;
|
||||
}
|
||||
@@ -238,7 +233,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
}
|
||||
|
||||
private void contextPath(MockHttpServletRequest result, UriComponents uriComponents) {
|
||||
if (contextPath == null) {
|
||||
if (this.contextPath == null) {
|
||||
List<String> pathSegments = uriComponents.getPathSegments();
|
||||
if (pathSegments.isEmpty()) {
|
||||
result.setContextPath("");
|
||||
@@ -248,11 +243,11 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!uriComponents.getPath().startsWith(contextPath)) {
|
||||
if (!uriComponents.getPath().startsWith(this.contextPath)) {
|
||||
throw new IllegalArgumentException(uriComponents.getPath() + " should start with contextPath "
|
||||
+ contextPath);
|
||||
+ this.contextPath);
|
||||
}
|
||||
result.setContextPath(contextPath);
|
||||
result.setContextPath(this.contextPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,21 +260,20 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
while (tokens.hasMoreTokens()) {
|
||||
String cookieName = tokens.nextToken().trim();
|
||||
if (!tokens.hasMoreTokens()) {
|
||||
throw new IllegalArgumentException("Expected value for cookie name " + cookieName
|
||||
+ ". Full cookie was " + cookieHeaderValue);
|
||||
throw new IllegalArgumentException("Expected value for cookie name '" + cookieName
|
||||
+ "'. Full cookie was " + cookieHeaderValue);
|
||||
}
|
||||
String cookieValue = tokens.nextToken().trim();
|
||||
processCookie(result, cookies, new Cookie(cookieName, cookieValue));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<com.gargoylesoftware.htmlunit.util.Cookie> managedCookies = webClient.getCookies(webRequest.getUrl());
|
||||
Set<com.gargoylesoftware.htmlunit.util.Cookie> managedCookies = this.webClient.getCookies(this.webRequest.getUrl());
|
||||
for (com.gargoylesoftware.htmlunit.util.Cookie cookie : managedCookies) {
|
||||
processCookie(result, cookies, new Cookie(cookie.getName(), cookie.getValue()));
|
||||
}
|
||||
if(parentCookies != null) {
|
||||
for(Cookie cookie : parentCookies) {
|
||||
if (parentCookies != null) {
|
||||
for (Cookie cookie : parentCookies) {
|
||||
cookies.add(cookie);
|
||||
}
|
||||
}
|
||||
@@ -297,7 +291,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
}
|
||||
|
||||
private String getCharset() {
|
||||
String charset = webRequest.getCharset();
|
||||
String charset = this.webRequest.getCharset();
|
||||
if (charset == null) {
|
||||
return "ISO-8859-1";
|
||||
}
|
||||
@@ -305,24 +299,24 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
}
|
||||
|
||||
private String header(String headerName) {
|
||||
return webRequest.getAdditionalHeaders().get(headerName);
|
||||
return this.webRequest.getAdditionalHeaders().get(headerName);
|
||||
}
|
||||
|
||||
private void headers(MockHttpServletRequest result) {
|
||||
for (Entry<String, String> header : webRequest.getAdditionalHeaders().entrySet()) {
|
||||
for (Entry<String, String> header : this.webRequest.getAdditionalHeaders().entrySet()) {
|
||||
result.addHeader(header.getKey(), header.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private MockHttpSession httpSession(MockHttpServletRequest request, final String sessionid) {
|
||||
MockHttpSession session;
|
||||
synchronized (sessions) {
|
||||
session = sessions.get(sessionid);
|
||||
synchronized (this.sessions) {
|
||||
session = this.sessions.get(sessionid);
|
||||
if (session == null) {
|
||||
session = new HtmlUnitMockHttpSession(request, sessionid);
|
||||
session.setNew(true);
|
||||
synchronized (sessions) {
|
||||
sessions.put(sessionid, session);
|
||||
synchronized (this.sessions) {
|
||||
this.sessions.put(sessionid, session);
|
||||
}
|
||||
addSessionCookie(request, sessionid);
|
||||
}
|
||||
@@ -371,7 +365,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (NameValuePair param : webRequest.getRequestParameters()) {
|
||||
for (NameValuePair param : this.webRequest.getRequestParameters()) {
|
||||
result.addParameter(param.getName(), param.getValue());
|
||||
}
|
||||
}
|
||||
@@ -416,7 +410,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
int serverPort = uriComponents.getPort();
|
||||
result.setServerPort(serverPort);
|
||||
if (serverPort == -1) {
|
||||
int portConnection = webRequest.getUrl().getDefaultPort();
|
||||
int portConnection = this.webRequest.getUrl().getDefaultPort();
|
||||
result.setLocalPort(serverPort);
|
||||
result.setRemotePort(portConnection);
|
||||
}
|
||||
@@ -426,7 +420,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
}
|
||||
|
||||
private UriComponents uriComponents() {
|
||||
URL url = webRequest.getUrl();
|
||||
URL url = this.webRequest.getUrl();
|
||||
UriComponentsBuilder uriBldr = UriComponentsBuilder.fromUriString(url.toExternalForm());
|
||||
return uriBldr.build();
|
||||
}
|
||||
@@ -441,7 +435,7 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
if (parent == null) {
|
||||
return this;
|
||||
}
|
||||
if(parent instanceof RequestBuilder) {
|
||||
if (parent instanceof RequestBuilder) {
|
||||
this.parentBuilder = (RequestBuilder) parent;
|
||||
}
|
||||
if (parent instanceof SmartRequestBuilder) {
|
||||
@@ -451,13 +445,13 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An extension to {@link MockHttpServletRequest} that ensures that when a new {@link HttpSession} is created, it is
|
||||
* added to the managed sessions.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* An extension to {@link MockHttpServletRequest} that ensures that
|
||||
* when a new {@link HttpSession} is created, it is added to the managed sessions.
|
||||
*/
|
||||
private final class HtmlUnitMockHttpServletRequest extends MockHttpServletRequest {
|
||||
|
||||
private HtmlUnitMockHttpServletRequest(ServletContext servletContext, String method, String requestURI) {
|
||||
super(servletContext, method, requestURI);
|
||||
}
|
||||
@@ -469,8 +463,8 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
setSession(newSession);
|
||||
newSession.setNew(true);
|
||||
String sessionid = newSession.getId();
|
||||
synchronized (sessions) {
|
||||
sessions.put(sessionid, newSession);
|
||||
synchronized (HtmlUnitRequestBuilder.this.sessions) {
|
||||
HtmlUnitRequestBuilder.this.sessions.put(sessionid, newSession);
|
||||
}
|
||||
addSessionCookie(this, sessionid);
|
||||
result = newSession;
|
||||
@@ -488,12 +482,12 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension to {@link MockHttpSession} that ensures when {@link #invalidate()} is called that the
|
||||
* {@link HttpSession} is removed from the managed sessions.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* An extension to {@link MockHttpSession} that ensures when
|
||||
* {@link #invalidate()} is called that the {@link HttpSession} is
|
||||
* removed from the managed sessions.
|
||||
*/
|
||||
private final class HtmlUnitMockHttpSession extends MockHttpSession {
|
||||
|
||||
private final MockHttpServletRequest request;
|
||||
|
||||
private HtmlUnitMockHttpSession(MockHttpServletRequest request) {
|
||||
@@ -508,16 +502,15 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
|
||||
|
||||
public void invalidate() {
|
||||
super.invalidate();
|
||||
synchronized (sessions) {
|
||||
sessions.remove(getId());
|
||||
synchronized (HtmlUnitRequestBuilder.this.sessions) {
|
||||
HtmlUnitRequestBuilder.this.sessions.remove(getId());
|
||||
}
|
||||
removeSessionCookie(request, getId());
|
||||
}
|
||||
}
|
||||
|
||||
private CookieManager getCookieManager() {
|
||||
return webClient.getCookieManager();
|
||||
return this.webClient.getCookieManager();
|
||||
}
|
||||
|
||||
private static final Pattern LOCALE_PATTERN = Pattern.compile("^\\s*(\\w{2})(?:-(\\w{2}))?(?:;q=(\\d+\\.\\d+))?$");
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,18 +13,22 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
|
||||
/**
|
||||
* Simplifies creating a WebClient that delegates to a MockMvc instance.
|
||||
* {@code MockMvcWebClientBuilder} simplifies the creation of a {@link WebClient}
|
||||
* that delegates to a {@link MockMvc} instance.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public class MockMvcWebClientBuilder extends MockMvcWebConnectionBuilderSupport<MockMvcWebClientBuilder> {
|
||||
@@ -42,56 +46,63 @@ public class MockMvcWebClientBuilder extends MockMvcWebConnectionBuilderSupport<
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with a WebApplicationContext.
|
||||
*
|
||||
* @param context the WebApplicationContext to use. Cannot be null.
|
||||
* Create a new instance with the supplied {@link WebApplicationContext}.
|
||||
* @param context the {@code WebApplicationContext} to create a {@link MockMvc}
|
||||
* instance from; never {@code null}
|
||||
* @return the MockMvcWebClientBuilder to customize
|
||||
*/
|
||||
public static MockMvcWebClientBuilder webAppContextSetup(WebApplicationContext context) {
|
||||
Assert.notNull(context, "WebApplicationContext must not be null");
|
||||
return new MockMvcWebClientBuilder(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance using a WebApplicationContext
|
||||
* @param context the WebApplicationContext to create a MockMvc instance from.
|
||||
* @param configurer the MockMvcConfigurer to apply
|
||||
* Cannot be null.
|
||||
* @return the MockMvcWebClientBuilder to use
|
||||
* Create a new instance with the supplied {@link WebApplicationContext}
|
||||
* and {@link MockMvcConfigurer}.
|
||||
* @param context the {@code WebApplicationContext} to create a {@link MockMvc}
|
||||
* instance from; never {@code null}
|
||||
* @param configurer the MockMvcConfigurer to apply; never {@code null}
|
||||
* @return the MockMvcWebClientBuilder to customize
|
||||
*/
|
||||
public static MockMvcWebClientBuilder webAppContextSetup(WebApplicationContext context, MockMvcConfigurer configurer) {
|
||||
Assert.notNull(context, "WebApplicationContext must not be null");
|
||||
Assert.notNull(configurer, "MockMvcConfigurer must not be null");
|
||||
return new MockMvcWebClientBuilder(context, configurer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with a MockMvc instance.
|
||||
*
|
||||
* @param mockMvc the MockMvc to use. Cannot be null.
|
||||
* Create a new instance with the supplied {@link MockMvc} instance.
|
||||
* @param mockMvc the {@code MockMvc} instance to use; never {@code null}
|
||||
* @return the MockMvcWebClientBuilder to customize
|
||||
*/
|
||||
public static MockMvcWebClientBuilder mockMvcSetup(MockMvc mockMvc) {
|
||||
Assert.notNull(mockMvc, "MockMvc must not be null");
|
||||
return new MockMvcWebClientBuilder(mockMvc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a WebClient that uses the provided MockMvc for any matching requests and a
|
||||
* WebClient with all the default settings for any other request.
|
||||
*
|
||||
* @return the WebClient to use
|
||||
* Create a {@link WebClient} that uses the configured {@link MockMvc}
|
||||
* instance for any matching requests and a {@code WebClient} with all
|
||||
* the default settings for any other requests.
|
||||
* @return the {@code WebClient} to use
|
||||
* @see #configureWebClient(WebClient)
|
||||
*/
|
||||
public WebClient createWebClient() {
|
||||
return configureWebClient(new WebClient());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a WebClient that uses the provided MockMvc for any matching requests and the
|
||||
* provided WebClient for any other request.
|
||||
*
|
||||
* @param webClient The WebClient to delegate to for requests that do not match. Cannot be null.
|
||||
*
|
||||
* Configure the supplied {@link WebClient} to use the configured
|
||||
* {@link MockMvc} instance for any matching requests and the supplied
|
||||
* {@code WebClient} for any other requests.
|
||||
* @param webClient the WebClient to delegate to for requests that do not
|
||||
* match; never {@code null}
|
||||
* @return the WebClient to use
|
||||
*/
|
||||
public WebClient configureWebClient(WebClient webClient) {
|
||||
Assert.notNull(webClient, "webClient must not be null");
|
||||
webClient.setWebConnection(createConnection(webClient.getWebConnection()));
|
||||
return webClient;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,18 +13,12 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
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 org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
@@ -34,31 +28,33 @@ import org.springframework.test.web.servlet.ResultActions;
|
||||
import org.springframework.test.web.servlet.htmlunit.webdriver.WebConnectionHtmlUnitDriver;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
import com.gargoylesoftware.htmlunit.WebConnection;
|
||||
import com.gargoylesoftware.htmlunit.WebRequest;
|
||||
import com.gargoylesoftware.htmlunit.WebResponse;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Allows {@link MockMvc} to transform a {@link WebRequest} into a {@link WebResponse}. This is the core integration
|
||||
* with <a href="http://htmlunit.sourceforge.net/">HTML Unit</a>.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example usage can be seen below:
|
||||
* </p>
|
||||
* {@code MockMvcWebConnection} enables {@link MockMvc} to transform a
|
||||
* {@link WebRequest} into a {@link WebResponse}.
|
||||
* <p>This is the core integration with <a href="http://htmlunit.sourceforge.net/">HtmlUnit</a>.
|
||||
* <p>Example usage can be seen below.
|
||||
*
|
||||
* <pre>
|
||||
* <pre class="code">
|
||||
* WebClient webClient = new WebClient();
|
||||
* MockMvc mockMvc = ...
|
||||
* MockMvcWebConnection webConnection = new MockMvcWebConnection(mockMvc);
|
||||
* mockConnection.setWebClient(webClient);
|
||||
* webClient.setWebConnection(webConnection);
|
||||
*
|
||||
* ... use webClient as normal ...
|
||||
* // Use webClient as normal ...
|
||||
* </pre>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
* @see WebConnectionHtmlUnitDriver
|
||||
*/
|
||||
public final class MockMvcWebConnection implements WebConnection {
|
||||
private WebClient webClient;
|
||||
|
||||
private final Map<String, MockHttpSession> sessions = new HashMap<String, MockHttpSession>();
|
||||
|
||||
@@ -66,26 +62,32 @@ public final class MockMvcWebConnection implements WebConnection {
|
||||
|
||||
private final String contextPath;
|
||||
|
||||
private WebClient webClient;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance that assumes the context root of the application is "". For example,
|
||||
* the URL http://localhost/test/this would use "" as the context root.
|
||||
*
|
||||
* @param mockMvc the MockMvc instance to use
|
||||
* Create a new instance that assumes the context path of the application
|
||||
* is {@code ""} (i.e., the root context).
|
||||
* <p>For example, the URL {@code http://localhost/test/this} would use
|
||||
* {@code ""} as the context path.
|
||||
* @param mockMvc the {@code MockMvc} instance to use; never {@code null}
|
||||
*/
|
||||
public MockMvcWebConnection(MockMvc mockMvc) {
|
||||
this(mockMvc, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with a specified context root.
|
||||
*
|
||||
* @param mockMvc the MockMvc instance to use
|
||||
* @param contextPath the contextPath to use. The value may be null in which case the first path segment of the URL is turned
|
||||
* into the contextPath. Otherwise it must conform to {@link HttpServletRequest#getContextPath()} which states it
|
||||
* can be empty string or it must start with a "/" and not end in a "/".
|
||||
* Create a new instance with the specified context path.
|
||||
* <p>The path may be {@code null} in which case the first path segment
|
||||
* of the URL is turned into the contextPath. Otherwise it must conform
|
||||
* to {@link javax.servlet.http.HttpServletRequest#getContextPath()}
|
||||
* which states that it can be an empty string and otherwise must start
|
||||
* with a "/" character and not end with a "/" character.
|
||||
* @param mockMvc the {@code MockMvc} instance to use; never {@code null}
|
||||
* @param contextPath the contextPath to use
|
||||
*/
|
||||
public MockMvcWebConnection(MockMvc mockMvc, String contextPath) {
|
||||
Assert.notNull(mockMvc, "mockMvc cannot be null");
|
||||
Assert.notNull(mockMvc, "mockMvc must not be null");
|
||||
validateContextPath(contextPath);
|
||||
|
||||
this.webClient = new WebClient();
|
||||
@@ -95,13 +97,13 @@ public final class MockMvcWebConnection implements WebConnection {
|
||||
|
||||
public WebResponse getResponse(WebRequest webRequest) throws IOException {
|
||||
long startTime = System.currentTimeMillis();
|
||||
HtmlUnitRequestBuilder requestBuilder = new HtmlUnitRequestBuilder(sessions, webClient, webRequest);
|
||||
requestBuilder.setContextPath(contextPath);
|
||||
HtmlUnitRequestBuilder requestBuilder = new HtmlUnitRequestBuilder(this.sessions, this.webClient, webRequest);
|
||||
requestBuilder.setContextPath(this.contextPath);
|
||||
|
||||
MockHttpServletResponse httpServletResponse = getResponse(requestBuilder);
|
||||
|
||||
String forwardedUrl = httpServletResponse.getForwardedUrl();
|
||||
while(forwardedUrl != null) {
|
||||
while (forwardedUrl != null) {
|
||||
requestBuilder.setForwardPostProcessor(new ForwardRequestPostProcessor(forwardedUrl));
|
||||
httpServletResponse = getResponse(requestBuilder);
|
||||
forwardedUrl = httpServletResponse.getForwardedUrl();
|
||||
@@ -111,18 +113,14 @@ public final class MockMvcWebConnection implements WebConnection {
|
||||
}
|
||||
|
||||
public void setWebClient(WebClient webClient) {
|
||||
Assert.notNull(webClient, "webClient cannot be null");
|
||||
Assert.notNull(webClient, "webClient must not be null");
|
||||
this.webClient = webClient;
|
||||
}
|
||||
|
||||
private CookieManager getCookieManager() {
|
||||
return webClient.getCookieManager();
|
||||
}
|
||||
|
||||
private MockHttpServletResponse getResponse(RequestBuilder requestBuilder) throws IOException {
|
||||
ResultActions resultActions;
|
||||
try {
|
||||
resultActions = mockMvc.perform(requestBuilder);
|
||||
resultActions = this.mockMvc.perform(requestBuilder);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw (IOException) new IOException(e.getMessage()).initCause(e);
|
||||
@@ -132,19 +130,23 @@ public final class MockMvcWebConnection implements WebConnection {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs validation on the contextPath
|
||||
*
|
||||
* @param contextPath the contextPath to validate
|
||||
* Validate the supplied {@code contextPath}.
|
||||
* <p>If the value is not {@code null}, it must conform to
|
||||
* {@link javax.servlet.http.HttpServletRequest#getContextPath()} which
|
||||
* states that it can be an empty string and otherwise must start with
|
||||
* a "/" character and not end with a "/" character.
|
||||
* @param contextPath the path to validate
|
||||
*/
|
||||
private static void validateContextPath(String contextPath) {
|
||||
static void validateContextPath(String contextPath) {
|
||||
if (contextPath == null || "".equals(contextPath)) {
|
||||
return;
|
||||
}
|
||||
if (contextPath.endsWith("/")) {
|
||||
throw new IllegalArgumentException("contextPath cannot end with /. Got '" + contextPath + "'");
|
||||
}
|
||||
if (!contextPath.startsWith("/")) {
|
||||
throw new IllegalArgumentException("contextPath must start with /. Got '" + contextPath + "'");
|
||||
throw new IllegalArgumentException("contextPath '" + contextPath + "' must start with '/'.");
|
||||
}
|
||||
if (contextPath.endsWith("/")) {
|
||||
throw new IllegalArgumentException("contextPath '" + contextPath + "' must not end with '/'.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,72 +13,80 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebConnection;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebConnection;
|
||||
|
||||
/**
|
||||
* Makes it easy to create a WebConnection that uses MockMvc and optionally delegates to
|
||||
* a real WebConnection for specific requests. The default is to use MockMvc for any host
|
||||
* that is "localhost" and otherwise use a real WebConnection.
|
||||
* Support class that simplifies the creation of a {@link WebConnection} that
|
||||
* uses {@link MockMvc} and optionally delegates to a real {@link WebConnection}
|
||||
* for specific requests.
|
||||
*
|
||||
* <p>The default is to use {@link MockMvc} for requests to {@code localhost}
|
||||
* and otherwise use a real {@link WebConnection}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public abstract class MockMvcWebConnectionBuilderSupport<T extends MockMvcWebConnectionBuilderSupport<T>> {
|
||||
private String contextPath = "";
|
||||
|
||||
private final MockMvc mockMvc;
|
||||
|
||||
private List<WebRequestMatcher> mockMvcRequestMatchers = new ArrayList<WebRequestMatcher>();
|
||||
private final List<WebRequestMatcher> mockMvcRequestMatchers = new ArrayList<WebRequestMatcher>();
|
||||
|
||||
private String contextPath = "";
|
||||
|
||||
private boolean alwaysUseMockMvc;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance using a MockMvc instance
|
||||
*
|
||||
* @param mockMvc the MockMvc instance to use. Cannot be null.
|
||||
* Create a new instance using the supplied {@link MockMvc} instance.
|
||||
* @param mockMvc the {@code MockMvc} instance to use; never {@code null}
|
||||
*/
|
||||
protected MockMvcWebConnectionBuilderSupport(MockMvc mockMvc) {
|
||||
Assert.notNull(mockMvc, "mockMvc cannot be null");
|
||||
Assert.notNull(mockMvc, "mockMvc must not be null");
|
||||
this.mockMvc = mockMvc;
|
||||
this.mockMvcRequestMatchers.add(new HostRequestMatcher("localhost"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance using a WebApplicationContext
|
||||
* @param context the WebApplicationContext to create a MockMvc instance from.
|
||||
* Cannot be null.
|
||||
* Create a new instance using the supplied {@link WebApplicationContext}.
|
||||
* @param context the {@code WebApplicationContext} to create a {@code MockMvc}
|
||||
* instance from; never {@code null}
|
||||
*/
|
||||
protected MockMvcWebConnectionBuilderSupport(WebApplicationContext context) {
|
||||
this(MockMvcBuilders.webAppContextSetup(context).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance using a WebApplicationContext
|
||||
* @param context the WebApplicationContext to create a MockMvc instance from.
|
||||
* @param configurer the MockMvcConfigurer to apply
|
||||
* Cannot be null.
|
||||
* Create a new instance using the supplied {@link WebApplicationContext}
|
||||
* and {@link MockMvcConfigurer}.
|
||||
* @param context the {@code WebApplicationContext} to create a {@code MockMvc}
|
||||
* instance from; never {@code null}
|
||||
* @param configurer the MockMvcConfigurer to apply; never {@code null}
|
||||
*/
|
||||
protected MockMvcWebConnectionBuilderSupport(WebApplicationContext context, MockMvcConfigurer configurer) {
|
||||
this(MockMvcBuilders.webAppContextSetup(context).apply(configurer).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* The context path to use. Default is "". If the value is null, then the first path
|
||||
* Set the context path to use.
|
||||
* <p>If the supplied value is {@code null} or empty, the first path
|
||||
* segment of the request URL is assumed to be the context path.
|
||||
*
|
||||
* @param contextPath the context path to use.
|
||||
* @return the builder for further customization
|
||||
* <p>Default is {@code ""}.
|
||||
* @param contextPath the context path to use
|
||||
* @return this builder for further customization
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T contextPath(String contextPath) {
|
||||
@@ -87,9 +95,9 @@ public abstract class MockMvcWebConnectionBuilderSupport<T extends MockMvcWebCon
|
||||
}
|
||||
|
||||
/**
|
||||
* Always use MockMvc no matter what the request looks like.
|
||||
*
|
||||
* @return the builder for further customization
|
||||
* Specify that {@link MockMvc} should always be used regardless of
|
||||
* what the request looks like.
|
||||
* @return this builder for further customization
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T alwaysUseMockMvc() {
|
||||
@@ -98,26 +106,26 @@ public abstract class MockMvcWebConnectionBuilderSupport<T extends MockMvcWebCon
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional WebRequestMatcher instances that if return true will ensure MockMvc
|
||||
* is used.
|
||||
*
|
||||
* @param matchers the WebRequestMatcher instances that if true will ensure MockMvc
|
||||
* processes the request.
|
||||
* @return the builder for further customization
|
||||
* Add additional {@link WebRequestMatcher} instances that will ensure
|
||||
* that {@link MockMvc} is used to process the request, if such a matcher
|
||||
* matches against the web request.
|
||||
* @param matchers additional {@code WebRequestMatcher} instances
|
||||
* @return this builder for further customization
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T useMockMvc(WebRequestMatcher... matchers) {
|
||||
for(WebRequestMatcher matcher : matchers) {
|
||||
for (WebRequestMatcher matcher : matchers) {
|
||||
this.mockMvcRequestMatchers.add(matcher);
|
||||
}
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional WebRequestMatcher instances that will return true if the host matches.
|
||||
*
|
||||
* @param hosts the additional hosts that will ensure MockMvc gets invoked (i.e. example.com or example.com:8080).
|
||||
* @return the builder for further customization
|
||||
* Add additional {@link WebRequestMatcher} instances that return {@code true}
|
||||
* if a supplied host matches — for example, {@code "example.com"} or
|
||||
* {@code "example.com:8080"}.
|
||||
* @param hosts additional hosts that ensure {@code MockMvc} gets invoked
|
||||
* @return this builder for further customization
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T useMockMvcForHosts(String... hosts) {
|
||||
@@ -126,31 +134,32 @@ public abstract class MockMvcWebConnectionBuilderSupport<T extends MockMvcWebCon
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new WebConnection that will use a MockMvc instance if one of the
|
||||
* specified WebRequestMatcher matches.
|
||||
*
|
||||
* @param defaultConnection the default WebConnection to use if none of the specified
|
||||
* WebRequestMatcher instances match. Cannot be null.
|
||||
* @return a new WebConnection that will use a MockMvc instance if one of the
|
||||
* specified WebRequestMatcher matches.
|
||||
*
|
||||
* @see #alwaysUseMockMvc
|
||||
* Create a new {@link WebConnection} that will use a {@link MockMvc}
|
||||
* instance if one of the specified {@link WebRequestMatcher} instances
|
||||
* matches.
|
||||
* @param defaultConnection the default WebConnection to use if none of
|
||||
* the specified {@code WebRequestMatcher} instances matches; never {@code null}
|
||||
* @return a new {@code WebConnection} that will use a {@code MockMvc}
|
||||
* instance if one of the specified {@code WebRequestMatcher} matches
|
||||
* @see #alwaysUseMockMvc()
|
||||
* @see #useMockMvc(WebRequestMatcher...)
|
||||
* @see #useMockMvcForHosts(String...)
|
||||
*/
|
||||
protected final WebConnection createConnection(WebConnection defaultConnection) {
|
||||
Assert.notNull(defaultConnection, "defaultConnection cannot be null");
|
||||
MockMvcWebConnection mockMvcWebConnection = new MockMvcWebConnection(mockMvc, contextPath);
|
||||
Assert.notNull(defaultConnection, "defaultConnection must not be null");
|
||||
MockMvcWebConnection mockMvcWebConnection = new MockMvcWebConnection(this.mockMvc, this.contextPath);
|
||||
|
||||
if(alwaysUseMockMvc) {
|
||||
if (this.alwaysUseMockMvc) {
|
||||
return mockMvcWebConnection;
|
||||
}
|
||||
|
||||
List<DelegatingWebConnection.DelegateWebConnection> delegates = new ArrayList<DelegatingWebConnection.DelegateWebConnection>(mockMvcRequestMatchers.size());
|
||||
for(WebRequestMatcher matcher : mockMvcRequestMatchers) {
|
||||
List<DelegatingWebConnection.DelegateWebConnection> delegates = new ArrayList<DelegatingWebConnection.DelegateWebConnection>(
|
||||
this.mockMvcRequestMatchers.size());
|
||||
for (WebRequestMatcher matcher : this.mockMvcRequestMatchers) {
|
||||
delegates.add(new DelegatingWebConnection.DelegateWebConnection(matcher, mockMvcWebConnection));
|
||||
}
|
||||
|
||||
return new DelegatingWebConnection(defaultConnection, delegates);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,6 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -20,32 +21,38 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebRequest;
|
||||
import com.gargoylesoftware.htmlunit.WebResponse;
|
||||
import com.gargoylesoftware.htmlunit.WebResponseData;
|
||||
import com.gargoylesoftware.htmlunit.util.NameValuePair;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
final class MockWebResponseBuilder {
|
||||
|
||||
private static final String DEFAULT_STATUS_MESSAGE = "N/A";
|
||||
|
||||
private final long startTime;
|
||||
|
||||
private final WebRequest webRequest;
|
||||
|
||||
private final MockHttpServletResponse response;
|
||||
|
||||
public MockWebResponseBuilder(long startTime, WebRequest webRequest, MockHttpServletResponse httpServletResponse) {
|
||||
Assert.notNull(webRequest, "webRequest");
|
||||
Assert.notNull(httpServletResponse, "httpServletResponse cannot be null");
|
||||
|
||||
public MockWebResponseBuilder(long startTime, WebRequest webRequest, MockHttpServletResponse response) {
|
||||
Assert.notNull(webRequest, "webRequest must not be null");
|
||||
Assert.notNull(response, "response must not be null");
|
||||
this.startTime = startTime;
|
||||
this.webRequest = webRequest;
|
||||
this.response = httpServletResponse;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public WebResponse build() throws IOException {
|
||||
@@ -56,38 +63,42 @@ final class MockWebResponseBuilder {
|
||||
|
||||
private WebResponseData webResponseData() throws IOException {
|
||||
List<NameValuePair> responseHeaders = responseHeaders();
|
||||
int statusCode = response.getRedirectedUrl() == null ? response.getStatus() : 301;
|
||||
int statusCode = (this.response.getRedirectedUrl() != null ? HttpStatus.MOVED_PERMANENTLY.value()
|
||||
: this.response.getStatus());
|
||||
String statusMessage = statusMessage(statusCode);
|
||||
return new WebResponseData(response.getContentAsByteArray(), statusCode, statusMessage, responseHeaders);
|
||||
return new WebResponseData(this.response.getContentAsByteArray(), statusCode, statusMessage, responseHeaders);
|
||||
}
|
||||
|
||||
private String statusMessage(int statusCode) {
|
||||
String errorMessage = response.getErrorMessage();
|
||||
if (errorMessage != null) {
|
||||
String errorMessage = this.response.getErrorMessage();
|
||||
if (StringUtils.hasText(errorMessage)) {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
try {
|
||||
return HttpStatus.valueOf(statusCode).getReasonPhrase();
|
||||
}
|
||||
catch (IllegalArgumentException useDefault) {
|
||||
catch (IllegalArgumentException ex) {
|
||||
// ignore
|
||||
}
|
||||
;
|
||||
return "N/A";
|
||||
|
||||
return DEFAULT_STATUS_MESSAGE;
|
||||
}
|
||||
|
||||
private List<NameValuePair> responseHeaders() {
|
||||
Collection<String> headerNames = response.getHeaderNames();
|
||||
Collection<String> headerNames = this.response.getHeaderNames();
|
||||
List<NameValuePair> responseHeaders = new ArrayList<NameValuePair>(headerNames.size());
|
||||
for (String headerName : headerNames) {
|
||||
List<Object> headerValues = response.getHeaderValues(headerName);
|
||||
List<Object> headerValues = this.response.getHeaderValues(headerName);
|
||||
for (Object value : headerValues) {
|
||||
responseHeaders.add(new NameValuePair(headerName, String.valueOf(value)));
|
||||
}
|
||||
}
|
||||
String location = response.getRedirectedUrl();
|
||||
String location = this.response.getRedirectedUrl();
|
||||
if (location != null) {
|
||||
responseHeaders.add(new NameValuePair("Location", location));
|
||||
}
|
||||
return responseHeaders;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,6 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
@@ -20,22 +21,25 @@ import java.util.regex.Pattern;
|
||||
import com.gargoylesoftware.htmlunit.WebRequest;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An implementation of WebRequestMatcher that allows matching on WebRequest#getUrl().toExternalForm() using a regular expression. For example, if you would like to match on the domain code.jquery.com, you might want to use the following:</p>
|
||||
* A {@link WebRequestMatcher} that allows matching on
|
||||
* {@code WebRequest#getUrl().toExternalForm()} using a regular expression.
|
||||
*
|
||||
* <pre>
|
||||
* WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*");
|
||||
* </pre>
|
||||
* <p>For example, if you would like to match on the domain {@code code.jquery.com},
|
||||
* you might want to use the following.
|
||||
*
|
||||
* <pre class="code">WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*");</pre>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
* @see org.springframework.test.web.servlet.htmlunit.DelegatingWebConnection
|
||||
*/
|
||||
public final class UrlRegexRequestMatcher implements WebRequestMatcher {
|
||||
private Pattern pattern;
|
||||
|
||||
private final Pattern pattern;
|
||||
|
||||
public UrlRegexRequestMatcher(String regex) {
|
||||
pattern = Pattern.compile(regex);
|
||||
this.pattern = Pattern.compile(regex);
|
||||
}
|
||||
|
||||
public UrlRegexRequestMatcher(Pattern pattern) {
|
||||
@@ -45,6 +49,7 @@ public final class UrlRegexRequestMatcher implements WebRequestMatcher {
|
||||
@Override
|
||||
public boolean matches(WebRequest request) {
|
||||
String url = request.getUrl().toExternalForm();
|
||||
return pattern.matcher(url).matches();
|
||||
return this.pattern.matcher(url).matches();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,22 +13,24 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebRequest;
|
||||
|
||||
/**
|
||||
* Strategy to match on a WebRequest
|
||||
* Strategy for matching on a {@link WebRequest}.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface WebRequestMatcher {
|
||||
|
||||
/**
|
||||
* Return true if matches on WebRequest, else false
|
||||
*
|
||||
* @param request the WebRequest to attempt to match on
|
||||
* @return true if matches on WebRequest, else false
|
||||
* Whether this matcher matches on the supplied web request.
|
||||
* @param request the {@link WebRequest} to attempt to match on
|
||||
* @return {@code true} if this matcher matches on the {@code WebRequest}
|
||||
*/
|
||||
boolean matches(WebRequest request);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/**
|
||||
* Support for MockMvc and HtmlUnit integration
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 4.2
|
||||
* Server-side support for testing Spring MVC applications with {@code MockMvc}
|
||||
* and HtmlUnit.
|
||||
* @see org.springframework.test.web.servlet.MockMvc
|
||||
*/
|
||||
package org.springframework.test.web.servlet.htmlunit;
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,9 +13,9 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit.webdriver;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.BrowserVersion;
|
||||
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
|
||||
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
@@ -23,18 +23,27 @@ import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnectionBuilder
|
||||
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.BrowserVersion;
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
|
||||
/**
|
||||
* Convenience class for building an HtmlUnitDriver that will delegate to MockMvc and
|
||||
* optionally delegate to an actual connection for specific requests.
|
||||
* Convenience class for building an {@link HtmlUnitDriver} that delegates
|
||||
* to {@link MockMvc} and optionally delegates to an actual connection for
|
||||
* specific requests.
|
||||
*
|
||||
* By default localhost will delegate to MockMvc and any other URL will delegate
|
||||
* <p>By default, the driver will delegate to {@code MockMvc} to handle
|
||||
* requests to {@code localhost} and to a {@link WebClient} to handle any
|
||||
* other URL (i.e. to perform an actual HTTP request).
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
*/
|
||||
public class MockMvcHtmlUnitDriverBuilder extends MockMvcWebConnectionBuilderSupport<MockMvcHtmlUnitDriverBuilder> {
|
||||
|
||||
private boolean javascriptEnabled = true;
|
||||
|
||||
|
||||
protected MockMvcHtmlUnitDriverBuilder(MockMvc mockMvc) {
|
||||
super(mockMvc);
|
||||
}
|
||||
@@ -48,9 +57,8 @@ public class MockMvcHtmlUnitDriverBuilder extends MockMvcWebConnectionBuilderSup
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with a WebApplicationContext.
|
||||
*
|
||||
* @param context the WebApplicationContext to use. Cannot be null.
|
||||
* Create a new instance using the supplied {@link WebApplicationContext}.
|
||||
* @param context the WebApplicationContext to use; never {@code null}
|
||||
* @return the MockMvcHtmlUnitDriverBuilder to customize
|
||||
*/
|
||||
public static MockMvcHtmlUnitDriverBuilder webAppContextSetup(WebApplicationContext context) {
|
||||
@@ -58,20 +66,21 @@ public class MockMvcHtmlUnitDriverBuilder extends MockMvcWebConnectionBuilderSup
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance using a WebApplicationContext
|
||||
* @param context the WebApplicationContext to create a MockMvc instance from.
|
||||
* @param configurer the MockMvcConfigurer to apply
|
||||
* Cannot be null.
|
||||
* Create a new instance using the supplied {@link WebApplicationContext}
|
||||
* and {@link MockMvcConfigurer}.
|
||||
* @param context the WebApplicationContext to create a MockMvc instance from;
|
||||
* never {@code null}
|
||||
* @param configurer the MockMvcConfigurer to apply; never {@code null}
|
||||
* @return the MockMvcHtmlUnitDriverBuilder to customize
|
||||
*/
|
||||
public static MockMvcHtmlUnitDriverBuilder webAppContextSetup(WebApplicationContext context, MockMvcConfigurer configurer) {
|
||||
public static MockMvcHtmlUnitDriverBuilder webAppContextSetup(WebApplicationContext context,
|
||||
MockMvcConfigurer configurer) {
|
||||
return new MockMvcHtmlUnitDriverBuilder(context, configurer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with a MockMvc instance.
|
||||
*
|
||||
* @param mockMvc the MockMvc to use. Cannot be null.
|
||||
* Create a new instance using the supplied {@link MockMvc} instance.
|
||||
* @param mockMvc the MockMvc instance to use; never {@code null}
|
||||
* @return the MockMvcHtmlUnitDriverBuilder to customize
|
||||
*/
|
||||
public static MockMvcHtmlUnitDriverBuilder mockMvcSetup(MockMvc mockMvc) {
|
||||
@@ -79,8 +88,8 @@ public class MockMvcHtmlUnitDriverBuilder extends MockMvcWebConnectionBuilderSup
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies if JavaScript should be enabled or not. Default is true.
|
||||
*
|
||||
* Specify whether JavaScript should be enabled.
|
||||
* <p>Default is {@code true}.
|
||||
* @param javascriptEnabled if JavaScript should be enabled or not.
|
||||
* @return the builder for further customizations
|
||||
*/
|
||||
@@ -90,10 +99,10 @@ public class MockMvcHtmlUnitDriverBuilder extends MockMvcWebConnectionBuilderSup
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new HtmlUnitDriver with the BrowserVersion set to CHROME. For additional
|
||||
* configuration options, use configureDriver.
|
||||
*
|
||||
* @return the HtmlUnitDriver to use
|
||||
* Create a new {@link HtmlUnitDriver} with the {@link BrowserVersion}
|
||||
* set to {@link BrowserVersion#CHROME CHROME}.
|
||||
* <p>For additional configuration options, use {@link #configureDriver}.
|
||||
* @return the {@code HtmlUnitDriver} to use
|
||||
* @see #configureDriver(WebConnectionHtmlUnitDriver)
|
||||
*/
|
||||
public HtmlUnitDriver createDriver() {
|
||||
@@ -101,14 +110,14 @@ public class MockMvcHtmlUnitDriverBuilder extends MockMvcWebConnectionBuilderSup
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures an existing WebConnectionHtmlUnitDriver.
|
||||
*
|
||||
* Configure an existing {@link WebConnectionHtmlUnitDriver}.
|
||||
* @param driver the WebConnectionHtmlUnitDriver to configure
|
||||
* @return the HtmlUnitDriver to use
|
||||
* @return the {@code HtmlUnitDriver} to use
|
||||
*/
|
||||
public HtmlUnitDriver configureDriver(WebConnectionHtmlUnitDriver driver) {
|
||||
driver.setJavascriptEnabled(javascriptEnabled);
|
||||
driver.setWebConnection(createConnection(driver.getWebConnection()));
|
||||
return driver;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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
|
||||
@@ -13,31 +13,38 @@
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.htmlunit.webdriver;
|
||||
|
||||
import org.openqa.selenium.Capabilities;
|
||||
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
|
||||
|
||||
import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnection;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.BrowserVersion;
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
import com.gargoylesoftware.htmlunit.WebConnection;
|
||||
import org.openqa.selenium.Capabilities;
|
||||
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Allows configuring the WebConnection for an HtmlUnitDriver instance. This is useful
|
||||
* because it allows a MockMvcWebConnection to be injected.
|
||||
* </p>
|
||||
* {@code WebConnectionHtmlUnitDriver} enables configuration of the
|
||||
* {@link WebConnection} for an {@link HtmlUnitDriver} instance.
|
||||
*
|
||||
* <p>This is useful because it allows a {@link MockMvcWebConnection} to
|
||||
* be injected.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
* @see MockMvcHtmlUnitDriverBuilder
|
||||
*/
|
||||
public class WebConnectionHtmlUnitDriver extends HtmlUnitDriver {
|
||||
|
||||
private WebClient webClient;
|
||||
|
||||
public WebConnectionHtmlUnitDriver(BrowserVersion version) {
|
||||
super(version);
|
||||
|
||||
public WebConnectionHtmlUnitDriver(BrowserVersion browserVersion) {
|
||||
super(browserVersion);
|
||||
}
|
||||
|
||||
public WebConnectionHtmlUnitDriver() {
|
||||
@@ -52,45 +59,48 @@ public class WebConnectionHtmlUnitDriver extends HtmlUnitDriver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures the WebClient that is used so that its WebConnection is accessible.
|
||||
*
|
||||
* @param client The client to modify
|
||||
* @return The modified client
|
||||
* Modify the supplied {@link WebClient}, {@linkplain #configureWebClient
|
||||
* configure} it, and retain a reference to it so that its {@link WebConnection}
|
||||
* is {@linkplain #getWebConnection accessible} for later use.
|
||||
* @param client the client to modify
|
||||
* @return the modified client
|
||||
* @see org.openqa.selenium.htmlunit.HtmlUnitDriver#modifyWebClient(WebClient)
|
||||
*/
|
||||
@Override
|
||||
protected final WebClient modifyWebClient(WebClient client) {
|
||||
webClient = super.modifyWebClient(client);
|
||||
webClient = configureWebClient(webClient);
|
||||
return webClient;
|
||||
protected final WebClient modifyWebClient(WebClient webClient) {
|
||||
this.webClient = super.modifyWebClient(webClient);
|
||||
this.webClient = configureWebClient(this.webClient);
|
||||
return this.webClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can override this method to customise the WebClient that the HtmlUnit
|
||||
* driver uses.
|
||||
*
|
||||
* @param client The client to modify
|
||||
* @return The modified client
|
||||
* Configure the supplied {@link WebClient}.
|
||||
* <p>The default implementation simply returns the supplied client
|
||||
* unmodified.
|
||||
* <p>Subclasses can override this method to customize the {@code WebClient}
|
||||
* that the {@link HtmlUnitDriver} driver uses.
|
||||
* @param client the client to configure
|
||||
* @return the configured client
|
||||
*/
|
||||
protected WebClient configureWebClient(WebClient client) {
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows accessing the current WebConnection
|
||||
*
|
||||
* @return the current WebConnection
|
||||
* Access the current {@link WebConnection} for the {@link WebClient}.
|
||||
* @return the current {@code WebConnection}
|
||||
*/
|
||||
public WebConnection getWebConnection() {
|
||||
return webClient.getWebConnection();
|
||||
return this.webClient.getWebConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the WebConnection to be used.
|
||||
*
|
||||
* @param webConnection the WebConnection to use. Cannot be null.
|
||||
* Set the {@link WebConnection} to be used with the {@link WebClient}.
|
||||
* @param webConnection the {@code WebConnection} to use; never {@code null}
|
||||
*/
|
||||
public void setWebConnection(WebConnection webConnection) {
|
||||
Assert.notNull(webConnection, "webConnection cannot be null");
|
||||
Assert.notNull(webConnection, "WebConnection must not be null");
|
||||
this.webClient.setWebConnection(webConnection);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Support for MockMvc and HtmlUnitDriver
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 4.2
|
||||
* Server-side support for testing Spring MVC applications with {@code MockMvc}
|
||||
* and the Selenium {@code HtmlUnitDriver}.
|
||||
* @see org.springframework.test.web.servlet.MockMvc
|
||||
* @see org.openqa.selenium.htmlunit.HtmlUnitDriver
|
||||
*/
|
||||
package org.springframework.test.web.servlet.htmlunit.webdriver;
|
||||
Reference in New Issue
Block a user