├── gradle.properties ├── .gitignore ├── mail-webapp ├── src │ ├── main │ │ ├── webapp │ │ │ ├── index.jsp │ │ │ └── WEB-INF │ │ │ │ └── templates │ │ │ │ └── messages │ │ │ │ ├── view.html │ │ │ │ ├── list.html │ │ │ │ └── form.html │ │ ├── resources │ │ │ └── log4j.xml │ │ └── java │ │ │ └── sample │ │ │ ├── data │ │ │ ├── MessageRepository.java │ │ │ └── Message.java │ │ │ ├── config │ │ │ ├── WebSecurityAppInitializer.java │ │ │ ├── WebMvcAppInitializer.java │ │ │ ├── WebSecurityConfig.java │ │ │ ├── DataConfig.java │ │ │ └── WebMvcConfig.java │ │ │ └── mvc │ │ │ └── MessageController.java │ └── test │ │ ├── resources │ │ └── GebConfig.groovy │ │ ├── java │ │ └── sample │ │ │ ├── fest │ │ │ ├── Assertions.java │ │ │ └── MessageAssert.java │ │ │ ├── webdriver │ │ │ ├── pages │ │ │ │ ├── AbstractPage.java │ │ │ │ ├── LoginPage.java │ │ │ │ ├── CreateMessagePage.java │ │ │ │ └── ViewMessagePage.java │ │ │ ├── WebDriverCreateMessageITests.java │ │ │ └── MockMvcHtmlUnitDriverCreateMessageTests.java │ │ │ ├── config │ │ │ └── MockDataConfig.java │ │ │ ├── htmlunit │ │ │ └── MockMvcHtmlUnitCreateMessageTests.java │ │ │ └── mockmvc │ │ │ └── MockMvcCreateMessageTests.java │ │ └── groovy │ │ └── sample │ │ └── geb │ │ ├── pages │ │ ├── MessageRow.groovy │ │ ├── CreateMessagePage.groovy │ │ ├── ViewMessagePage.groovy │ │ └── LoginPage.groovy │ │ ├── CreateMessagesISpec.groovy │ │ └── GebCreateMessagesSpec.groovy └── build.gradle ├── spring-test-htmlunit ├── src │ ├── main │ │ ├── webapp │ │ │ ├── index.jsp │ │ │ └── WEB-INF │ │ │ │ ├── templates │ │ │ │ └── messages │ │ │ │ │ ├── view.html │ │ │ │ │ ├── list.html │ │ │ │ │ └── form.html │ │ │ │ ├── web.xml │ │ │ │ ├── spring │ │ │ │ └── spring-data.xml │ │ │ │ └── message-servlet.xml │ │ └── java │ │ │ └── org │ │ │ └── springframework │ │ │ └── test │ │ │ └── web │ │ │ └── servlet │ │ │ └── htmlunit │ │ │ ├── matchers │ │ │ ├── WebRequestMatcher.java │ │ │ ├── UrlRegexRequestMatcher.java │ │ │ └── HostRequestMatcher.java │ │ │ ├── ForwardRequestPostProcessor.java │ │ │ ├── webdriver │ │ │ ├── WebConnectionHtmlUnitDriver.java │ │ │ └── MockMvcHtmlUnitDriverBuilder.java │ │ │ ├── MockWebResponseBuilder.java │ │ │ ├── DelegatingWebConnection.java │ │ │ ├── MockMvcWebClientBuilder.java │ │ │ ├── MockMvcWebConnection.java │ │ │ ├── MockMvcWebConnectionBuilderSupport.java │ │ │ └── HtmlUnitRequestBuilder.java │ └── test │ │ └── java │ │ └── org │ │ └── springframework │ │ └── test │ │ └── web │ │ └── servlet │ │ └── htmlunit │ │ ├── ForwardController.java │ │ ├── HelloController.java │ │ ├── matchers │ │ ├── UrlRegexRequestMatcherTests.java │ │ └── HostRequestMatcherTests.java │ │ ├── webdriver │ │ ├── WebConnectionHtmlUnitDriverTests.java │ │ └── MockMvcHtmlUnitDriverBuilderTests.java │ │ ├── MockMvcWebConnectionTests.java │ │ ├── MockMvcWebClientBuilderTests.java │ │ ├── MockMvcConnectionBuilderSupportTests.java │ │ ├── MockWebResponseBuilderTests.java │ │ └── DelegatingWebConnectionTests.java └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── README.adoc ├── src └── test │ └── java │ └── docs │ ├── webdriver │ ├── why │ │ ├── ViewMessagePage.java │ │ ├── WhyWebDriversTests.java │ │ └── CreateMessagePage.java │ └── WebDriverDocTests.java │ └── htmlunit │ └── HtmlUnitDocTests.java ├── publish-maven.gradle ├── gradlew.bat ├── gradlew └── ide └── intellij └── spring-intellij-code-style.xml /gradle.properties: -------------------------------------------------------------------------------- 1 | version=1.0.0.BUILD-SNAPSHOT 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .gradle 3 | .project 4 | .settings 5 | bin 6 | build 7 | target 8 | .idea 9 | *.iml -------------------------------------------------------------------------------- /mail-webapp/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello World!

4 | 5 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello World!

4 | 5 | 6 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'spring-test-htmlunit-build' 2 | 3 | include 'spring-test-htmlunit' 4 | include 'mail-webapp' 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-test-htmlunit/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /mail-webapp/src/test/resources/GebConfig.groovy: -------------------------------------------------------------------------------- 1 | reportsDir = 'build/geb-reports/' 2 | baseUrl = System.getProperty('geb.build.baseUrl','http://localhost:8080/') 3 | driver = { new org.openqa.selenium.htmlunit.HtmlUnitDriver(true) } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Mar 14 16:18:45 CDT 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-2.4-all.zip 7 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Spring MVC Test HtmlUnit 2 | Rob Winch 3 | 4 | This project has been merged http://docs.spring.io/spring/docs/4.2.0.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#spring-mvc-test-server-htmlunit[into spring-test-4.2.0.RELEASE]. The spring-test-html project is not being maintained separately anymore. Please report issues at https://jira.spring.io/browse/SPR 5 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/matchers/WebRequestMatcher.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.web.servlet.htmlunit.matchers; 2 | 3 | import com.gargoylesoftware.htmlunit.WebRequest; 4 | 5 | /** 6 | * Strategy to match on a WebRequest 7 | * 8 | * @author Rob Winch 9 | */ 10 | public interface WebRequestMatcher { 11 | /** 12 | * Return true if matches on WebRequest, else false 13 | * 14 | * @param request the WebRequest to attempt to match on 15 | * @return true if matches on WebRequest, else false 16 | */ 17 | boolean matches(WebRequest request); 18 | } 19 | -------------------------------------------------------------------------------- /mail-webapp/src/main/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /spring-test-htmlunit/build.gradle: -------------------------------------------------------------------------------- 1 | description = 'Provides integration between Spring MVC Test and HtmlUnit' 2 | 3 | 4 | dependencies { 5 | compile "org.springframework:spring-test:$springVersion", 6 | "org.springframework:spring-context:$springVersion", 7 | "org.springframework:spring-web:$springVersion", 8 | "net.sourceforge.htmlunit:htmlunit:$htmlunitVersion" 9 | 10 | optional "org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion" 11 | 12 | provided "javax.servlet:javax.servlet-api:$servletApiVersion" 13 | 14 | testCompile 'org.easytesting:fest-assert:1.4', 15 | "org.springframework:spring-webmvc:$springVersion", 16 | "junit:junit:$junitVersion", 17 | "org.mockito:mockito-all:$mockitoVersion" 18 | 19 | jacoco "org.jacoco:org.jacoco.agent:$jacocoVersion:runtime" 20 | } -------------------------------------------------------------------------------- /mail-webapp/src/main/java/sample/data/MessageRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.data; 14 | 15 | import org.springframework.data.repository.CrudRepository; 16 | 17 | /** 18 | * 19 | * @author Rob Winch 20 | * 21 | */ 22 | public interface MessageRepository extends CrudRepository { 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/docs/webdriver/why/ViewMessagePage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package docs.webdriver.why; 17 | 18 | import com.gargoylesoftware.htmlunit.html.HtmlPage; 19 | 20 | /** 21 | * @author Rob Winch 22 | */ 23 | public class ViewMessagePage { 24 | public ViewMessagePage(HtmlPage page) {} 25 | } 26 | -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/fest/Assertions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.fest; 17 | 18 | import sample.data.Message; 19 | 20 | /** 21 | * @author Rob Winch 22 | */ 23 | public class Assertions extends org.fest.assertions.Assertions { 24 | 25 | public static MessageAssert assertThat(Message message) { 26 | return new MessageAssert(message); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /mail-webapp/src/test/groovy/sample/geb/pages/MessageRow.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.geb.pages 14 | 15 | import geb.Module 16 | 17 | 18 | /** 19 | * Represents a Message when viewed in a list view 20 | * @author Rob Winch 21 | * 22 | */ 23 | class MessageRow extends Module { 24 | static content = { 25 | cell { $("td", it) } 26 | user { cell(0).text() } 27 | subject { cell(1).text() } 28 | link { cell(1).$('a') } 29 | } 30 | } -------------------------------------------------------------------------------- /mail-webapp/src/main/java/sample/config/WebSecurityAppInitializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.config; 17 | 18 | import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; 19 | 20 | /** 21 | * @author Rob Winch 22 | */ 23 | public class WebSecurityAppInitializer extends AbstractSecurityWebApplicationInitializer { 24 | public WebSecurityAppInitializer() { 25 | super(WebSecurityConfig.class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /mail-webapp/src/main/webapp/WEB-INF/templates/messages/view.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Messages : View 6 | 7 | 8 | 9 |
10 |

Messages : View

11 |
Some Success message
12 | 13 |
14 |
ID
15 |
123
16 |
Date
17 |
July 11, 2012 2:17:16 PM CDT
18 |
Summary
19 |
A short summary...
20 |
Message
21 |
A detailed message that is longer than the summary.
22 |
23 |
24 | 25 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/webapp/WEB-INF/templates/messages/view.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Messages : View 6 | 7 | 8 | 9 |
10 |

Messages : View

