Browse Source
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-13158pull/849/head
28 changed files with 4123 additions and 0 deletions
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
/* |
||||
* 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; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
/* |
||||
* 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; |
||||
} |
||||
} |
||||
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
/* |
||||
* 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); |
||||
} |
||||
} |
||||
@ -0,0 +1,523 @@
@@ -0,0 +1,523 @@
|
||||
/* |
||||
* 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+))?$"); |
||||
} |
||||
@ -0,0 +1,97 @@
@@ -0,0 +1,97 @@
|
||||
/* |
||||
* 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; |
||||
} |
||||
} |
||||
@ -0,0 +1,150 @@
@@ -0,0 +1,150 @@
|
||||
/* |
||||
* 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 + "'"); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,156 @@
@@ -0,0 +1,156 @@
|
||||
/* |
||||
* 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); |
||||
} |
||||
} |
||||
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
/* |
||||
* 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; |
||||
} |
||||
} |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
/* |
||||
* 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(); |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
/* |
||||
* 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); |
||||
} |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
/** |
||||
* Support for MockMvc and HtmlUnit integration |
||||
* |
||||
* @author Rob Winch |
||||
* @since 4.2 |
||||
*/ |
||||
package org.springframework.test.web.servlet.htmlunit; |
||||
@ -0,0 +1,114 @@
@@ -0,0 +1,114 @@
|
||||
/* |
||||
* 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; |
||||
} |
||||
} |
||||
@ -0,0 +1,96 @@
@@ -0,0 +1,96 @@
|
||||
/* |
||||
* 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); |
||||
} |
||||
} |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
/** |
||||
* Support for MockMvc and HtmlUnitDriver |
||||
* |
||||
* @author Rob Winch |
||||
* @since 4.2 |
||||
*/ |
||||
package org.springframework.test.web.servlet.htmlunit.webdriver; |
||||
@ -0,0 +1,137 @@
@@ -0,0 +1,137 @@
|
||||
/* |
||||
* 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 {} |
||||
} |
||||
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
/* |
||||
* 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:/"; |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
/* |
||||
* 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"; |
||||
} |
||||
} |
||||
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
/* |
||||
* 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));; |
||||
} |
||||
} |
||||
@ -0,0 +1,782 @@
@@ -0,0 +1,782 @@
|
||||
/* |
||||
* 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.MalformedURLException; |
||||
import java.net.URL; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collections; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Locale; |
||||
import java.util.Map; |
||||
import javax.servlet.ServletContext; |
||||
import javax.servlet.http.Cookie; |
||||
import javax.servlet.http.HttpSession; |
||||
|
||||
import com.gargoylesoftware.htmlunit.CookieManager; |
||||
import com.gargoylesoftware.htmlunit.HttpMethod; |
||||
import com.gargoylesoftware.htmlunit.WebClient; |
||||
import com.gargoylesoftware.htmlunit.WebRequest; |
||||
import com.gargoylesoftware.htmlunit.util.NameValuePair; |
||||
import org.apache.commons.io.IOUtils; |
||||
import org.apache.http.auth.UsernamePasswordCredentials; |
||||
import static org.hamcrest.Matchers.*; |
||||
import static org.junit.Assert.assertThat; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest; |
||||
import org.springframework.mock.web.MockHttpSession; |
||||
import org.springframework.mock.web.MockServletContext; |
||||
import org.springframework.test.util.ReflectionTestUtils; |
||||
import org.springframework.test.web.servlet.MockMvc; |
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders; |
||||
|
||||
/** |
||||
* |
||||
* @author Rob Winch |
||||
* |
||||
*/ |
||||
public class HtmlUnitRequestBuilderTests { |
||||
private WebRequest webRequest; |
||||
|
||||
private ServletContext servletContext; |
||||
|
||||
private Map<String, MockHttpSession> sessions; |
||||
|
||||
private WebClient webClient; |
||||
|
||||
private HtmlUnitRequestBuilder requestBuilder; |
||||
|
||||
@Before |
||||
public void setUp() throws Exception { |
||||
sessions = new HashMap<>(); |
||||
webRequest = new WebRequest(new URL("http://example.com:80/test/this/here")); |
||||
webRequest.setHttpMethod(HttpMethod.GET); |
||||
webRequest.setRequestParameters(new ArrayList<>()); |
||||
webClient = new WebClient(); |
||||
requestBuilder = new HtmlUnitRequestBuilder(sessions, webClient, webRequest); |
||||
servletContext = new MockServletContext(); |
||||
} |
||||
|
||||
// --- constructor
|
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
public void constructorNullSessions() { |
||||
new HtmlUnitRequestBuilder(null, webClient, webRequest); |
||||
} |
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
public void constructorNullWebClient() { |
||||
new HtmlUnitRequestBuilder(sessions, null, webRequest); |
||||
} |
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
public void constructorNullWebRequest() { |
||||
new HtmlUnitRequestBuilder(sessions, webClient, null); |
||||
} |
||||
|
||||
// --- buildRequest
|
||||
|
||||
@Test |
||||
public void buildRequestBasicAuth() { |
||||
String base64Credentials = "dXNlcm5hbWU6cGFzc3dvcmQ="; |
||||
String authzHeaderValue = "Basic: " + base64Credentials; |
||||
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(base64Credentials); |
||||
webRequest.setCredentials(credentials); |
||||
webRequest.setAdditionalHeader("Authorization", authzHeaderValue); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getAuthType(), equalTo("Basic")); |
||||
assertThat(actualRequest.getHeader("Authorization"), equalTo(authzHeaderValue)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestCharacterEncoding() { |
||||
String charset = "UTF-8"; |
||||
webRequest.setCharset(charset); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getCharacterEncoding(), equalTo(charset)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestDefaultCharacterEncoding() { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getCharacterEncoding(), equalTo("ISO-8859-1")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestContentLength() { |
||||
String content = "some content that has length"; |
||||
webRequest.setHttpMethod(HttpMethod.POST); |
||||
webRequest.setRequestBody(content); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getContentLength(), equalTo(content.length())); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestContentType() { |
||||
String contentType = "text/html;charset=UTF-8"; |
||||
webRequest.setAdditionalHeader("Content-Type", contentType); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getContentType(), equalTo(contentType)); |
||||
assertThat(actualRequest.getHeader("Content-Type"), equalTo(contentType)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestContextPathUsesFirstSegmentByDefault() { |
||||
String contextPath = requestBuilder.buildRequest(servletContext).getContextPath(); |
||||
|
||||
assertThat(contextPath, equalTo("/test")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestContextPathUsesNoFirstSegmentWithDefault() throws MalformedURLException { |
||||
webRequest.setUrl(new URL("http://example.com/")); |
||||
String contextPath = requestBuilder.buildRequest(servletContext).getContextPath(); |
||||
|
||||
assertThat(contextPath, equalTo("")); |
||||
} |
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
public void buildRequestContextPathInvalid() { |
||||
requestBuilder.setContextPath("/invalid"); |
||||
|
||||
requestBuilder.buildRequest(servletContext).getContextPath(); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestContextPathEmpty() { |
||||
String expected = ""; |
||||
requestBuilder.setContextPath(expected); |
||||
|
||||
String contextPath = requestBuilder.buildRequest(servletContext).getContextPath(); |
||||
|
||||
assertThat(contextPath, equalTo(expected)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestContextPathExplicit() { |
||||
String expected = "/test"; |
||||
requestBuilder.setContextPath(expected); |
||||
|
||||
String contextPath = requestBuilder.buildRequest(servletContext).getContextPath(); |
||||
|
||||
assertThat(contextPath, equalTo(expected)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestContextPathMulti() { |
||||
String expected = "/test/this"; |
||||
requestBuilder.setContextPath(expected); |
||||
|
||||
String contextPath = requestBuilder.buildRequest(servletContext).getContextPath(); |
||||
|
||||
assertThat(contextPath, equalTo(expected)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestCookiesNull() { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getCookies(), nullValue()); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestCookiesSingle() { |
||||
webRequest.setAdditionalHeader("Cookie", "name=value"); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
Cookie[] cookies = actualRequest.getCookies(); |
||||
assertThat(cookies.length, equalTo(1)); |
||||
assertThat(cookies[0].getName(), equalTo("name")); |
||||
assertThat(cookies[0].getValue(), equalTo("value")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestCookiesMulti() { |
||||
webRequest.setAdditionalHeader("Cookie", "name=value; name2=value2"); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
Cookie[] cookies = actualRequest.getCookies(); |
||||
assertThat(cookies.length, equalTo(2)); |
||||
Cookie cookie = cookies[0]; |
||||
assertThat(cookie.getName(), equalTo("name")); |
||||
assertThat(cookie.getValue(), equalTo("value")); |
||||
cookie = cookies[1]; |
||||
assertThat(cookie.getName(), equalTo("name2")); |
||||
assertThat(cookie.getValue(), equalTo("value2")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestInputStream() throws Exception { |
||||
String content = "some content that has length"; |
||||
webRequest.setHttpMethod(HttpMethod.POST); |
||||
webRequest.setRequestBody(content); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(IOUtils.toString(actualRequest.getInputStream()), equalTo(content)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocalAddr() { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocalAddr(), equalTo("127.0.0.1")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocaleDefault() { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocale(), equalTo(Locale.getDefault())); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocaleDa() { |
||||
webRequest.setAdditionalHeader("Accept-Language", "da"); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocale(), equalTo(new Locale("da"))); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocaleEnGbQ08() { |
||||
webRequest.setAdditionalHeader("Accept-Language", "en-gb;q=0.8"); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocale(), equalTo(new Locale("en", "gb", "0.8"))); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocaleEnQ07() { |
||||
webRequest.setAdditionalHeader("Accept-Language", "en;q=0.7"); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocale(), equalTo(new Locale("en", "", "0.7"))); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocaleEnUs() { |
||||
webRequest.setAdditionalHeader("Accept-Language", "en-US"); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocale(), equalTo(Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocaleFr() { |
||||
webRequest.setAdditionalHeader("Accept-Language", "fr"); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocale(), equalTo(Locale.FRENCH)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocaleMulti() { |
||||
webRequest.setAdditionalHeader("Accept-Language", "da, en-gb;q=0.8, en;q=0.7"); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
// FIXME Locale.ENGLISH is due to fact cannot remove it from MockHttpServletRequest
|
||||
List<Locale> expected = Arrays.asList(new Locale("da"), new Locale("en", "gb", "0.8"), new Locale("en", "", |
||||
"0.7"), Locale.ENGLISH); |
||||
assertThat(Collections.list(actualRequest.getLocales()), equalTo(expected)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocaleName() { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocalName(), equalTo("localhost")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocalPort() { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocalPort(), equalTo(80)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestLocalMissing() throws Exception { |
||||
webRequest.setUrl(new URL("http://localhost/test/this")); |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getLocalPort(), equalTo(-1)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestMethods() { |
||||
HttpMethod[] methods = HttpMethod.values(); |
||||
|
||||
for (HttpMethod expectedMethod : methods) { |
||||
webRequest.setHttpMethod(expectedMethod); |
||||
String actualMethod = requestBuilder.buildRequest(servletContext).getMethod(); |
||||
assertThat(actualMethod, equalTo(actualMethod)); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestParameterMap() throws Exception { |
||||
setParameter("name", "value"); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getParameterMap().size(), equalTo(1)); |
||||
assertThat(actualRequest.getParameter("name"), equalTo("value")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestParameterMapQuery() throws Exception { |
||||
webRequest.setUrl(new URL("http://example.com/example/?name=value")); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getParameterMap().size(), equalTo(1)); |
||||
assertThat(actualRequest.getParameter("name"), equalTo("value")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestParameterMapQueryMulti() throws Exception { |
||||
webRequest.setUrl(new URL("http://example.com/example/?name=value¶m2=value+2")); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getParameterMap().size(), equalTo(2)); |
||||
assertThat(actualRequest.getParameter("name"), equalTo("value")); |
||||
assertThat(actualRequest.getParameter("param2"), equalTo("value 2")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestPathInfo() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getPathInfo(), nullValue()); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestPathInfoNull() throws Exception { |
||||
webRequest.setUrl(new URL("http://example.com/example")); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getPathInfo(), nullValue()); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestAndAntPathRequestMatcher() throws Exception { |
||||
webRequest.setUrl(new URL("http://example.com/app/login/authenticate")); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
// verify it is going to work with Spring Security's AntPathRequestMatcher
|
||||
assertThat(actualRequest.getPathInfo(), nullValue()); |
||||
assertThat(actualRequest.getServletPath(), equalTo("/login/authenticate")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestProtocol() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getProtocol(), equalTo("HTTP/1.1")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestQuery() throws Exception { |
||||
String expectedQuery = "aparam=avalue"; |
||||
webRequest.setUrl(new URL("http://example.com/example?" + expectedQuery)); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getQueryString(), equalTo(expectedQuery)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestReader() throws Exception { |
||||
String expectedBody = "request body"; |
||||
webRequest.setHttpMethod(HttpMethod.POST); |
||||
webRequest.setRequestBody(expectedBody); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(IOUtils.toString(actualRequest.getReader()), equalTo(expectedBody)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestRemoteAddr() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getRemoteAddr(), equalTo("127.0.0.1")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestRemoteHost() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getRemoteAddr(), equalTo("127.0.0.1")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestRemotePort() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getRemotePort(), equalTo(80)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestRemotePort8080() throws Exception { |
||||
webRequest.setUrl(new URL("http://example.com:8080/")); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getRemotePort(), equalTo(8080)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestRemotePort80WithDefault() throws Exception { |
||||
webRequest.setUrl(new URL("http://example.com/")); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getRemotePort(), equalTo(80)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestRequestedSessionId() throws Exception { |
||||
String sessionId = "session-id"; |
||||
webRequest.setAdditionalHeader("Cookie", "JSESSIONID=" + sessionId); |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getRequestedSessionId(), equalTo(sessionId)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestRequestedSessionIdNull() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getRequestedSessionId(), nullValue()); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestUri() { |
||||
String uri = requestBuilder.buildRequest(servletContext).getRequestURI(); |
||||
assertThat(uri, equalTo("/test/this/here")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestUrl() { |
||||
String uri = requestBuilder.buildRequest(servletContext).getRequestURL().toString(); |
||||
assertThat(uri, equalTo("http://example.com/test/this/here")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSchemeHttp() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getScheme(), equalTo("http")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSchemeHttps() throws Exception { |
||||
webRequest.setUrl(new URL("https://example.com/")); |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getScheme(), equalTo("https")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestServerName() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getServerName(), equalTo("example.com")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestServerPort() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getServerPort(), equalTo(80)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestServerPortDefault() throws Exception { |
||||
webRequest.setUrl(new URL("https://example.com/")); |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getServerPort(), equalTo(-1)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestServletContext() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getServletContext(), equalTo(servletContext)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestServletPath() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getServletPath(), equalTo("/this/here")); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSession() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
HttpSession newSession = actualRequest.getSession(); |
||||
assertThat(newSession, notNullValue()); |
||||
assertSingleSessionCookie( |
||||
"JSESSIONID=" + newSession.getId() + "; Path=/test; Domain=example.com"); |
||||
|
||||
webRequest.setAdditionalHeader("Cookie", "JSESSIONID=" + newSession.getId()); |
||||
|
||||
requestBuilder = new HtmlUnitRequestBuilder(sessions, webClient, webRequest); |
||||
actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getSession(), sameInstance(newSession)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSessionWithExistingSession() throws Exception { |
||||
String sessionId = "session-id"; |
||||
webRequest.setAdditionalHeader("Cookie", "JSESSIONID=" + sessionId); |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
HttpSession session = actualRequest.getSession(); |
||||
assertThat(session.getId(), equalTo(sessionId)); |
||||
assertSingleSessionCookie("JSESSIONID=" + session.getId() + "; Path=/test; Domain=example.com"); |
||||
|
||||
requestBuilder = new HtmlUnitRequestBuilder(sessions, webClient, webRequest); |
||||
actualRequest = requestBuilder.buildRequest(servletContext); |
||||
assertThat(actualRequest.getSession(), equalTo(session)); |
||||
|
||||
webRequest.setAdditionalHeader("Cookie", "JSESSIONID=" + sessionId + "NEW"); |
||||
actualRequest = requestBuilder.buildRequest(servletContext); |
||||
assertThat(actualRequest.getSession(), not(equalTo(session))); |
||||
assertSingleSessionCookie("JSESSIONID=" + actualRequest.getSession().getId() |
||||
+ "; Path=/test; Domain=example.com"); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSessionTrue() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
HttpSession session = actualRequest.getSession(true); |
||||
assertThat(session, notNullValue()); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSessionFalseIsNull() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
HttpSession session = actualRequest.getSession(false); |
||||
assertThat(session, nullValue()); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSessionFalseWithExistingSession() throws Exception { |
||||
String sessionId = "session-id"; |
||||
webRequest.setAdditionalHeader("Cookie", "JSESSIONID=" + sessionId); |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
HttpSession session = actualRequest.getSession(false); |
||||
assertThat(session, notNullValue()); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSessionIsNew() throws Exception { |
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getSession().isNew(), equalTo(true)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSessionIsNewFalse() throws Exception { |
||||
String sessionId = "session-id"; |
||||
webRequest.setAdditionalHeader("Cookie", "JSESSIONID=" + sessionId); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getSession().isNew(), equalTo(false)); |
||||
} |
||||
|
||||
@Test |
||||
public void buildRequestSessionInvalidate() throws Exception { |
||||
String sessionId = "session-id"; |
||||
webRequest.setAdditionalHeader("Cookie", "JSESSIONID=" + sessionId); |
||||
|
||||
MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); |
||||
HttpSession sessionToRemove = actualRequest.getSession(); |
||||
sessionToRemove.invalidate(); |
||||
|
||||
assertThat(sessions.containsKey(sessionToRemove.getId()), equalTo(false)); |
||||
assertSingleSessionCookie("JSESSIONID=" + sessionToRemove.getId() |
||||
+ "; Expires=Thu, 01-Jan-1970 00:00:01 GMT; Path=/test; Domain=example.com"); |
||||
|
||||
webRequest.removeAdditionalHeader("Cookie"); |
||||
requestBuilder = new HtmlUnitRequestBuilder(sessions, webClient, webRequest); |
||||
|
||||
actualRequest = requestBuilder.buildRequest(servletContext); |
||||
|
||||
assertThat(actualRequest.getSession().isNew(), equalTo(true)); |
||||
assertThat(sessions.containsKey(sessionToRemove.getId()), equalTo(false)); |
||||
} |
||||
|
||||
// --- setContextPath
|
||||
|
||||
@Test |
||||
public void setContextPathNull() { |
||||
requestBuilder.setContextPath(null); |
||||
|
||||
assertThat(getContextPath(), nullValue()); |
||||
} |
||||
|
||||
@Test |
||||
public void setContextPathEmptyString() { |
||||
requestBuilder.setContextPath(""); |
||||
|
||||
assertThat(getContextPath(), isEmptyString()); |
||||
} |
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
public void setContextPathDoesNotStartWithSlash() { |
||||
requestBuilder.setContextPath("abc/def"); |
||||
} |
||||
|
||||
@Test(expected = IllegalArgumentException.class) |
||||
public void setContextPathEndsWithSlash() { |
||||
requestBuilder.setContextPath("/abc/def/"); |
||||
} |
||||
|
||||
@Test |
||||
public void setContextPath() { |
||||
String expectedContextPath = "/abc/def"; |
||||
requestBuilder.setContextPath(expectedContextPath); |
||||
|
||||
assertThat(getContextPath(), equalTo(expectedContextPath)); |
||||
} |
||||
|
||||
@Test |
||||
public void mergeHeader() throws Exception { |
||||
String headerName = "PARENT"; |
||||
String headerValue = "VALUE"; |
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new HelloController()) |
||||
.defaultRequest(get("/").header(headerName, headerValue)) |
||||
.build(); |
||||
|
||||
assertThat(mockMvc.perform(requestBuilder).andReturn().getRequest().getHeader(headerName), equalTo(headerValue)); |
||||
} |
||||
|
||||
@Test |
||||
public void mergeSession() throws Exception { |
||||
String attrName = "PARENT"; |
||||
String attrValue = "VALUE"; |
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new HelloController()) |
||||
.defaultRequest(get("/").sessionAttr(attrName, attrValue)) |
||||
.build(); |
||||
|
||||
assertThat(mockMvc.perform(requestBuilder).andReturn().getRequest().getSession().getAttribute(attrName), equalTo(attrValue)); |
||||
} |
||||
|
||||
@Test |
||||
public void mergeSessionNotInitialized() throws Exception { |
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new HelloController()) |
||||
.defaultRequest(get("/")) |
||||
.build(); |
||||
|
||||
assertThat(mockMvc.perform(requestBuilder).andReturn().getRequest().getSession(false), nullValue()); |
||||
} |
||||
|
||||
@Test |
||||
public void mergeParameter() throws Exception { |
||||
String paramName = "PARENT"; |
||||
String paramValue = "VALUE"; |
||||
String paramValue2 = "VALUE2"; |
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new HelloController()) |
||||
.defaultRequest(get("/").param(paramName, paramValue, paramValue2)) |
||||
.build(); |
||||
|
||||
assertThat(Arrays.asList(mockMvc.perform(requestBuilder).andReturn().getRequest().getParameterValues(paramName)), contains(paramValue, paramValue2)); |
||||
} |
||||
|
||||
@Test |
||||
public void mergeCookie() throws Exception { |
||||
String cookieName = "PARENT"; |
||||
String cookieValue = "VALUE"; |
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new HelloController()) |
||||
.defaultRequest(get("/").cookie(new Cookie(cookieName,cookieValue))) |
||||
.build(); |
||||
|
||||
Cookie[] cookies = mockMvc.perform(requestBuilder).andReturn().getRequest().getCookies(); |
||||
assertThat(cookies, notNullValue()); |
||||
assertThat(cookies.length, equalTo(1)); |
||||
Cookie cookie = cookies[0]; |
||||
assertThat(cookie.getName(), equalTo(cookieName)); |
||||
assertThat(cookie.getValue(), equalTo(cookieValue)); |
||||
} |
||||
|
||||
@Test |
||||
public void mergeRequestAttribute() throws Exception { |
||||
String attrName = "PARENT"; |
||||
String attrValue = "VALUE"; |
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new HelloController()) |
||||
.defaultRequest(get("/").requestAttr(attrName,attrValue)) |
||||
.build(); |
||||
|
||||
assertThat(mockMvc.perform(requestBuilder).andReturn().getRequest().getAttribute(attrName), equalTo(attrValue)); |
||||
} |
||||
|
||||
|
||||
private void assertSingleSessionCookie(String expected) { |
||||
com.gargoylesoftware.htmlunit.util.Cookie jsessionidCookie = webClient.getCookieManager().getCookie("JSESSIONID"); |
||||
if (expected == null || expected.contains("Expires=Thu, 01-Jan-1970 00:00:01 GMT")) { |
||||
assertThat(jsessionidCookie, nullValue()); |
||||
return; |
||||
} |
||||
String actual = jsessionidCookie.getValue(); |
||||
assertThat("JSESSIONID=" + actual + |
||||
"; Path=/test; Domain=example.com", equalTo(expected)); |
||||
} |
||||
|
||||
private void setParameter(String name, String value) { |
||||
webRequest.getRequestParameters().add(new NameValuePair(name, value)); |
||||
} |
||||
|
||||
private String getContextPath() { |
||||
return (String) ReflectionTestUtils.getField(requestBuilder, "contextPath"); |
||||
} |
||||
} |
||||
@ -0,0 +1,155 @@
@@ -0,0 +1,155 @@
|
||||
/* |
||||
* 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(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,117 @@
@@ -0,0 +1,117 @@
|
||||
/* |
||||
* 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"; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
/* |
||||
* 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/"); |
||||
} |
||||
} |
||||
@ -0,0 +1,135 @@
@@ -0,0 +1,135 @@
|
||||
/* |
||||
* 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));; |
||||
} |
||||
} |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* |
||||
* 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)); |
||||
} |
||||
} |
||||
@ -0,0 +1,136 @@
@@ -0,0 +1,136 @@
|
||||
/* |
||||
* 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; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
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); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue