Migrate Thymeleaf tests to application runner
This commit is contained in:
		
							parent
							
								
									cf0811b0db
								
							
						
					
					
						commit
						29b1b38cc6
					
				| 
						 | 
				
			
			@ -22,7 +22,6 @@ import java.util.Locale;
 | 
			
		|||
 | 
			
		||||
import nz.net.ultraq.thymeleaf.LayoutDialect;
 | 
			
		||||
import nz.net.ultraq.thymeleaf.decorators.strategies.GroupingStrategy;
 | 
			
		||||
import org.junit.After;
 | 
			
		||||
import org.junit.Rule;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.thymeleaf.TemplateEngine;
 | 
			
		||||
| 
						 | 
				
			
			@ -36,14 +35,11 @@ import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
 | 
			
		|||
import org.thymeleaf.spring5.view.reactive.ThymeleafReactiveViewResolver;
 | 
			
		||||
import org.thymeleaf.templateresolver.ITemplateResolver;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
 | 
			
		||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
 | 
			
		||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
 | 
			
		||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
 | 
			
		||||
import org.springframework.boot.test.rule.OutputCapture;
 | 
			
		||||
import org.springframework.boot.test.util.TestPropertyValues;
 | 
			
		||||
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.context.annotation.Import;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
 | 
			
		||||
import org.springframework.mock.web.server.MockServerWebExchange;
 | 
			
		||||
| 
						 | 
				
			
			@ -60,212 +56,215 @@ import static org.hamcrest.Matchers.not;
 | 
			
		|||
 *
 | 
			
		||||
 * @author Brian Clozel
 | 
			
		||||
 * @author Kazuki Shimizu
 | 
			
		||||
 * @author Stephane Nicoll
 | 
			
		||||
 */
 | 
			
		||||
public class ThymeleafReactiveAutoConfigurationTests {
 | 
			
		||||
 | 
			
		||||
	@Rule
 | 
			
		||||
	public OutputCapture output = new OutputCapture();
 | 
			
		||||
 | 
			
		||||
	private AnnotationConfigReactiveWebApplicationContext context;
 | 
			
		||||
 | 
			
		||||
	@After
 | 
			