11 |
Some Success message
12 | 13 |
14 |
ID
15 |
123
16 |
Date
17 |
July 11, 2012 2:17:16 PM CDT
18 |
Summary
19 |
A short summary...
20 |
Message
21 |
A detailed message that is longer than the summary.
22 |
23 |
24 | 25 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/ForwardController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit; 17 | 18 | import org.springframework.stereotype.Controller; 19 | import org.springframework.web.bind.annotation.RequestMapping; 20 | 21 | /** 22 | * @author Rob Winch 23 | */ 24 | @Controller 25 | public class ForwardController { 26 | 27 | @RequestMapping("/forward") 28 | public String forward() { 29 | return "forward:/"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | Sample Application 6 | 7 | 8 | contextConfigLocation 9 | 10 | /WEB-INF/spring/*.xml 11 | 12 | 13 | 14 | 15 | org.springframework.web.context.ContextLoaderListener 16 | 17 | 18 | 19 | message 20 | org.springframework.web.servlet.DispatcherServlet 21 | 1 22 | 23 | 24 | 25 | message 26 | / 27 | 28 | 29 | 30 | index.jsp 31 | 32 | 33 | -------------------------------------------------------------------------------- /mail-webapp/src/test/groovy/sample/geb/pages/CreateMessagePage.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.geb.pages 14 | 15 | import geb.Page 16 | 17 | 18 | /** 19 | * Represents the page that a {@link Message} is created on. 20 | * 21 | * @author Rob Winch 22 | * 23 | */ 24 | // tag::class[] 25 | class CreateMessagePage extends Page { 26 | static at = { assert title == 'Messages : Create'; true } 27 | static url = 'messages/form' 28 | static content = { 29 | submit { $('input[type=submit]') } 30 | form { $('form') } 31 | errors(required:false) { $('label.error, .alert-error')?.text() } 32 | } 33 | } 34 | // end::class[] -------------------------------------------------------------------------------- /mail-webapp/src/test/groovy/sample/geb/pages/ViewMessagePage.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.geb.pages 14 | 15 | 16 | import geb.Page 17 | 18 | 19 | /** 20 | * Represents the page where a {@link Message} details can be viewed. 21 | * @author Rob Winch 22 | * 23 | */ 24 | class ViewMessagePage extends Page { 25 | static at = { assert title == 'Messages : View'; true } 26 | static url = 'messages/' 27 | static content = { 28 | success(required:false) { $('.alert-success')?.text() } 29 | id { $('dd')[0].text() } 30 | date { $('dd')[1].text() } 31 | summary { $('dd')[2].text() } 32 | message { $('dd')[3].text() } 33 | } 34 | } -------------------------------------------------------------------------------- /mail-webapp/src/main/webapp/WEB-INF/templates/messages/list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Messages : View all 6 | 7 | 8 | 9 |
10 |

Messages : View all

11 |
12 | Create Message 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
IDCreatedSummary
No messages
1July 11, 2012 2:17:16 PM CDTThe summary
33 |
34 | 35 | -------------------------------------------------------------------------------- /mail-webapp/src/test/groovy/sample/geb/pages/LoginPage.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.geb.pages 14 | 15 | import geb.Page 16 | 17 | 18 | /** 19 | * Represents the page that a {@link Message} is created on. 20 | * 21 | * @author Rob Winch 22 | * 23 | */ 24 | class LoginPage extends Page { 25 | static at = { assert title == 'Login Page'; true } 26 | static url = 'login' 27 | 28 | static content = { 29 | usernameInput { $("input[name=username]") } 30 | passwordInput { $("input[name=password]") } 31 | submitButton { $("input[type=submit]") } 32 | } 33 | 34 | void login(username='user',password='password') { 35 | usernameInput = username 36 | passwordInput = password 37 | submitButton.click() 38 | } 39 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/HelloController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit; 17 | 18 | import org.springframework.stereotype.Controller; 19 | import org.springframework.web.bind.annotation.RequestMapping; 20 | import org.springframework.web.bind.annotation.ResponseBody; 21 | import org.springframework.web.bind.annotation.RestController; 22 | 23 | import javax.servlet.http.HttpServletRequest; 24 | 25 | /** 26 | * @author Rob Winch 27 | */ 28 | @Controller 29 | public class HelloController { 30 | @RequestMapping 31 | @ResponseBody 32 | public String header(HttpServletRequest request) { 33 | return "hello"; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mail-webapp/src/main/java/sample/config/WebMvcAppInitializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.config; 17 | 18 | import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 19 | 20 | /** 21 | * @author Rob Winch 22 | */ 23 | public class WebMvcAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 24 | @Override 25 | protected Class[] getRootConfigClasses() { 26 | return null; 27 | } 28 | 29 | @Override 30 | protected Class[] getServletConfigClasses() { 31 | return new Class[] { DataConfig.class, WebMvcConfig.class}; 32 | } 33 | 34 | @Override 35 | protected String[] getServletMappings() { 36 | return new String[] { "/"}; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/webapp/WEB-INF/templates/messages/list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Messages : View all 6 | 7 | 8 | 9 |
10 |

Messages : View all

11 |
12 | Create Message 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
IDCreatedSummary
No messages
1July 11, 2012 2:17:16 PM CDTThe summary
33 |
34 | 35 | -------------------------------------------------------------------------------- /src/test/java/docs/webdriver/why/WhyWebDriversTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package docs.webdriver.why; 17 | 18 | import com.gargoylesoftware.htmlunit.html.HtmlPage; 19 | import com.gargoylesoftware.htmlunit.html.HtmlTextInput; 20 | 21 | /** 22 | * @author Rob Winch 23 | */ 24 | public class WhyWebDriversTests { 25 | 26 | // tag::create-message[] 27 | public HtmlPage createMessage(HtmlPage currentPage, String summary, String text) { 28 | setSummary(currentPage, summary); 29 | // end::create-message[] 30 | return null; 31 | } 32 | 33 | // tag::set-summary[] 34 | public void setSummary(HtmlPage currentPage, String summary) { 35 | // tag::set-summary-input[] 36 | HtmlTextInput summaryInput = currentPage.getHtmlElementById("summary"); 37 | summaryInput.setValueAttribute(summary); 38 | // end::set-summary-input[] 39 | } 40 | // end::set-summary[] 41 | } 42 | -------------------------------------------------------------------------------- /mail-webapp/src/main/java/sample/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.config; 17 | 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.context.annotation.Configuration; 20 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 21 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 22 | import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; 23 | 24 | /** 25 | * @author Rob Winch 26 | */ 27 | @EnableWebMvcSecurity 28 | @Configuration 29 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 30 | @Autowired 31 | public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 32 | auth 33 | .inMemoryAuthentication() 34 | .withUser("user").password("password").roles("USER"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/matchers/UrlRegexRequestMatcherTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit.matchers; 17 | 18 | import com.gargoylesoftware.htmlunit.WebRequest; 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | 22 | import java.net.URL; 23 | 24 | import static org.fest.assertions.Assertions.assertThat; 25 | 26 | /** 27 | * @author Rob Winch 28 | */ 29 | public class UrlRegexRequestMatcherTests { 30 | 31 | @Test 32 | public void classlevelJavadoc() throws Exception { 33 | WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*"); 34 | 35 | boolean matches = cdnMatcher.matches(new WebRequest(new URL("http://code.jquery.com/jquery-1.11.0.min.js"))); 36 | assertThat(matches).isTrue(); 37 | 38 | matches = cdnMatcher.matches(new WebRequest(new URL("http://localhost/jquery-1.11.0.min.js"))); 39 | assertThat(matches).isFalse(); 40 | } 41 | } -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/webdriver/pages/AbstractPage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.webdriver.pages; 14 | 15 | import org.openqa.selenium.WebDriver; 16 | import org.openqa.selenium.WebElement; 17 | import org.openqa.selenium.support.FindBy; 18 | 19 | /** 20 | * Represents the common elements in a page within the message application. 21 | * 22 | * @author Rob Winch 23 | * 24 | */ 25 | public class AbstractPage { 26 | protected WebDriver driver; 27 | 28 | @FindBy(css = "label.error, .alert-error") 29 | private WebElement errors; 30 | 31 | public AbstractPage(WebDriver driver) { 32 | setDriver(driver); 33 | } 34 | 35 | public void setDriver(WebDriver driver) { 36 | this.driver = driver; 37 | } 38 | 39 | public String getErrors() { 40 | return errors.getText(); 41 | } 42 | 43 | static void get(WebDriver driver, String relativeUrl) { 44 | String url = System.getProperty("geb.build.baseUrl","http://localhost:9990/") + relativeUrl; 45 | driver.get(url); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /mail-webapp/src/main/webapp/WEB-INF/templates/messages/form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Messages : Create 5 | 6 | 7 | 8 |
9 |

Messages : Create

10 |
11 |
12 |

Validation error

13 |
14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |
23 |
24 | 25 | 26 | 33 | 34 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/ForwardRequestPostProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package org.springframework.test.web.servlet.htmlunit; 18 | 19 | import org.springframework.beans.Mergeable; 20 | import org.springframework.mock.web.MockHttpServletRequest; 21 | import org.springframework.test.web.servlet.RequestBuilder; 22 | import org.springframework.test.web.servlet.SmartRequestBuilder; 23 | import org.springframework.test.web.servlet.request.RequestPostProcessor; 24 | import org.springframework.util.Assert; 25 | 26 | /** 27 | * @author Rob Winch 28 | */ 29 | final class ForwardRequestPostProcessor implements RequestPostProcessor { 30 | private final String forwardUrl; 31 | 32 | public ForwardRequestPostProcessor(String url) { 33 | Assert.hasText(url, "Forward url must have text"); 34 | forwardUrl = url; 35 | } 36 | 37 | @Override 38 | public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { 39 | request.setServletPath(forwardUrl); 40 | return request; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/webapp/WEB-INF/spring/spring-data.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/WebConnectionHtmlUnitDriverTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.web.servlet.htmlunit.webdriver; 2 | 3 | import com.gargoylesoftware.htmlunit.WebConnection; 4 | import com.gargoylesoftware.htmlunit.WebRequest; 5 | import static org.fest.assertions.Assertions.assertThat; 6 | import static org.junit.Assert.fail; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import static org.mockito.Matchers.any; 11 | import org.mockito.Mock; 12 | import static org.mockito.Mockito.when; 13 | import org.mockito.runners.MockitoJUnitRunner; 14 | 15 | /** 16 | * @author Rob Winch 17 | */ 18 | // tag::junit-spring-setup[] 19 | @RunWith(MockitoJUnitRunner.class) 20 | public class WebConnectionHtmlUnitDriverTests { 21 | @Mock 22 | WebConnection connection; 23 | 24 | WebConnectionHtmlUnitDriver driver; 25 | 26 | @Before 27 | public void setup() throws Exception { 28 | driver = new WebConnectionHtmlUnitDriver(); 29 | 30 | when(connection.getResponse(any(WebRequest.class))).thenThrow(new InternalError("")); 31 | } 32 | 33 | @Test 34 | public void getWebConnectionDefaultNotNull() { 35 | assertThat(driver.getWebConnection()).isNotNull(); 36 | } 37 | 38 | @Test 39 | public void setWebConnection() { 40 | driver.setWebConnection(connection); 41 | 42 | assertThat(driver.getWebConnection()).isEqualTo(connection); 43 | try { 44 | driver.get("https://example.com"); 45 | fail("Expected Exception"); 46 | } catch (InternalError success) {} 47 | } 48 | 49 | @Test(expected = IllegalArgumentException.class) 50 | public void setWebConnectionNull() { 51 | driver.setWebConnection(null); 52 | } 53 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/webapp/WEB-INF/templates/messages/form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Messages : Create 6 | 7 | 8 | 9 |
10 |

Messages : Create

11 |
12 |
13 |

Validation error

14 |
15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 |
23 |
24 |
25 | 26 | 27 | 34 | 35 | -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/webdriver/pages/LoginPage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.webdriver.pages; 14 | 15 | import org.openqa.selenium.WebDriver; 16 | import org.openqa.selenium.WebElement; 17 | import org.openqa.selenium.support.FindBy; 18 | import org.openqa.selenium.support.PageFactory; 19 | 20 | /** 21 | * Represents the page where a {@link sample.data.Message} is created. 22 | * 23 | * @author Rob Winch 24 | * 25 | */ 26 | public class LoginPage extends AbstractPage { 27 | 28 | private WebElement username; 29 | 30 | private WebElement password; 31 | 32 | private WebElement submit; 33 | 34 | public LoginPage(WebDriver driver) { 35 | super(driver); 36 | } 37 | 38 | public void login(String username, String password) { 39 | this.username.sendKeys(username); 40 | this.password.sendKeys(password); 41 | this.submit.click(); 42 | } 43 | 44 | public static void login(WebDriver driver) { 45 | get(driver, "login"); 46 | LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class); 47 | loginPage.login("user","password"); 48 | } 49 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/webapp/WEB-INF/message-servlet.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/matchers/UrlRegexRequestMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit.matchers; 17 | 18 | import com.gargoylesoftware.htmlunit.WebRequest; 19 | 20 | import java.util.regex.Pattern; 21 | 22 | /** 23 | *

24 | * 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:

25 | * 26 | *
27 |  * WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*");
28 |  * 
29 | * 30 | * @author Rob Winch 31 | * @see org.springframework.test.web.servlet.htmlunit.DelegatingWebConnection 32 | */ 33 | public final class UrlRegexRequestMatcher implements WebRequestMatcher { 34 | private Pattern pattern; 35 | 36 | public UrlRegexRequestMatcher(String regex) { 37 | pattern = Pattern.compile(regex); 38 | } 39 | 40 | public UrlRegexRequestMatcher(Pattern pattern) { 41 | this.pattern = pattern; 42 | } 43 | 44 | @Override 45 | public boolean matches(WebRequest request) { 46 | String url = request.getUrl().toExternalForm(); 47 | return pattern.matcher(url).matches(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/docs/webdriver/why/CreateMessagePage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package docs.webdriver.why; 17 | 18 | import com.gargoylesoftware.htmlunit.html.HtmlPage; 19 | import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; 20 | import com.gargoylesoftware.htmlunit.html.HtmlTextInput; 21 | 22 | /** 23 | * @author Rob Winch 24 | */ 25 | // tag::class[] 26 | public class CreateMessagePage { 27 | HtmlPage currentPage; 28 | 29 | HtmlTextInput summaryInput; 30 | 31 | HtmlSubmitInput submit; 32 | 33 | public CreateMessagePage(HtmlPage currentPage) { 34 | this.currentPage = currentPage; 35 | this.summaryInput = currentPage.getHtmlElementById("summary"); 36 | this.submit = currentPage.getHtmlElementById("submit"); 37 | } 38 | 39 | public T createMessage(String summary, String text) throws Exception { 40 | setSummary(summary); 41 | 42 | HtmlPage result = submit.click(); 43 | boolean error = CreateMessagePage.at(result); 44 | 45 | return (T) (error ? new CreateMessagePage(result) : new ViewMessagePage(result)); 46 | } 47 | 48 | public void setSummary(String summary) throws Exception { 49 | summaryInput.setValueAttribute(summary); 50 | } 51 | 52 | public static boolean at(HtmlPage page) { 53 | return "Create Message".equals(page.getTitleText()); 54 | } 55 | } 56 | // end::class[] 57 | -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/fest/MessageAssert.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.fest; 17 | 18 | import org.fest.assertions.ObjectAssert; 19 | import org.springframework.test.util.MatcherAssertionErrors; 20 | import sample.data.Message; 21 | 22 | import java.util.Calendar; 23 | 24 | import static org.fest.assertions.Assertions.assertThat; 25 | 26 | /** 27 | * @author Rob Winch 28 | */ 29 | public class MessageAssert extends ObjectAssert { 30 | 31 | public MessageAssert(Message message) { 32 | super(message); 33 | } 34 | 35 | @Override 36 | public MessageAssert isEqualTo(Object expected) { 37 | isEqualToIgnoringGeneratedFields(expected); 38 | Message expectedMessage = (Message) expected; 39 | Message actualMessage = (Message) actual; 40 | assertThat(actualMessage.getId()).isEqualTo(expectedMessage.getId()); 41 | assertThat(actualMessage.getCreated()).isEqualTo(expectedMessage.getCreated()); 42 | return this; 43 | } 44 | 45 | public MessageAssert isEqualToIgnoringGeneratedFields(Object expected) { 46 | assertThat(expected).isInstanceOf(Message.class); 47 | Message expectedMessage = (Message) expected; 48 | Message actualMessage = (Message) actual; 49 | assertThat(actualMessage.getSummary()).isEqualTo(expectedMessage.getSummary()); 50 | assertThat(actualMessage.getText()).isEqualTo(expectedMessage.getText()); 51 | return this; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /mail-webapp/src/main/java/sample/data/Message.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.data; 14 | 15 | import java.util.Calendar; 16 | 17 | import javax.persistence.Entity; 18 | import javax.persistence.GeneratedValue; 19 | import javax.persistence.GenerationType; 20 | import javax.persistence.Id; 21 | import javax.persistence.Version; 22 | 23 | import org.hibernate.validator.constraints.NotEmpty; 24 | 25 | /** 26 | * 27 | * @author Rob Winch 28 | * 29 | */ 30 | @Entity 31 | public class Message { 32 | @Id 33 | @GeneratedValue(strategy = GenerationType.AUTO) 34 | private Long id; 35 | 36 | @NotEmpty(message = "Message is required.") 37 | private String text; 38 | 39 | @NotEmpty(message = "Summary is required.") 40 | private String summary; 41 | 42 | @Version 43 | private Calendar created = Calendar.getInstance(); 44 | 45 | public Long getId() { 46 | return id; 47 | } 48 | 49 | public void setId(Long id) { 50 | this.id = id; 51 | } 52 | 53 | public Calendar getCreated() { 54 | return created; 55 | } 56 | 57 | public void setCreated(Calendar created) { 58 | this.created = created; 59 | } 60 | 61 | public String getText() { 62 | return text; 63 | } 64 | 65 | public void setText(String text) { 66 | this.text = text; 67 | } 68 | 69 | public String getSummary() { 70 | return summary; 71 | } 72 | 73 | public void setSummary(String summary) { 74 | this.summary = summary; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/webdriver/pages/CreateMessagePage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.webdriver.pages; 14 | 15 | import org.openqa.selenium.WebDriver; 16 | import org.openqa.selenium.WebElement; 17 | import org.openqa.selenium.support.FindBy; 18 | import org.openqa.selenium.support.PageFactory; 19 | import sample.data.Message; 20 | 21 | /** 22 | * Represents the page where a {@link Message} is created. 23 | * 24 | * @author Rob Winch 25 | * 26 | */ 27 | // tag::class[] 28 | public class CreateMessagePage 29 | extends AbstractPage { // <1> 30 | 31 | // <2> 32 | private WebElement summary; 33 | 34 | private WebElement text; 35 | 36 | // <3> 37 | @FindBy(css = "input[type=submit]") 38 | private WebElement submit; 39 | 40 | public CreateMessagePage(WebDriver driver) { 41 | super(driver); 42 | } 43 | 44 | public T createMessage(Class resultPage, String summary, String details) { 45 | this.summary.sendKeys(summary); 46 | this.text.sendKeys(details); 47 | this.submit.click(); 48 | return PageFactory.initElements(driver, resultPage); 49 | } 50 | 51 | public static CreateMessagePage to(WebDriver driver) { 52 | // driver.get("http://localhost:8080/messages/form"); 53 | get(driver, "messages/form"); 54 | return PageFactory.initElements(driver, CreateMessagePage.class); 55 | } 56 | } 57 | // tag::class[] -------------------------------------------------------------------------------- /publish-maven.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven' 2 | 3 | ext.optionalDeps = [] 4 | ext.providedDeps = [] 5 | 6 | ext.optional = { optionalDeps << it } 7 | ext.provided = { providedDeps << it } 8 | 9 | install { 10 | repositories.mavenInstaller { 11 | customizePom(pom, project) 12 | } 13 | } 14 | 15 | def customizePom(pom, gradleProject) { 16 | pom.whenConfigured { generatedPom -> 17 | // respect 'optional' and 'provided' dependencies 18 | gradleProject.optionalDeps.each { dep -> 19 | generatedPom.dependencies.find { it.artifactId == dep.name }?.optional = true 20 | } 21 | gradleProject.providedDeps.each { dep -> 22 | generatedPom.dependencies.find { it.artifactId == dep.name }?.scope = 'provided' 23 | } 24 | 25 | // eliminate test-scoped dependencies (no need in maven central poms) 26 | generatedPom.dependencies.removeAll { dep -> 27 | dep.scope == 'test' 28 | } 29 | 30 | // add all items necessary for maven central publication 31 | generatedPom.project { 32 | name = gradleProject.description 33 | description = gradleProject.description 34 | url = 'https://github.com/rwinch/spring-test-htmlunit' 35 | licenses { 36 | license { 37 | name 'The Apache Software License, Version 2.0' 38 | url 'https://www.apache.org/licenses/LICENSE-2.0.txt' 39 | distribution 'repo' 40 | } 41 | } 42 | scm { 43 | url = 'https://github.com/spring-projects/spring-test-htmlunit' 44 | connection = 'scm:git:git://github.com/spring-projects/spring-test-htmlunit' 45 | developerConnection = 'scm:git:git://github.com/spring-projects/spring-test-htmlunit' 46 | } 47 | developers { 48 | developer { 49 | id = 'rwinch' 50 | name = 'Rob Winch' 51 | email = 'rwinch@pivotal.com' 52 | } 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /mail-webapp/src/test/groovy/sample/geb/CreateMessagesISpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.geb 14 | 15 | import geb.Page 16 | import geb.spock.GebReportingSpec 17 | import org.springframework.beans.factory.annotation.Autowired 18 | import org.springframework.test.web.geb.pages.* 19 | import sample.geb.pages.CreateMessagePage 20 | import sample.geb.pages.LoginPage 21 | import sample.geb.pages.ViewMessagePage 22 | import spock.lang.Stepwise 23 | 24 | /** 25 | * 26 | * @author Rob Winch 27 | * 28 | */ 29 | @Stepwise 30 | class CreateMessagesISpec extends GebReportingSpec { 31 | 32 | def 'login success'() { 33 | setup: 34 | to LoginPage 35 | when: 36 | login() 37 | to CreateMessagePage 38 | then: 39 | at CreateMessagePage 40 | } 41 | 42 | def 'missing field with javascript validation displays error'() { 43 | setup: 44 | to CreateMessagePage 45 | at CreateMessagePage 46 | when: 47 | submit.click(CreateMessagePage) 48 | then: 49 | errors.contains('This field is required.') 50 | } 51 | 52 | def 'missing field server side validation displays error'() { 53 | setup: 54 | to CreateMessagePage 55 | at CreateMessagePage 56 | when: 57 | form.summary = 'Summary' 58 | submit.click(CreateMessagePage) 59 | then: 60 | errors.contains('Message is required.') 61 | } 62 | 63 | def 'successfully create new message'() { 64 | setup: 65 | def expectedSummary = 'Spring Rocks' 66 | def expectedMessage = 'In case you didn\'t know, Spring Rocks!' 67 | to CreateMessagePage 68 | at CreateMessagePage 69 | when: 70 | form.summary = expectedSummary 71 | form.text = expectedMessage 72 | submit.click(ViewMessagePage) 73 | then: 74 | at ViewMessagePage 75 | success == 'Successfully created a new message' 76 | id 77 | date 78 | summary == expectedSummary 79 | message == expectedMessage 80 | } 81 | } -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/webdriver/pages/ViewMessagePage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.webdriver.pages; 14 | 15 | import org.openqa.selenium.WebDriver; 16 | import org.openqa.selenium.WebElement; 17 | import org.openqa.selenium.support.FindBy; 18 | import sample.data.Message; 19 | 20 | import java.text.DateFormat; 21 | import java.text.ParseException; 22 | import java.util.Calendar; 23 | import java.util.Locale; 24 | 25 | /** 26 | * Represents the page where the {@link Message} details can be viewed. 27 | * 28 | * @author Rob Winch 29 | * 30 | */ 31 | public class ViewMessagePage extends AbstractPage { 32 | @FindBy(className = "alert-success") 33 | private WebElement success; 34 | 35 | private WebElement id; 36 | 37 | private WebElement created; 38 | 39 | private WebElement summary; 40 | 41 | private WebElement text; 42 | 43 | public ViewMessagePage(WebDriver driver) { 44 | super(driver); 45 | } 46 | 47 | public String getSuccess() { 48 | return success.getText(); 49 | } 50 | 51 | public Long getId() { 52 | return Long.parseLong(id.getText()); 53 | } 54 | 55 | public Calendar getCreated() throws ParseException { 56 | Calendar result = Calendar.getInstance(); 57 | DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.ENGLISH); 58 | result.setTime(format.parse(created.getText())); 59 | return result; 60 | } 61 | 62 | public String getSummary() { 63 | return summary.getText(); 64 | } 65 | 66 | public String getText() { 67 | return text.getText(); 68 | } 69 | 70 | // tag::get-message[] 71 | public Message getMessage() throws ParseException { 72 | Message message = new Message(); 73 | message.setId(getId()); 74 | message.setCreated(getCreated()); 75 | message.setSummary(getSummary()); 76 | message.setText(getText()); 77 | return message; 78 | } 79 | // end::get-message[] 80 | } 81 | -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/config/MockDataConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.config; 17 | 18 | import static org.mockito.Matchers.any; 19 | import static org.mockito.Matchers.anyLong; 20 | import static org.mockito.Mockito.mock; 21 | import static org.mockito.Mockito.when; 22 | 23 | import java.util.Calendar; 24 | import java.util.Locale; 25 | 26 | import org.mockito.invocation.InvocationOnMock; 27 | import org.mockito.stubbing.Answer; 28 | import org.springframework.context.annotation.Bean; 29 | import org.springframework.context.annotation.Configuration; 30 | 31 | import sample.data.Message; 32 | import sample.data.MessageRepository; 33 | 34 | /** 35 | * @author Rob Winch 36 | */ 37 | @Configuration 38 | public class MockDataConfig { 39 | 40 | @Bean 41 | public MessageRepository messageRepository() { 42 | final Message message = createMessage(); 43 | MessageRepository messages = mock(MessageRepository.class); 44 | when(messages.save(any(Message.class))).thenAnswer(new Answer() { 45 | @Override 46 | public Message answer(InvocationOnMock invocation) throws Throwable { 47 | Object[] args = invocation.getArguments(); 48 | Message result = (Message) args[0]; 49 | result.setId(message.getId()); 50 | result.setCreated(message.getCreated()); 51 | return result; 52 | } 53 | }); 54 | when(messages.findOne(anyLong())).thenReturn(message); 55 | return messages; 56 | } 57 | 58 | @Bean 59 | public Message createMessage() { 60 | Calendar created = Calendar.getInstance(Locale.ENGLISH); 61 | // we need to clear out the milliseconds since we are not interested in being that precise 62 | created.set(Calendar.MILLISECOND, 0); 63 | created.getTime().setTime(1397672456000L); 64 | Message message = new Message(); 65 | message.setCreated(created); 66 | message.setId(123L); 67 | message.setSummary("Spring Rocks"); 68 | message.setText("In case you didn't know, Spring Rocks!"); 69 | return message; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /mail-webapp/src/main/java/sample/config/DataConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.config; 17 | 18 | import javax.sql.DataSource; 19 | 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 23 | import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; 24 | import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; 25 | import org.springframework.orm.jpa.JpaTransactionManager; 26 | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 27 | import org.springframework.orm.jpa.vendor.Database; 28 | import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; 29 | import sample.data.Message; 30 | import org.springframework.transaction.PlatformTransactionManager; 31 | import sample.data.MessageRepository; 32 | 33 | 34 | @Configuration 35 | @EnableJpaRepositories(basePackageClasses = MessageRepository.class) 36 | public class DataConfig { 37 | 38 | @Bean 39 | public DataSource dataSource() { 40 | EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); 41 | return builder.setType(EmbeddedDatabaseType.HSQL).build(); 42 | } 43 | 44 | @Bean 45 | public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 46 | HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 47 | vendorAdapter.setDatabase(Database.HSQL); 48 | vendorAdapter.setGenerateDdl(true); 49 | 50 | LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); 51 | factory.setJpaVendorAdapter(vendorAdapter); 52 | factory.setPackagesToScan(Message.class.getPackage().getName()); 53 | factory.setDataSource(dataSource()); 54 | 55 | return factory; 56 | } 57 | 58 | @Bean 59 | public PlatformTransactionManager transactionManager() { 60 | JpaTransactionManager txManager = new JpaTransactionManager(); 61 | txManager.setEntityManagerFactory(entityManagerFactory().getObject()); 62 | return txManager; 63 | } 64 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /mail-webapp/src/main/java/sample/mvc/MessageController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.mvc; 14 | 15 | import javax.validation.Valid; 16 | 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.stereotype.Controller; 19 | import sample.data.Message; 20 | import sample.data.MessageRepository; 21 | import org.springframework.validation.BindingResult; 22 | import org.springframework.web.bind.annotation.ModelAttribute; 23 | import org.springframework.web.bind.annotation.PathVariable; 24 | import org.springframework.web.bind.annotation.RequestMapping; 25 | import org.springframework.web.bind.annotation.RequestMethod; 26 | import org.springframework.web.servlet.ModelAndView; 27 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 28 | 29 | /** 30 | * 31 | * @author Rob Winch 32 | * 33 | */ 34 | @Controller 35 | @RequestMapping("/messages/") 36 | public class MessageController { 37 | private MessageRepository messageRepository; 38 | 39 | @Autowired 40 | public MessageController(MessageRepository messageRepository) { 41 | this.messageRepository = messageRepository; 42 | } 43 | 44 | @RequestMapping 45 | public ModelAndView list() { 46 | Iterable messages = messageRepository.findAll(); 47 | return new ModelAndView("messages/list", "messages", messages); 48 | } 49 | 50 | @RequestMapping("{id}") 51 | public ModelAndView view(@PathVariable("id") 52 | Long id) { 53 | Message message = messageRepository.findOne(id); 54 | return new ModelAndView("messages/view", "message", message); 55 | } 56 | 57 | @RequestMapping(value = "form", method = RequestMethod.GET) 58 | public String createForm(@ModelAttribute 59 | Message message) { 60 | return "messages/form"; 61 | } 62 | 63 | @RequestMapping(method = RequestMethod.POST) 64 | public ModelAndView create(@Valid 65 | Message message, BindingResult result, RedirectAttributes redirect) { 66 | if (result.hasErrors()) { 67 | return new ModelAndView("messages/form"); 68 | } 69 | message = messageRepository.save(message); 70 | redirect.addFlashAttribute("globalMessage", "Successfully created a new message"); 71 | return new ModelAndView("redirect:/messages/{message.id}", "message.id", message.getId()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/matchers/HostRequestMatcherTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit.matchers; 17 | 18 | import java.net.URL; 19 | 20 | import com.gargoylesoftware.htmlunit.WebRequest; 21 | import static org.fest.assertions.Assertions.assertThat; 22 | import org.junit.Test; 23 | 24 | /** 25 | * @author Rob Winch 26 | */ 27 | public class HostRequestMatcherTests { 28 | 29 | @Test 30 | public void localhostMatches() throws Exception { 31 | WebRequestMatcher matcher = new HostRequestMatcher("localhost"); 32 | 33 | boolean matches = matcher.matches(new WebRequest(new URL("http://localhost/jquery-1.11.0.min.js"))); 34 | assertThat(matches).isTrue(); 35 | 36 | matches = matcher.matches(new WebRequest(new URL("http://example.com/jquery-1.11.0.min.js"))); 37 | assertThat(matches).isFalse(); 38 | } 39 | 40 | @Test 41 | public void multipleHosts() throws Exception { 42 | WebRequestMatcher matcher = new HostRequestMatcher("localhost","example.com"); 43 | 44 | boolean matches = matcher.matches(new WebRequest(new URL("http://localhost/jquery-1.11.0.min.js"))); 45 | assertThat(matches).isTrue(); 46 | 47 | matches = matcher.matches(new WebRequest(new URL("http://example.com/jquery-1.11.0.min.js"))); 48 | assertThat(matches).isTrue(); 49 | } 50 | 51 | @Test 52 | public void specificPort() throws Exception { 53 | WebRequestMatcher matcher = new HostRequestMatcher("localhost:8080"); 54 | 55 | boolean matches = matcher.matches(new WebRequest(new URL("http://localhost:8080/jquery-1.11.0.min.js"))); 56 | assertThat(matches).isTrue(); 57 | 58 | matches = matcher.matches(new WebRequest(new URL("http://localhost:9090/jquery-1.11.0.min.js"))); 59 | assertThat(matches).isFalse(); 60 | } 61 | 62 | @Test 63 | public void defaultPortInMatcher() throws Exception { 64 | WebRequestMatcher matcher = new HostRequestMatcher("localhost:80"); 65 | 66 | boolean matches = matcher.matches(new WebRequest(new URL("http://localhost:80/jquery-1.11.0.min.js"))); 67 | assertThat(matches).isTrue(); 68 | 69 | matches = matcher.matches(new WebRequest(new URL("http://localhost/jquery-1.11.0.min.js"))); 70 | assertThat(matches).isTrue(); 71 | 72 | matches = matcher.matches(new WebRequest(new URL("http://localhost:9090/jquery-1.11.0.min.js"))); 73 | assertThat(matches).isFalse(); 74 | } 75 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2014 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit; 17 | 18 | import com.gargoylesoftware.htmlunit.Page; 19 | import com.gargoylesoftware.htmlunit.WebClient; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | import org.springframework.test.web.servlet.MockMvc; 23 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 24 | 25 | import java.io.IOException; 26 | 27 | import static org.fest.assertions.Assertions.assertThat; 28 | 29 | /** 30 | * @author Rob Winch 31 | */ 32 | public class MockMvcWebConnectionTests { 33 | MockMvc mockMvc; 34 | 35 | WebClient webClient; 36 | 37 | @Before 38 | public void setup() { 39 | mockMvc = MockMvcBuilders 40 | .standaloneSetup(new HelloController(), new ForwardController()) 41 | .build(); 42 | 43 | webClient = new WebClient(); 44 | } 45 | 46 | @Test 47 | public void contextPathNull() throws IOException { 48 | webClient.setWebConnection(new MockMvcWebConnection(mockMvc, null)); 49 | 50 | Page page = webClient.getPage("http://localhost/context/a"); 51 | 52 | assertThat(page.getWebResponse().getStatusCode()).isEqualTo(200); 53 | } 54 | 55 | @Test 56 | public void contextPathExplicit() throws IOException { 57 | webClient.setWebConnection(new MockMvcWebConnection(mockMvc, "/context")); 58 | 59 | Page page = webClient.getPage("http://localhost/context/a"); 60 | 61 | assertThat(page.getWebResponse().getStatusCode()).isEqualTo(200); 62 | } 63 | 64 | @Test 65 | public void contextPathEmpty() throws IOException { 66 | webClient.setWebConnection(new MockMvcWebConnection(mockMvc, "")); 67 | 68 | Page page = webClient.getPage("http://localhost/context/a"); 69 | 70 | assertThat(page.getWebResponse().getStatusCode()).isEqualTo(200); 71 | } 72 | 73 | @Test 74 | public void forward() throws IOException { 75 | webClient.setWebConnection(new MockMvcWebConnection(mockMvc, "")); 76 | 77 | Page page = webClient.getPage("http://localhost/forward"); 78 | 79 | assertThat(page.getWebResponse().getContentAsString()).isEqualTo("hello"); 80 | } 81 | 82 | @Test(expected = IllegalArgumentException.class) 83 | public void contextPathDoesNotStartWithSlash() throws IOException { 84 | new MockMvcWebConnection(mockMvc, "context"); 85 | } 86 | 87 | @Test(expected = IllegalArgumentException.class) 88 | public void contextPathEndsWithSlash() throws IOException { 89 | new MockMvcWebConnection(mockMvc, "/context/"); 90 | } 91 | } -------------------------------------------------------------------------------- /mail-webapp/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'groovy' 2 | apply plugin: 'war' 3 | apply plugin: 'com.bmuschko.tomcat' 4 | 5 | tasks.findByPath("artifactoryPublish")?.enabled = false 6 | sonarRunner { 7 | skipProject = true 8 | } 9 | 10 | task integrationTomcatRunWar(type: com.bmuschko.gradle.tomcat.tasks.TomcatRun, dependsOn: war) { 11 | contextPath = '' 12 | daemon = true 13 | doFirst { 14 | // delay reserving ports to ensure they are still available 15 | def ports = reservePorts(3) 16 | httpPort = ports[0] 17 | ajpPort = ports[1] 18 | stopPort = ports[2] 19 | } 20 | } 21 | 22 | task integrationTomcatStop(type: com.bmuschko.gradle.tomcat.tasks.TomcatStop, dependsOn: war) { 23 | doFirst { 24 | stopPort = integrationTomcatRunWar.stopPort 25 | } 26 | } 27 | 28 | test { 29 | doFirst { 30 | def host = 'localhost:' + integrationTomcatRunWar.httpPort 31 | systemProperties['geb.build.baseUrl'] = 'http://' + host + integrationTomcatRunWar.contextPath + '/' 32 | systemProperties['geb.build.reportsDir'] = 'build/geb-reports' 33 | } 34 | } 35 | 36 | description = 'Spring MVC Test HtmlUnit Sample' 37 | 38 | tasks.findByPath("artifactoryPublish")?.enabled = false 39 | 40 | dependencies { 41 | def tomcatVersion = '7.0.61' 42 | tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}", 43 | "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}" 44 | tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") 45 | 46 | compile "org.springframework:spring-context:$springVersion", 47 | "org.springframework:spring-webmvc:$springVersion", 48 | "org.springframework.data:spring-data-jpa:1.5.1.RELEASE", 49 | "org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final", 50 | "org.hibernate:hibernate-entitymanager:4.3.4.Final", 51 | "org.hibernate:hibernate-validator:4.1.0.Final", 52 | "org.aspectj:aspectjrt:1.6.10", 53 | "javax.validation:validation-api:1.0.0.GA", 54 | "org.slf4j:slf4j-log4j12:$slf4jVersion", 55 | "org.slf4j:jcl-over-slf4j:$slf4jVersion", 56 | "org.hsqldb:hsqldb:2.3.2", 57 | "org.thymeleaf:thymeleaf:2.1.2.RELEASE", 58 | "org.thymeleaf:thymeleaf-spring4:2.1.2.RELEASE", 59 | "org.springframework.security:spring-security-web:$springSecurityVersion", 60 | "org.springframework.security:spring-security-config:$springSecurityVersion" 61 | 62 | providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion" 63 | 64 | testCompile project(':spring-test-htmlunit'), 65 | "org.springframework:spring-test:$springVersion", 66 | "org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion", 67 | "org.seleniumhq.selenium:selenium-support:$seleniumVersion", 68 | "org.gebish:geb-spock:$gebVersion", 69 | "org.spockframework:spock-core:$spockVersion", 70 | "org.spockframework:spock-spring:$spockVersion", 71 | "junit:junit:$junitVersion", 72 | 'org.easytesting:fest-assert-core:2.0M10', 73 | "org.mockito:mockito-all:$mockitoVersion", 74 | "org.codehaus.groovy:groovy:2.4.3", 75 | 'org.easytesting:fest-assert:1.4', 76 | "org.springframework.security:spring-security-test:$springSecurityVersion" 77 | 78 | jacoco "org.jacoco:org.jacoco.agent:$jacocoVersion:runtime" 79 | } 80 | 81 | eclipse.wtp.component.contextPath = '' 82 | 83 | test { 84 | dependsOn integrationTomcatRunWar 85 | finalizedBy integrationTomcatStop 86 | } -------------------------------------------------------------------------------- /src/test/java/docs/htmlunit/HtmlUnitDocTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package docs.htmlunit; 17 | 18 | import com.gargoylesoftware.htmlunit.WebClient; 19 | import org.junit.Test; 20 | import org.junit.runner.RunWith; 21 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; 22 | 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.context.annotation.Configuration; 25 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 26 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 27 | import org.springframework.test.context.ContextConfiguration; 28 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 29 | import org.springframework.test.context.web.WebAppConfiguration; 30 | import org.springframework.test.web.servlet.MockMvc; 31 | import org.springframework.test.web.servlet.htmlunit.MockMvcWebClientBuilder; 32 | import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnection; 33 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 34 | import org.springframework.web.context.WebApplicationContext; 35 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 36 | 37 | /** 38 | * @author Rob Winch 39 | */ 40 | @RunWith(SpringJUnit4ClassRunner.class) 41 | @ContextConfiguration 42 | @WebAppConfiguration 43 | public class HtmlUnitDocTests { 44 | @Autowired 45 | WebApplicationContext context; 46 | 47 | WebClient webClient; 48 | 49 | @Test 50 | public void webclientWithMockMvc() { 51 | // tag::webclient-mockmvc[] 52 | MockMvc mockMvc = MockMvcBuilders 53 | .webAppContextSetup(context) 54 | .apply(springSecurity()) 55 | .build(); 56 | 57 | webClient = MockMvcWebClientBuilder 58 | .mockMvcSetup(mockMvc) 59 | // for illustration only - defaults to "" 60 | .contextPath("") 61 | .createWebClient(); 62 | // end::webclient-mockmvc[] 63 | } 64 | 65 | @Test 66 | public void webclientVerbose() { 67 | // tag::webclient-verbose[] 68 | String contextPath = ""; 69 | MockMvc mockMvc = MockMvcBuilders 70 | .webAppContextSetup(context) 71 | .apply(springSecurity()) 72 | .build(); 73 | 74 | webClient = new WebClient(); 75 | webClient.setWebConnection(new MockMvcWebConnection(mockMvc, contextPath)); 76 | // end::webclient-verbose[] 77 | } 78 | 79 | @Configuration 80 | @EnableWebMvc 81 | @EnableWebSecurity 82 | static class Config { 83 | @Autowired 84 | public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 85 | auth 86 | .inMemoryAuthentication(); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/matchers/HostRequestMatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit.matchers; 17 | 18 | import java.net.URL; 19 | import java.util.Arrays; 20 | import java.util.HashSet; 21 | import java.util.Set; 22 | import java.util.regex.Pattern; 23 | 24 | import com.gargoylesoftware.htmlunit.WebRequest; 25 | 26 | /** 27 | *

28 | * An implementation of WebRequestMatcher that allows matching on the host and optionally 29 | * the port of WebRequest#getUrl(). For example, the following would match any request to 30 | * the host "code.jquery.com" without regard for the port: 31 | *

32 | * 33 | *
34 |  * WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com");
35 |  * 
36 | * 37 | * Multiple hosts can also be passed in. For example, the following would match an request 38 | * to the host "code.jquery.com" or the host "cdn.com" without regard for the port: 39 | * 40 | *
41 |  * WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com", "cdn.com");
42 |  * 
43 | * 44 | *

45 | * Alternatively, one can also specify the port. For example, the following would match 46 | * any request to the host "code.jquery.com" with the port of 80. 47 | *

48 | * 49 | *
50 |  * WebRequestMatcher cdnMatcher = new HostMatcher("code.jquery.com:80");
51 |  * 
52 | * 53 | *

54 | * The above cdnMatcher would match: "http://code.jquery.com/jquery.js" (default port of 55 | * 80) and "http://code.jquery.com:80/jquery.js". However, it would not match 56 | * "https://code.jquery.com/jquery.js" (default port of 443). 57 | *

58 | * 59 | * @author Rob Winch 60 | * @see org.springframework.test.web.servlet.htmlunit.matchers.UrlRegexRequestMatcher 61 | * @see org.springframework.test.web.servlet.htmlunit.DelegatingWebConnection 62 | */ 63 | public final class HostRequestMatcher implements WebRequestMatcher { 64 | private final Set hosts = new HashSet(); 65 | 66 | /** 67 | * Creates a new instance 68 | * 69 | * @param hosts the hosts to match on (i.e. "localhost", "example.com:443") 70 | */ 71 | public HostRequestMatcher(String... hosts) { 72 | this.hosts.addAll(Arrays.asList(hosts)); 73 | } 74 | 75 | @Override 76 | public boolean matches(WebRequest request) { 77 | URL url = request.getUrl(); 78 | String host = url.getHost(); 79 | 80 | if(hosts.contains(host)) { 81 | return true; 82 | } 83 | 84 | int port = url.getPort(); 85 | if(port == -1) { 86 | port = url.getDefaultPort(); 87 | } 88 | String hostAndPort = host + ":" + port; 89 | 90 | return hosts.contains(hostAndPort); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/test/java/docs/webdriver/WebDriverDocTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package docs.webdriver; 17 | 18 | import org.junit.Test; 19 | import org.junit.runner.RunWith; 20 | import org.openqa.selenium.WebDriver; 21 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; 22 | 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.context.annotation.Configuration; 25 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 26 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 27 | import org.springframework.test.context.ContextConfiguration; 28 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 29 | import org.springframework.test.context.web.WebAppConfiguration; 30 | import org.springframework.test.web.servlet.MockMvc; 31 | import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnection; 32 | import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder; 33 | import org.springframework.test.web.servlet.htmlunit.webdriver.WebConnectionHtmlUnitDriver; 34 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 35 | import org.springframework.web.context.WebApplicationContext; 36 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 37 | 38 | /** 39 | * @author Rob Winch 40 | */ 41 | @RunWith(SpringJUnit4ClassRunner.class) 42 | @ContextConfiguration 43 | @WebAppConfiguration 44 | public class WebDriverDocTests { 45 | @Autowired 46 | WebApplicationContext context; 47 | 48 | WebDriver driver; 49 | 50 | @Test 51 | public void webDriverWithMockMvc() { 52 | // tag::webdriver-mockmvc[] 53 | MockMvc mockMvc = MockMvcBuilders 54 | .webAppContextSetup(context) 55 | .apply(springSecurity()) 56 | .build(); 57 | 58 | driver = MockMvcHtmlUnitDriverBuilder 59 | .mockMvcSetup(mockMvc) 60 | // for illustration only - defaults to "" 61 | .contextPath("") 62 | .createDriver(); 63 | // end::webdriver-mockmvc[] 64 | } 65 | 66 | @Test 67 | public void webDriverVerbose() { 68 | // tag::webdriver-verbose[] 69 | String contextPath = ""; 70 | MockMvc mockMvc = MockMvcBuilders 71 | .webAppContextSetup(context) 72 | .apply(springSecurity()) 73 | .build(); 74 | 75 | WebConnectionHtmlUnitDriver driver = new WebConnectionHtmlUnitDriver(); 76 | driver.setWebConnection(new MockMvcWebConnection(mockMvc, contextPath)); 77 | // end::webdriver-verbose[] 78 | } 79 | 80 | @Configuration 81 | @EnableWebMvc 82 | @EnableWebSecurity 83 | static class Config { 84 | @Autowired 85 | public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 86 | auth 87 | .inMemoryAuthentication(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /mail-webapp/src/main/java/sample/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.config; 17 | 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.ComponentScan; 21 | import org.springframework.core.Ordered; 22 | import org.springframework.data.repository.support.DomainClassConverter; 23 | import org.springframework.format.support.FormattingConversionService; 24 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 25 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 26 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 27 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 28 | import org.thymeleaf.spring4.SpringTemplateEngine; 29 | import org.thymeleaf.spring4.view.ThymeleafViewResolver; 30 | import org.thymeleaf.templateresolver.ServletContextTemplateResolver; 31 | import org.thymeleaf.templateresolver.TemplateResolver; 32 | import sample.mvc.MessageController; 33 | 34 | @EnableWebMvc 35 | @ComponentScan(basePackageClasses = MessageController.class) 36 | public class WebMvcConfig extends WebMvcConfigurerAdapter { 37 | 38 | @Autowired 39 | private FormattingConversionService mvcConversionService; 40 | 41 | @Override 42 | public void addViewControllers(ViewControllerRegistry registry) { 43 | registry.addViewController("/login").setViewName("login"); 44 | registry.setOrder(Ordered.HIGHEST_PRECEDENCE); 45 | } 46 | 47 | @Override 48 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 49 | registry 50 | .addResourceHandler("/resources/**") 51 | .addResourceLocations("/resources/") 52 | .setCachePeriod(31556926); 53 | registry.setOrder(Ordered.HIGHEST_PRECEDENCE); 54 | } 55 | 56 | @Bean 57 | public TemplateResolver templateResolver() { 58 | TemplateResolver result = new ServletContextTemplateResolver(); 59 | result.setPrefix("/WEB-INF/templates/"); 60 | result.setSuffix(".html"); 61 | result.setTemplateMode("HTML5"); 62 | return result; 63 | } 64 | 65 | @Bean 66 | public SpringTemplateEngine templateEngine(TemplateResolver templateResolver) { 67 | SpringTemplateEngine templateEngine = new SpringTemplateEngine(); 68 | templateEngine.setTemplateResolver(templateResolver); 69 | return templateEngine; 70 | } 71 | 72 | @Bean 73 | public ThymeleafViewResolver viewResolver(SpringTemplateEngine templateEngine) { 74 | ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); 75 | viewResolver.setTemplateEngine(templateEngine); 76 | return viewResolver; 77 | } 78 | 79 | @Bean 80 | public DomainClassConverter domainClassConverter() { 81 | return new DomainClassConverter(mvcConversionService); 82 | } 83 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/webdriver/WebConnectionHtmlUnitDriver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit.webdriver; 17 | 18 | import com.gargoylesoftware.htmlunit.BrowserVersion; 19 | import com.gargoylesoftware.htmlunit.WebClient; 20 | import com.gargoylesoftware.htmlunit.WebConnection; 21 | import org.openqa.selenium.Capabilities; 22 | import org.openqa.selenium.htmlunit.HtmlUnitDriver; 23 | import org.springframework.test.web.servlet.MockMvc; 24 | import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnection; 25 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 26 | import org.springframework.util.Assert; 27 | import org.springframework.web.context.WebApplicationContext; 28 | 29 | /** 30 | *

31 | * Allows configuring the WebConnection for an HtmlUnitDriver instance. This is useful 32 | * because it allows a MockMvcWebConnection to be injected. 33 | *

34 | * 35 | * @author Rob Winch 36 | * @since 1.0 37 | * @see MockMvcHtmlUnitDriverBuilder 38 | */ 39 | public class WebConnectionHtmlUnitDriver extends HtmlUnitDriver { 40 | private WebClient webClient; 41 | 42 | public WebConnectionHtmlUnitDriver(BrowserVersion version) { 43 | super(version); 44 | } 45 | 46 | public WebConnectionHtmlUnitDriver() { 47 | } 48 | 49 | public WebConnectionHtmlUnitDriver(boolean enableJavascript) { 50 | super(enableJavascript); 51 | } 52 | 53 | public WebConnectionHtmlUnitDriver(Capabilities capabilities) { 54 | super(capabilities); 55 | } 56 | 57 | /** 58 | * Captures the WebClient that is used so that its WebConnection is accessible. 59 | * 60 | * @param client The client to modify 61 | * @return The modified client 62 | */ 63 | @Override 64 | protected final WebClient modifyWebClient(WebClient client) { 65 | webClient = super.modifyWebClient(client); 66 | webClient = configureWebClient(webClient); 67 | return webClient; 68 | } 69 | 70 | /** 71 | * Subclasses can override this method to customise the WebClient that the HtmlUnit 72 | * driver uses. 73 | * 74 | * @param client The client to modify 75 | * @return The modified client 76 | */ 77 | protected WebClient configureWebClient(WebClient client) { 78 | return client; 79 | } 80 | 81 | /** 82 | * Allows accessing the current WebConnection 83 | * 84 | * @return the current WebConnection 85 | */ 86 | public WebConnection getWebConnection() { 87 | return webClient.getWebConnection(); 88 | } 89 | 90 | /** 91 | * Sets the WebConnection to be used. 92 | * 93 | * @param webConnection the WebConnection to use. Cannot be null. 94 | */ 95 | public void setWebConnection(WebConnection webConnection) { 96 | Assert.notNull(webConnection, "webConnection cannot be null"); 97 | this.webClient.setWebConnection(webConnection); 98 | } 99 | } -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/webdriver/WebDriverCreateMessageITests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.webdriver; 14 | 15 | import org.junit.After; 16 | import org.junit.Before; 17 | import org.junit.Test; 18 | import org.openqa.selenium.WebDriver; 19 | import org.openqa.selenium.htmlunit.HtmlUnitDriver; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.web.context.WebApplicationContext; 22 | import sample.config.MockDataConfig; 23 | import sample.data.Message; 24 | import sample.webdriver.pages.CreateMessagePage; 25 | import sample.webdriver.pages.LoginPage; 26 | import sample.webdriver.pages.ViewMessagePage; 27 | 28 | import java.text.ParseException; 29 | 30 | import static sample.fest.Assertions.assertThat; 31 | 32 | /** 33 | *

34 | * An integration test that validates the {@link CreateMessagePage}. Notice that we are able to reuse the same page 35 | * objects as the {@link MockMvcHtmlUnitDriverCreateMessageTests}. 36 | *

37 | *

38 | * NOTE The web application must actually be running for this test to pass. 39 | *

40 | * 41 | * @author Rob Winch 42 | * @see MockMvcHtmlUnitDriverCreateMessageTests 43 | */ 44 | public class WebDriverCreateMessageITests { 45 | private Message expectedMessage = new MockDataConfig().createMessage(); 46 | 47 | @Autowired 48 | private WebApplicationContext context; 49 | 50 | private WebDriver driver; 51 | 52 | @Before 53 | public void setup() { 54 | driver = new HtmlUnitDriver(true); 55 | LoginPage.login(driver); 56 | } 57 | 58 | @After 59 | public void destroy() { 60 | if(driver != null) { 61 | driver.close(); 62 | } 63 | } 64 | 65 | @Test 66 | public void missingFieldWithJavascriptValidationDisplaysError() { 67 | CreateMessagePage messagePage = CreateMessagePage.to(driver); 68 | messagePage = messagePage.createMessage(CreateMessagePage.class, "", ""); 69 | assertThat(messagePage.getErrors()).isEqualTo("This field is required."); 70 | } 71 | 72 | @Test 73 | public void missingFieldServerSideValidationDisplaysError() { 74 | CreateMessagePage messagePage = CreateMessagePage.to(driver); 75 | messagePage = messagePage.createMessage(CreateMessagePage.class, "Summary", ""); 76 | assertThat(messagePage.getErrors()).isEqualTo("Message is required."); 77 | } 78 | 79 | @Test 80 | public void successfullyCreateMessage() throws ParseException { 81 | String expectedSummary = expectedMessage.getSummary(); 82 | String expectedText = expectedMessage.getText(); 83 | 84 | CreateMessagePage page = CreateMessagePage.to(driver); 85 | 86 | ViewMessagePage viewMessagePage = page.createMessage(ViewMessagePage.class, expectedSummary, expectedText); 87 | assertThat(viewMessagePage.getMessage()).isEqualToIgnoringGeneratedFields(expectedMessage); 88 | assertThat(viewMessagePage.getSuccess()).isEqualTo("Successfully created a new message"); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/MockWebResponseBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit; 17 | 18 | import java.io.IOException; 19 | import java.util.ArrayList; 20 | import java.util.Collection; 21 | import java.util.List; 22 | 23 | import org.springframework.http.HttpStatus; 24 | import org.springframework.mock.web.MockHttpServletResponse; 25 | import org.springframework.util.Assert; 26 | 27 | import com.gargoylesoftware.htmlunit.WebRequest; 28 | import com.gargoylesoftware.htmlunit.WebResponse; 29 | import com.gargoylesoftware.htmlunit.WebResponseData; 30 | import com.gargoylesoftware.htmlunit.util.NameValuePair; 31 | 32 | /** 33 | * @author Rob Winch 34 | * 35 | */ 36 | final class MockWebResponseBuilder { 37 | private final long startTime; 38 | 39 | private final WebRequest webRequest; 40 | 41 | private final MockHttpServletResponse response; 42 | 43 | public MockWebResponseBuilder(long startTime, WebRequest webRequest, MockHttpServletResponse httpServletResponse) { 44 | Assert.notNull(webRequest, "webRequest"); 45 | Assert.notNull(httpServletResponse, "httpServletResponse cannot be null"); 46 | this.startTime = startTime; 47 | this.webRequest = webRequest; 48 | this.response = httpServletResponse; 49 | } 50 | 51 | public WebResponse build() throws IOException { 52 | WebResponseData webResponseData = webResponseData(); 53 | long endTime = System.currentTimeMillis(); 54 | return new WebResponse(webResponseData, webRequest, endTime - startTime); 55 | } 56 | 57 | private WebResponseData webResponseData() throws IOException { 58 | List responseHeaders = responseHeaders(); 59 | int statusCode = response.getRedirectedUrl() == null ? response.getStatus() : 301; 60 | String statusMessage = statusMessage(statusCode); 61 | return new WebResponseData(response.getContentAsByteArray(), statusCode, statusMessage, responseHeaders); 62 | } 63 | 64 | private String statusMessage(int statusCode) { 65 | String errorMessage = response.getErrorMessage(); 66 | if (errorMessage != null) { 67 | return errorMessage; 68 | } 69 | try { 70 | return HttpStatus.valueOf(statusCode).getReasonPhrase(); 71 | } 72 | catch (IllegalArgumentException useDefault) { 73 | } 74 | ; 75 | return "N/A"; 76 | } 77 | 78 | private List responseHeaders() { 79 | Collection headerNames = response.getHeaderNames(); 80 | List responseHeaders = new ArrayList(headerNames.size()); 81 | for (String headerName : headerNames) { 82 | List headerValues = response.getHeaderValues(headerName); 83 | for (Object value : headerValues) { 84 | responseHeaders.add(new NameValuePair(headerName, String.valueOf(value))); 85 | } 86 | } 87 | String location = response.getRedirectedUrl(); 88 | if (location != null) { 89 | responseHeaders.add(new NameValuePair("Location", location)); 90 | } 91 | return responseHeaders; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit; 17 | 18 | import com.gargoylesoftware.htmlunit.WebConnection; 19 | import com.gargoylesoftware.htmlunit.WebRequest; 20 | import com.gargoylesoftware.htmlunit.WebResponse; 21 | import org.springframework.test.web.servlet.htmlunit.matchers.WebRequestMatcher; 22 | import org.springframework.util.Assert; 23 | 24 | import java.io.IOException; 25 | import java.util.Arrays; 26 | import java.util.List; 27 | 28 | /** 29 | *

30 | * Implementation of WebConnection that allows delegating to various WebConnection implementations. For example, if 31 | * you host your JavaScript on the domain code.jquery.com, you might want to use the following:

32 | *
33 |  * WebClient webClient = new WebClient();
34 |  *
35 |  * MockMvc mockMvc = ...
36 |  * MockMvcWebConnection mockConnection = new MockMvcWebConnection(mockMvc);
37 |  *
38 |  * WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*");
39 |  * WebConnection httpConnection = new HttpWebConnection(webClient);
40 |  * WebConnection webConnection = new DelegatingWebConnection(mockConnection, new DelegateWebConnection(cdnMatcher, httpConnection));
41 |  *
42 |  * webClient.setWebConnection(webConnection);
43 |  *
44 |  * WebClient webClient = new WebClient();
45 |  * webClient.setWebConnection(webConnection);
46 |  * 
47 | * @author Rob Winch 48 | */ 49 | public final class DelegatingWebConnection implements WebConnection { 50 | private final List connections; 51 | private final WebConnection defaultConnection; 52 | 53 | public DelegatingWebConnection(WebConnection defaultConnection, List connections) { 54 | Assert.notNull(defaultConnection, "defaultConnection cannot be null"); 55 | Assert.notEmpty(connections, "connections cannot be empty"); 56 | this.connections = connections; 57 | this.defaultConnection = defaultConnection; 58 | } 59 | 60 | public DelegatingWebConnection(WebConnection defaultConnection,DelegateWebConnection... connections) { 61 | this(defaultConnection, Arrays.asList(connections)); 62 | } 63 | 64 | @Override 65 | public WebResponse getResponse(WebRequest request) throws IOException { 66 | for(DelegateWebConnection connection : connections) { 67 | if(connection.getMatcher().matches(request)) { 68 | return connection.getDelegate().getResponse(request); 69 | } 70 | } 71 | return defaultConnection.getResponse(request); 72 | } 73 | 74 | public final static class DelegateWebConnection { 75 | private final WebRequestMatcher matcher; 76 | private final WebConnection delegate; 77 | 78 | public DelegateWebConnection(WebRequestMatcher matcher, WebConnection delegate) { 79 | this.matcher = matcher; 80 | this.delegate = delegate; 81 | } 82 | 83 | private WebRequestMatcher getMatcher() { 84 | return matcher; 85 | } 86 | 87 | private WebConnection getDelegate() { 88 | return delegate; 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit; 17 | 18 | import com.gargoylesoftware.htmlunit.WebClient; 19 | 20 | import org.springframework.test.web.servlet.MockMvc; 21 | import org.springframework.test.web.servlet.setup.MockMvcConfigurer; 22 | import org.springframework.web.context.WebApplicationContext; 23 | 24 | /** 25 | * Simplifies creating a WebClient that delegates to a MockMvc instance. 26 | * 27 | * @author Rob Winch 28 | * @since 1.0 29 | */ 30 | public class MockMvcWebClientBuilder extends MockMvcWebConnectionBuilderSupport { 31 | 32 | protected MockMvcWebClientBuilder(MockMvc mockMvc) { 33 | super(mockMvc); 34 | } 35 | 36 | protected MockMvcWebClientBuilder(WebApplicationContext context) { 37 | super(context); 38 | } 39 | 40 | protected MockMvcWebClientBuilder(WebApplicationContext context, MockMvcConfigurer configurer) { 41 | super(context, configurer); 42 | } 43 | 44 | /** 45 | * Creates a new instance with a WebApplicationContext. 46 | * 47 | * @param context the WebApplicationContext to use. Cannot be null. 48 | * @return the MockMvcWebClientBuilder to customize 49 | */ 50 | public static MockMvcWebClientBuilder webAppContextSetup(WebApplicationContext context) { 51 | return new MockMvcWebClientBuilder(context); 52 | } 53 | 54 | /** 55 | * Creates a new instance using a WebApplicationContext 56 | * @param context the WebApplicationContext to create a MockMvc instance from. 57 | * @param configurer the MockMvcConfigurer to apply 58 | * Cannot be null. 59 | * @return the MockMvcWebClientBuilder to use 60 | */ 61 | public static MockMvcWebClientBuilder webAppContextSetup(WebApplicationContext context, MockMvcConfigurer configurer) { 62 | return new MockMvcWebClientBuilder(context, configurer); 63 | } 64 | 65 | /** 66 | * Creates a new instance with a MockMvc instance. 67 | * 68 | * @param mockMvc the MockMvc to use. Cannot be null. 69 | * @return the MockMvcWebClientBuilder to customize 70 | */ 71 | public static MockMvcWebClientBuilder mockMvcSetup(MockMvc mockMvc) { 72 | return new MockMvcWebClientBuilder(mockMvc); 73 | } 74 | 75 | /** 76 | * Creates a WebClient that uses the provided MockMvc for any matching requests and a 77 | * WebClient with all the default settings for any other request. 78 | * 79 | * @return the WebClient to use 80 | */ 81 | public WebClient createWebClient() { 82 | return configureWebClient(new WebClient()); 83 | } 84 | 85 | /** 86 | * Creates a WebClient that uses the provided MockMvc for any matching requests and the 87 | * provided WebClient for any other request. 88 | * 89 | * @param webClient The WebClient to delegate to for requests that do not match. Cannot be null. 90 | * 91 | * @return the WebClient to use 92 | */ 93 | public WebClient configureWebClient(WebClient webClient) { 94 | webClient.setWebConnection(createConnection(webClient.getWebConnection())); 95 | return webClient; 96 | } 97 | } -------------------------------------------------------------------------------- /mail-webapp/src/test/groovy/sample/geb/GebCreateMessagesSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package sample.geb 14 | 15 | import geb.spock.GebReportingSpec 16 | import org.openqa.selenium.WebDriver 17 | import org.springframework.beans.factory.annotation.Autowired 18 | import org.springframework.security.test.context.support.WithMockUser 19 | import org.springframework.test.context.ContextConfiguration 20 | import org.springframework.test.context.web.WebAppConfiguration 21 | import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder 22 | import org.springframework.web.context.WebApplicationContext 23 | import sample.config.MockDataConfig 24 | import sample.config.WebMvcConfig 25 | import sample.config.WebSecurityConfig 26 | import sample.data.Message 27 | import sample.geb.pages.CreateMessagePage 28 | import sample.geb.pages.ViewMessagePage 29 | 30 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity 31 | 32 | /** 33 | * 34 | * @author Rob Winch 35 | * 36 | */ 37 | // tag::spock-spring-setup[] 38 | @ContextConfiguration(classes=[WebMvcConfig, WebSecurityConfig, MockDataConfig]) // <1> 39 | @WebAppConfiguration // <2> 40 | @WithMockUser // <3> 41 | class GebCreateMessagesSpec 42 | extends GebReportingSpec { // <4> 43 | 44 | @Autowired 45 | WebApplicationContext context; 46 | // end::spock-spring-setup[] 47 | 48 | @Autowired 49 | Message expectedMessage; 50 | 51 | // tag::webdriver[] 52 | def setup() { 53 | browser.driver = MockMvcHtmlUnitDriverBuilder 54 | .webAppContextSetup(context, springSecurity()) 55 | .createDriver() 56 | } 57 | // end::webdriver[] 58 | 59 | def destroy() { 60 | browser.driver?.close() 61 | } 62 | 63 | def 'missing field with javascript validation displays error'() { 64 | setup: 65 | to CreateMessagePage 66 | at CreateMessagePage 67 | when: 68 | submit.click(CreateMessagePage) 69 | // tag::at-create-message[] 70 | then: 71 | at CreateMessagePage 72 | errors.contains('This field is required.') 73 | // end::at-create-message[] 74 | } 75 | 76 | def 'missing field server side validation displays error'() { 77 | setup: 78 | to CreateMessagePage 79 | at CreateMessagePage 80 | when: 81 | form.summary = 'Summary' 82 | submit.click(CreateMessagePage) 83 | then: 84 | errors.contains('Message is required.') 85 | } 86 | 87 | def 'successfully create new message'() { 88 | setup: 89 | def expectedSummary = 'Spring Rocks' 90 | def expectedMessage = 'In case you didn\'t know, Spring Rocks!' 91 | // tag::to-create-message[] 92 | to CreateMessagePage 93 | // end::to-create-message[] 94 | at CreateMessagePage 95 | // tag::create-message[] 96 | when: 97 | form.summary = expectedSummary 98 | form.text = expectedMessage 99 | submit.click(ViewMessagePage) 100 | // end::create-message[] 101 | // tag::create-message-assert[] 102 | then: 103 | at ViewMessagePage 104 | success == 'Successfully created a new message' 105 | id 106 | date 107 | summary == expectedSummary 108 | message == expectedMessage 109 | 110 | // end::create-message-assert[] 111 | } 112 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit; 17 | 18 | import java.io.IOException; 19 | import java.net.URL; 20 | import javax.servlet.http.HttpServletRequest; 21 | 22 | import com.gargoylesoftware.htmlunit.WebClient; 23 | import com.gargoylesoftware.htmlunit.WebRequest; 24 | import com.gargoylesoftware.htmlunit.WebResponse; 25 | import static org.fest.assertions.Assertions.assertThat; 26 | import org.junit.Before; 27 | import org.junit.Test; 28 | import org.junit.runner.RunWith; 29 | 30 | import org.springframework.beans.factory.annotation.Autowired; 31 | import org.springframework.context.annotation.Configuration; 32 | import org.springframework.test.context.ContextConfiguration; 33 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 34 | import org.springframework.test.context.web.WebAppConfiguration; 35 | import org.springframework.test.web.servlet.MockMvc; 36 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 37 | import org.springframework.web.bind.annotation.RequestMapping; 38 | import org.springframework.web.bind.annotation.RestController; 39 | import org.springframework.web.context.WebApplicationContext; 40 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 41 | 42 | /** 43 | * @author Rob Winch 44 | */ 45 | @RunWith(SpringJUnit4ClassRunner.class) 46 | @ContextConfiguration 47 | @WebAppConfiguration 48 | public class MockMvcWebClientBuilderTests { 49 | @Autowired 50 | WebApplicationContext context; 51 | 52 | MockMvc mockMvc; 53 | 54 | WebClient webClient; 55 | 56 | @Before 57 | public void setup() { 58 | mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); 59 | webClient = new WebClient(); 60 | } 61 | 62 | @Test(expected = IllegalArgumentException.class) 63 | public void mockMvcSetupNull() { 64 | MockMvcWebClientBuilder.mockMvcSetup(null); 65 | } 66 | 67 | @Test(expected = IllegalArgumentException.class) 68 | public void webAppContextSetupNull() { 69 | MockMvcWebClientBuilder.webAppContextSetup(null); 70 | } 71 | 72 | @Test 73 | public void mockMvcSetupconfigureWebClient() throws Exception { 74 | webClient = MockMvcWebClientBuilder 75 | .mockMvcSetup(mockMvc) 76 | .configureWebClient(webClient); 77 | 78 | assertMvcProcessed("http://localhost/test"); 79 | assertDelegateProcessed("http://example.com/"); 80 | } 81 | 82 | @Test 83 | public void mockMvcSetupCreateWebClient() throws Exception { 84 | webClient = MockMvcWebClientBuilder 85 | .mockMvcSetup(mockMvc) 86 | .createWebClient(); 87 | 88 | assertMvcProcessed("http://localhost/test"); 89 | assertDelegateProcessed("http://example.com/"); 90 | } 91 | 92 | private void assertMvcProcessed(String url) throws Exception { 93 | assertThat(getWebResponse(url).getContentAsString()).isEqualTo("mvc"); 94 | } 95 | 96 | private void assertDelegateProcessed(String url) throws Exception { 97 | assertThat(getWebResponse(url).getContentAsString()).isNotEqualTo("mvc"); 98 | } 99 | 100 | private WebResponse getWebResponse(String url) throws IOException { 101 | return webClient.getWebConnection().getResponse(new WebRequest(new URL(url))); 102 | } 103 | 104 | @Configuration 105 | @EnableWebMvc 106 | static class Config { 107 | @RestController 108 | static class ContextPathController { 109 | @RequestMapping 110 | public String contextPath(HttpServletRequest request) { 111 | return "mvc"; 112 | } 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/webdriver/MockMvcHtmlUnitDriverCreateMessageTests.java: -------------------------------------------------------------------------------- 1 | package sample.webdriver; 2 | 3 | import java.text.ParseException; 4 | 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.openqa.selenium.WebDriver; 10 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; 11 | import sample.config.MockDataConfig; 12 | import sample.config.WebMvcConfig; 13 | import sample.config.WebSecurityConfig; 14 | import sample.data.Message; 15 | import static sample.fest.Assertions.assertThat; 16 | import sample.webdriver.pages.CreateMessagePage; 17 | import sample.webdriver.pages.ViewMessagePage; 18 | 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.security.test.context.support.WithMockUser; 21 | import org.springframework.test.context.ContextConfiguration; 22 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 23 | import org.springframework.test.context.web.WebAppConfiguration; 24 | import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder; 25 | import org.springframework.web.context.WebApplicationContext; 26 | 27 | /** 28 | * An end to end test that validates the {@link CreateMessagePage}. A few things to notice: 29 | * 30 | *
    31 | *
  • You will see that all the tests are the same as {@link WebDriverCreateMessageITests}. This shows how little difference 32 | * there is in how you would write the tests.
  • 33 | *
  • The only difference is how we initialize our {@link WebDriver}
  • 34 | *
  • We do not need to run the web application on a server for this test since we are using 35 | * {@link org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriver}
  • 36 | *
37 | * 38 | * @author Rob Winch 39 | * 40 | */ 41 | // tag::junit-spring-setup[] 42 | @RunWith(SpringJUnit4ClassRunner.class) // <1> 43 | @ContextConfiguration(classes = {WebMvcConfig.class, WebSecurityConfig.class, MockDataConfig.class}) // <2> 44 | @WebAppConfiguration // <3> 45 | @WithMockUser // <4> 46 | public class MockMvcHtmlUnitDriverCreateMessageTests { 47 | @Autowired 48 | WebApplicationContext context; 49 | // end::junit-spring-setup[] 50 | 51 | @Autowired 52 | Message expectedMessage; 53 | 54 | // tag::webdriver[] 55 | WebDriver driver; 56 | 57 | @Before 58 | public void setup() { 59 | driver = MockMvcHtmlUnitDriverBuilder 60 | .webAppContextSetup(context, springSecurity()) 61 | .createDriver(); 62 | } 63 | // end::webdriver[] 64 | 65 | // tag::cleanup[] 66 | @After 67 | public void destroy() { 68 | if(driver != null) { 69 | driver.close(); 70 | } 71 | } 72 | // end::cleanup[] 73 | 74 | @Test 75 | public void missingFieldWithJavascriptValidationDisplaysError() { 76 | CreateMessagePage messagePage = CreateMessagePage.to(driver); 77 | messagePage = messagePage.createMessage(CreateMessagePage.class, "", ""); 78 | assertThat(messagePage.getErrors()).isEqualTo("This field is required."); 79 | } 80 | 81 | @Test 82 | public void missingFieldServerSideValidationDisplaysError() { 83 | CreateMessagePage messagePage = CreateMessagePage.to(driver); 84 | messagePage = messagePage.createMessage(CreateMessagePage.class, "Summary", ""); 85 | assertThat(messagePage.getErrors()).isEqualTo("Message is required."); 86 | } 87 | 88 | @Test 89 | public void successfullyCreateMessage() throws ParseException { 90 | String expectedSummary = expectedMessage.getSummary(); 91 | String expectedText = expectedMessage.getText(); 92 | 93 | // tag::to-create-message[] 94 | CreateMessagePage page = CreateMessagePage.to(driver); 95 | // end::to-create-message[] 96 | 97 | // tag::create-message[] 98 | ViewMessagePage viewMessagePage = 99 | page.createMessage(ViewMessagePage.class, expectedSummary, expectedText); 100 | // end::create-message[] 101 | 102 | // tag::create-message-assert[] 103 | assertThat(viewMessagePage.getMessage()).isEqualTo(expectedMessage); 104 | assertThat(viewMessagePage.getSuccess()).isEqualTo("Successfully created a new message"); 105 | // end::create-message-assert[] 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/htmlunit/MockMvcHtmlUnitCreateMessageTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.htmlunit; 17 | 18 | import com.gargoylesoftware.htmlunit.WebClient; 19 | import com.gargoylesoftware.htmlunit.html.*; 20 | import org.junit.After; 21 | import org.junit.Before; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.security.test.context.support.WithMockUser; 26 | import org.springframework.test.context.ContextConfiguration; 27 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 28 | import org.springframework.test.context.web.WebAppConfiguration; 29 | import org.springframework.test.web.servlet.MockMvc; 30 | import org.springframework.test.web.servlet.htmlunit.MockMvcWebClientBuilder; 31 | import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnection; 32 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 33 | import org.springframework.web.context.WebApplicationContext; 34 | import sample.config.MockDataConfig; 35 | import sample.config.WebMvcConfig; 36 | import sample.config.WebSecurityConfig; 37 | 38 | import java.io.IOException; 39 | 40 | import static org.fest.assertions.Assertions.assertThat; 41 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; 42 | 43 | /** 44 | * @author Rob Winch 45 | */ 46 | // tag::junit-spring-setup[] 47 | @RunWith(SpringJUnit4ClassRunner.class) // <1> 48 | @ContextConfiguration(classes = {WebMvcConfig.class, WebSecurityConfig.class, MockDataConfig.class}) // <2> 49 | @WebAppConfiguration // <3> 50 | @WithMockUser // <4> 51 | public class MockMvcHtmlUnitCreateMessageTests { 52 | 53 | @Autowired 54 | WebApplicationContext context; 55 | // end::junit-spring-setup[] 56 | 57 | 58 | // tag::webclient[] 59 | WebClient webClient; 60 | 61 | @Before 62 | public void setup() { 63 | webClient = MockMvcWebClientBuilder 64 | .webAppContextSetup(context, springSecurity()) 65 | // for illustration only - defaults to "" 66 | .contextPath("") 67 | .createWebClient(); 68 | } 69 | // end::webclient[] 70 | 71 | @After 72 | public void cleanup() { 73 | this.webClient.close(); 74 | } 75 | 76 | @Test 77 | public void createMessage() throws IOException { 78 | // Load the Create Message Form 79 | // tag::create-form[] 80 | HtmlPage createMsgFormPage = webClient.getPage("http://localhost/messages/form"); 81 | // end::create-form[] 82 | 83 | // Submit the create message form 84 | // tag::submit-form[] 85 | HtmlForm form = createMsgFormPage.getHtmlElementById("messageForm"); 86 | HtmlTextInput summaryInput = createMsgFormPage.getHtmlElementById("summary"); 87 | summaryInput.setValueAttribute("Spring Rocks"); 88 | HtmlTextArea textInput = createMsgFormPage.getHtmlElementById("text"); 89 | textInput.setText("In case you didn't know, Spring Rocks!"); 90 | HtmlSubmitInput submit = form.getOneHtmlElementByAttribute("input", "type", "submit"); 91 | HtmlPage newMessagePage = submit.click(); 92 | // end::submit-form[] 93 | 94 | // verify we successfully created a message and displayed the newly create message 95 | // tag::verify-form[] 96 | assertThat(newMessagePage.getUrl().toString()).endsWith("/messages/123"); 97 | String id = newMessagePage.getHtmlElementById("id").getTextContent(); 98 | assertThat(id).isEqualTo("123"); 99 | String summary = newMessagePage.getHtmlElementById("summary").getTextContent(); 100 | assertThat(summary).isEqualTo("Spring Rocks"); 101 | String text = newMessagePage.getHtmlElementById("text").getTextContent(); 102 | assertThat(text).isEqualTo("In case you didn't know, Spring Rocks!"); 103 | // end::verify-form[] 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /mail-webapp/src/test/java/sample/mockmvc/MockMvcCreateMessageTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package sample.mockmvc; 17 | 18 | import org.junit.After; 19 | import org.junit.Before; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.mockito.invocation.InvocationOnMock; 23 | import org.mockito.stubbing.Answer; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.test.context.ContextConfiguration; 26 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 27 | import org.springframework.test.context.web.WebAppConfiguration; 28 | import org.springframework.test.web.servlet.MockMvc; 29 | import sample.config.MockDataConfig; 30 | import sample.config.WebMvcConfig; 31 | import sample.data.Message; 32 | import sample.data.MessageRepository; 33 | import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; 34 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 35 | import org.springframework.web.context.WebApplicationContext; 36 | 37 | import javax.servlet.http.HttpServletRequest; 38 | import java.util.Calendar; 39 | 40 | import static org.mockito.Matchers.any; 41 | import static org.mockito.Matchers.anyLong; 42 | import static org.mockito.Mockito.reset; 43 | import static org.mockito.Mockito.when; 44 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 45 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 46 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; 47 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 48 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath; 49 | 50 | /** 51 | * @author Rob Winch 52 | */ 53 | @RunWith(SpringJUnit4ClassRunner.class) 54 | @ContextConfiguration(classes = {WebMvcConfig.class, MockDataConfig.class}) 55 | @WebAppConfiguration 56 | public class MockMvcCreateMessageTests { 57 | 58 | @Autowired 59 | private WebApplicationContext context; 60 | 61 | private MockMvc mockMvc; 62 | 63 | @Before 64 | public void setup() { 65 | this.mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); 66 | } 67 | 68 | @Test 69 | public void createMessage() throws Exception { 70 | // tag::create-message[] 71 | MockHttpServletRequestBuilder createMessage = post("/messages/") 72 | .param("summary", "Spring Rocks") 73 | .param("text", "In case you didn't know, Spring Rocks!"); 74 | 75 | mockMvc.perform(createMessage) 76 | .andExpect(status().is3xxRedirection()) 77 | .andExpect(redirectedUrl("/messages/123")); 78 | // end::create-message[] 79 | } 80 | 81 | @Test 82 | public void createMessageForm() throws Exception { 83 | // tag::create-message-form[] 84 | mockMvc.perform(get("/messages/form")) 85 | .andExpect(xpath("//input[@name='summary']").exists()) 86 | .andExpect(xpath("//textarea[@name='text']").exists()); 87 | // end::create-message-form[] 88 | } 89 | 90 | @Test 91 | public void createMessageFormSubmit() throws Exception { 92 | // tag::create-message-form-submit[] 93 | String summaryParamName = "summary"; 94 | String textParamName = "text"; 95 | mockMvc.perform(get("/messages/form")) 96 | .andExpect(xpath("//input[@name='" + summaryParamName + "']").exists()) 97 | .andExpect(xpath("//textarea[@name='" + textParamName + "']").exists()); 98 | 99 | MockHttpServletRequestBuilder createMessage = post("/messages/") 100 | .param(summaryParamName, "Spring Rocks") 101 | .param(textParamName, "In case you didn't know, Spring Rocks!"); 102 | 103 | mockMvc.perform(createMessage) 104 | .andExpect(status().is3xxRedirection()) 105 | .andExpect(redirectedUrl("/messages/123")); 106 | // end::create-message-form-submit[] 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit.webdriver; 17 | 18 | import com.gargoylesoftware.htmlunit.BrowserVersion; 19 | import org.openqa.selenium.htmlunit.HtmlUnitDriver; 20 | 21 | import org.springframework.test.web.servlet.MockMvc; 22 | import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnectionBuilderSupport; 23 | import org.springframework.test.web.servlet.setup.MockMvcConfigurer; 24 | import org.springframework.web.context.WebApplicationContext; 25 | 26 | /** 27 | * Convenience class for building an HtmlUnitDriver that will delegate to MockMvc and 28 | * optionally delegate to an actual connection for specific requests. 29 | * 30 | * By default localhost will delegate to MockMvc and any other URL will delegate 31 | * 32 | * @author Rob Winch 33 | * @since 1.0 34 | */ 35 | public class MockMvcHtmlUnitDriverBuilder extends MockMvcWebConnectionBuilderSupport { 36 | private boolean javascriptEnabled = true; 37 | 38 | protected MockMvcHtmlUnitDriverBuilder(MockMvc mockMvc) { 39 | super(mockMvc); 40 | } 41 | 42 | protected MockMvcHtmlUnitDriverBuilder(WebApplicationContext context) { 43 | super(context); 44 | } 45 | 46 | protected MockMvcHtmlUnitDriverBuilder(WebApplicationContext context, MockMvcConfigurer configurer) { 47 | super(context, configurer); 48 | } 49 | 50 | /** 51 | * Creates a new instance with a WebApplicationContext. 52 | * 53 | * @param context the WebApplicationContext to use. Cannot be null. 54 | * @return the MockMvcHtmlUnitDriverBuilder to customize 55 | */ 56 | public static MockMvcHtmlUnitDriverBuilder webAppContextSetup(WebApplicationContext context) { 57 | return new MockMvcHtmlUnitDriverBuilder(context); 58 | } 59 | 60 | /** 61 | * Creates a new instance using a WebApplicationContext 62 | * @param context the WebApplicationContext to create a MockMvc instance from. 63 | * @param configurer the MockMvcConfigurer to apply 64 | * Cannot be null. 65 | * @return the MockMvcHtmlUnitDriverBuilder to customize 66 | */ 67 | public static MockMvcHtmlUnitDriverBuilder webAppContextSetup(WebApplicationContext context, MockMvcConfigurer configurer) { 68 | return new MockMvcHtmlUnitDriverBuilder(context, configurer); 69 | } 70 | 71 | /** 72 | * Creates a new instance with a MockMvc instance. 73 | * 74 | * @param mockMvc the MockMvc to use. Cannot be null. 75 | * @return the MockMvcHtmlUnitDriverBuilder to customize 76 | */ 77 | public static MockMvcHtmlUnitDriverBuilder mockMvcSetup(MockMvc mockMvc) { 78 | return new MockMvcHtmlUnitDriverBuilder(mockMvc); 79 | } 80 | 81 | /** 82 | * Specifies if JavaScript should be enabled or not. Default is true. 83 | * 84 | * @param javascriptEnabled if JavaScript should be enabled or not. 85 | * @return the builder for further customizations 86 | */ 87 | public MockMvcHtmlUnitDriverBuilder javascriptEnabled(boolean javascriptEnabled) { 88 | this.javascriptEnabled = javascriptEnabled; 89 | return this; 90 | } 91 | 92 | /** 93 | * Creates a new HtmlUnitDriver with the BrowserVersion set to CHROME. For additional 94 | * configuration options, use configureDriver. 95 | * 96 | * @return the HtmlUnitDriver to use 97 | * @see #configureDriver(WebConnectionHtmlUnitDriver) 98 | */ 99 | public HtmlUnitDriver createDriver() { 100 | return configureDriver(new WebConnectionHtmlUnitDriver(BrowserVersion.CHROME)); 101 | } 102 | 103 | /** 104 | * Configures an existing WebConnectionHtmlUnitDriver. 105 | * 106 | * @param driver the WebConnectionHtmlUnitDriver to configure 107 | * @return the HtmlUnitDriver to use 108 | */ 109 | public HtmlUnitDriver configureDriver(WebConnectionHtmlUnitDriver driver) { 110 | driver.setJavascriptEnabled(javascriptEnabled); 111 | driver.setWebConnection(createConnection(driver.getWebConnection())); 112 | return driver; 113 | } 114 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilderTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit.webdriver; 17 | 18 | import java.io.IOException; 19 | import javax.servlet.http.HttpServletRequest; 20 | 21 | import static org.fest.assertions.Assertions.assertThat; 22 | import org.junit.Before; 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.openqa.selenium.htmlunit.HtmlUnitDriver; 26 | 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.context.annotation.Configuration; 29 | import org.springframework.test.context.ContextConfiguration; 30 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 31 | import org.springframework.test.context.web.WebAppConfiguration; 32 | import org.springframework.test.web.servlet.MockMvc; 33 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 34 | import org.springframework.web.bind.annotation.RequestMapping; 35 | import org.springframework.web.bind.annotation.RestController; 36 | import org.springframework.web.context.WebApplicationContext; 37 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 38 | 39 | /** 40 | * @author Rob Winch 41 | */ 42 | @RunWith(SpringJUnit4ClassRunner.class) 43 | @ContextConfiguration 44 | @WebAppConfiguration 45 | public class MockMvcHtmlUnitDriverBuilderTests { 46 | 47 | public static final String EXPECTED_BODY = "MockMvcHtmlUnitDriverBuilderTests mvc"; 48 | 49 | @Autowired 50 | WebApplicationContext context; 51 | 52 | MockMvc mockMvc; 53 | 54 | HtmlUnitDriver driver; 55 | 56 | @Before 57 | public void setup() { 58 | mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); 59 | } 60 | 61 | @Test(expected = IllegalArgumentException.class) 62 | public void mockMvcSetupNull() { 63 | MockMvcHtmlUnitDriverBuilder.mockMvcSetup(null); 64 | } 65 | 66 | @Test(expected = IllegalArgumentException.class) 67 | public void webAppContextSetupNull() { 68 | MockMvcHtmlUnitDriverBuilder.webAppContextSetup(null); 69 | } 70 | 71 | @Test 72 | public void mockMvcSetupConfigureDriver() throws Exception { 73 | driver = MockMvcHtmlUnitDriverBuilder 74 | .mockMvcSetup(mockMvc) 75 | .configureDriver(new WebConnectionHtmlUnitDriver()); 76 | 77 | assertMvcProcessed("http://localhost/test"); 78 | assertDelegateProcessed("http://example.com/"); 79 | } 80 | 81 | @Test 82 | public void mockMvcSetupCreateDriver() throws Exception { 83 | driver = MockMvcHtmlUnitDriverBuilder 84 | .mockMvcSetup(mockMvc) 85 | .createDriver(); 86 | 87 | assertMvcProcessed("http://localhost/test"); 88 | assertDelegateProcessed("http://example.com/"); 89 | } 90 | 91 | @Test 92 | public void javascriptEnabledDefaultEnabled() { 93 | driver = MockMvcHtmlUnitDriverBuilder 94 | .mockMvcSetup(mockMvc) 95 | .createDriver(); 96 | 97 | assertThat(driver.isJavascriptEnabled()).isTrue(); 98 | } 99 | 100 | @Test 101 | public void javascriptEnabledDisabled() { 102 | driver = MockMvcHtmlUnitDriverBuilder 103 | .mockMvcSetup(mockMvc) 104 | .javascriptEnabled(false) 105 | .createDriver(); 106 | 107 | assertThat(driver.isJavascriptEnabled()).isFalse(); 108 | } 109 | 110 | private void assertMvcProcessed(String url) throws Exception { 111 | assertThat(get(url)).contains(EXPECTED_BODY); 112 | } 113 | 114 | private void assertDelegateProcessed(String url) throws Exception { 115 | assertThat(get(url)).doesNotContain(EXPECTED_BODY); 116 | } 117 | 118 | private String get(String url) throws IOException { 119 | driver.get(url); 120 | return driver.getPageSource(); 121 | } 122 | 123 | @Configuration 124 | @EnableWebMvc 125 | static class Config { 126 | @RestController 127 | static class ContextPathController { 128 | @RequestMapping 129 | public String contextPath(HttpServletRequest request) { 130 | return EXPECTED_BODY; 131 | } 132 | } 133 | } 134 | 135 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcConnectionBuilderSupportTests.java: -------------------------------------------------------------------------------- 1 | package org.springframework.test.web.servlet.htmlunit; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | import com.gargoylesoftware.htmlunit.WebConnection; 9 | import com.gargoylesoftware.htmlunit.WebRequest; 10 | import com.gargoylesoftware.htmlunit.WebResponse; 11 | import static org.fest.assertions.Assertions.assertThat; 12 | import org.junit.Before; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import static org.mockito.Mockito.mock; 16 | 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.test.context.ContextConfiguration; 20 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 21 | import org.springframework.test.context.web.WebAppConfiguration; 22 | import org.springframework.test.web.servlet.MockMvc; 23 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 24 | import org.springframework.web.bind.annotation.RequestMapping; 25 | import org.springframework.web.bind.annotation.RestController; 26 | import org.springframework.web.context.WebApplicationContext; 27 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 28 | 29 | /** 30 | * @author Rob Winch 31 | */ 32 | @RunWith(SpringJUnit4ClassRunner.class) 33 | @ContextConfiguration 34 | @WebAppConfiguration 35 | public class MockMvcConnectionBuilderSupportTests { 36 | @Autowired 37 | WebApplicationContext context; 38 | 39 | MockMvc mockMvc; 40 | 41 | WebConnection delegateConnection; 42 | 43 | WebConnection connection; 44 | 45 | @Before 46 | public void setup() { 47 | delegateConnection = mock(WebConnection.class); 48 | mockMvc = MockMvcBuilders.webAppContextSetup(context).build(); 49 | 50 | connection = new MockMvcWebConnectionBuilderSupport(mockMvc){} 51 | .createConnection(delegateConnection); 52 | } 53 | 54 | @Test(expected = IllegalArgumentException.class) 55 | public void constructorMockMvcNull() { 56 | new MockMvcWebConnectionBuilderSupport((MockMvc)null){}; 57 | } 58 | 59 | @Test(expected = IllegalArgumentException.class) 60 | public void constructorContextNull() { 61 | new MockMvcWebConnectionBuilderSupport((WebApplicationContext)null){}; 62 | } 63 | 64 | @Test 65 | public void context() throws Exception { 66 | connection = new MockMvcWebConnectionBuilderSupport(context){} 67 | .createConnection(delegateConnection); 68 | 69 | assertMvcProcessed("http://localhost/"); 70 | assertDelegateProcessed("http://example.com/"); 71 | } 72 | 73 | @Test 74 | public void mockMvc() throws Exception { 75 | assertMvcProcessed("http://localhost/"); 76 | assertDelegateProcessed("http://example.com/"); 77 | } 78 | 79 | @Test 80 | public void mockMvcExampleDotCom() throws Exception { 81 | connection = new MockMvcWebConnectionBuilderSupport(context){} 82 | .useMockMvcForHosts("example.com") 83 | .createConnection(delegateConnection); 84 | 85 | assertMvcProcessed("http://localhost/"); 86 | assertMvcProcessed("http://example.com/"); 87 | assertDelegateProcessed("http://other.com/"); 88 | } 89 | 90 | @Test 91 | public void mockMvcAlwaysUseMockMvc() throws Exception { 92 | connection = new MockMvcWebConnectionBuilderSupport(context){} 93 | .alwaysUseMockMvc() 94 | .createConnection(delegateConnection); 95 | 96 | assertMvcProcessed("http://other.com/"); 97 | } 98 | 99 | @Test 100 | public void defaultContextPathEmpty() throws Exception { 101 | connection = new MockMvcWebConnectionBuilderSupport(context){} 102 | .createConnection(delegateConnection); 103 | 104 | assertThat(getWebResponse("http://localhost/abc").getContentAsString()).isEqualTo(""); 105 | } 106 | 107 | @Test 108 | public void defaultContextPathCustom() throws Exception { 109 | connection = new MockMvcWebConnectionBuilderSupport(context){} 110 | .contextPath("/abc") 111 | .createConnection(delegateConnection); 112 | 113 | assertThat(getWebResponse("http://localhost/abc/def").getContentAsString()).isEqualTo("/abc"); 114 | } 115 | 116 | private void assertMvcProcessed(String url) throws Exception { 117 | assertThat(getWebResponse(url)).isNotNull(); 118 | } 119 | 120 | private void assertDelegateProcessed(String url) throws Exception { 121 | assertThat(getWebResponse(url)).isNull(); 122 | } 123 | 124 | private WebResponse getWebResponse(String url) throws IOException { 125 | return connection.getResponse(new WebRequest(new URL(url))); 126 | } 127 | 128 | @Configuration 129 | @EnableWebMvc 130 | static class Config { 131 | @RestController 132 | static class ContextPathController { 133 | @RequestMapping 134 | public String contextPath(HttpServletRequest request) { 135 | return request.getContextPath(); 136 | } 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/MockWebResponseBuilderTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package org.springframework.test.web.servlet.htmlunit; 14 | 15 | import static org.fest.assertions.Assertions.assertThat; 16 | 17 | import java.net.URL; 18 | import java.util.List; 19 | 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | import org.springframework.mock.web.MockHttpServletResponse; 23 | import org.springframework.test.web.servlet.htmlunit.MockWebResponseBuilder; 24 | 25 | import com.gargoylesoftware.htmlunit.WebRequest; 26 | import com.gargoylesoftware.htmlunit.WebResponse; 27 | import com.gargoylesoftware.htmlunit.util.NameValuePair; 28 | 29 | /** 30 | * 31 | * @author Rob Winch 32 | */ 33 | public class MockWebResponseBuilderTests { 34 | 35 | private WebRequest webRequest; 36 | 37 | private MockHttpServletResponse httpServletResponse; 38 | 39 | private MockWebResponseBuilder responseBuilder; 40 | 41 | @Before 42 | public void setUp() throws Exception { 43 | webRequest = new WebRequest(new URL("http://example.com:80/test/this/here")); 44 | httpServletResponse = new MockHttpServletResponse(); 45 | 46 | responseBuilder = new MockWebResponseBuilder(System.currentTimeMillis(), webRequest, httpServletResponse); 47 | } 48 | 49 | // --- constructor 50 | 51 | @Test(expected = IllegalArgumentException.class) 52 | public void constructorNullWebRequest() { 53 | new MockWebResponseBuilder(0L, null, httpServletResponse); 54 | } 55 | 56 | @Test(expected = IllegalArgumentException.class) 57 | public void constructorNullResponse() throws Exception { 58 | new MockWebResponseBuilder(0L, new WebRequest(new URL("http://example.com:80/test/this/here")), null); 59 | } 60 | 61 | // --- build 62 | 63 | @Test 64 | public void buildContent() throws Exception { 65 | httpServletResponse.getWriter().write("expected content"); 66 | 67 | WebResponse webResponse = responseBuilder.build(); 68 | 69 | assertThat(webResponse.getContentAsString()).isEqualTo("expected content"); 70 | } 71 | 72 | @Test 73 | public void buildContentCharset() throws Exception { 74 | httpServletResponse.addHeader("Content-Type", "text/html; charset=UTF-8"); 75 | WebResponse webResponse = responseBuilder.build(); 76 | 77 | assertThat(webResponse.getContentCharset()).isEqualTo("UTF-8"); 78 | } 79 | 80 | @Test 81 | public void buildContentType() throws Exception { 82 | httpServletResponse.addHeader("Content-Type", "text/html; charset-UTF-8"); 83 | WebResponse webResponse = responseBuilder.build(); 84 | 85 | assertThat(webResponse.getContentType()).isEqualTo("text/html"); 86 | } 87 | 88 | @Test 89 | public void buildResponseHeaders() throws Exception { 90 | httpServletResponse.addHeader("Content-Type", "text/html"); 91 | httpServletResponse.addHeader("X-Test", "value"); 92 | WebResponse webResponse = responseBuilder.build(); 93 | 94 | List responseHeaders = webResponse.getResponseHeaders(); 95 | assertThat(responseHeaders.size()).isEqualTo(2); 96 | NameValuePair header = responseHeaders.get(0); 97 | assertThat(header.getName()).isEqualTo("Content-Type"); 98 | assertThat(header.getValue()).isEqualTo("text/html"); 99 | header = responseHeaders.get(1); 100 | assertThat(header.getName()).isEqualTo("X-Test"); 101 | assertThat(header.getValue()).isEqualTo("value"); 102 | } 103 | 104 | @Test 105 | public void buildStatus() throws Exception { 106 | WebResponse webResponse = responseBuilder.build(); 107 | 108 | assertThat(webResponse.getStatusCode()).isEqualTo(200); 109 | assertThat(webResponse.getStatusMessage()).isEqualTo("OK"); 110 | } 111 | 112 | @Test 113 | public void buildStatusNotOk() throws Exception { 114 | httpServletResponse.setStatus(401); 115 | WebResponse webResponse = responseBuilder.build(); 116 | 117 | assertThat(webResponse.getStatusCode()).isEqualTo(401); 118 | assertThat(webResponse.getStatusMessage()).isEqualTo("Unauthorized"); 119 | } 120 | 121 | @Test 122 | public void buildStatusCustomMessage() throws Exception { 123 | httpServletResponse.sendError(401, "Custom"); 124 | WebResponse webResponse = responseBuilder.build(); 125 | 126 | assertThat(webResponse.getStatusCode()).isEqualTo(401); 127 | assertThat(webResponse.getStatusMessage()).isEqualTo("Custom"); 128 | } 129 | 130 | @Test 131 | public void buildWebRequest() throws Exception { 132 | WebResponse webResponse = responseBuilder.build(); 133 | 134 | assertThat(webResponse.getWebRequest()).isEqualTo(webRequest); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/test/java/org/springframework/test/web/servlet/htmlunit/DelegatingWebConnectionTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit; 17 | 18 | import com.gargoylesoftware.htmlunit.*; 19 | import com.gargoylesoftware.htmlunit.util.NameValuePair; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.mockito.Mock; 24 | import org.mockito.runners.MockitoJUnitRunner; 25 | import org.springframework.stereotype.Controller; 26 | import org.springframework.test.web.servlet.MockMvc; 27 | import org.springframework.test.web.servlet.htmlunit.matchers.UrlRegexRequestMatcher; 28 | import org.springframework.test.web.servlet.htmlunit.matchers.WebRequestMatcher; 29 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 30 | 31 | import java.net.URL; 32 | import java.util.Collections; 33 | 34 | import static org.fest.assertions.Assertions.assertThat; 35 | import static org.mockito.Mockito.*; 36 | import static org.springframework.test.web.servlet.htmlunit.DelegatingWebConnection.DelegateWebConnection; 37 | 38 | /** 39 | * @author Rob Winch 40 | */ 41 | @RunWith(MockitoJUnitRunner.class) 42 | public class DelegatingWebConnectionTests { 43 | private DelegatingWebConnection webConnection; 44 | 45 | @Mock 46 | private WebRequestMatcher matcher1; 47 | @Mock 48 | private WebRequestMatcher matcher2; 49 | @Mock 50 | private WebConnection defaultConnection; 51 | @Mock 52 | private WebConnection connection1; 53 | @Mock 54 | private WebConnection connection2; 55 | 56 | private WebRequest request; 57 | private WebResponse expectedResponse; 58 | 59 | @Before 60 | public void setUp() throws Exception { 61 | request = new WebRequest(new URL("http://localhost/")); 62 | WebResponseData data = new WebResponseData("".getBytes("UTF-8"),200, "", Collections.emptyList()); 63 | expectedResponse = new WebResponse(data, request, 100L); 64 | webConnection = new DelegatingWebConnection(defaultConnection, new DelegateWebConnection(matcher1,connection1), new DelegateWebConnection(matcher2,connection2)); 65 | } 66 | 67 | @Test 68 | public void getResponseDefault() throws Exception { 69 | when(defaultConnection.getResponse(request)).thenReturn(expectedResponse); 70 | 71 | WebResponse response = webConnection.getResponse(request); 72 | 73 | assertThat(response).isSameAs(expectedResponse); 74 | verify(matcher1).matches(request); 75 | verify(matcher2).matches(request); 76 | verifyNoMoreInteractions(connection1,connection2); 77 | verify(defaultConnection).getResponse(request); 78 | } 79 | 80 | @Test 81 | public void getResponseAllMatches() throws Exception { 82 | when(matcher1.matches(request)).thenReturn(true); 83 | when(matcher2.matches(request)).thenReturn(true); 84 | when(connection1.getResponse(request)).thenReturn(expectedResponse); 85 | 86 | WebResponse response = webConnection.getResponse(request); 87 | 88 | assertThat(response).isSameAs(expectedResponse); 89 | verify(matcher1).matches(request); 90 | verifyNoMoreInteractions(matcher2,connection2,defaultConnection); 91 | verify(connection1).getResponse(request); 92 | } 93 | 94 | @Test 95 | public void getResponseSecondMatches() throws Exception { 96 | when(matcher2.matches(request)).thenReturn(true); 97 | when(connection2.getResponse(request)).thenReturn(expectedResponse); 98 | 99 | WebResponse response = webConnection.getResponse(request); 100 | 101 | assertThat(response).isSameAs(expectedResponse); 102 | verify(matcher1).matches(request); 103 | verify(matcher2).matches(request); 104 | verifyNoMoreInteractions(connection1,defaultConnection); 105 | verify(connection2).getResponse(request); 106 | } 107 | 108 | @Test 109 | public void classlevelJavadoc() throws Exception { 110 | WebClient webClient = new WebClient(); 111 | 112 | MockMvc mockMvc = MockMvcBuilders.standaloneSetup(TestController.class).build(); 113 | MockMvcWebConnection mockConnection = new MockMvcWebConnection(mockMvc); 114 | 115 | WebRequestMatcher cdnMatcher = new UrlRegexRequestMatcher(".*?//code.jquery.com/.*"); 116 | WebConnection httpConnection = new HttpWebConnection(webClient); 117 | WebConnection webConnection = new DelegatingWebConnection(mockConnection, new DelegateWebConnection(cdnMatcher, httpConnection)); 118 | 119 | webClient.setWebConnection(webConnection); 120 | 121 | Page page = webClient.getPage("http://code.jquery.com/jquery-1.11.0.min.js"); 122 | assertThat(page.getWebResponse().getStatusCode()).isEqualTo(200); 123 | assertThat(page.getWebResponse().getContentAsString()).isNotEmpty(); 124 | } 125 | 126 | @Controller 127 | static class TestController {} 128 | } -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package org.springframework.test.web.servlet.htmlunit; 14 | 15 | import java.io.IOException; 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | import org.springframework.mock.web.MockHttpServletResponse; 20 | import org.springframework.mock.web.MockHttpSession; 21 | import org.springframework.test.web.servlet.MockMvc; 22 | import org.springframework.test.web.servlet.RequestBuilder; 23 | import org.springframework.test.web.servlet.ResultActions; 24 | import org.springframework.test.web.servlet.htmlunit.webdriver.WebConnectionHtmlUnitDriver; 25 | import org.springframework.util.Assert; 26 | 27 | import com.gargoylesoftware.htmlunit.CookieManager; 28 | import com.gargoylesoftware.htmlunit.WebConnection; 29 | import com.gargoylesoftware.htmlunit.WebRequest; 30 | import com.gargoylesoftware.htmlunit.WebResponse; 31 | 32 | import javax.servlet.http.HttpServletRequest; 33 | 34 | /** 35 | *

36 | * Allows {@link MockMvc} to transform a {@link WebRequest} into a {@link WebResponse}. This is the core integration 37 | * with HTML Unit. 38 | *

39 | *

40 | * Example usage can be seen below: 41 | *

42 | * 43 | *
 44 |  * MockMvc mockMvc = ...
 45 |  * MockMvcWebConnection webConnection = new MockMvcWebConnection(mockMvc);
 46 |  * WebClient webClient = new WebClient();
 47 |  * webClient.setWebConnection(webConnection);
 48 |  *
 49 |  * ... use webClient as normal ...
 50 |  * 
51 | * 52 | * @author Rob Winch 53 | * @see WebConnectionHtmlUnitDriver 54 | */ 55 | public final class MockMvcWebConnection implements WebConnection { 56 | private final CookieManager cookieManager; 57 | 58 | private final Map sessions = new HashMap(); 59 | 60 | private final MockMvc mockMvc; 61 | 62 | private final String contextPath; 63 | 64 | /** 65 | * Creates a new instance that assumes the context root of the application is "". For example, 66 | * the URL http://localhost/test/this would use "" as the context root. 67 | * 68 | * @param mockMvc the MockMvc instance to use 69 | */ 70 | public MockMvcWebConnection(MockMvc mockMvc) { 71 | this(mockMvc, ""); 72 | } 73 | 74 | /** 75 | * Creates a new instance with a specified context root. 76 | * 77 | * @param mockMvc the MockMvc instance to use 78 | * @param contextPath the contextPath to use. The value may be null in which case the first path segment of the URL is turned 79 | * into the contextPath. Otherwise it must conform to {@link HttpServletRequest#getContextPath()} which states it 80 | * can be empty string or it must start with a "/" and not end in a "/". 81 | */ 82 | public MockMvcWebConnection(MockMvc mockMvc, String contextPath) { 83 | Assert.notNull(mockMvc, "mockMvc cannot be null"); 84 | validateContextPath(contextPath); 85 | 86 | this.mockMvc = mockMvc; 87 | this.cookieManager = new CookieManager(); 88 | this.contextPath = contextPath; 89 | } 90 | 91 | public WebResponse getResponse(WebRequest webRequest) throws IOException { 92 | long startTime = System.currentTimeMillis(); 93 | HtmlUnitRequestBuilder requestBuilder = new HtmlUnitRequestBuilder(sessions, cookieManager, webRequest); 94 | requestBuilder.setContextPath(contextPath); 95 | 96 | MockHttpServletResponse httpServletResponse = getResponse(requestBuilder); 97 | 98 | String forwardedUrl = httpServletResponse.getForwardedUrl(); 99 | while(forwardedUrl != null) { 100 | requestBuilder.setForwardPostProcessor(new ForwardRequestPostProcessor(forwardedUrl)); 101 | httpServletResponse = getResponse(requestBuilder); 102 | forwardedUrl = httpServletResponse.getForwardedUrl(); 103 | } 104 | 105 | return new MockWebResponseBuilder(startTime, webRequest, httpServletResponse).build(); 106 | } 107 | 108 | private MockHttpServletResponse getResponse(RequestBuilder requestBuilder) throws IOException { 109 | ResultActions resultActions; 110 | try { 111 | resultActions = mockMvc.perform(requestBuilder); 112 | } 113 | catch (Exception e) { 114 | throw (IOException) new IOException(e.getMessage()).initCause(e); 115 | } 116 | 117 | return resultActions.andReturn().getResponse(); 118 | } 119 | 120 | /** 121 | * Performs validation on the contextPath 122 | * 123 | * @param contextPath the contextPath to validate 124 | */ 125 | private static void validateContextPath(String contextPath) { 126 | if (contextPath == null || "".equals(contextPath)) { 127 | return; 128 | } 129 | if (contextPath.endsWith("/")) { 130 | throw new IllegalArgumentException("contextPath cannot end with /. Got '" + contextPath + "'"); 131 | } 132 | if (!contextPath.startsWith("/")) { 133 | throw new IllegalArgumentException("contextPath must start with /. Got '" + contextPath + "'"); 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="-Xmx1024M -XX:MaxPermSize=256M" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionBuilderSupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package org.springframework.test.web.servlet.htmlunit; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import com.gargoylesoftware.htmlunit.WebConnection; 22 | 23 | import org.springframework.test.web.servlet.MockMvc; 24 | import org.springframework.test.web.servlet.htmlunit.matchers.HostRequestMatcher; 25 | import org.springframework.test.web.servlet.htmlunit.matchers.WebRequestMatcher; 26 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 27 | import org.springframework.test.web.servlet.setup.MockMvcConfigurer; 28 | import org.springframework.util.Assert; 29 | import org.springframework.web.context.WebApplicationContext; 30 | 31 | /** 32 | * Makes it easy to create a WebConnection that uses MockMvc and optionally delegates to 33 | * a real WebConnection for specific requests. The default is to use MockMvc for any host 34 | * that is "localhost" and otherwise use a real WebConnection. 35 | * 36 | * @author Rob Winch 37 | * @since 1.0 38 | */ 39 | public abstract class MockMvcWebConnectionBuilderSupport> { 40 | private String contextPath = ""; 41 | 42 | private final MockMvc mockMvc; 43 | 44 | private List mockMvcRequestMatchers = new ArrayList(); 45 | 46 | private boolean alwaysUseMockMvc; 47 | 48 | /** 49 | * Creates a new instance using a MockMvc instance 50 | * 51 | * @param mockMvc the MockMvc instance to use. Cannot be null. 52 | */ 53 | protected MockMvcWebConnectionBuilderSupport(MockMvc mockMvc) { 54 | Assert.notNull(mockMvc, "mockMvc cannot be null"); 55 | this.mockMvc = mockMvc; 56 | this.mockMvcRequestMatchers.add(new HostRequestMatcher("localhost")); 57 | } 58 | 59 | /** 60 | * Creates a new instance using a WebApplicationContext 61 | * @param context the WebApplicationContext to create a MockMvc instance from. 62 | * Cannot be null. 63 | */ 64 | protected MockMvcWebConnectionBuilderSupport(WebApplicationContext context) { 65 | this(MockMvcBuilders.webAppContextSetup(context).build()); 66 | } 67 | 68 | /** 69 | * Creates a new instance using a WebApplicationContext 70 | * @param context the WebApplicationContext to create a MockMvc instance from. 71 | * @param configurer the MockMvcConfigurer to apply 72 | * Cannot be null. 73 | */ 74 | protected MockMvcWebConnectionBuilderSupport(WebApplicationContext context, MockMvcConfigurer configurer) { 75 | this(MockMvcBuilders.webAppContextSetup(context).apply(configurer).build()); 76 | } 77 | 78 | /** 79 | * The context path to use. Default is "". If the value is null, then the first path 80 | * segment of the request URL is assumed to be the context path. 81 | * 82 | * @param contextPath the context path to use. 83 | * @return the builder for further customization 84 | */ 85 | public T contextPath(String contextPath) { 86 | this.contextPath = contextPath; 87 | return (T) this; 88 | } 89 | 90 | /** 91 | * Always use MockMvc no matter what the request looks like. 92 | * 93 | * @return the builder for further customization 94 | */ 95 | public T alwaysUseMockMvc() { 96 | this.alwaysUseMockMvc = true; 97 | return (T) this; 98 | } 99 | 100 | /** 101 | * Add additional WebRequestMatcher instances that if return true will ensure MockMvc 102 | * is used. 103 | * 104 | * @param matchers the WebRequestMatcher instances that if true will ensure MockMvc 105 | * processes the request. 106 | * @return the builder for further customization 107 | */ 108 | public T useMockMvc(WebRequestMatcher... matchers) { 109 | for(WebRequestMatcher matcher : matchers) { 110 | this.mockMvcRequestMatchers.add(matcher); 111 | } 112 | return (T) this; 113 | } 114 | 115 | /** 116 | * Add additional WebRequestMatcher instances that will return true if the host matches. 117 | * 118 | * @param hosts the additional hosts that will ensure MockMvc gets invoked (i.e. example.com or example.com:8080). 119 | * @return the builder for further customization 120 | */ 121 | public T useMockMvcForHosts(String... hosts) { 122 | this.mockMvcRequestMatchers.add(new HostRequestMatcher(hosts)); 123 | return (T) this; 124 | } 125 | 126 | /** 127 | * Creates a new WebConnection that will use a MockMvc instance if one of the 128 | * specified WebRequestMatcher matches. 129 | * 130 | * @param defaultConnection the default WebConnection to use if none of the specified 131 | * WebRequestMatcher instances match. Cannot be null. 132 | * @return a new WebConnection that will use a MockMvc instance if one of the 133 | * specified WebRequestMatcher matches. 134 | * 135 | * @see #alwaysUseMockMvc 136 | * @see #useMockMvc(WebRequestMatcher...) 137 | * @see #useMockMvcForHosts(String...) 138 | */ 139 | protected final WebConnection createConnection(WebConnection defaultConnection) { 140 | Assert.notNull(defaultConnection, "defaultConnection cannot be null"); 141 | MockMvcWebConnection mockMvcWebConnection = new MockMvcWebConnection(mockMvc, contextPath); 142 | 143 | if(alwaysUseMockMvc) { 144 | return mockMvcWebConnection; 145 | } 146 | 147 | List delegates = new ArrayList(mockMvcRequestMatchers.size()); 148 | for(WebRequestMatcher matcher : mockMvcRequestMatchers) { 149 | delegates.add(new DelegatingWebConnection.DelegateWebConnection(matcher, mockMvcWebConnection)); 150 | } 151 | 152 | return new DelegatingWebConnection(defaultConnection, delegates); 153 | } 154 | } -------------------------------------------------------------------------------- /ide/intellij/spring-intellij-code-style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 194 | 195 | -------------------------------------------------------------------------------- /spring-test-htmlunit/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 5 | * the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | * specific language governing permissions and limitations under the License. 12 | */ 13 | package org.springframework.test.web.servlet.htmlunit; 14 | 15 | import java.io.UnsupportedEncodingException; 16 | import java.net.URL; 17 | import java.net.URLDecoder; 18 | import java.util.*; 19 | import java.util.Map.Entry; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | 23 | import javax.servlet.ServletContext; 24 | import javax.servlet.http.Cookie; 25 | import javax.servlet.http.HttpServletRequest; 26 | import javax.servlet.http.HttpSession; 27 | 28 | import org.springframework.beans.Mergeable; 29 | import org.springframework.http.MediaType; 30 | import org.springframework.mock.web.MockHttpServletRequest; 31 | import org.springframework.mock.web.MockHttpSession; 32 | import org.springframework.test.web.servlet.RequestBuilder; 33 | import org.springframework.test.web.servlet.SmartRequestBuilder; 34 | import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; 35 | import org.springframework.test.web.servlet.request.RequestPostProcessor; 36 | import org.springframework.util.Assert; 37 | import org.springframework.web.util.UriComponents; 38 | import org.springframework.web.util.UriComponentsBuilder; 39 | 40 | import com.gargoylesoftware.htmlunit.CookieManager; 41 | import com.gargoylesoftware.htmlunit.WebRequest; 42 | import com.gargoylesoftware.htmlunit.util.NameValuePair; 43 | 44 | /** 45 | *

46 | * Internal class used to allow a {@link WebRequest} into a {@link MockHttpServletRequest} using Spring MVC Test's 47 | * {@link RequestBuilder}. 48 | *

49 | *

50 | * By default the first path segment of the URL is used as the contextPath. To override this default see 51 | * {@link #setContextPath(String)}. 52 | *

53 | * 54 | * @author Rob Winch 55 | * @see MockMvcWebConnection 56 | */ 57 | final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { 58 | private final Map sessions; 59 | 60 | private final CookieManager cookieManager; 61 | 62 | private final WebRequest webRequest; 63 | 64 | private String contextPath; 65 | 66 | private RequestBuilder parentBuilder; 67 | 68 | private SmartRequestBuilder parentPostProcessor; 69 | 70 | private RequestPostProcessor forwardPostProcessor; 71 | 72 | /** 73 | * 74 | * @param sessions A {@link Map} of the {@link HttpSession#getId()} to currently managed {@link HttpSession} 75 | * objects. Cannot be null. 76 | * @param cookieManager The {@link CookieManager} used for managing {@link HttpSession}'s JSESSIONID cookie. 77 | * @param webRequest The {@link WebRequest} to transform into a {@link MockHttpServletRequest}. Cannot be null. 78 | */ 79 | public HtmlUnitRequestBuilder(Map sessions, CookieManager cookieManager, 80 | WebRequest webRequest) { 81 | Assert.notNull(sessions, "sessions cannot be null"); 82 | Assert.notNull(cookieManager, "cookieManager"); 83 | Assert.notNull(webRequest, "webRequest cannot be null"); 84 | 85 | this.sessions = sessions; 86 | this.cookieManager = cookieManager; 87 | this.webRequest = webRequest; 88 | } 89 | 90 | public MockHttpServletRequest buildRequest(ServletContext servletContext) { 91 | String charset = getCharset(); 92 | String httpMethod = webRequest.getHttpMethod().name(); 93 | UriComponents uriComponents = uriComponents(); 94 | 95 | MockHttpServletRequest result = new HtmlUnitMockHttpServletRequest(servletContext, httpMethod, 96 | uriComponents.getPath()); 97 | parent(result, parentBuilder); 98 | result.setServerName(uriComponents.getHost()); // needs to be first for additional headers 99 | authType(result); 100 | result.setCharacterEncoding(charset); 101 | content(result, charset); 102 | contextPath(result, uriComponents); 103 | contentType(result); 104 | cookies(result); 105 | headers(result); 106 | locales(result); 107 | servletPath(uriComponents, result); 108 | params(result, uriComponents); 109 | ports(uriComponents, result); 110 | result.setProtocol("HTTP/1.1"); 111 | result.setQueryString(uriComponents.getQuery()); 112 | result.setScheme(uriComponents.getScheme()); 113 | pathInfo(uriComponents,result); 114 | 115 | return postProcess(result); 116 | } 117 | 118 | private MockHttpServletRequest postProcess(MockHttpServletRequest request) { 119 | if(parentPostProcessor != null) { 120 | request = parentPostProcessor.postProcessRequest(request); 121 | } 122 | if(forwardPostProcessor != null) { 123 | request = forwardPostProcessor.postProcessRequest(request); 124 | } 125 | 126 | return request; 127 | } 128 | 129 | private void parent(MockHttpServletRequest result, RequestBuilder parent) { 130 | if(parent == null) { 131 | return; 132 | } 133 | MockHttpServletRequest parentRequest = parent.buildRequest(result.getServletContext()); 134 | 135 | // session 136 | HttpSession parentSession = parentRequest.getSession(false); 137 | if(parentSession != null) { 138 | Enumeration attrNames = parentSession.getAttributeNames(); 139 | while(attrNames.hasMoreElements()) { 140 | String attrName = attrNames.nextElement(); 141 | Object attrValue = parentSession.getAttribute(attrName); 142 | result.getSession().setAttribute(attrName, attrValue); 143 | } 144 | } 145 | 146 | // header 147 | Enumeration headerNames = parentRequest.getHeaderNames(); 148 | while(headerNames.hasMoreElements()) { 149 | String attrName = headerNames.nextElement(); 150 | Enumeration attrValues = parentRequest.getHeaders(attrName); 151 | while(attrValues.hasMoreElements()) { 152 | String attrValue = attrValues.nextElement(); 153 | result.addHeader(attrName, attrValue); 154 | } 155 | } 156 | 157 | // parameter 158 | Map parentParams = parentRequest.getParameterMap(); 159 | for(Map.Entry parentParam : parentParams.entrySet()) { 160 | String paramName = parentParam.getKey(); 161 | String[] paramValues = parentParam.getValue(); 162 | result.addParameter(paramName, paramValues); 163 | } 164 | 165 | // cookie 166 | Cookie[] parentCookies = parentRequest.getCookies(); 167 | if(parentCookies != null) { 168 | result.setCookies(parentCookies); 169 | } 170 | 171 | // request attribute 172 | Enumeration parentAttrNames = parentRequest.getAttributeNames(); 173 | while(parentAttrNames.hasMoreElements()) { 174 | String parentAttrName = parentAttrNames.nextElement(); 175 | result.setAttribute(parentAttrName, parentRequest.getAttribute(parentAttrName)); 176 | } 177 | } 178 | 179 | /** 180 | * Sets the contextPath to be used. The value may be null in which case the first path segment of the URL is turned 181 | * into the contextPath. Otherwise it must conform to {@link HttpServletRequest#getContextPath()} which states it 182 | * can be empty string or it must start with a "/" and not end in a "/". 183 | * 184 | * @param contextPath A valid contextPath 185 | * @throws IllegalArgumentException if contextPath is not a valid {@link HttpServletRequest#getContextPath()}. 186 | */ 187 | public void setContextPath(String contextPath) { 188 | if (contextPath == null || "".equals(contextPath)) { 189 | this.contextPath = contextPath; 190 | return; 191 | } 192 | if (contextPath.endsWith("/")) { 193 | throw new IllegalArgumentException("contextPath cannot end with /. Got '" + contextPath + "'"); 194 | } 195 | if (!contextPath.startsWith("/")) { 196 | throw new IllegalArgumentException("contextPath must start with /. Got '" + contextPath + "'"); 197 | } 198 | this.contextPath = contextPath; 199 | } 200 | 201 | public void setForwardPostProcessor(RequestPostProcessor postProcessor) { 202 | this.forwardPostProcessor = postProcessor; 203 | } 204 | 205 | private void authType(MockHttpServletRequest request) { 206 | String authorization = header("Authorization"); 207 | if (authorization != null) { 208 | String[] authzParts = authorization.split(": "); 209 | request.setAuthType(authzParts[0]); 210 | } 211 | } 212 | 213 | private void content(MockHttpServletRequest result, String charset) { 214 | String requestBody = webRequest.getRequestBody(); 215 | if (requestBody == null) { 216 | return; 217 | } 218 | try { 219 | result.setContent(requestBody.getBytes(charset)); 220 | } 221 | catch (UnsupportedEncodingException e) { 222 | throw new RuntimeException(e); 223 | } 224 | } 225 | 226 | private void contentType(MockHttpServletRequest result) { 227 | String contentType = header("Content-Type"); 228 | result.setContentType(contentType == null ? MediaType.ALL_VALUE.toString() : contentType); 229 | } 230 | 231 | private void contextPath(MockHttpServletRequest result, UriComponents uriComponents) { 232 | if (contextPath == null) { 233 | List pathSegments = uriComponents.getPathSegments(); 234 | if (pathSegments.isEmpty()) { 235 | result.setContextPath(""); 236 | } 237 | else { 238 | result.setContextPath("/" + pathSegments.get(0)); 239 | } 240 | } 241 | else { 242 | if (!uriComponents.getPath().startsWith(contextPath)) { 243 | throw new IllegalArgumentException(uriComponents.getPath() + " should start with contextPath " 244 | + contextPath); 245 | } 246 | result.setContextPath(contextPath); 247 | } 248 | } 249 | 250 | private void cookies(MockHttpServletRequest result) { 251 | String cookieHeaderValue = header("Cookie"); 252 | Cookie[] parentCookies = result.getCookies(); 253 | List cookies = new ArrayList(); 254 | if (cookieHeaderValue != null) { 255 | StringTokenizer tokens = new StringTokenizer(cookieHeaderValue, "=;"); 256 | while (tokens.hasMoreTokens()) { 257 | String cookieName = tokens.nextToken().trim(); 258 | if (!tokens.hasMoreTokens()) { 259 | throw new IllegalArgumentException("Expected value for cookie name " + cookieName 260 | + ". Full cookie was " + cookieHeaderValue); 261 | } 262 | String cookieValue = tokens.nextToken().trim(); 263 | processCookie(result, cookies, new Cookie(cookieName, cookieValue)); 264 | } 265 | } 266 | 267 | Set managedCookies = cookieManager.getCookies(webRequest.getUrl()); 268 | for (com.gargoylesoftware.htmlunit.util.Cookie cookie : managedCookies) { 269 | processCookie(result, cookies, new Cookie(cookie.getName(), cookie.getValue())); 270 | } 271 | if(parentCookies != null) { 272 | for(Cookie cookie : parentCookies) { 273 | cookies.add(cookie); 274 | } 275 | } 276 | if (!cookies.isEmpty()) { 277 | result.setCookies(cookies.toArray(new Cookie[0])); 278 | } 279 | } 280 | 281 | private void processCookie(MockHttpServletRequest result, List cookies, Cookie cookie) { 282 | cookies.add(cookie); 283 | if ("JSESSIONID".equals(cookie.getName())) { 284 | result.setRequestedSessionId(cookie.getValue()); 285 | result.setSession(httpSession(result, cookie.getValue())); 286 | } 287 | } 288 | 289 | private String getCharset() { 290 | String charset = webRequest.getCharset(); 291 | if (charset == null) { 292 | return "ISO-8859-1"; 293 | } 294 | return charset; 295 | } 296 | 297 | private String header(String headerName) { 298 | return webRequest.getAdditionalHeaders().get(headerName); 299 | } 300 | 301 | private void headers(MockHttpServletRequest result) { 302 | for (Entry header : webRequest.getAdditionalHeaders().entrySet()) { 303 | result.addHeader(header.getKey(), header.getValue()); 304 | } 305 | } 306 | 307 | private MockHttpSession httpSession(MockHttpServletRequest request, final String sessionid) { 308 | MockHttpSession session; 309 | synchronized (sessions) { 310 | session = sessions.get(sessionid); 311 | if (session == null) { 312 | session = new HtmlUnitMockHttpSession(request, sessionid); 313 | session.setNew(true); 314 | synchronized (sessions) { 315 | sessions.put(sessionid, session); 316 | } 317 | addSessionCookie(request, sessionid); 318 | } 319 | else { 320 | session.setNew(false); 321 | } 322 | } 323 | return session; 324 | } 325 | 326 | private void addSessionCookie(MockHttpServletRequest request, String sessionid) { 327 | cookieManager.addCookie(createCookie(request, sessionid)); 328 | } 329 | 330 | private void removeSessionCookie(MockHttpServletRequest request, String sessionid) { 331 | cookieManager.removeCookie(createCookie(request, sessionid)); 332 | } 333 | 334 | private com.gargoylesoftware.htmlunit.util.Cookie createCookie(MockHttpServletRequest request, String sessionid) { 335 | return new com.gargoylesoftware.htmlunit.util.Cookie(request.getServerName(), "JSESSIONID", sessionid, 336 | request.getContextPath() + "/", null, request.isSecure(), true); 337 | } 338 | 339 | private void locales(MockHttpServletRequest result) { 340 | String locale = header("Accept-Language"); 341 | if (locale == null) { 342 | result.addPreferredLocale(Locale.getDefault()); 343 | } 344 | else { 345 | String[] locales = locale.split(", "); 346 | for (int i = locales.length - 1; i >= 0; i--) { 347 | result.addPreferredLocale(parseLocale(locales[i])); 348 | } 349 | } 350 | } 351 | 352 | private void params(MockHttpServletRequest result, UriComponents uriComponents) { 353 | for (Entry> values : uriComponents.getQueryParams().entrySet()) { 354 | String name = values.getKey(); 355 | for (String value : values.getValue()) { 356 | try { 357 | result.addParameter(name, URLDecoder.decode(value, "UTF-8")); 358 | } 359 | catch (UnsupportedEncodingException e) { 360 | throw new RuntimeException(e); 361 | } 362 | } 363 | } 364 | for (NameValuePair param : webRequest.getRequestParameters()) { 365 | result.addParameter(param.getName(), param.getValue()); 366 | } 367 | } 368 | 369 | private Locale parseLocale(String locale) { 370 | Matcher matcher = LOCALE_PATTERN.matcher(locale); 371 | if (!matcher.matches()) { 372 | throw new IllegalArgumentException("Invalid locale " + locale); 373 | } 374 | String language = matcher.group(1); 375 | String country = matcher.group(2); 376 | if (country == null) { 377 | country = ""; 378 | } 379 | String qualifier = matcher.group(3); 380 | if (qualifier == null) { 381 | qualifier = ""; 382 | } 383 | return new Locale(language, country, qualifier); 384 | } 385 | 386 | private void pathInfo(UriComponents uriComponents, MockHttpServletRequest result) { 387 | result.setPathInfo(null); 388 | } 389 | 390 | private void servletPath(MockHttpServletRequest result, String requestPath) { 391 | String servletPath = requestPath.substring(result.getContextPath().length()); 392 | if ("".equals(servletPath)) { 393 | servletPath = null; 394 | } 395 | result.setServletPath(servletPath); 396 | } 397 | 398 | private void servletPath(UriComponents uriComponents, MockHttpServletRequest result) { 399 | if ("".equals(result.getPathInfo())) { 400 | result.setPathInfo(null); 401 | } 402 | servletPath(result, uriComponents.getPath()); 403 | } 404 | 405 | private void ports(UriComponents uriComponents, MockHttpServletRequest result) { 406 | int serverPort = uriComponents.getPort(); 407 | result.setServerPort(serverPort); 408 | if (serverPort == -1) { 409 | int portConnection = webRequest.getUrl().getDefaultPort(); 410 | result.setLocalPort(serverPort); 411 | result.setRemotePort(portConnection); 412 | } 413 | else { 414 | result.setRemotePort(serverPort); 415 | } 416 | } 417 | 418 | private UriComponents uriComponents() { 419 | URL url = webRequest.getUrl(); 420 | UriComponentsBuilder uriBldr = UriComponentsBuilder.fromUriString(url.toExternalForm()); 421 | return uriBldr.build(); 422 | } 423 | 424 | @Override 425 | public boolean isMergeEnabled() { 426 | return true; 427 | } 428 | 429 | @Override 430 | public Object merge(Object parent) { 431 | if (parent == null) { 432 | return this; 433 | } 434 | if(parent instanceof RequestBuilder) { 435 | this.parentBuilder = (RequestBuilder) parent; 436 | } 437 | if (parent instanceof SmartRequestBuilder) { 438 | this.parentPostProcessor = (SmartRequestBuilder) parent; 439 | } 440 | 441 | return this; 442 | } 443 | 444 | /** 445 | * An extension to {@link MockHttpServletRequest} that ensures that when a new {@link HttpSession} is created, it is 446 | * added to the managed sessions. 447 | * 448 | * @author Rob Winch 449 | */ 450 | private final class HtmlUnitMockHttpServletRequest extends MockHttpServletRequest { 451 | private HtmlUnitMockHttpServletRequest(ServletContext servletContext, String method, String requestURI) { 452 | super(servletContext, method, requestURI); 453 | } 454 | 455 | public HttpSession getSession(boolean create) { 456 | HttpSession result = super.getSession(false); 457 | if (result == null && create) { 458 | HtmlUnitMockHttpSession newSession = new HtmlUnitMockHttpSession(this); 459 | setSession(newSession); 460 | newSession.setNew(true); 461 | String sessionid = newSession.getId(); 462 | synchronized (sessions) { 463 | sessions.put(sessionid, newSession); 464 | } 465 | addSessionCookie(this, sessionid); 466 | result = newSession; 467 | } 468 | return result; 469 | } 470 | 471 | public HttpSession getSession() { 472 | return super.getSession(); 473 | } 474 | 475 | public void setSession(HttpSession session) { 476 | super.setSession(session); 477 | } 478 | } 479 | 480 | /** 481 | * An extension to {@link MockHttpSession} that ensures when {@link #invalidate()} is called that the 482 | * {@link HttpSession} is removed from the managed sessions. 483 | * 484 | * @author Rob Winch 485 | */ 486 | private final class HtmlUnitMockHttpSession extends MockHttpSession { 487 | private final MockHttpServletRequest request; 488 | 489 | private HtmlUnitMockHttpSession(MockHttpServletRequest request) { 490 | super(request.getServletContext()); 491 | this.request = request; 492 | } 493 | 494 | private HtmlUnitMockHttpSession(MockHttpServletRequest request, String id) { 495 | super(request.getServletContext(), id); 496 | this.request = request; 497 | } 498 | 499 | public void invalidate() { 500 | super.invalidate(); 501 | synchronized (sessions) { 502 | sessions.remove(getId()); 503 | } 504 | removeSessionCookie(request, getId()); 505 | } 506 | } 507 | 508 | private static final Pattern LOCALE_PATTERN = Pattern.compile("^\\s*(\\w{2})(?:-(\\w{2}))?(?:;q=(\\d+\\.\\d+))?$"); 509 | } 510 | --------------------------------------------------------------------------------