提交 b73e3942 编写于 作者: R Rob Winch 提交者: Sam Brannen

Introduce support for HtmlUnit in Spring MVC Test

This commit introduces integration between MockMvc and HtmlUnit, thus
simplifying end-to-end testing when using HTML-based views and enabling
developers to do the following.

 - Easily test HTML pages using tools such as HtmlUnit, WebDriver, & Geb
   without the need to deploy to a Servlet container

 - Test JavaScript within pages

 - Optionally test using mock services to speed up testing

 - Share logic between in-container, end-to-end tests and
   out-of-container integration tests

Issue: SPR-13158
上级 c5a037a5
......@@ -44,6 +44,7 @@ configure(allprojects) { project ->
ext.httpclientVersion = "4.5"
ext.httpasyncVersion = "4.1"
ext.jackson2Version = "2.6.0"
ext.htmlunitVersion = "2.17"
ext.jasperreportsVersion = "6.1.0"
ext.javamailVersion = "1.5.4"
ext.jettyVersion = "9.3.1.v20150714"
......@@ -56,6 +57,7 @@ configure(allprojects) { project ->
ext.poiVersion = "3.12"
ext.protobufVersion = "2.6.1"
ext.reactorVersion = "2.0.4.RELEASE"
ext.seleniumVersion = "2.46.0"
ext.slf4jVersion = "1.7.12"
ext.snakeyamlVersion = "1.15"
ext.snifferVersion = "1.14"
......@@ -1009,6 +1011,8 @@ project("spring-test") {
optional("com.jayway.jsonpath:json-path:2.0.0")
optional("org.skyscreamer:jsonassert:1.2.3")
optional("xmlunit:xmlunit:${xmlunitVersion}")
optional("net.sourceforge.htmlunit:htmlunit:$htmlunitVersion")
optional("org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion")
testCompile(project(":spring-context-support"))
testCompile(project(":spring-oxm"))
testCompile("javax.mail:javax.mail-api:${javamailVersion}")
......
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import org.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>
* WebClient webClient = new WebClient();
*
* MockMvc mockMvc = ...
* MockMvcWebConnection mockConnection = new MockMvcWebConnection(mockMvc);
* mockConnection.setWebClient(webClient);
*
* WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*");
* WebConnection httpConnection = new HttpWebConnection(webClient);
* WebConnection webConnection = new DelegatingWebConnection(mockConnection, new DelegateWebConnection(cdnMatcher, httpConnection));
*
* webClient.setWebConnection(webConnection);
*
* WebClient webClient = new WebClient();
* webClient.setWebConnection(webConnection);
* </pre>
* @author Rob Winch
* @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");
this.connections = connections;
this.defaultConnection = defaultConnection;
}
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)) {
return connection.getDelegate().getResponse(request);
}
}
return defaultConnection.getResponse(request);
}
public final static class DelegateWebConnection {
private final WebRequestMatcher matcher;
private final WebConnection delegate;
public DelegateWebConnection(WebRequestMatcher matcher, WebConnection delegate) {
this.matcher = matcher;
this.delegate = delegate;
}
private WebRequestMatcher getMatcher() {
return matcher;
}
private WebConnection getDelegate() {
return delegate;
}
}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
import org.springframework.util.Assert;
/**
* @author Rob Winch
* @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;
}
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
request.setServletPath(forwardUrl);
return request;
}
}
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.net.URL;
import java.util.Arrays;
import java.util.HashSet;
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>
*
* <pre>
* WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com");
* </pre>
*
* 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>
* WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com", "cdn.com");
* </pre>
*
* <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>
* WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com:80");
* </pre>
*
* <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>
*
* @author Rob Winch
* @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")
*/
public HostRequestMatcher(String... hosts) {
this.hosts.addAll(Arrays.asList(hosts));
}
@Override
public boolean matches(WebRequest request) {
URL url = request.getUrl();
String host = url.getHost();
if(hosts.contains(host)) {
return true;
}
int port = url.getPort();
if(port == -1) {
port = url.getDefaultPort();
}
String hostAndPort = host + ":" + port;
return hosts.contains(hostAndPort);
}
}
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.ServletContext;
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;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.SmartRequestBuilder;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
import org.springframework.util.Assert;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
/**
* <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>
*
* @author Rob Winch
* @since 4.2
* @see MockMvcWebConnection
*/
final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable {
private final Map<String, MockHttpSession> sessions;
private final WebClient webClient;
private final WebRequest webRequest;
private String contextPath;
private RequestBuilder parentBuilder;
private SmartRequestBuilder parentPostProcessor;
private RequestPostProcessor forwardPostProcessor;
/**
*
* @param sessions A {@link Map} of the {@link HttpSession#getId()} to currently managed {@link HttpSession}
* objects. Cannot be null.
* @param webClient the WebClient for retrieving cookies
* @param webRequest The {@link WebRequest} to transform into a {@link MockHttpServletRequest}. Cannot be 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");
this.sessions = sessions;
this.webClient = webClient;
this.webRequest = webRequest;
}
public MockHttpServletRequest buildRequest(ServletContext servletContext) {
String charset = getCharset();
String httpMethod = webRequest.getHttpMethod().name();
UriComponents uriComponents = uriComponents();
MockHttpServletRequest result = new HtmlUnitMockHttpServletRequest(servletContext, httpMethod,
uriComponents.getPath());
parent(result, parentBuilder);
result.setServerName(uriComponents.getHost()); // needs to be first for additional headers
authType(result);
result.setCharacterEncoding(charset);
content(result, charset);
contextPath(result, uriComponents);
contentType(result);
cookies(result);
headers(result);
locales(result);
servletPath(uriComponents, result);
params(result, uriComponents);
ports(uriComponents, result);
result.setProtocol("HTTP/1.1");
result.setQueryString(uriComponents.getQuery());
result.setScheme(uriComponents.getScheme());
pathInfo(uriComponents,result);
return postProcess(result);
}
private MockHttpServletRequest postProcess(MockHttpServletRequest request) {
if(parentPostProcessor != null) {
request = parentPostProcessor.postProcessRequest(request);
}
if(forwardPostProcessor != null) {
request = forwardPostProcessor.postProcessRequest(request);
}
return request;
}
private void parent(MockHttpServletRequest result, RequestBuilder parent) {
if(parent == null) {
return;
}
MockHttpServletRequest parentRequest = parent.buildRequest(result.getServletContext());
// session
HttpSession parentSession = parentRequest.getSession(false);
if(parentSession != null) {
Enumeration<String> attrNames = parentSession.getAttributeNames();
while(attrNames.hasMoreElements()) {
String attrName = attrNames.nextElement();
Object attrValue = parentSession.getAttribute(attrName);
result.getSession().setAttribute(attrName, attrValue);
}
}
// header
Enumeration<String> headerNames = parentRequest.getHeaderNames();
while(headerNames.hasMoreElements()) {
String attrName = headerNames.nextElement();
Enumeration<String> attrValues = parentRequest.getHeaders(attrName);
while(attrValues.hasMoreElements()) {
String attrValue = attrValues.nextElement();
result.addHeader(attrName, attrValue);
}
}
// parameter
Map<String, String[]> parentParams = parentRequest.getParameterMap();
for(Map.Entry<String,String[]> parentParam : parentParams.entrySet()) {
String paramName = parentParam.getKey();
String[] paramValues = parentParam.getValue();
result.addParameter(paramName, paramValues);
}
// cookie
Cookie[] parentCookies = parentRequest.getCookies();
if(parentCookies != null) {
result.setCookies(parentCookies);
}
// request attribute
Enumeration<String> parentAttrNames = parentRequest.getAttributeNames();
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()}.
*/
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 + "'");
}
this.contextPath = contextPath;
}
public void setForwardPostProcessor(RequestPostProcessor postProcessor) {
this.forwardPostProcessor = postProcessor;
}
private void authType(MockHttpServletRequest request) {
String authorization = header("Authorization");
if (authorization != null) {
String[] authzParts = authorization.split(": ");
request.setAuthType(authzParts[0]);
}
}
private void content(MockHttpServletRequest result, String charset) {
String requestBody = webRequest.getRequestBody();
if (requestBody == null) {
return;
}
try {
result.setContent(requestBody.getBytes(charset));
}
catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
private void contentType(MockHttpServletRequest result) {
String contentType = header("Content-Type");
result.setContentType(contentType == null ? MediaType.ALL_VALUE.toString() : contentType);
}
private void contextPath(MockHttpServletRequest result, UriComponents uriComponents) {
if (contextPath == null) {
List<String> pathSegments = uriComponents.getPathSegments();
if (pathSegments.isEmpty()) {
result.setContextPath("");
}
else {
result.setContextPath("/" + pathSegments.get(0));
}
}
else {
if (!uriComponents.getPath().startsWith(contextPath)) {
throw new IllegalArgumentException(uriComponents.getPath() + " should start with contextPath "
+ contextPath);
}
result.setContextPath(contextPath);
}
}
private void cookies(MockHttpServletRequest result) {
String cookieHeaderValue = header("Cookie");
Cookie[] parentCookies = result.getCookies();
List<Cookie> cookies = new ArrayList<Cookie>();
if (cookieHeaderValue != null) {
StringTokenizer tokens = new StringTokenizer(cookieHeaderValue, "=;");
while (tokens.hasMoreTokens()) {
String cookieName = tokens.nextToken().trim();
if (!tokens.hasMoreTokens()) {
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());
for (com.gargoylesoftware.htmlunit.util.Cookie cookie : managedCookies) {
processCookie(result, cookies, new Cookie(cookie.getName(), cookie.getValue()));
}
if(parentCookies != null) {
for(Cookie cookie : parentCookies) {
cookies.add(cookie);
}
}
if (!cookies.isEmpty()) {
result.setCookies(cookies.toArray(new Cookie[0]));
}
}
private void processCookie(MockHttpServletRequest result, List<Cookie> cookies, Cookie cookie) {
cookies.add(cookie);
if ("JSESSIONID".equals(cookie.getName())) {
result.setRequestedSessionId(cookie.getValue());
result.setSession(httpSession(result, cookie.getValue()));
}
}
private String getCharset() {
String charset = webRequest.getCharset();
if (charset == null) {
return "ISO-8859-1";
}
return charset;
}
private String header(String headerName) {
return webRequest.getAdditionalHeaders().get(headerName);
}
private void headers(MockHttpServletRequest result) {
for (Entry<String, String> header : 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);
if (session == null) {
session = new HtmlUnitMockHttpSession(request, sessionid);
session.setNew(true);
synchronized (sessions) {
sessions.put(sessionid, session);
}
addSessionCookie(request, sessionid);
}
else {
session.setNew(false);
}
}
return session;
}
private void addSessionCookie(MockHttpServletRequest request, String sessionid) {
getCookieManager().addCookie(createCookie(request, sessionid));
}
private void removeSessionCookie(MockHttpServletRequest request, String sessionid) {
getCookieManager().removeCookie(createCookie(request, sessionid));
}
private com.gargoylesoftware.htmlunit.util.Cookie createCookie(MockHttpServletRequest request, String sessionid) {
return new com.gargoylesoftware.htmlunit.util.Cookie(request.getServerName(), "JSESSIONID", sessionid,
request.getContextPath() + "/", null, request.isSecure(), true);
}
private void locales(MockHttpServletRequest result) {
String locale = header("Accept-Language");
if (locale == null) {
result.addPreferredLocale(Locale.getDefault());
}
else {
String[] locales = locale.split(", ");
for (int i = locales.length - 1; i >= 0; i--) {
result.addPreferredLocale(parseLocale(locales[i]));
}
}
}
private void params(MockHttpServletRequest result, UriComponents uriComponents) {
for (Entry<String, List<String>> values : uriComponents.getQueryParams().entrySet()) {
String name = values.getKey();
for (String value : values.getValue()) {
try {
result.addParameter(name, URLDecoder.decode(value, "UTF-8"));
}
catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
for (NameValuePair param : webRequest.getRequestParameters()) {
result.addParameter(param.getName(), param.getValue());
}
}
private Locale parseLocale(String locale) {
Matcher matcher = LOCALE_PATTERN.matcher(locale);
if (!matcher.matches()) {
throw new IllegalArgumentException("Invalid locale " + locale);
}
String language = matcher.group(1);
String country = matcher.group(2);
if (country == null) {
country = "";
}
String qualifier = matcher.group(3);
if (qualifier == null) {
qualifier = "";
}
return new Locale(language, country, qualifier);
}
private void pathInfo(UriComponents uriComponents, MockHttpServletRequest result) {
result.setPathInfo(null);
}
private void servletPath(MockHttpServletRequest result, String requestPath) {
String servletPath = requestPath.substring(result.getContextPath().length());
if ("".equals(servletPath)) {
servletPath = null;
}
result.setServletPath(servletPath);
}
private void servletPath(UriComponents uriComponents, MockHttpServletRequest result) {
if ("".equals(result.getPathInfo())) {
result.setPathInfo(null);
}
servletPath(result, uriComponents.getPath());
}
private void ports(UriComponents uriComponents, MockHttpServletRequest result) {
int serverPort = uriComponents.getPort();
result.setServerPort(serverPort);
if (serverPort == -1) {
int portConnection = webRequest.getUrl().getDefaultPort();
result.setLocalPort(serverPort);
result.setRemotePort(portConnection);
}
else {
result.setRemotePort(serverPort);
}
}
private UriComponents uriComponents() {
URL url = webRequest.getUrl();
UriComponentsBuilder uriBldr = UriComponentsBuilder.fromUriString(url.toExternalForm());
return uriBldr.build();
}
@Override
public boolean isMergeEnabled() {
return true;
}
@Override
public Object merge(Object parent) {
if (parent == null) {
return this;
}
if(parent instanceof RequestBuilder) {
this.parentBuilder = (RequestBuilder) parent;
}
if (parent instanceof SmartRequestBuilder) {
this.parentPostProcessor = (SmartRequestBuilder) parent;
}
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
*/
private final class HtmlUnitMockHttpServletRequest extends MockHttpServletRequest {
private HtmlUnitMockHttpServletRequest(ServletContext servletContext, String method, String requestURI) {
super(servletContext, method, requestURI);
}
public HttpSession getSession(boolean create) {
HttpSession result = super.getSession(false);
if (result == null && create) {
HtmlUnitMockHttpSession newSession = new HtmlUnitMockHttpSession(this);
setSession(newSession);
newSession.setNew(true);
String sessionid = newSession.getId();
synchronized (sessions) {
sessions.put(sessionid, newSession);
}
addSessionCookie(this, sessionid);
result = newSession;
}
return result;
}
public HttpSession getSession() {
return super.getSession();
}
public void setSession(HttpSession session) {
super.setSession(session);
}
}
/**
* 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
*/
private final class HtmlUnitMockHttpSession extends MockHttpSession {
private final MockHttpServletRequest request;
private HtmlUnitMockHttpSession(MockHttpServletRequest request) {
super(request.getServletContext());
this.request = request;
}
private HtmlUnitMockHttpSession(MockHttpServletRequest request, String id) {
super(request.getServletContext(), id);
this.request = request;
}
public void invalidate() {
super.invalidate();
synchronized (sessions) {
sessions.remove(getId());
}
removeSessionCookie(request, getId());
}
}
private CookieManager getCookieManager() {
return webClient.getCookieManager();
}
private static final Pattern LOCALE_PATTERN = Pattern.compile("^\\s*(\\w{2})(?:-(\\w{2}))?(?:;q=(\\d+\\.\\d+))?$");
}
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import com.gargoylesoftware.htmlunit.WebClient;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
import org.springframework.web.context.WebApplicationContext;
/**
* Simplifies creating a WebClient that delegates to a MockMvc instance.
*
* @author Rob Winch
* @since 4.2
*/
public class MockMvcWebClientBuilder extends MockMvcWebConnectionBuilderSupport<MockMvcWebClientBuilder> {
protected MockMvcWebClientBuilder(MockMvc mockMvc) {
super(mockMvc);
}
protected MockMvcWebClientBuilder(WebApplicationContext context) {
super(context);
}
protected MockMvcWebClientBuilder(WebApplicationContext context, MockMvcConfigurer configurer) {
super(context, configurer);
}
/**
* Creates a new instance with a WebApplicationContext.
*
* @param context the WebApplicationContext to use. Cannot be null.
* @return the MockMvcWebClientBuilder to customize
*/
public static MockMvcWebClientBuilder webAppContextSetup(WebApplicationContext context) {
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
*/
public static MockMvcWebClientBuilder webAppContextSetup(WebApplicationContext context, MockMvcConfigurer configurer) {
return new MockMvcWebClientBuilder(context, configurer);
}
/**
* Creates a new instance with a MockMvc instance.
*
* @param mockMvc the MockMvc to use. Cannot be null.
* @return the MockMvcWebClientBuilder to customize
*/
public static MockMvcWebClientBuilder mockMvcSetup(MockMvc mockMvc) {
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
*/
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.
*
* @return the WebClient to use
*/
public WebClient configureWebClient(WebClient webClient) {
webClient.setWebConnection(createConnection(webClient.getWebConnection()));
return webClient;
}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package 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;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.htmlunit.webdriver.WebConnectionHtmlUnitDriver;
import org.springframework.util.Assert;
/**
* <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>
*
* <pre>
* WebClient webClient = new WebClient();
* MockMvc mockMvc = ...
* MockMvcWebConnection webConnection = new MockMvcWebConnection(mockMvc);
* mockConnection.setWebClient(webClient);
* webClient.setWebConnection(webConnection);
*
* ... use webClient as normal ...
* </pre>
*
* @author Rob Winch
* @since 4.2
* @see WebConnectionHtmlUnitDriver
*/
public final class MockMvcWebConnection implements WebConnection {
private WebClient webClient;
private final Map<String, MockHttpSession> sessions = new HashMap<String, MockHttpSession>();
private final MockMvc mockMvc;
private final String contextPath;
/**
* 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
*/
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 "/".
*/
public MockMvcWebConnection(MockMvc mockMvc, String contextPath) {
Assert.notNull(mockMvc, "mockMvc cannot be null");
validateContextPath(contextPath);
this.webClient = new WebClient();
this.mockMvc = mockMvc;
this.contextPath = contextPath;
}
public WebResponse getResponse(WebRequest webRequest) throws IOException {
long startTime = System.currentTimeMillis();
HtmlUnitRequestBuilder requestBuilder = new HtmlUnitRequestBuilder(sessions, webClient, webRequest);
requestBuilder.setContextPath(contextPath);
MockHttpServletResponse httpServletResponse = getResponse(requestBuilder);
String forwardedUrl = httpServletResponse.getForwardedUrl();
while(forwardedUrl != null) {
requestBuilder.setForwardPostProcessor(new ForwardRequestPostProcessor(forwardedUrl));
httpServletResponse = getResponse(requestBuilder);
forwardedUrl = httpServletResponse.getForwardedUrl();
}
return new MockWebResponseBuilder(startTime, webRequest, httpServletResponse).build();
}
public void setWebClient(WebClient webClient) {
Assert.notNull(webClient, "webClient cannot 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);
}
catch (Exception e) {
throw (IOException) new IOException(e.getMessage()).initCause(e);
}
return resultActions.andReturn().getResponse();
}
/**
* Performs validation on the contextPath
*
* @param contextPath the contextPath to validate
*/
private 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 + "'");
}
}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package 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;
/**
* 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.
*
* @author Rob Winch
* @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 boolean alwaysUseMockMvc;
/**
* Creates a new instance using a MockMvc instance
*
* @param mockMvc the MockMvc instance to use. Cannot be null.
*/
protected MockMvcWebConnectionBuilderSupport(MockMvc mockMvc) {
Assert.notNull(mockMvc, "mockMvc cannot 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.
*/
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.
*/
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
* 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
*/
@SuppressWarnings("unchecked")
public T contextPath(String contextPath) {
this.contextPath = contextPath;
return (T) this;
}
/**
* Always use MockMvc no matter what the request looks like.
*
* @return the builder for further customization
*/
@SuppressWarnings("unchecked")
public T alwaysUseMockMvc() {
this.alwaysUseMockMvc = true;
return (T) this;
}
/**
* 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
*/
@SuppressWarnings("unchecked")
public T useMockMvc(WebRequestMatcher... 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
*/
@SuppressWarnings("unchecked")
public T useMockMvcForHosts(String... hosts) {
this.mockMvcRequestMatchers.add(new HostRequestMatcher(hosts));
return (T) this;
}
/**
* 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
* @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);
if(alwaysUseMockMvc) {
return mockMvcWebConnection;
}
List<DelegatingWebConnection.DelegateWebConnection> delegates = new ArrayList<DelegatingWebConnection.DelegateWebConnection>(mockMvcRequestMatchers.size());
for(WebRequestMatcher matcher : mockMvcRequestMatchers) {
delegates.add(new DelegatingWebConnection.DelegateWebConnection(matcher, mockMvcWebConnection));
}
return new DelegatingWebConnection(defaultConnection, delegates);
}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.WebResponseData;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.util.Assert;
/**
* @author Rob Winch
* @since 4.2
*/
final class MockWebResponseBuilder {
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");
this.startTime = startTime;
this.webRequest = webRequest;
this.response = httpServletResponse;
}
public WebResponse build() throws IOException {
WebResponseData webResponseData = webResponseData();
long endTime = System.currentTimeMillis();
return new WebResponse(webResponseData, webRequest, endTime - startTime);
}
private WebResponseData webResponseData() throws IOException {
List<NameValuePair> responseHeaders = responseHeaders();
int statusCode = response.getRedirectedUrl() == null ? response.getStatus() : 301;
String statusMessage = statusMessage(statusCode);
return new WebResponseData(response.getContentAsByteArray(), statusCode, statusMessage, responseHeaders);
}
private String statusMessage(int statusCode) {
String errorMessage = response.getErrorMessage();
if (errorMessage != null) {
return errorMessage;
}
try {
return HttpStatus.valueOf(statusCode).getReasonPhrase();
}
catch (IllegalArgumentException useDefault) {
}
;
return "N/A";
}
private List<NameValuePair> responseHeaders() {
Collection<String> headerNames = response.getHeaderNames();
List<NameValuePair> responseHeaders = new ArrayList<NameValuePair>(headerNames.size());
for (String headerName : headerNames) {
List<Object> headerValues = response.getHeaderValues(headerName);
for (Object value : headerValues) {
responseHeaders.add(new NameValuePair(headerName, String.valueOf(value)));
}
}
String location = response.getRedirectedUrl();
if (location != null) {
responseHeaders.add(new NameValuePair("Location", location));
}
return responseHeaders;
}
}
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
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>
*
* <pre>
* WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*");
* </pre>
*
* @author Rob Winch
* @since 4.2
* @see org.springframework.test.web.servlet.htmlunit.DelegatingWebConnection
*/
public final class UrlRegexRequestMatcher implements WebRequestMatcher {
private Pattern pattern;
public UrlRegexRequestMatcher(String regex) {
pattern = Pattern.compile(regex);
}
public UrlRegexRequestMatcher(Pattern pattern) {
this.pattern = pattern;
}
@Override
public boolean matches(WebRequest request) {
String url = request.getUrl().toExternalForm();
return pattern.matcher(url).matches();
}
}
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import com.gargoylesoftware.htmlunit.WebRequest;
/**
* Strategy to match on a 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
*/
boolean matches(WebRequest request);
}
/**
* Support for MockMvc and HtmlUnit integration
*
* @author Rob Winch
* @since 4.2
*/
package org.springframework.test.web.servlet.htmlunit;
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package 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;
import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnectionBuilderSupport;
import org.springframework.test.web.servlet.setup.MockMvcConfigurer;
import org.springframework.web.context.WebApplicationContext;
/**
* Convenience class for building an HtmlUnitDriver that will delegate to MockMvc and
* optionally delegate to an actual connection for specific requests.
*
* By default localhost will delegate to MockMvc and any other URL will delegate
*
* @author Rob Winch
* @since 4.2
*/
public class MockMvcHtmlUnitDriverBuilder extends MockMvcWebConnectionBuilderSupport<MockMvcHtmlUnitDriverBuilder> {
private boolean javascriptEnabled = true;
protected MockMvcHtmlUnitDriverBuilder(MockMvc mockMvc) {
super(mockMvc);
}
protected MockMvcHtmlUnitDriverBuilder(WebApplicationContext context) {
super(context);
}
protected MockMvcHtmlUnitDriverBuilder(WebApplicationContext context, MockMvcConfigurer configurer) {
super(context, configurer);
}
/**
* Creates a new instance with a WebApplicationContext.
*
* @param context the WebApplicationContext to use. Cannot be null.
* @return the MockMvcHtmlUnitDriverBuilder to customize
*/
public static MockMvcHtmlUnitDriverBuilder webAppContextSetup(WebApplicationContext context) {
return new MockMvcHtmlUnitDriverBuilder(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 MockMvcHtmlUnitDriverBuilder to customize
*/
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.
* @return the MockMvcHtmlUnitDriverBuilder to customize
*/
public static MockMvcHtmlUnitDriverBuilder mockMvcSetup(MockMvc mockMvc) {
return new MockMvcHtmlUnitDriverBuilder(mockMvc);
}
/**
* Specifies if JavaScript should be enabled or not. Default is true.
*
* @param javascriptEnabled if JavaScript should be enabled or not.
* @return the builder for further customizations
*/
public MockMvcHtmlUnitDriverBuilder javascriptEnabled(boolean javascriptEnabled) {
this.javascriptEnabled = javascriptEnabled;
return this;
}
/**
* Creates a new HtmlUnitDriver with the BrowserVersion set to CHROME. For additional
* configuration options, use configureDriver.
*
* @return the HtmlUnitDriver to use
* @see #configureDriver(WebConnectionHtmlUnitDriver)
*/
public HtmlUnitDriver createDriver() {
return configureDriver(new WebConnectionHtmlUnitDriver(BrowserVersion.CHROME));
}
/**
* Configures an existing WebConnectionHtmlUnitDriver.
*
* @param driver the WebConnectionHtmlUnitDriver to configure
* @return the HtmlUnitDriver to use
*/
public HtmlUnitDriver configureDriver(WebConnectionHtmlUnitDriver driver) {
driver.setJavascriptEnabled(javascriptEnabled);
driver.setWebConnection(createConnection(driver.getWebConnection()));
return driver;
}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit.webdriver;
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>
*
* @author Rob Winch
* @since 4.2
* @see MockMvcHtmlUnitDriverBuilder
*/
public class WebConnectionHtmlUnitDriver extends HtmlUnitDriver {
private WebClient webClient;
public WebConnectionHtmlUnitDriver(BrowserVersion version) {
super(version);
}
public WebConnectionHtmlUnitDriver() {
}
public WebConnectionHtmlUnitDriver(boolean enableJavascript) {
super(enableJavascript);
}
public WebConnectionHtmlUnitDriver(Capabilities capabilities) {
super(capabilities);
}
/**
* Captures the WebClient that is used so that its WebConnection is accessible.
*
* @param client The client to modify
* @return The modified client
*/
@Override
protected final WebClient modifyWebClient(WebClient client) {
webClient = super.modifyWebClient(client);
webClient = configureWebClient(webClient);
return 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
*/
protected WebClient configureWebClient(WebClient client) {
return client;
}
/**
* Allows accessing the current WebConnection
*
* @return the current WebConnection
*/
public WebConnection getWebConnection() {
return webClient.getWebConnection();
}
/**
* Sets the WebConnection to be used.
*
* @param webConnection the WebConnection to use. Cannot be null.
*/
public void setWebConnection(WebConnection webConnection) {
Assert.notNull(webConnection, "webConnection cannot be null");
this.webClient.setWebConnection(webConnection);
}
}
\ No newline at end of file
/**
* Support for MockMvc and HtmlUnitDriver
*
* @author Rob Winch
* @since 4.2
*/
package org.springframework.test.web.servlet.htmlunit.webdriver;
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.net.URL;
import java.util.Collections;
import com.gargoylesoftware.htmlunit.HttpWebConnection;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.WebResponseData;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.sameInstance;
import static org.hamcrest.Matchers.isEmptyString;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import static org.mockito.Mockito.*;
import org.mockito.runners.MockitoJUnitRunner;
import static org.springframework.test.web.servlet.htmlunit.DelegatingWebConnection.DelegateWebConnection;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
/**
* @author Rob Winch
*/
@RunWith(MockitoJUnitRunner.class)
public class DelegatingWebConnectionTests {
private DelegatingWebConnection webConnection;
@Mock
private WebRequestMatcher matcher1;
@Mock
private WebRequestMatcher matcher2;
@Mock
private WebConnection defaultConnection;
@Mock
private WebConnection connection1;
@Mock
private WebConnection connection2;
private WebRequest request;
private WebResponse expectedResponse;
@Before
public void setUp() throws Exception {
request = new WebRequest(new URL("http://localhost/"));
WebResponseData data = new WebResponseData("".getBytes("UTF-8"),200, "", Collections.<NameValuePair>emptyList());
expectedResponse = new WebResponse(data, request, 100L);
webConnection = new DelegatingWebConnection(defaultConnection, new DelegateWebConnection(matcher1,connection1), new DelegateWebConnection(matcher2,connection2));
}
@Test
public void getResponseDefault() throws Exception {
when(defaultConnection.getResponse(request)).thenReturn(expectedResponse);
WebResponse response = webConnection.getResponse(request);
assertThat(response, sameInstance(expectedResponse));
verify(matcher1).matches(request);
verify(matcher2).matches(request);
verifyNoMoreInteractions(connection1,connection2);
verify(defaultConnection).getResponse(request);
}
@Test
public void getResponseAllMatches() throws Exception {
when(matcher1.matches(request)).thenReturn(true);
when(matcher2.matches(request)).thenReturn(true);
when(connection1.getResponse(request)).thenReturn(expectedResponse);
WebResponse response = webConnection.getResponse(request);
assertThat(response, sameInstance(expectedResponse));
verify(matcher1).matches(request);
verifyNoMoreInteractions(matcher2,connection2,defaultConnection);
verify(connection1).getResponse(request);
}
@Test
public void getResponseSecondMatches() throws Exception {
when(matcher2.matches(request)).thenReturn(true);
when(connection2.getResponse(request)).thenReturn(expectedResponse);
WebResponse response = webConnection.getResponse(request);
assertThat(response, sameInstance(expectedResponse));
verify(matcher1).matches(request);
verify(matcher2).matches(request);
verifyNoMoreInteractions(connection1,defaultConnection);
verify(connection2).getResponse(request);
}
@Test
public void classlevelJavadoc() throws Exception {
WebClient webClient = new WebClient();
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(TestController.class).build();
MockMvcWebConnection mockConnection = new MockMvcWebConnection(mockMvc);
mockConnection.setWebClient(webClient);
WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*");
WebConnection httpConnection = new HttpWebConnection(webClient);
WebConnection webConnection = new DelegatingWebConnection(mockConnection, new DelegateWebConnection(cdnMatcher, httpConnection));
webClient.setWebConnection(webConnection);
Page page = webClient.getPage("http://code.jquery.com/jquery-1.11.0.min.js");
assertThat(page.getWebResponse().getStatusCode(), equalTo(200));
assertThat(page.getWebResponse().getContentAsString(), not(isEmptyString()));
}
@Controller
static class TestController {}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author Rob Winch
*/
@Controller
public class ForwardController {
@RequestMapping("/forward")
public String forward() {
return "forward:/";
}
}
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author Rob Winch
*/
@Controller
public class HelloController {
@RequestMapping
@ResponseBody
public String header(HttpServletRequest request) {
return "hello";
}
}
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.net.URL;
import com.gargoylesoftware.htmlunit.WebRequest;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import org.junit.Test;
import org.springframework.test.web.servlet.htmlunit.HostRequestMatcher;
import org.springframework.test.web.servlet.htmlunit.WebRequestMatcher;
/**
* @author Rob Winch
*/
public class HostRequestMatcherTests {
@Test
public void localhostMatches() throws Exception {
WebRequestMatcher matcher = new HostRequestMatcher("localhost");
boolean matches = matcher.matches(new WebRequest(new URL("http://localhost/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(true));;
matches = matcher.matches(new WebRequest(new URL("http://example.com/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(false));;
}
@Test
public void multipleHosts() throws Exception {
WebRequestMatcher matcher = new HostRequestMatcher("localhost","example.com");
boolean matches = matcher.matches(new WebRequest(new URL("http://localhost/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(true));;
matches = matcher.matches(new WebRequest(new URL("http://example.com/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(true));;
}
@Test
public void specificPort() throws Exception {
WebRequestMatcher matcher = new HostRequestMatcher("localhost:8080");
boolean matches = matcher.matches(new WebRequest(new URL("http://localhost:8080/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(true));;
matches = matcher.matches(new WebRequest(new URL("http://localhost:9090/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(false));;
}
@Test
public void defaultPortInMatcher() throws Exception {
WebRequestMatcher matcher = new HostRequestMatcher("localhost:80");
boolean matches = matcher.matches(new WebRequest(new URL("http://localhost:80/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(true));;
matches = matcher.matches(new WebRequest(new URL("http://localhost/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(true));;
matches = matcher.matches(new WebRequest(new URL("http://localhost:9090/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(false));;
}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import java.net.URL;
import javax.servlet.http.HttpServletRequest;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.Mockito.mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
* @author Rob Winch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class MockMvcConnectionBuilderSupportTests {
@Autowired
WebApplicationContext context;
MockMvc mockMvc;
WebConnection delegateConnection;
WebConnection connection;
@Before
public void setup() {
delegateConnection = mock(WebConnection.class);
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
connection = new MockMvcWebConnectionBuilderSupport(mockMvc){}
.createConnection(delegateConnection);
}
@Test(expected = IllegalArgumentException.class)
public void constructorMockMvcNull() {
new MockMvcWebConnectionBuilderSupport((MockMvc)null){};
}
@Test(expected = IllegalArgumentException.class)
public void constructorContextNull() {
new MockMvcWebConnectionBuilderSupport((WebApplicationContext)null){};
}
@Test
public void context() throws Exception {
connection = new MockMvcWebConnectionBuilderSupport(context){}
.createConnection(delegateConnection);
assertMvcProcessed("http://localhost/");
assertDelegateProcessed("http://example.com/");
}
@Test
public void mockMvc() throws Exception {
assertMvcProcessed("http://localhost/");
assertDelegateProcessed("http://example.com/");
}
@Test
public void mockMvcExampleDotCom() throws Exception {
connection = new MockMvcWebConnectionBuilderSupport(context){}
.useMockMvcForHosts("example.com")
.createConnection(delegateConnection);
assertMvcProcessed("http://localhost/");
assertMvcProcessed("http://example.com/");
assertDelegateProcessed("http://other.com/");
}
@Test
public void mockMvcAlwaysUseMockMvc() throws Exception {
connection = new MockMvcWebConnectionBuilderSupport(context){}
.alwaysUseMockMvc()
.createConnection(delegateConnection);
assertMvcProcessed("http://other.com/");
}
@Test
public void defaultContextPathEmpty() throws Exception {
connection = new MockMvcWebConnectionBuilderSupport(context){}
.createConnection(delegateConnection);
assertThat(getWebResponse("http://localhost/abc").getContentAsString(), equalTo(""));;
}
@Test
public void defaultContextPathCustom() throws Exception {
connection = new MockMvcWebConnectionBuilderSupport(context) {
}.contextPath("/abc").createConnection(delegateConnection);
assertThat(getWebResponse("http://localhost/abc/def").getContentAsString(), equalTo("/abc"));;
}
private void assertMvcProcessed(String url) throws Exception {
assertThat(getWebResponse(url), notNullValue());
}
private void assertDelegateProcessed(String url) throws Exception {
assertThat(getWebResponse(url), nullValue());
}
private WebResponse getWebResponse(String url) throws IOException {
return connection.getResponse(new WebRequest(new URL(url)));
}
@Configuration
@EnableWebMvc
static class Config {
@RestController
static class ContextPathController {
@RequestMapping
public String contextPath(HttpServletRequest request) {
return request.getContextPath();
}
}
}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import java.net.URL;
import javax.servlet.http.HttpServletRequest;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
* @author Rob Winch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class MockMvcWebClientBuilderTests {
@Autowired
WebApplicationContext context;
MockMvc mockMvc;
WebClient webClient;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
webClient = new WebClient();
}
@Test(expected = IllegalArgumentException.class)
public void mockMvcSetupNull() {
MockMvcWebClientBuilder.mockMvcSetup(null);
}
@Test(expected = IllegalArgumentException.class)
public void webAppContextSetupNull() {
MockMvcWebClientBuilder.webAppContextSetup(null);
}
@Test
public void mockMvcSetupconfigureWebClient() throws Exception {
webClient = MockMvcWebClientBuilder
.mockMvcSetup(mockMvc)
.configureWebClient(webClient);
assertMvcProcessed("http://localhost/test");
assertDelegateProcessed("http://example.com/");
}
@Test
public void mockMvcSetupCreateWebClient() throws Exception {
webClient = MockMvcWebClientBuilder
.mockMvcSetup(mockMvc)
.createWebClient();
assertMvcProcessed("http://localhost/test");
assertDelegateProcessed("http://example.com/");
}
private void assertMvcProcessed(String url) throws Exception {
assertThat(getWebResponse(url).getContentAsString(), equalTo("mvc"));;
}
private void assertDelegateProcessed(String url) throws Exception {
assertThat(getWebResponse(url).getContentAsString(), not(equalTo("mvc")));
}
private WebResponse getWebResponse(String url) throws IOException {
return webClient.getWebConnection().getResponse(new WebRequest(new URL(url)));
}
@Configuration
@EnableWebMvc
static class Config {
@RestController
static class ContextPathController {
@RequestMapping
public String contextPath(HttpServletRequest request) {
return "mvc";
}
}
}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
/**
* @author Rob Winch
*/
public class MockMvcWebConnectionTests {
MockMvc mockMvc;
WebClient webClient;
@Before
public void setup() {
mockMvc = MockMvcBuilders
.standaloneSetup(new HelloController(), new ForwardController())
.build();
webClient = new WebClient();
}
@Test
public void contextPathNull() throws IOException {
webClient.setWebConnection(new MockMvcWebConnection(mockMvc, null));
Page page = webClient.getPage("http://localhost/context/a");
assertThat(page.getWebResponse().getStatusCode(), equalTo(200));;
}
@Test
public void contextPathExplicit() throws IOException {
webClient.setWebConnection(new MockMvcWebConnection(mockMvc, "/context"));
Page page = webClient.getPage("http://localhost/context/a");
assertThat(page.getWebResponse().getStatusCode(), equalTo(200));;
}
@Test
public void contextPathEmpty() throws IOException {
webClient.setWebConnection(new MockMvcWebConnection(mockMvc, ""));
Page page = webClient.getPage("http://localhost/context/a");
assertThat(page.getWebResponse().getStatusCode(), equalTo(200));;
}
@Test
public void forward() throws IOException {
webClient.setWebConnection(new MockMvcWebConnection(mockMvc, ""));
Page page = webClient.getPage("http://localhost/forward");
assertThat(page.getWebResponse().getContentAsString(), equalTo("hello"));;
}
@Test(expected = IllegalArgumentException.class)
public void contextPathDoesNotStartWithSlash() throws IOException {
new MockMvcWebConnection(mockMvc, "context");
}
@Test(expected = IllegalArgumentException.class)
public void contextPathEndsWithSlash() throws IOException {
new MockMvcWebConnection(mockMvc, "/context/");
}
}
\ No newline at end of file
/*
* Copyright 2012 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.net.URL;
import java.util.List;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletResponse;
/**
*
* @author Rob Winch
*/
public class MockWebResponseBuilderTests {
private WebRequest webRequest;
private MockHttpServletResponse httpServletResponse;
private MockWebResponseBuilder responseBuilder;
@Before
public void setUp() throws Exception {
webRequest = new WebRequest(new URL("http://example.com:80/test/this/here"));
httpServletResponse = new MockHttpServletResponse();
responseBuilder = new MockWebResponseBuilder(System.currentTimeMillis(), webRequest, httpServletResponse);
}
// --- constructor
@Test(expected = IllegalArgumentException.class)
public void constructorNullWebRequest() {
new MockWebResponseBuilder(0L, null, httpServletResponse);
}
@Test(expected = IllegalArgumentException.class)
public void constructorNullResponse() throws Exception {
new MockWebResponseBuilder(0L, new WebRequest(new URL("http://example.com:80/test/this/here")), null);
}
// --- build
@Test
public void buildContent() throws Exception {
httpServletResponse.getWriter().write("expected content");
WebResponse webResponse = responseBuilder.build();
assertThat(webResponse.getContentAsString(), equalTo("expected content"));;
}
@Test
public void buildContentCharset() throws Exception {
httpServletResponse.addHeader("Content-Type", "text/html; charset=UTF-8");
WebResponse webResponse = responseBuilder.build();
assertThat(webResponse.getContentCharset(), equalTo("UTF-8"));;
}
@Test
public void buildContentType() throws Exception {
httpServletResponse.addHeader("Content-Type", "text/html; charset-UTF-8");
WebResponse webResponse = responseBuilder.build();
assertThat(webResponse.getContentType(), equalTo("text/html"));;
}
@Test
public void buildResponseHeaders() throws Exception {
httpServletResponse.addHeader("Content-Type", "text/html");
httpServletResponse.addHeader("X-Test", "value");
WebResponse webResponse = responseBuilder.build();
List<NameValuePair> responseHeaders = webResponse.getResponseHeaders();
assertThat(responseHeaders.size(), equalTo(2));;
NameValuePair header = responseHeaders.get(0);
assertThat(header.getName(), equalTo("Content-Type"));;
assertThat(header.getValue(), equalTo("text/html"));;
header = responseHeaders.get(1);
assertThat(header.getName(), equalTo("X-Test"));;
assertThat(header.getValue(), equalTo("value"));;
}
@Test
public void buildStatus() throws Exception {
WebResponse webResponse = responseBuilder.build();
assertThat(webResponse.getStatusCode(), equalTo(200));;
assertThat(webResponse.getStatusMessage(), equalTo("OK"));;
}
@Test
public void buildStatusNotOk() throws Exception {
httpServletResponse.setStatus(401);
WebResponse webResponse = responseBuilder.build();
assertThat(webResponse.getStatusCode(), equalTo(401));;
assertThat(webResponse.getStatusMessage(), equalTo("Unauthorized"));;
}
@Test
public void buildStatusCustomMessage() throws Exception {
httpServletResponse.sendError(401, "Custom");
WebResponse webResponse = responseBuilder.build();
assertThat(webResponse.getStatusCode(), equalTo(401));;
assertThat(webResponse.getStatusMessage(), equalTo("Custom"));;
}
@Test
public void buildWebRequest() throws Exception {
WebResponse webResponse = responseBuilder.build();
assertThat(webResponse.getWebRequest(), equalTo(webRequest));;
}
}
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit;
import java.net.URL;
import com.gargoylesoftware.htmlunit.WebRequest;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import org.junit.Test;
import org.springframework.test.web.servlet.htmlunit.UrlRegexRequestMatcher;
import org.springframework.test.web.servlet.htmlunit.WebRequestMatcher;
/**
* @author Rob Winch
*/
public class UrlRegexRequestMatcherTests {
@Test
public void classlevelJavadoc() throws Exception {
WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*");
boolean matches = cdnMatcher.matches(new WebRequest(new URL("http://code.jquery.com/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(true));
matches = cdnMatcher.matches(new WebRequest(new URL("http://localhost/jquery-1.11.0.min.js")));
assertThat(matches, equalTo(false));
}
}
\ No newline at end of file
/*
* Copyright 2002-2015 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.test.web.servlet.htmlunit.webdriver;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
* @author Rob Winch
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class MockMvcHtmlUnitDriverBuilderTests {
public static final String EXPECTED_BODY = "MockMvcHtmlUnitDriverBuilderTests mvc";
@Autowired
WebApplicationContext context;
MockMvc mockMvc;
HtmlUnitDriver driver;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Test(expected = IllegalArgumentException.class)
public void mockMvcSetupNull() {
MockMvcHtmlUnitDriverBuilder.mockMvcSetup(null);
}
@Test(expected = IllegalArgumentException.class)
public void webAppContextSetupNull() {
MockMvcHtmlUnitDriverBuilder.webAppContextSetup(null);
}
@Test
public void mockMvcSetupConfigureDriver() throws Exception {
driver = MockMvcHtmlUnitDriverBuilder
.mockMvcSetup(mockMvc)
.configureDriver(new WebConnectionHtmlUnitDriver());
assertMvcProcessed("http://localhost/test");
assertDelegateProcessed("http://example.com/");
}
@Test
public void mockMvcSetupCreateDriver() throws Exception {
driver = MockMvcHtmlUnitDriverBuilder
.mockMvcSetup(mockMvc)
.createDriver();
assertMvcProcessed("http://localhost/test");
assertDelegateProcessed("http://example.com/");
}
@Test
public void javascriptEnabledDefaultEnabled() {
driver = MockMvcHtmlUnitDriverBuilder
.mockMvcSetup(mockMvc)
.createDriver();
assertThat(driver.isJavascriptEnabled(), equalTo(true));
}
@Test
public void javascriptEnabledDisabled() {
driver = MockMvcHtmlUnitDriverBuilder
.mockMvcSetup(mockMvc)
.javascriptEnabled(false)
.createDriver();
assertThat(driver.isJavascriptEnabled(), equalTo(false));
}
private void assertMvcProcessed(String url) throws Exception {
assertThat(get(url), containsString(EXPECTED_BODY));
}
private void assertDelegateProcessed(String url) throws Exception {
assertThat(get(url), not(containsString(EXPECTED_BODY)));
}
private String get(String url) throws IOException {
driver.get(url);
return driver.getPageSource();
}
@Configuration
@EnableWebMvc
static class Config {
@RestController
static class ContextPathController {
@RequestMapping
public String contextPath(HttpServletRequest request) {
return EXPECTED_BODY;
}
}
}
}
\ No newline at end of file
package org.springframework.test.web.servlet.htmlunit.webdriver;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.fail;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.Matchers.any;
import org.mockito.Mock;
import static org.mockito.Mockito.when;
import org.mockito.runners.MockitoJUnitRunner;
/**
* @author Rob Winch
*/
// tag::junit-spring-setup[]
@RunWith(MockitoJUnitRunner.class)
public class WebConnectionHtmlUnitDriverTests {
@Mock
WebConnection connection;
WebConnectionHtmlUnitDriver driver;
@Before
public void setup() throws Exception {
driver = new WebConnectionHtmlUnitDriver();
when(connection.getResponse(any(WebRequest.class))).thenThrow(new InternalError(""));
}
@Test
public void getWebConnectionDefaultNotNull() {
assertThat(driver.getWebConnection(), notNullValue());
}
@Test
public void setWebConnection() {
driver.setWebConnection(connection);
assertThat(driver.getWebConnection(), equalTo(connection));
try {
driver.get("https://example.com");
fail("Expected Exception");
} catch (InternalError success) {}
}
@Test(expected = IllegalArgumentException.class)
public void setWebConnectionNull() {
driver.setWebConnection(null);
}
}
\ No newline at end of file
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册