		||||
	public void close() {
 | 
			
		||||
		if (this.context != null) {
 | 
			
		||||
			this.context.close();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	private ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
 | 
			
		||||
			.withConfiguration(AutoConfigurations.of(ThymeleafAutoConfiguration.class));
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void createFromConfigClass() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.suffix:.html");
 | 
			
		||||
		TemplateEngine engine = this.context.getBean(TemplateEngine.class);
 | 
			
		||||
		Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
 | 
			
		||||
		String result = engine.process("template", attrs);
 | 
			
		||||
		assertThat(result).isEqualTo("<html>bar</html>");
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.thymeleaf.suffix:.html")
 | 
			
		||||
				.run((context) -> {
 | 
			
		||||
					TemplateEngine engine = context.getBean(TemplateEngine.class);
 | 
			
		||||
					Context attrs = new Context(Locale.UK,
 | 
			
		||||
							Collections.singletonMap("foo", "bar"));
 | 
			
		||||
					String result = engine.process("template", attrs);
 | 
			
		||||
					assertThat(result).isEqualTo("<html>bar</html>");
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideCharacterEncoding() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.encoding:UTF-16");
 | 
			
		||||
		ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class);
 | 
			
		||||
		assertThat(resolver instanceof SpringResourceTemplateResolver).isTrue();
 | 
			
		||||
		assertThat(((SpringResourceTemplateResolver) resolver).getCharacterEncoding())
 | 
			
		||||
				.isEqualTo("UTF-16");
 | 
			
		||||
		ThymeleafReactiveViewResolver views = this.context
 | 
			
		||||
				.getBean(ThymeleafReactiveViewResolver.class);
 | 
			
		||||
		assertThat(views.getDefaultCharset().name()).isEqualTo("UTF-16");
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.thymeleaf.encoding:UTF-16")
 | 
			
		||||
				.run((context) -> {
 | 
			
		||||
					ITemplateResolver resolver = context.getBean(ITemplateResolver.class);
 | 
			
		||||
					assertThat(resolver)
 | 
			
		||||
							.isInstanceOf(SpringResourceTemplateResolver.class);
 | 
			
		||||
					assertThat(((SpringResourceTemplateResolver) resolver)
 | 
			
		||||
							.getCharacterEncoding()).isEqualTo("UTF-16");
 | 
			
		||||
					ThymeleafReactiveViewResolver views = context
 | 
			
		||||
							.getBean(ThymeleafReactiveViewResolver.class);
 | 
			
		||||
					assertThat(views.getDefaultCharset().name()).isEqualTo("UTF-16");
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideMediaTypes() {
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.reactive.media-types:text/html,text/plain");
 | 
			
		||||
		ThymeleafReactiveViewResolver views = this.context
 | 
			
		||||
				.getBean(ThymeleafReactiveViewResolver.class);
 | 
			
		||||
		assertThat(views.getSupportedMediaTypes()).contains(MediaType.TEXT_HTML,
 | 
			
		||||
				MediaType.TEXT_PLAIN);
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues(
 | 
			
		||||
						"spring.thymeleaf.reactive.media-types:text/html,text/plain")
 | 
			
		||||
				.run((context) -> assertThat(
 | 
			
		||||
						context.getBean(ThymeleafReactiveViewResolver.class)
 | 
			
		||||
								.getSupportedMediaTypes()).contains(MediaType.TEXT_HTML,
 | 
			
		||||
										MediaType.TEXT_PLAIN));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideTemplateResolverOrder() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.templateResolverOrder:25");
 | 
			
		||||
		ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class);
 | 
			
		||||
		assertThat(resolver.getOrder()).isEqualTo(Integer.valueOf(25));
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.thymeleaf.templateResolverOrder:25")
 | 
			
		||||
				.run((context) -> assertThat(
 | 
			
		||||
						context.getBean(ITemplateResolver.class).getOrder())
 | 
			
		||||
								.isEqualTo(Integer.valueOf(25)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideViewNames() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.viewNames:foo,bar");
 | 
			
		||||
		ThymeleafReactiveViewResolver views = this.context
 | 
			
		||||
				.getBean(ThymeleafReactiveViewResolver.class);
 | 
			
		||||
		assertThat(views.getViewNames()).isEqualTo(new String[] { "foo", "bar" });
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.thymeleaf.viewNames:foo,bar")
 | 
			
		||||
				.run((context) -> assertThat(context
 | 
			
		||||
						.getBean(ThymeleafReactiveViewResolver.class).getViewNames())
 | 
			
		||||
								.isEqualTo(new String[] { "foo", "bar" }));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideMaxChunkSize() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.reactive.maxChunkSize:8KB");
 | 
			
		||||
		ThymeleafReactiveViewResolver views = this.context
 | 
			
		||||
				.getBean(ThymeleafReactiveViewResolver.class);
 | 
			
		||||
		assertThat(views.getResponseMaxChunkSizeBytes()).isEqualTo(Integer.valueOf(8192));
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues("spring.thymeleaf.reactive.maxChunkSize:8KB")
 | 
			
		||||
				.run((context) -> assertThat(
 | 
			
		||||
						context.getBean(ThymeleafReactiveViewResolver.class)
 | 
			
		||||
								.getResponseMaxChunkSizeBytes())
 | 
			
		||||
										.isEqualTo(Integer.valueOf(8192)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideFullModeViewNames() {
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.reactive.fullModeViewNames:foo,bar");
 | 
			
		||||
		ThymeleafReactiveViewResolver views = this.context
 | 
			
		||||
				.getBean(ThymeleafReactiveViewResolver.class);
 | 
			
		||||
		assertThat(views.getFullModeViewNames()).isEqualTo(new String[] { "foo", "bar" });
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues("spring.thymeleaf.reactive.fullModeViewNames:foo,bar")
 | 
			
		||||
				.run((context) -> assertThat(
 | 
			
		||||
						context.getBean(ThymeleafReactiveViewResolver.class)
 | 
			
		||||
								.getFullModeViewNames())
 | 
			
		||||
										.isEqualTo(new String[] { "foo", "bar" }));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideChunkedModeViewNames() {
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.reactive.chunkedModeViewNames:foo,bar");
 | 
			
		||||
		ThymeleafReactiveViewResolver views = this.context
 | 
			
		||||
				.getBean(ThymeleafReactiveViewResolver.class);
 | 
			
		||||
		assertThat(views.getChunkedModeViewNames())
 | 
			
		||||
				.isEqualTo(new String[] { "foo", "bar" });
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues(
 | 
			
		||||
						"spring.thymeleaf.reactive.chunkedModeViewNames:foo,bar")
 | 
			
		||||
				.run((context) -> assertThat(
 | 
			
		||||
						context.getBean(ThymeleafReactiveViewResolver.class)
 | 
			
		||||
								.getChunkedModeViewNames())
 | 
			
		||||
										.isEqualTo(new String[] { "foo", "bar" }));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideEnableSpringElCompiler() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.enable-spring-el-compiler:true");
 | 
			
		||||
		assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class)
 | 
			
		||||
				.getEnableSpringELCompiler()).isTrue();
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues("spring.thymeleaf.enable-spring-el-compiler:true")
 | 
			
		||||
				.run((context) -> assertThat(
 | 
			
		||||
						context.getBean(SpringWebFluxTemplateEngine.class)
 | 
			
		||||
								.getEnableSpringELCompiler()).isTrue());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void enableSpringElCompilerIsDisabledByDefault() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class)
 | 
			
		||||
				.getEnableSpringELCompiler()).isFalse();
 | 
			
		||||
		this.contextRunner.run(
 | 
			
		||||
				(context) -> assertThat(context.getBean(SpringWebFluxTemplateEngine.class)
 | 
			
		||||
						.getEnableSpringELCompiler()).isFalse());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideRenderHiddenMarkersBeforeCheckboxes() {
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.render-hidden-markers-before-checkboxes:true");
 | 
			
		||||
		assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class)
 | 
			
		||||
				.getRenderHiddenMarkersBeforeCheckboxes()).isTrue();
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues(
 | 
			
		||||
						"spring.thymeleaf.render-hidden-markers-before-checkboxes:true")
 | 
			
		||||
				.run((context) -> assertThat(
 | 
			
		||||
						context.getBean(SpringWebFluxTemplateEngine.class)
 | 
			
		||||
								.getRenderHiddenMarkersBeforeCheckboxes()).isTrue());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void enableRenderHiddenMarkersBeforeCheckboxesIsDisabledByDefault() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class)
 | 
			
		||||
				.getRenderHiddenMarkersBeforeCheckboxes()).isFalse();
 | 
			
		||||
		this.contextRunner.run(
 | 
			
		||||
				(context) -> assertThat(context.getBean(SpringWebFluxTemplateEngine.class)
 | 
			
		||||
						.getRenderHiddenMarkersBeforeCheckboxes()).isFalse());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void templateLocationDoesNotExist() {
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.prefix:classpath:/no-such-directory/");
 | 
			
		||||
		this.output.expect(containsString("Cannot find template location"));
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues(
 | 
			
		||||
						"spring.thymeleaf.prefix:classpath:/no-such-directory/")
 | 
			
		||||
				.run((context) -> this.output
 | 
			
		||||
						.expect(containsString("Cannot find template location")));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void templateLocationEmpty() {
 | 
			
		||||
		new File("target/test-classes/templates/empty-directory").mkdir();
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.prefix:classpath:/templates/empty-directory/");
 | 
			
		||||
		this.output.expect(not(containsString("Cannot find template location")));
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues(
 | 
			
		||||
						"spring.thymeleaf.prefix:classpath:/templates/empty-directory/")
 | 
			
		||||
				.run((context) -> this.output
 | 
			
		||||
						.expect(not(containsString("Cannot find template location"))));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void useDataDialect() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		ISpringWebFluxTemplateEngine engine = this.context
 | 
			
		||||
				.getBean(ISpringWebFluxTemplateEngine.class);
 | 
			
		||||
		Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
 | 
			
		||||
		String result = engine.process("data-dialect", attrs);
 | 
			
		||||
		assertThat(result).isEqualTo("<html><body data-foo=\"bar\"></body></html>");
 | 
			
		||||
		this.contextRunner.run((context) -> {
 | 
			
		||||
			ISpringWebFluxTemplateEngine engine = context
 | 
			
		||||
					.getBean(ISpringWebFluxTemplateEngine.class);
 | 
			
		||||
			Context attrs = new Context(Locale.UK,
 | 
			
		||||
					Collections.singletonMap("foo", "bar"));
 | 
			
		||||
			String result = engine.process("data-dialect", attrs);
 | 
			
		||||
			assertThat(result).isEqualTo("<html><body data-foo=\"bar\"></body></html>");
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void useJava8TimeDialect() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		ISpringWebFluxTemplateEngine engine = this.context
 | 
			
		||||
				.getBean(ISpringWebFluxTemplateEngine.class);
 | 
			
		||||
		Context attrs = new Context(Locale.UK);
 | 
			
		||||
		String result = engine.process("java8time-dialect", attrs);
 | 
			
		||||
		assertThat(result).isEqualTo("<html><body>2015-11-24</body></html>");
 | 
			
		||||
		this.contextRunner.run((context) -> {
 | 
			
		||||
			ISpringWebFluxTemplateEngine engine = context
 | 
			
		||||
					.getBean(ISpringWebFluxTemplateEngine.class);
 | 
			
		||||
			Context attrs = new Context(Locale.UK);
 | 
			
		||||
			String result = engine.process("java8time-dialect", attrs);
 | 
			
		||||
			assertThat(result).isEqualTo("<html><body>2015-11-24</body></html>");
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void useSecurityDialect() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		ISpringWebFluxTemplateEngine engine = this.context
 | 
			
		||||
				.getBean(ISpringWebFluxTemplateEngine.class);
 | 
			
		||||
		MockServerWebExchange exchange = MockServerWebExchange
 | 
			
		||||
				.from(MockServerHttpRequest.get("/test").build());
 | 
			
		||||
		exchange.getAttributes().put(
 | 
			
		||||
				SpringSecurityContextUtils.SECURITY_CONTEXT_MODEL_ATTRIBUTE_NAME,
 | 
			
		||||
				new SecurityContextImpl(
 | 
			
		||||
						new TestingAuthenticationToken("alice", "admin")));
 | 
			
		||||
		IContext attrs = new SpringWebFluxContext(exchange);
 | 
			
		||||
		String result = engine.process("security-dialect", attrs);
 | 
			
		||||
		assertThat(result).isEqualTo(
 | 
			
		||||
				"<html><body><div>alice</div></body></html>" + System.lineSeparator());
 | 
			
		||||
		this.contextRunner.run((context) -> {
 | 
			
		||||
			ISpringWebFluxTemplateEngine engine = context
 | 
			
		||||
					.getBean(ISpringWebFluxTemplateEngine.class);
 | 
			
		||||
			MockServerWebExchange exchange = MockServerWebExchange
 | 
			
		||||
					.from(MockServerHttpRequest.get("/test").build());
 | 
			
		||||
			exchange.getAttributes().put(
 | 
			
		||||
					SpringSecurityContextUtils.SECURITY_CONTEXT_MODEL_ATTRIBUTE_NAME,
 | 
			
		||||
					new SecurityContextImpl(
 | 
			
		||||
							new TestingAuthenticationToken("alice", "admin")));
 | 
			
		||||
			IContext attrs = new SpringWebFluxContext(exchange);
 | 
			
		||||
			String result = engine.process("security-dialect", attrs);
 | 
			
		||||
			assertThat(result).isEqualTo("<html><body><div>alice</div></body></html>"
 | 
			
		||||
					+ System.lineSeparator());
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void renderTemplate() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		ISpringWebFluxTemplateEngine engine = this.context
 | 
			
		||||
				.getBean(ISpringWebFluxTemplateEngine.class);
 | 
			
		||||
		Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
 | 
			
		||||
		String result = engine.process("home", attrs);
 | 
			
		||||
		assertThat(result).isEqualTo("<html><body>bar</body></html>");
 | 
			
		||||
		this.contextRunner.run((context) -> {
 | 
			
		||||
			ISpringWebFluxTemplateEngine engine = context
 | 
			
		||||
					.getBean(ISpringWebFluxTemplateEngine.class);
 | 
			
		||||
			Context attrs = new Context(Locale.UK,
 | 
			
		||||
					Collections.singletonMap("foo", "bar"));
 | 
			
		||||
			String result = engine.process("home", attrs);
 | 
			
		||||
			assertThat(result).isEqualTo("<html><body>bar</body></html>");
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void layoutDialectCanBeCustomized() {
 | 
			
		||||
		load(LayoutDialectConfiguration.class);
 | 
			
		||||
		LayoutDialect layoutDialect = this.context.getBean(LayoutDialect.class);
 | 
			
		||||
		assertThat(ReflectionTestUtils.getField(layoutDialect, "sortingStrategy"))
 | 
			
		||||
				.isInstanceOf(GroupingStrategy.class);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void load(Class<?> config, String... envVariables) {
 | 
			
		||||
		this.context = new AnnotationConfigReactiveWebApplicationContext();
 | 
			
		||||
		TestPropertyValues.of(envVariables).applyTo(this.context);
 | 
			
		||||
		if (config != null) {
 | 
			
		||||
			this.context.register(config);
 | 
			
		||||
		}
 | 
			
		||||
		this.context.register(config);
 | 
			
		||||
		this.context.refresh();
 | 
			
		||||
		this.contextRunner.withUserConfiguration(LayoutDialectConfiguration.class)
 | 
			
		||||
				.run((context) -> assertThat(ReflectionTestUtils.getField(
 | 
			
		||||
						context.getBean(LayoutDialect.class), "sortingStrategy"))
 | 
			
		||||
								.isInstanceOf(GroupingStrategy.class));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@ImportAutoConfiguration({ ThymeleafAutoConfiguration.class,
 | 
			
		||||
			PropertyPlaceholderAutoConfiguration.class })
 | 
			
		||||
	protected static class BaseConfiguration {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@Import(BaseConfiguration.class)
 | 
			
		||||
	static class LayoutDialectConfiguration {
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,6 @@ import javax.servlet.DispatcherType;
 | 
			
		|||
 | 
			
		||||
import nz.net.ultraq.thymeleaf.LayoutDialect;
 | 
			
		||||
import nz.net.ultraq.thymeleaf.decorators.strategies.GroupingStrategy;
 | 
			
		||||
import org.junit.After;
 | 
			
		||||
import org.junit.Rule;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.thymeleaf.TemplateEngine;
 | 
			
		||||
| 
						 | 
				
			
			@ -38,16 +37,14 @@ import org.thymeleaf.spring5.view.ThymeleafView;
 | 
			
		|||
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
 | 
			
		||||
import org.thymeleaf.templateresolver.ITemplateResolver;
 | 
			
		||||
 | 
			
		||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
 | 
			
		||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
 | 
			
		||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
 | 
			
		||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
 | 
			
		||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
 | 
			
		||||
import org.springframework.boot.test.rule.OutputCapture;
 | 
			
		||||
import org.springframework.boot.test.util.TestPropertyValues;
 | 
			
		||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
 | 
			
		||||
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
 | 
			
		||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.context.annotation.Import;
 | 
			
		||||
import org.springframework.mock.web.MockHttpServletRequest;
 | 
			
		||||
import org.springframework.mock.web.MockHttpServletResponse;
 | 
			
		||||
import org.springframework.mock.web.MockServletContext;
 | 
			
		||||
| 
						 | 
				
			
			@ -55,13 +52,13 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
 | 
			
		|||
import org.springframework.security.core.context.SecurityContextHolder;
 | 
			
		||||
import org.springframework.security.core.context.SecurityContextImpl;
 | 
			
		||||
import org.springframework.test.util.ReflectionTestUtils;
 | 
			
		||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
 | 
			
		||||
import org.springframework.web.servlet.ViewResolver;
 | 
			
		||||
import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter;
 | 
			
		||||
import org.springframework.web.servlet.support.RequestContext;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.hamcrest.Matchers.containsString;
 | 
			
		||||
import static org.hamcrest.Matchers.not;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests for {@link ThymeleafAutoConfiguration} in Servlet-based applications.
 | 
			
		||||
| 
						 | 
				
			
			@ -78,271 +75,284 @@ public class ThymeleafServletAutoConfigurationTests {
 | 
			
		|||
	@Rule
 | 
			
		||||
	public OutputCapture output = new OutputCapture();
 | 
			
		||||
 | 
			
		||||
	private AnnotationConfigWebApplicationContext context;
 | 
			
		||||
 | 
			
		||||
	@After
 | 
			
		||||
	public void close() {
 | 
			
		||||
		if (this.context != null) {
 | 
			
		||||
			this.context.close();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
 | 
			
		||||
			.withConfiguration(AutoConfigurations.of(ThymeleafAutoConfiguration.class));
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void createFromConfigClass() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.mode:HTML",
 | 
			
		||||
				"spring.thymeleaf.suffix:");
 | 
			
		||||
		TemplateEngine engine = this.context.getBean(TemplateEngine.class);
 | 
			
		||||
		Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
 | 
			
		||||
		String result = engine.process("template.html", attrs);
 | 
			
		||||
		assertThat(result).isEqualTo("<html>bar</html>");
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.thymeleaf.mode:HTML",
 | 
			
		||||
				"spring.thymeleaf.suffix:").run((context) -> {
 | 
			
		||||
					assertThat(context).hasSingleBean(TemplateEngine.class);
 | 
			
		||||
					TemplateEngine engine = context.getBean(TemplateEngine.class);
 | 
			
		||||
					Context attrs = new Context(Locale.UK,
 | 
			
		||||
							Collections.singletonMap("foo", "bar"));
 | 
			
		||||
					String result = engine.process("template.html", attrs);
 | 
			
		||||
					assertThat(result).isEqualTo("<html>bar</html>");
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideCharacterEncoding() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.encoding:UTF-16");
 | 
			
		||||
		ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class);
 | 
			
		||||
		assertThat(resolver instanceof SpringResourceTemplateResolver).isTrue();
 | 
			
		||||
		assertThat(((SpringResourceTemplateResolver) resolver).getCharacterEncoding())
 | 
			
		||||
				.isEqualTo("UTF-16");
 | 
			
		||||
		ThymeleafViewResolver views = this.context.getBean(ThymeleafViewResolver.class);
 | 
			
		||||
		assertThat(views.getCharacterEncoding()).isEqualTo("UTF-16");
 | 
			
		||||
		assertThat(views.getContentType()).isEqualTo("text/html;charset=UTF-16");
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.thymeleaf.encoding:UTF-16")
 | 
			
		||||
				.run((context) -> {
 | 
			
		||||
					ITemplateResolver resolver = context.getBean(ITemplateResolver.class);
 | 
			
		||||
					assertThat(resolver)
 | 
			
		||||
							.isInstanceOf(SpringResourceTemplateResolver.class);
 | 
			
		||||
					assertThat(((SpringResourceTemplateResolver) resolver)
 | 
			
		||||
							.getCharacterEncoding()).isEqualTo("UTF-16");
 | 
			
		||||
					ThymeleafViewResolver views = context
 | 
			
		||||
							.getBean(ThymeleafViewResolver.class);
 | 
			
		||||
					assertThat(views.getCharacterEncoding()).isEqualTo("UTF-16");
 | 
			
		||||
					assertThat(views.getContentType())
 | 
			
		||||
							.isEqualTo("text/html;charset=UTF-16");
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideDisableProducePartialOutputWhileProcessing() {
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.servlet.produce-partial-output-while-processing:false");
 | 
			
		||||
		assertThat(this.context.getBean(ThymeleafViewResolver.class)
 | 
			
		||||
				.getProducePartialOutputWhileProcessing()).isFalse();
 | 
			
		||||
		this.contextRunner.withPropertyValues(
 | 
			
		||||
				"spring.thymeleaf.servlet.produce-partial-output-while-processing:false")
 | 
			
		||||
				.run((context) -> assertThat(context.getBean(ThymeleafViewResolver.class)
 | 
			
		||||
						.getProducePartialOutputWhileProcessing()).isFalse());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void disableProducePartialOutputWhileProcessingIsEnabledByDefault() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		assertThat(this.context.getBean(ThymeleafViewResolver.class)
 | 
			
		||||
				.getProducePartialOutputWhileProcessing()).isTrue();
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.run((context) -> assertThat(context.getBean(ThymeleafViewResolver.class)
 | 
			
		||||
						.getProducePartialOutputWhileProcessing()).isTrue());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideTemplateResolverOrder() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.templateResolverOrder:25");
 | 
			
		||||
		ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class);
 | 
			
		||||
		assertThat(resolver.getOrder()).isEqualTo(Integer.valueOf(25));
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.thymeleaf.templateResolverOrder:25")
 | 
			
		||||
				.run((context) -> assertThat(
 | 
			
		||||
						context.getBean(ITemplateResolver.class).getOrder())
 | 
			
		||||
								.isEqualTo(Integer.valueOf(25)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideViewNames() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.viewNames:foo,bar");
 | 
			
		||||
		ThymeleafViewResolver views = this.context.getBean(ThymeleafViewResolver.class);
 | 
			
		||||
		assertThat(views.getViewNames()).isEqualTo(new String[] { "foo", "bar" });
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.thymeleaf.viewNames:foo,bar")
 | 
			
		||||
				.run((context) -> assertThat(
 | 
			
		||||
						context.getBean(ThymeleafViewResolver.class).getViewNames())
 | 
			
		||||
								.isEqualTo(new String[] { "foo", "bar" }));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideEnableSpringElCompiler() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.enable-spring-el-compiler:true");
 | 
			
		||||
		assertThat(this.context.getBean(SpringTemplateEngine.class)
 | 
			
		||||
				.getEnableSpringELCompiler()).isTrue();
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues("spring.thymeleaf.enable-spring-el-compiler:true")
 | 
			
		||||
				.run((context) -> assertThat(context.getBean(SpringTemplateEngine.class)
 | 
			
		||||
						.getEnableSpringELCompiler()).isTrue());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void enableSpringElCompilerIsDisabledByDefault() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		assertThat(this.context.getBean(SpringTemplateEngine.class)
 | 
			
		||||
				.getEnableSpringELCompiler()).isFalse();
 | 
			
		||||
		this.contextRunner.run((context) -> assertThat(
 | 
			
		||||
				context.getBean(SpringTemplateEngine.class).getEnableSpringELCompiler())
 | 
			
		||||
						.isFalse());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void overrideRenderHiddenMarkersBeforeCheckboxes() {
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.render-hidden-markers-before-checkboxes:true");
 | 
			
		||||
		assertThat(this.context.getBean(SpringTemplateEngine.class)
 | 
			
		||||
				.getRenderHiddenMarkersBeforeCheckboxes()).isTrue();
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues(
 | 
			
		||||
						"spring.thymeleaf.render-hidden-markers-before-checkboxes:true")
 | 
			
		||||
				.run((context) -> assertThat(context.getBean(SpringTemplateEngine.class)
 | 
			
		||||
						.getRenderHiddenMarkersBeforeCheckboxes()).isTrue());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void enableRenderHiddenMarkersBeforeCheckboxesIsDisabledByDefault() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		assertThat(this.context.getBean(SpringTemplateEngine.class)
 | 
			
		||||
				.getRenderHiddenMarkersBeforeCheckboxes()).isFalse();
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.run((context) -> assertThat(context.getBean(SpringTemplateEngine.class)
 | 
			
		||||
						.getRenderHiddenMarkersBeforeCheckboxes()).isFalse());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void templateLocationDoesNotExist() {
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.prefix:classpath:/no-such-directory/");
 | 
			
		||||
		this.output.expect(containsString("Cannot find template location"));
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues(
 | 
			
		||||
						"spring.thymeleaf.prefix:classpath:/no-such-directory/")
 | 
			
		||||
				.run((context) -> this.output
 | 
			
		||||
						.expect(containsString("Cannot find template location")));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void templateLocationEmpty() {
 | 
			
		||||
		new File("target/test-classes/templates/empty-directory").mkdir();
 | 
			
		||||
		load(BaseConfiguration.class,
 | 
			
		||||
				"spring.thymeleaf.prefix:classpath:/templates/empty-directory/");
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withPropertyValues(
 | 
			
		||||
						"spring.thymeleaf.prefix:classpath:/templates/empty-directory/")
 | 
			
		||||
				.run((context) -> this.output
 | 
			
		||||
						.expect(not(containsString("Cannot find template location"))));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void createLayoutFromConfigClass() throws Exception {
 | 
			
		||||
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
 | 
			
		||||
		context.register(ThymeleafAutoConfiguration.class,
 | 
			
		||||
				PropertyPlaceholderAutoConfiguration.class);
 | 
			
		||||
		MockServletContext servletContext = new MockServletContext();
 | 
			
		||||
		context.setServletContext(servletContext);
 | 
			
		||||
		context.refresh();
 | 
			
		||||
		ThymeleafView view = (ThymeleafView) context.getBean(ThymeleafViewResolver.class)
 | 
			
		||||
				.resolveViewName("view", Locale.UK);
 | 
			
		||||
		MockHttpServletResponse response = new MockHttpServletResponse();
 | 
			
		||||
		MockHttpServletRequest request = new MockHttpServletRequest();
 | 
			
		||||
		request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
 | 
			
		||||
		view.render(Collections.singletonMap("foo", "bar"), request, response);
 | 
			
		||||
		String result = response.getContentAsString();
 | 
			
		||||
		assertThat(result).contains("<title>Content</title>");
 | 
			
		||||
		assertThat(result).contains("<span>bar</span>");
 | 
			
		||||
		context.close();
 | 
			
		||||
	public void createLayoutFromConfigClass() {
 | 
			
		||||
		this.contextRunner.run((context) -> {
 | 
			
		||||
			ThymeleafView view = (ThymeleafView) context
 | 
			
		||||
					.getBean(ThymeleafViewResolver.class)
 | 
			
		||||
					.resolveViewName("view", Locale.UK);
 | 
			
		||||
			MockHttpServletResponse response = new MockHttpServletResponse();
 | 
			
		||||
			MockHttpServletRequest request = new MockHttpServletRequest();
 | 
			
		||||
			request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE,
 | 
			
		||||
					context);
 | 
			
		||||
			view.render(Collections.singletonMap("foo", "bar"), request, response);
 | 
			
		||||
			String result = response.getContentAsString();
 | 
			
		||||
			assertThat(result).contains("<title>Content</title>");
 | 
			
		||||
			assertThat(result).contains("<span>bar</span>");
 | 
			
		||||
			context.close();
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void useDataDialect() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		TemplateEngine engine = this.context.getBean(TemplateEngine.class);
 | 
			
		||||
		Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
 | 
			
		||||
		String result = engine.process("data-dialect", attrs);
 | 
			
		||||
		assertThat(result).isEqualTo("<html><body data-foo=\"bar\"></body></html>");
 | 
			
		||||
		this.contextRunner.run((context) -> {
 | 
			
		||||
			TemplateEngine engine = context.getBean(TemplateEngine.class);
 | 
			
		||||
			Context attrs = new Context(Locale.UK,
 | 
			
		||||
					Collections.singletonMap("foo", "bar"));
 | 
			
		||||
			String result = engine.process("data-dialect", attrs);
 | 
			
		||||
			assertThat(result).isEqualTo("<html><body data-foo=\"bar\"></body></html>");
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void useJava8TimeDialect() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		TemplateEngine engine = this.context.getBean(TemplateEngine.class);
 | 
			
		||||
		Context attrs = new Context(Locale.UK);
 | 
			
		||||
		String result = engine.process("java8time-dialect", attrs);
 | 
			
		||||
		assertThat(result).isEqualTo("<html><body>2015-11-24</body></html>");
 | 
			
		||||
		this.contextRunner.run((context) -> {
 | 
			
		||||
			TemplateEngine engine = context.getBean(TemplateEngine.class);
 | 
			
		||||
			Context attrs = new Context(Locale.UK);
 | 
			
		||||
			String result = engine.process("java8time-dialect", attrs);
 | 
			
		||||
			assertThat(result).isEqualTo("<html><body>2015-11-24</body></html>");
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void useSecurityDialect() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		TemplateEngine engine = this.context.getBean(TemplateEngine.class);
 | 
			
		||||
		WebContext attrs = new WebContext(new MockHttpServletRequest(),
 | 
			
		||||
				new MockHttpServletResponse(), new MockServletContext());
 | 
			
		||||
		try {
 | 
			
		||||
			SecurityContextHolder.setContext(new SecurityContextImpl(
 | 
			
		||||
					new TestingAuthenticationToken("alice", "admin")));
 | 
			
		||||
			String result = engine.process("security-dialect", attrs);
 | 
			
		||||
			assertThat(result).isEqualTo("<html><body><div>alice</div></body></html>"
 | 
			
		||||
					+ System.lineSeparator());
 | 
			
		||||
		}
 | 
			
		||||
		finally {
 | 
			
		||||
			SecurityContextHolder.clearContext();
 | 
			
		||||
		}
 | 
			
		||||
		this.contextRunner.run((context) -> {
 | 
			
		||||
			TemplateEngine engine = context.getBean(TemplateEngine.class);
 | 
			
		||||
			WebContext attrs = new WebContext(new MockHttpServletRequest(),
 | 
			
		||||
					new MockHttpServletResponse(), new MockServletContext());
 | 
			
		||||
			try {
 | 
			
		||||
				SecurityContextHolder.setContext(new SecurityContextImpl(
 | 
			
		||||
						new TestingAuthenticationToken("alice", "admin")));
 | 
			
		||||
				String result = engine.process("security-dialect", attrs);
 | 
			
		||||
				assertThat(result).isEqualTo("<html><body><div>alice</div></body></html>"
 | 
			
		||||
						+ System.lineSeparator());
 | 
			
		||||
			}
 | 
			
		||||
			finally {
 | 
			
		||||
				SecurityContextHolder.clearContext();
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void renderTemplate() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		TemplateEngine engine = this.context.getBean(TemplateEngine.class);
 | 
			
		||||
		Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
 | 
			
		||||
		String result = engine.process("home", attrs);
 | 
			
		||||
		assertThat(result).isEqualTo("<html><body>bar</body></html>");
 | 
			
		||||
		this.contextRunner.run((context) -> {
 | 
			
		||||
			TemplateEngine engine = context.getBean(TemplateEngine.class);
 | 
			
		||||
			Context attrs = new Context(Locale.UK,
 | 
			
		||||
					Collections.singletonMap("foo", "bar"));
 | 
			
		||||
			String result = engine.process("home", attrs);
 | 
			
		||||
			assertThat(result).isEqualTo("<html><body>bar</body></html>");
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void renderNonWebAppTemplate() {
 | 
			
		||||
		try (AnnotationConfigApplicationContext customContext = new AnnotationConfigApplicationContext(
 | 
			
		||||
				ThymeleafAutoConfiguration.class,
 | 
			
		||||
				PropertyPlaceholderAutoConfiguration.class)) {
 | 
			
		||||
			assertThat(customContext.getBeanNamesForType(ViewResolver.class).length)
 | 
			
		||||
					.isEqualTo(0);
 | 
			
		||||
			TemplateEngine engine = customContext.getBean(TemplateEngine.class);
 | 
			
		||||
			Context attrs = new Context(Locale.UK,
 | 
			
		||||
					Collections.singletonMap("greeting", "Hello World"));
 | 
			
		||||
			String result = engine.process("message", attrs);
 | 
			
		||||
			assertThat(result).contains("Hello World");
 | 
			
		||||
		}
 | 
			
		||||
		new ApplicationContextRunner()
 | 
			
		||||
				.withConfiguration(
 | 
			
		||||
						AutoConfigurations.of(ThymeleafAutoConfiguration.class))
 | 
			
		||||
				.run((context) -> {
 | 
			
		||||
					assertThat(context).doesNotHaveBean(ViewResolver.class);
 | 
			
		||||
					TemplateEngine engine = context.getBean(TemplateEngine.class);
 | 
			
		||||
					Context attrs = new Context(Locale.UK,
 | 
			
		||||
							Collections.singletonMap("greeting", "Hello World"));
 | 
			
		||||
					String result = engine.process("message", attrs);
 | 
			
		||||
					assertThat(result).contains("Hello World");
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void registerResourceHandlingFilterDisabledByDefault() {
 | 
			
		||||
		load(BaseConfiguration.class);
 | 
			
		||||
		assertThat(this.context.getBeansOfType(FilterRegistrationBean.class)).isEmpty();
 | 
			
		||||
		this.contextRunner.run((context) -> assertThat(context)
 | 
			
		||||
				.doesNotHaveBean(FilterRegistrationBean.class));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void registerResourceHandlingFilterOnlyIfResourceChainIsEnabled() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.resources.chain.enabled:true");
 | 
			
		||||
		FilterRegistrationBean<?> registration = this.context
 | 
			
		||||
				.getBean(FilterRegistrationBean.class);
 | 
			
		||||
		assertThat(registration.getFilter())
 | 
			
		||||
				.isInstanceOf(ResourceUrlEncodingFilter.class);
 | 
			
		||||
		assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes",
 | 
			
		||||
				EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR));
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.resources.chain.enabled:true")
 | 
			
		||||
				.run((context) -> {
 | 
			
		||||
					FilterRegistrationBean<?> registration = context
 | 
			
		||||
							.getBean(FilterRegistrationBean.class);
 | 
			
		||||
					assertThat(registration.getFilter())
 | 
			
		||||
							.isInstanceOf(ResourceUrlEncodingFilter.class);
 | 
			
		||||
					assertThat(registration).hasFieldOrPropertyWithValue(
 | 
			
		||||
							"dispatcherTypes",
 | 
			
		||||
							EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR));
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	@SuppressWarnings("rawtypes")
 | 
			
		||||
	public void registerResourceHandlingFilterWithOtherRegistrationBean() {
 | 
			
		||||
		// gh-14897
 | 
			
		||||
		load(FilterRegistrationOtherConfiguration.class,
 | 
			
		||||
				"spring.resources.chain.enabled:true");
 | 
			
		||||
		Map<String, FilterRegistrationBean> beans = this.context
 | 
			
		||||
				.getBeansOfType(FilterRegistrationBean.class);
 | 
			
		||||
		assertThat(beans).hasSize(2);
 | 
			
		||||
		FilterRegistrationBean registration = beans.values().stream()
 | 
			
		||||
				.filter((r) -> r.getFilter() instanceof ResourceUrlEncodingFilter)
 | 
			
		||||
				.findFirst().get();
 | 
			
		||||
		assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes",
 | 
			
		||||
				EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR));
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withUserConfiguration(FilterRegistrationOtherConfiguration.class)
 | 
			
		||||
				.withPropertyValues("spring.resources.chain.enabled:true")
 | 
			
		||||
				.run((context) -> {
 | 
			
		||||
					Map<String, FilterRegistrationBean> beans = context
 | 
			
		||||
							.getBeansOfType(FilterRegistrationBean.class);
 | 
			
		||||
					assertThat(beans).hasSize(2);
 | 
			
		||||
					FilterRegistrationBean registration = beans.values().stream().filter(
 | 
			
		||||
							(r) -> r.getFilter() instanceof ResourceUrlEncodingFilter)
 | 
			
		||||
							.findFirst().get();
 | 
			
		||||
					assertThat(registration).hasFieldOrPropertyWithValue(
 | 
			
		||||
							"dispatcherTypes",
 | 
			
		||||
							EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR));
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	@SuppressWarnings("rawtypes")
 | 
			
		||||
	public void registerResourceHandlingFilterWithResourceRegistrationBean() {
 | 
			
		||||
		// gh-14926
 | 
			
		||||
		load(FilterRegistrationResourceConfiguration.class,
 | 
			
		||||
				"spring.resources.chain.enabled:true");
 | 
			
		||||
		Map<String, FilterRegistrationBean> beans = this.context
 | 
			
		||||
				.getBeansOfType(FilterRegistrationBean.class);
 | 
			
		||||
		assertThat(beans).hasSize(1);
 | 
			
		||||
		FilterRegistrationBean registration = beans.values().stream()
 | 
			
		||||
				.filter((r) -> r.getFilter() instanceof ResourceUrlEncodingFilter)
 | 
			
		||||
				.findFirst().get();
 | 
			
		||||
		assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes",
 | 
			
		||||
				EnumSet.of(DispatcherType.INCLUDE));
 | 
			
		||||
		this.contextRunner
 | 
			
		||||
				.withUserConfiguration(FilterRegistrationResourceConfiguration.class)
 | 
			
		||||
				.withPropertyValues("spring.resources.chain.enabled:true")
 | 
			
		||||
				.run((context) -> {
 | 
			
		||||
					Map<String, FilterRegistrationBean> beans = context
 | 
			
		||||
							.getBeansOfType(FilterRegistrationBean.class);
 | 
			
		||||
					assertThat(beans).hasSize(1);
 | 
			
		||||
					FilterRegistrationBean registration = beans.values().stream().filter(
 | 
			
		||||
							(r) -> r.getFilter() instanceof ResourceUrlEncodingFilter)
 | 
			
		||||
							.findFirst().get();
 | 
			
		||||
					assertThat(registration).hasFieldOrPropertyWithValue(
 | 
			
		||||
							"dispatcherTypes", EnumSet.of(DispatcherType.INCLUDE));
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void layoutDialectCanBeCustomized() {
 | 
			
		||||
		load(LayoutDialectConfiguration.class);
 | 
			
		||||
		LayoutDialect layoutDialect = this.context.getBean(LayoutDialect.class);
 | 
			
		||||
		assertThat(ReflectionTestUtils.getField(layoutDialect, "sortingStrategy"))
 | 
			
		||||
				.isInstanceOf(GroupingStrategy.class);
 | 
			
		||||
		this.contextRunner.withUserConfiguration(LayoutDialectConfiguration.class)
 | 
			
		||||
				.run((context) -> assertThat(ReflectionTestUtils.getField(
 | 
			
		||||
						context.getBean(LayoutDialect.class), "sortingStrategy"))
 | 
			
		||||
								.isInstanceOf(GroupingStrategy.class));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void cachingCanBeDisabled() {
 | 
			
		||||
		load(BaseConfiguration.class, "spring.thymeleaf.cache:false");
 | 
			
		||||
		assertThat(this.context.getBean(ThymeleafViewResolver.class).isCache()).isFalse();
 | 
			
		||||
		SpringResourceTemplateResolver templateResolver = this.context
 | 
			
		||||
				.getBean(SpringResourceTemplateResolver.class);
 | 
			
		||||
		assertThat(templateResolver.isCacheable()).isFalse();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void load(Class<?> config, String... envVariables) {
 | 
			
		||||
		this.context = new AnnotationConfigWebApplicationContext();
 | 
			
		||||
		TestPropertyValues.of(envVariables).applyTo(this.context);
 | 
			
		||||
		this.context.register(config);
 | 
			
		||||
		this.context.refresh();
 | 
			
		||||
		this.contextRunner.withPropertyValues("spring.thymeleaf.cache:false")
 | 
			
		||||
				.run((context) -> {
 | 
			
		||||
					assertThat(context.getBean(ThymeleafViewResolver.class).isCache())
 | 
			
		||||
							.isFalse();
 | 
			
		||||
					SpringResourceTemplateResolver templateResolver = context
 | 
			
		||||
							.getBean(SpringResourceTemplateResolver.class);
 | 
			
		||||
					assertThat(templateResolver.isCacheable()).isFalse();
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@ImportAutoConfiguration({ ThymeleafAutoConfiguration.class,
 | 
			
		||||
			PropertyPlaceholderAutoConfiguration.class })
 | 
			
		||||
	static class BaseConfiguration {
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@Import(BaseConfiguration.class)
 | 
			
		||||
	static class LayoutDialectConfiguration {
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
| 
						 | 
				
			
			@ -353,12 +363,11 @@ public class ThymeleafServletAutoConfigurationTests {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@Import(BaseConfiguration.class)
 | 
			
		||||
	static class FilterRegistrationResourceConfiguration {
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public FilterRegistrationBean<ResourceUrlEncodingFilter> filterRegistration() {
 | 
			
		||||
			FilterRegistrationBean<ResourceUrlEncodingFilter> bean = new FilterRegistrationBean<ResourceUrlEncodingFilter>(
 | 
			
		||||
			FilterRegistrationBean<ResourceUrlEncodingFilter> bean = new FilterRegistrationBean<>(
 | 
			
		||||
					new ResourceUrlEncodingFilter());
 | 
			
		||||
			bean.setDispatcherTypes(EnumSet.of(DispatcherType.INCLUDE));
 | 
			
		||||
			return bean;
 | 
			
		||||
| 
						 | 
				
			
			@ -367,13 +376,11 @@ public class ThymeleafServletAutoConfigurationTests {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	@Configuration
 | 
			
		||||
	@Import(BaseConfiguration.class)
 | 
			
		||||
	static class FilterRegistrationOtherConfiguration {
 | 
			
		||||
 | 
			
		||||
		@Bean
 | 
			
		||||
		public FilterRegistrationBean<OrderedCharacterEncodingFilter> filterRegistration() {
 | 
			
		||||
			return new FilterRegistrationBean<OrderedCharacterEncodingFilter>(
 | 
			
		||||
					new OrderedCharacterEncodingFilter());
 | 
			
		||||
			return new FilterRegistrationBean<>(new OrderedCharacterEncodingFilter());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue