Merge branch '2.1.x'

pull/16278/head
Stephane Nicoll 6 years ago
commit 465053c11e

@ -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,15 +35,12 @@ 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.test.util.TestPropertyValues;
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.testsupport.BuildOutput;
import org.springframework.boot.testsupport.rule.OutputCapture;
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;
@ -59,216 +55,217 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Brian Clozel
* @author Kazuki Shimizu
* @author Stephane Nicoll
*/
public class ThymeleafReactiveAutoConfigurationTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
@Rule
public final OutputCapture output = new OutputCapture();
private AnnotationConfigReactiveWebApplicationContext context;
private final BuildOutput buildOutput = new BuildOutput(getClass());
@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/");
assertThat(this.output.toString()).contains("Cannot find template location");
this.contextRunner
.withPropertyValues(
"spring.thymeleaf.prefix:classpath:/no-such-directory/")
.run((context) -> assertThat(this.output.toString())
.contains("Cannot find template location"));
}
@Test
public void templateLocationEmpty() {
new File(this.buildOutput.getTestResourcesLocation(),
"empty-templates/empty-directory").mkdirs();
load(BaseConfiguration.class,
"spring.thymeleaf.prefix:classpath:/empty-templates/empty-directory/");
assertThat(this.output.toString())
.doesNotContain("Cannot find template location");
this.contextRunner.withPropertyValues(
"spring.thymeleaf.prefix:classpath:/empty-templates/empty-directory/")
.run((context) -> assertThat(this.output.toString())
.doesNotContain("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();
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration({ ThymeleafAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class })
protected static class BaseConfiguration {
this.contextRunner.withUserConfiguration(LayoutDialectConfiguration.class)
.run((context) -> assertThat(ReflectionTestUtils.getField(
context.getBean(LayoutDialect.class), "sortingStrategy"))
.isInstanceOf(GroupingStrategy.class));
}
@Configuration(proxyBeanMethods = false)
@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,17 +37,16 @@ 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.FilteredClassLoader;
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.testsupport.BuildOutput;
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;
@ -56,13 +54,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.
@ -76,277 +74,297 @@ import static org.hamcrest.Matchers.containsString;
*/
public class ThymeleafServletAutoConfigurationTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
@Rule
public OutputCapture output = new OutputCapture();
private AnnotationConfigWebApplicationContext context;
private final BuildOutput buildOutput = new BuildOutput(getClass());
@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 autoConfigurationBackOffWithoutThymeleafSpring() {
this.contextRunner
.withClassLoader(new FilteredClassLoader("org.thymeleaf.spring5"))
.run((context) -> assertThat(context)
.doesNotHaveBean(TemplateEngine.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(this.buildOutput.getTestResourcesLocation(),
"empty-templates/empty-directory").mkdirs();
load(BaseConfiguration.class,
"spring.thymeleaf.prefix:classpath:/empty-templates/empty-directory/");
this.contextRunner.withPropertyValues(
"spring.thymeleaf.prefix:classpath:/empty-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();
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration({ ThymeleafAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class })
static class BaseConfiguration {
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(proxyBeanMethods = false)
@Import(BaseConfiguration.class)
static class LayoutDialectConfiguration {
@Bean
@ -357,7 +375,6 @@ public class ThymeleafServletAutoConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
@Import(BaseConfiguration.class)
static class FilterRegistrationResourceConfiguration {
@Bean
@ -371,7 +388,6 @@ public class ThymeleafServletAutoConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
@Import(BaseConfiguration.class)
static class FilterRegistrationOtherConfiguration {
@Bean

Loading…
Cancel
Save