001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.test.web.servlet.htmlunit.webdriver; 018 019import com.gargoylesoftware.htmlunit.BrowserVersion; 020import com.gargoylesoftware.htmlunit.WebClient; 021import org.openqa.selenium.htmlunit.HtmlUnitDriver; 022 023import org.springframework.lang.Nullable; 024import org.springframework.test.web.servlet.MockMvc; 025import org.springframework.test.web.servlet.htmlunit.MockMvcWebConnectionBuilderSupport; 026import org.springframework.test.web.servlet.htmlunit.WebRequestMatcher; 027import org.springframework.test.web.servlet.setup.MockMvcConfigurer; 028import org.springframework.util.Assert; 029import org.springframework.web.context.WebApplicationContext; 030 031/** 032 * {@code MockMvcHtmlUnitDriverBuilder} simplifies the building of an 033 * {@link HtmlUnitDriver} that delegates to {@link MockMvc} and optionally 034 * delegates to an actual connection for specific requests. 035 * 036 * <p>By default, the driver will delegate to {@code MockMvc} to handle 037 * requests to {@code localhost} and to a {@link WebClient} to handle any 038 * other URL (i.e. to perform an actual HTTP request). 039 * 040 * @author Rob Winch 041 * @author Sam Brannen 042 * @since 4.2 043 * @see #mockMvcSetup(MockMvc) 044 * @see #webAppContextSetup(WebApplicationContext) 045 * @see #webAppContextSetup(WebApplicationContext, MockMvcConfigurer) 046 * @see #javascriptEnabled(boolean) 047 * @see #withDelegate(WebConnectionHtmlUnitDriver) 048 * @see #build() 049 */ 050public class MockMvcHtmlUnitDriverBuilder extends MockMvcWebConnectionBuilderSupport<MockMvcHtmlUnitDriverBuilder> { 051 052 @Nullable 053 private HtmlUnitDriver driver; 054 055 private boolean javascriptEnabled = true; 056 057 058 protected MockMvcHtmlUnitDriverBuilder(MockMvc mockMvc) { 059 super(mockMvc); 060 } 061 062 protected MockMvcHtmlUnitDriverBuilder(WebApplicationContext context) { 063 super(context); 064 } 065 066 protected MockMvcHtmlUnitDriverBuilder(WebApplicationContext context, MockMvcConfigurer configurer) { 067 super(context, configurer); 068 } 069 070 071 /** 072 * Create a new {@code MockMvcHtmlUnitDriverBuilder} based on the supplied 073 * {@link MockMvc} instance. 074 * @param mockMvc the {@code MockMvc} instance to use (never {@code null}) 075 * @return the MockMvcHtmlUnitDriverBuilder to customize 076 */ 077 public static MockMvcHtmlUnitDriverBuilder mockMvcSetup(MockMvc mockMvc) { 078 Assert.notNull(mockMvc, "MockMvc must not be null"); 079 return new MockMvcHtmlUnitDriverBuilder(mockMvc); 080 } 081 082 /** 083 * Create a new {@code MockMvcHtmlUnitDriverBuilder} based on the supplied 084 * {@link WebApplicationContext}. 085 * @param context the {@code WebApplicationContext} to create a {@link MockMvc} 086 * instance from (never {@code null}) 087 * @return the MockMvcHtmlUnitDriverBuilder to customize 088 */ 089 public static MockMvcHtmlUnitDriverBuilder webAppContextSetup(WebApplicationContext context) { 090 Assert.notNull(context, "WebApplicationContext must not be null"); 091 return new MockMvcHtmlUnitDriverBuilder(context); 092 } 093 094 /** 095 * Create a new {@code MockMvcHtmlUnitDriverBuilder} based on the supplied 096 * {@link WebApplicationContext} and {@link MockMvcConfigurer}. 097 * @param context the {@code WebApplicationContext} to create a {@link MockMvc} 098 * instance from (never {@code null}) 099 * @param configurer the {@code MockMvcConfigurer} to apply (never {@code null}) 100 * @return the MockMvcHtmlUnitDriverBuilder to customize 101 */ 102 public static MockMvcHtmlUnitDriverBuilder webAppContextSetup(WebApplicationContext context, 103 MockMvcConfigurer configurer) { 104 105 Assert.notNull(context, "WebApplicationContext must not be null"); 106 Assert.notNull(configurer, "MockMvcConfigurer must not be null"); 107 return new MockMvcHtmlUnitDriverBuilder(context, configurer); 108 } 109 110 /** 111 * Specify whether JavaScript should be enabled. 112 * <p>Default is {@code true}. 113 * @param javascriptEnabled {@code true} if JavaScript should be enabled 114 * @return this builder for further customizations 115 * @see #build() 116 */ 117 public MockMvcHtmlUnitDriverBuilder javascriptEnabled(boolean javascriptEnabled) { 118 this.javascriptEnabled = javascriptEnabled; 119 return this; 120 } 121 122 /** 123 * Supply the {@code WebConnectionHtmlUnitDriver} that the driver 124 * {@linkplain #build built} by this builder should delegate to when 125 * processing non-{@linkplain WebRequestMatcher matching} requests. 126 * @param driver the {@code WebConnectionHtmlUnitDriver} to delegate to 127 * for requests that do not match (never {@code null}) 128 * @return this builder for further customizations 129 * @see #build() 130 */ 131 public MockMvcHtmlUnitDriverBuilder withDelegate(WebConnectionHtmlUnitDriver driver) { 132 Assert.notNull(driver, "HtmlUnitDriver must not be null"); 133 driver.setJavascriptEnabled(this.javascriptEnabled); 134 driver.setWebConnection(createConnection(driver.getWebClient())); 135 this.driver = driver; 136 return this; 137 } 138 139 /** 140 * Build the {@link HtmlUnitDriver} configured via this builder. 141 * <p>The returned driver will use the configured {@link MockMvc} instance 142 * for processing any {@linkplain WebRequestMatcher matching} requests 143 * and a delegate {@code HtmlUnitDriver} for all other requests. 144 * <p>If a {@linkplain #withDelegate delegate} has been explicitly configured, 145 * it will be used; otherwise, a default {@code WebConnectionHtmlUnitDriver} 146 * with the {@link BrowserVersion} set to {@link BrowserVersion#CHROME CHROME} 147 * will be configured as the delegate. 148 * @return the {@code HtmlUnitDriver} to use 149 * @see #withDelegate(WebConnectionHtmlUnitDriver) 150 */ 151 public HtmlUnitDriver build() { 152 return (this.driver != null ? this.driver : 153 withDelegate(new WebConnectionHtmlUnitDriver(BrowserVersion.CHROME)).build()); 154 } 155 156}