|
|
@ -26,7 +26,6 @@ import javax.servlet.DispatcherType;
|
|
|
|
|
|
|
|
|
|
|
|
import nz.net.ultraq.thymeleaf.LayoutDialect;
|
|
|
|
import nz.net.ultraq.thymeleaf.LayoutDialect;
|
|
|
|
import nz.net.ultraq.thymeleaf.decorators.strategies.GroupingStrategy;
|
|
|
|
import nz.net.ultraq.thymeleaf.decorators.strategies.GroupingStrategy;
|
|
|
|
import org.junit.After;
|
|
|
|
|
|
|
|
import org.junit.Rule;
|
|
|
|
import org.junit.Rule;
|
|
|
|
import org.junit.Test;
|
|
|
|
import org.junit.Test;
|
|
|
|
import org.thymeleaf.TemplateEngine;
|
|
|
|
import org.thymeleaf.TemplateEngine;
|
|
|
@ -38,17 +37,16 @@ import org.thymeleaf.spring5.view.ThymeleafView;
|
|
|
|
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
|
|
|
|
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
|
|
|
|
import org.thymeleaf.templateresolver.ITemplateResolver;
|
|
|
|
import org.thymeleaf.templateresolver.ITemplateResolver;
|
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
|
|
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|
|
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
|
|
|
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.rule.OutputCapture;
|
|
|
|
import org.springframework.boot.test.util.TestPropertyValues;
|
|
|
|
|
|
|
|
import org.springframework.boot.testsupport.BuildOutput;
|
|
|
|
import org.springframework.boot.testsupport.BuildOutput;
|
|
|
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|
|
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
|
|
|
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
|
|
|
|
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.Bean;
|
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
|
import org.springframework.context.annotation.Import;
|
|
|
|
|
|
|
|
import org.springframework.mock.web.MockHttpServletRequest;
|
|
|
|
import org.springframework.mock.web.MockHttpServletRequest;
|
|
|
|
import org.springframework.mock.web.MockHttpServletResponse;
|
|
|
|
import org.springframework.mock.web.MockHttpServletResponse;
|
|
|
|
import org.springframework.mock.web.MockServletContext;
|
|
|
|
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.SecurityContextHolder;
|
|
|
|
import org.springframework.security.core.context.SecurityContextImpl;
|
|
|
|
import org.springframework.security.core.context.SecurityContextImpl;
|
|
|
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
|
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
|
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
|
|
|
|
|
|
|
import org.springframework.web.servlet.ViewResolver;
|
|
|
|
import org.springframework.web.servlet.ViewResolver;
|
|
|
|
import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter;
|
|
|
|
import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter;
|
|
|
|
import org.springframework.web.servlet.support.RequestContext;
|
|
|
|
import org.springframework.web.servlet.support.RequestContext;
|
|
|
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
import static org.hamcrest.Matchers.containsString;
|
|
|
|
import static org.hamcrest.Matchers.containsString;
|
|
|
|
|
|
|
|
import static org.hamcrest.Matchers.not;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Tests for {@link ThymeleafAutoConfiguration} in Servlet-based applications.
|
|
|
|
* Tests for {@link ThymeleafAutoConfiguration} in Servlet-based applications.
|
|
|
@ -76,277 +74,297 @@ import static org.hamcrest.Matchers.containsString;
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public class ThymeleafServletAutoConfigurationTests {
|
|
|
|
public class ThymeleafServletAutoConfigurationTests {
|
|
|
|
|
|
|
|
|
|
|
|
private final BuildOutput buildOutput = new BuildOutput(getClass());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Rule
|
|
|
|
@Rule
|
|
|
|
public OutputCapture output = new OutputCapture();
|
|
|
|
public OutputCapture output = new OutputCapture();
|
|
|
|
|
|
|
|
|
|
|
|
private AnnotationConfigWebApplicationContext context;
|
|
|
|
private final BuildOutput buildOutput = new BuildOutput(getClass());
|
|
|
|
|
|
|
|
|
|
|
|
@After
|
|
|
|
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
|
|
|
public void close() {
|
|
|
|
.withConfiguration(AutoConfigurations.of(ThymeleafAutoConfiguration.class));
|
|
|
|
if (this.context != null) {
|
|
|
|
|
|
|
|
this.context.close();
|
|
|
|
@Test
|
|
|
|
}
|
|
|
|
public void autoConfigurationBackOffWithoutThymeleafSpring() {
|
|
|
|
|
|
|
|
this.contextRunner
|
|
|
|
|
|
|
|
.withClassLoader(new FilteredClassLoader("org.thymeleaf.spring5"))
|
|
|
|
|
|
|
|
.run((context) -> assertThat(context)
|
|
|
|
|
|
|
|
.doesNotHaveBean(TemplateEngine.class));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void createFromConfigClass() {
|
|
|
|
public void createFromConfigClass() {
|
|
|
|
load(BaseConfiguration.class, "spring.thymeleaf.mode:HTML",
|
|
|
|
this.contextRunner.withPropertyValues("spring.thymeleaf.mode:HTML",
|
|
|
|
"spring.thymeleaf.suffix:");
|
|
|
|
"spring.thymeleaf.suffix:").run((context) -> {
|
|
|
|
TemplateEngine engine = this.context.getBean(TemplateEngine.class);
|
|
|
|
assertThat(context).hasSingleBean(TemplateEngine.class);
|
|
|
|
Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
|
|
|
|
TemplateEngine engine = context.getBean(TemplateEngine.class);
|
|
|
|
String result = engine.process("template.html", attrs);
|
|
|
|
Context attrs = new Context(Locale.UK,
|
|
|
|
assertThat(result).isEqualTo("<html>bar</html>");
|
|
|
|
Collections.singletonMap("foo", "bar"));
|
|
|
|
|
|
|
|
String result = engine.process("template.html", attrs);
|
|
|
|
|
|
|
|
assertThat(result).isEqualTo("<html>bar</html>");
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void overrideCharacterEncoding() {
|
|
|
|
public void overrideCharacterEncoding() {
|
|
|
|
load(BaseConfiguration.class, "spring.thymeleaf.encoding:UTF-16");
|
|
|
|
this.contextRunner.withPropertyValues("spring.thymeleaf.encoding:UTF-16")
|
|
|
|
ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class);
|
|
|
|
.run((context) -> {
|
|
|
|
assertThat(resolver instanceof SpringResourceTemplateResolver).isTrue();
|
|
|
|
ITemplateResolver resolver = context.getBean(ITemplateResolver.class);
|
|
|
|
assertThat(((SpringResourceTemplateResolver) resolver).getCharacterEncoding())
|
|
|
|
assertThat(resolver)
|
|
|
|
.isEqualTo("UTF-16");
|
|
|
|
.isInstanceOf(SpringResourceTemplateResolver.class);
|
|
|
|
ThymeleafViewResolver views = this.context.getBean(ThymeleafViewResolver.class);
|
|
|
|
assertThat(((SpringResourceTemplateResolver) resolver)
|
|
|
|
assertThat(views.getCharacterEncoding()).isEqualTo("UTF-16");
|
|
|
|
.getCharacterEncoding()).isEqualTo("UTF-16");
|
|
|
|
assertThat(views.getContentType()).isEqualTo("text/html;charset=UTF-16");
|
|
|
|
ThymeleafViewResolver views = context
|
|
|
|
|
|
|
|
.getBean(ThymeleafViewResolver.class);
|
|
|
|
|
|
|
|
assertThat(views.getCharacterEncoding()).isEqualTo("UTF-16");
|
|
|
|
|
|
|
|
assertThat(views.getContentType())
|
|
|
|
|
|
|
|
.isEqualTo("text/html;charset=UTF-16");
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void overrideDisableProducePartialOutputWhileProcessing() {
|
|
|
|
public void overrideDisableProducePartialOutputWhileProcessing() {
|
|
|
|
load(BaseConfiguration.class,
|
|
|
|
this.contextRunner.withPropertyValues(
|
|
|
|
"spring.thymeleaf.servlet.produce-partial-output-while-processing:false");
|
|
|
|
"spring.thymeleaf.servlet.produce-partial-output-while-processing:false")
|
|
|
|
assertThat(this.context.getBean(ThymeleafViewResolver.class)
|
|
|
|
.run((context) -> assertThat(context.getBean(ThymeleafViewResolver.class)
|
|
|
|
.getProducePartialOutputWhileProcessing()).isFalse();
|
|
|
|
.getProducePartialOutputWhileProcessing()).isFalse());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void disableProducePartialOutputWhileProcessingIsEnabledByDefault() {
|
|
|
|
public void disableProducePartialOutputWhileProcessingIsEnabledByDefault() {
|
|
|
|
load(BaseConfiguration.class);
|
|
|
|
this.contextRunner
|
|
|
|
assertThat(this.context.getBean(ThymeleafViewResolver.class)
|
|
|
|
.run((context) -> assertThat(context.getBean(ThymeleafViewResolver.class)
|
|
|
|
.getProducePartialOutputWhileProcessing()).isTrue();
|
|
|
|
.getProducePartialOutputWhileProcessing()).isTrue());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void overrideTemplateResolverOrder() {
|
|
|
|
public void overrideTemplateResolverOrder() {
|
|
|
|
load(BaseConfiguration.class, "spring.thymeleaf.templateResolverOrder:25");
|
|
|
|
this.contextRunner.withPropertyValues("spring.thymeleaf.templateResolverOrder:25")
|
|
|
|
ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class);
|
|
|
|
.run((context) -> assertThat(
|
|
|
|
assertThat(resolver.getOrder()).isEqualTo(Integer.valueOf(25));
|
|
|
|
context.getBean(ITemplateResolver.class).getOrder())
|
|
|
|
|
|
|
|
.isEqualTo(Integer.valueOf(25)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void overrideViewNames() {
|
|
|
|
public void overrideViewNames() {
|
|
|
|
load(BaseConfiguration.class, "spring.thymeleaf.viewNames:foo,bar");
|
|
|
|
this.contextRunner.withPropertyValues("spring.thymeleaf.viewNames:foo,bar")
|
|
|
|
ThymeleafViewResolver views = this.context.getBean(ThymeleafViewResolver.class);
|
|
|
|
.run((context) -> assertThat(
|
|
|
|
assertThat(views.getViewNames()).isEqualTo(new String[] { "foo", "bar" });
|
|
|
|
context.getBean(ThymeleafViewResolver.class).getViewNames())
|
|
|
|
|
|
|
|
.isEqualTo(new String[] { "foo", "bar" }));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void overrideEnableSpringElCompiler() {
|
|
|
|
public void overrideEnableSpringElCompiler() {
|
|
|
|
load(BaseConfiguration.class, "spring.thymeleaf.enable-spring-el-compiler:true");
|
|
|
|
this.contextRunner
|
|
|
|
assertThat(this.context.getBean(SpringTemplateEngine.class)
|
|
|
|
.withPropertyValues("spring.thymeleaf.enable-spring-el-compiler:true")
|
|
|
|
.getEnableSpringELCompiler()).isTrue();
|
|
|
|
.run((context) -> assertThat(context.getBean(SpringTemplateEngine.class)
|
|
|
|
|
|
|
|
.getEnableSpringELCompiler()).isTrue());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void enableSpringElCompilerIsDisabledByDefault() {
|
|
|
|
public void enableSpringElCompilerIsDisabledByDefault() {
|
|
|
|
load(BaseConfiguration.class);
|
|
|
|
this.contextRunner.run((context) -> assertThat(
|
|
|
|
assertThat(this.context.getBean(SpringTemplateEngine.class)
|
|
|
|
context.getBean(SpringTemplateEngine.class).getEnableSpringELCompiler())
|
|
|
|
.getEnableSpringELCompiler()).isFalse();
|
|
|
|
.isFalse());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void overrideRenderHiddenMarkersBeforeCheckboxes() {
|
|
|
|
public void overrideRenderHiddenMarkersBeforeCheckboxes() {
|
|
|
|
load(BaseConfiguration.class,
|
|
|
|
this.contextRunner
|
|
|
|
"spring.thymeleaf.render-hidden-markers-before-checkboxes:true");
|
|
|
|
.withPropertyValues(
|
|
|
|
assertThat(this.context.getBean(SpringTemplateEngine.class)
|
|
|
|
"spring.thymeleaf.render-hidden-markers-before-checkboxes:true")
|
|
|
|
.getRenderHiddenMarkersBeforeCheckboxes()).isTrue();
|
|
|
|
.run((context) -> assertThat(context.getBean(SpringTemplateEngine.class)
|
|
|
|
|
|
|
|
.getRenderHiddenMarkersBeforeCheckboxes()).isTrue());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void enableRenderHiddenMarkersBeforeCheckboxesIsDisabledByDefault() {
|
|
|
|
public void enableRenderHiddenMarkersBeforeCheckboxesIsDisabledByDefault() {
|
|
|
|
load(BaseConfiguration.class);
|
|
|
|
this.contextRunner
|
|
|
|
assertThat(this.context.getBean(SpringTemplateEngine.class)
|
|
|
|
.run((context) -> assertThat(context.getBean(SpringTemplateEngine.class)
|
|
|
|
.getRenderHiddenMarkersBeforeCheckboxes()).isFalse();
|
|
|
|
.getRenderHiddenMarkersBeforeCheckboxes()).isFalse());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void templateLocationDoesNotExist() {
|
|
|
|
public void templateLocationDoesNotExist() {
|
|
|
|
load(BaseConfiguration.class,
|
|
|
|
this.contextRunner
|
|
|
|
"spring.thymeleaf.prefix:classpath:/no-such-directory/");
|
|
|
|
.withPropertyValues(
|
|
|
|
this.output.expect(containsString("Cannot find template location"));
|
|
|
|
"spring.thymeleaf.prefix:classpath:/no-such-directory/")
|
|
|
|
|
|
|
|
.run((context) -> this.output
|
|
|
|
|
|
|
|
.expect(containsString("Cannot find template location")));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void templateLocationEmpty() {
|
|
|
|
public void templateLocationEmpty() {
|
|
|
|
new File(this.buildOutput.getTestResourcesLocation(),
|
|
|
|
new File(this.buildOutput.getTestResourcesLocation(),
|
|
|
|
"empty-templates/empty-directory").mkdirs();
|
|
|
|
"empty-templates/empty-directory").mkdirs();
|
|
|
|
load(BaseConfiguration.class,
|
|
|
|
this.contextRunner.withPropertyValues(
|
|
|
|
"spring.thymeleaf.prefix:classpath:/empty-templates/empty-directory/");
|
|
|
|
"spring.thymeleaf.prefix:classpath:/empty-templates/empty-directory/")
|
|
|
|
|
|
|
|
.run((context) -> this.output
|
|
|
|
|
|
|
|
.expect(not(containsString("Cannot find template location"))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void createLayoutFromConfigClass() throws Exception {
|
|
|
|
public void createLayoutFromConfigClass() {
|
|
|
|
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
|
|
|
this.contextRunner.run((context) -> {
|
|
|
|
context.register(ThymeleafAutoConfiguration.class,
|
|
|
|
ThymeleafView view = (ThymeleafView) context
|
|
|
|
PropertyPlaceholderAutoConfiguration.class);
|
|
|
|
.getBean(ThymeleafViewResolver.class)
|
|
|
|
MockServletContext servletContext = new MockServletContext();
|
|
|
|
.resolveViewName("view", Locale.UK);
|
|
|
|
context.setServletContext(servletContext);
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
|
|
|
context.refresh();
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
|
ThymeleafView view = (ThymeleafView) context.getBean(ThymeleafViewResolver.class)
|
|
|
|
request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE,
|
|
|
|
.resolveViewName("view", Locale.UK);
|
|
|
|
context);
|
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
|
|
|
view.render(Collections.singletonMap("foo", "bar"), request, response);
|
|
|
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
|
String result = response.getContentAsString();
|
|
|
|
request.setAttribute(RequestContext.WEB_APPLICATION_CONTEXT_ATTRIBUTE, context);
|
|
|
|
assertThat(result).contains("<title>Content</title>");
|
|
|
|
view.render(Collections.singletonMap("foo", "bar"), request, response);
|
|
|
|
assertThat(result).contains("<span>bar</span>");
|
|
|
|
String result = response.getContentAsString();
|
|
|
|
context.close();
|
|
|
|
assertThat(result).contains("<title>Content</title>");
|
|
|
|
});
|
|
|
|
assertThat(result).contains("<span>bar</span>");
|
|
|
|
|
|
|
|
context.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void useDataDialect() {
|
|
|
|
public void useDataDialect() {
|
|
|
|
load(BaseConfiguration.class);
|
|
|
|
this.contextRunner.run((context) -> {
|
|
|
|
TemplateEngine engine = this.context.getBean(TemplateEngine.class);
|
|
|
|
TemplateEngine engine = context.getBean(TemplateEngine.class);
|
|
|
|
Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
|
|
|
|
Context attrs = new Context(Locale.UK,
|
|
|
|
String result = engine.process("data-dialect", attrs);
|
|
|
|
Collections.singletonMap("foo", "bar"));
|
|
|
|
assertThat(result).isEqualTo("<html><body data-foo=\"bar\"></body></html>");
|
|
|
|
String result = engine.process("data-dialect", attrs);
|
|
|
|
|
|
|
|
assertThat(result).isEqualTo("<html><body data-foo=\"bar\"></body></html>");
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void useJava8TimeDialect() {
|
|
|
|
public void useJava8TimeDialect() {
|
|
|
|
load(BaseConfiguration.class);
|
|
|
|
this.contextRunner.run((context) -> {
|
|
|
|
TemplateEngine engine = this.context.getBean(TemplateEngine.class);
|
|
|
|
TemplateEngine engine = context.getBean(TemplateEngine.class);
|
|
|
|
Context attrs = new Context(Locale.UK);
|
|
|
|
Context attrs = new Context(Locale.UK);
|
|
|
|
String result = engine.process("java8time-dialect", attrs);
|
|
|
|
String result = engine.process("java8time-dialect", attrs);
|
|
|
|
assertThat(result).isEqualTo("<html><body>2015-11-24</body></html>");
|
|
|
|
assertThat(result).isEqualTo("<html><body>2015-11-24</body></html>");
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void useSecurityDialect() {
|
|
|
|
public void useSecurityDialect() {
|
|
|
|
load(BaseConfiguration.class);
|
|
|
|
this.contextRunner.run((context) -> {
|
|
|
|
TemplateEngine engine = this.context.getBean(TemplateEngine.class);
|
|
|
|
TemplateEngine engine = context.getBean(TemplateEngine.class);
|
|
|
|
WebContext attrs = new WebContext(new MockHttpServletRequest(),
|
|
|
|
WebContext attrs = new WebContext(new MockHttpServletRequest(),
|
|
|
|
new MockHttpServletResponse(), new MockServletContext());
|
|
|
|
new MockHttpServletResponse(), new MockServletContext());
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
SecurityContextHolder.setContext(new SecurityContextImpl(
|
|
|
|
SecurityContextHolder.setContext(new SecurityContextImpl(
|
|
|
|
new TestingAuthenticationToken("alice", "admin")));
|
|
|
|
new TestingAuthenticationToken("alice", "admin")));
|
|
|
|
String result = engine.process("security-dialect", attrs);
|
|
|
|
String result = engine.process("security-dialect", attrs);
|
|
|
|
assertThat(result).isEqualTo("<html><body><div>alice</div></body></html>"
|
|
|
|
assertThat(result).isEqualTo("<html><body><div>alice</div></body></html>"
|
|
|
|
+ System.lineSeparator());
|
|
|
|
+ System.lineSeparator());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finally {
|
|
|
|
finally {
|
|
|
|
SecurityContextHolder.clearContext();
|
|
|
|
SecurityContextHolder.clearContext();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void renderTemplate() {
|
|
|
|
public void renderTemplate() {
|
|
|
|
load(BaseConfiguration.class);
|
|
|
|
this.contextRunner.run((context) -> {
|
|
|
|
TemplateEngine engine = this.context.getBean(TemplateEngine.class);
|
|
|
|
TemplateEngine engine = context.getBean(TemplateEngine.class);
|
|
|
|
Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar"));
|
|
|
|
Context attrs = new Context(Locale.UK,
|
|
|
|
String result = engine.process("home", attrs);
|
|
|
|
Collections.singletonMap("foo", "bar"));
|
|
|
|
assertThat(result).isEqualTo("<html><body>bar</body></html>");
|
|
|
|
String result = engine.process("home", attrs);
|
|
|
|
|
|
|
|
assertThat(result).isEqualTo("<html><body>bar</body></html>");
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void renderNonWebAppTemplate() {
|
|
|
|
public void renderNonWebAppTemplate() {
|
|
|
|
try (AnnotationConfigApplicationContext customContext = new AnnotationConfigApplicationContext(
|
|
|
|
new ApplicationContextRunner()
|
|
|
|
ThymeleafAutoConfiguration.class,
|
|
|
|
.withConfiguration(
|
|
|
|
PropertyPlaceholderAutoConfiguration.class)) {
|
|
|
|
AutoConfigurations.of(ThymeleafAutoConfiguration.class))
|
|
|
|
assertThat(customContext.getBeanNamesForType(ViewResolver.class).length)
|
|
|
|
.run((context) -> {
|
|
|
|
.isEqualTo(0);
|
|
|
|
assertThat(context).doesNotHaveBean(ViewResolver.class);
|
|
|
|
TemplateEngine engine = customContext.getBean(TemplateEngine.class);
|
|
|
|
TemplateEngine engine = context.getBean(TemplateEngine.class);
|
|
|
|
Context attrs = new Context(Locale.UK,
|
|
|
|
Context attrs = new Context(Locale.UK,
|
|
|
|
Collections.singletonMap("greeting", "Hello World"));
|
|
|
|
Collections.singletonMap("greeting", "Hello World"));
|
|
|
|
String result = engine.process("message", attrs);
|
|
|
|
String result = engine.process("message", attrs);
|
|
|
|
assertThat(result).contains("Hello World");
|
|
|
|
assertThat(result).contains("Hello World");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void registerResourceHandlingFilterDisabledByDefault() {
|
|
|
|
public void registerResourceHandlingFilterDisabledByDefault() {
|
|
|
|
load(BaseConfiguration.class);
|
|
|
|
this.contextRunner.run((context) -> assertThat(context)
|
|
|
|
assertThat(this.context.getBeansOfType(FilterRegistrationBean.class)).isEmpty();
|
|
|
|
.doesNotHaveBean(FilterRegistrationBean.class));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void registerResourceHandlingFilterOnlyIfResourceChainIsEnabled() {
|
|
|
|
public void registerResourceHandlingFilterOnlyIfResourceChainIsEnabled() {
|
|
|
|
load(BaseConfiguration.class, "spring.resources.chain.enabled:true");
|
|
|
|
this.contextRunner.withPropertyValues("spring.resources.chain.enabled:true")
|
|
|
|
FilterRegistrationBean<?> registration = this.context
|
|
|
|
.run((context) -> {
|
|
|
|
.getBean(FilterRegistrationBean.class);
|
|
|
|
FilterRegistrationBean<?> registration = context
|
|
|
|
assertThat(registration.getFilter())
|
|
|
|
.getBean(FilterRegistrationBean.class);
|
|
|
|
.isInstanceOf(ResourceUrlEncodingFilter.class);
|
|
|
|
assertThat(registration.getFilter())
|
|
|
|
assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes",
|
|
|
|
.isInstanceOf(ResourceUrlEncodingFilter.class);
|
|
|
|
EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR));
|
|
|
|
assertThat(registration).hasFieldOrPropertyWithValue(
|
|
|
|
|
|
|
|
"dispatcherTypes",
|
|
|
|
|
|
|
|
EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR));
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
|
|
public void registerResourceHandlingFilterWithOtherRegistrationBean() {
|
|
|
|
public void registerResourceHandlingFilterWithOtherRegistrationBean() {
|
|
|
|
// gh-14897
|
|
|
|
// gh-14897
|
|
|
|
load(FilterRegistrationOtherConfiguration.class,
|
|
|
|
this.contextRunner
|
|
|
|
"spring.resources.chain.enabled:true");
|
|
|
|
.withUserConfiguration(FilterRegistrationOtherConfiguration.class)
|
|
|
|
Map<String, FilterRegistrationBean> beans = this.context
|
|
|
|
.withPropertyValues("spring.resources.chain.enabled:true")
|
|
|
|
.getBeansOfType(FilterRegistrationBean.class);
|
|
|
|
.run((context) -> {
|
|
|
|
assertThat(beans).hasSize(2);
|
|
|
|
Map<String, FilterRegistrationBean> beans = context
|
|
|
|
FilterRegistrationBean registration = beans.values().stream()
|
|
|
|
.getBeansOfType(FilterRegistrationBean.class);
|
|
|
|
.filter((r) -> r.getFilter() instanceof ResourceUrlEncodingFilter)
|
|
|
|
assertThat(beans).hasSize(2);
|
|
|
|
.findFirst().get();
|
|
|
|
FilterRegistrationBean registration = beans.values().stream().filter(
|
|
|
|
assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes",
|
|
|
|
(r) -> r.getFilter() instanceof ResourceUrlEncodingFilter)
|
|
|
|
EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR));
|
|
|
|
.findFirst().get();
|
|
|
|
|
|
|
|
assertThat(registration).hasFieldOrPropertyWithValue(
|
|
|
|
|
|
|
|
"dispatcherTypes",
|
|
|
|
|
|
|
|
EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR));
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
|
|
public void registerResourceHandlingFilterWithResourceRegistrationBean() {
|
|
|
|
public void registerResourceHandlingFilterWithResourceRegistrationBean() {
|
|
|
|
// gh-14926
|
|
|
|
// gh-14926
|
|
|
|
load(FilterRegistrationResourceConfiguration.class,
|
|
|
|
this.contextRunner
|
|
|
|
"spring.resources.chain.enabled:true");
|
|
|
|
.withUserConfiguration(FilterRegistrationResourceConfiguration.class)
|
|
|
|
Map<String, FilterRegistrationBean> beans = this.context
|
|
|
|
.withPropertyValues("spring.resources.chain.enabled:true")
|
|
|
|
.getBeansOfType(FilterRegistrationBean.class);
|
|
|
|
.run((context) -> {
|
|
|
|
assertThat(beans).hasSize(1);
|
|
|
|
Map<String, FilterRegistrationBean> beans = context
|
|
|
|
FilterRegistrationBean registration = beans.values().stream()
|
|
|
|
.getBeansOfType(FilterRegistrationBean.class);
|
|
|
|
.filter((r) -> r.getFilter() instanceof ResourceUrlEncodingFilter)
|
|
|
|
assertThat(beans).hasSize(1);
|
|
|
|
.findFirst().get();
|
|
|
|
FilterRegistrationBean registration = beans.values().stream().filter(
|
|
|
|
assertThat(registration).hasFieldOrPropertyWithValue("dispatcherTypes",
|
|
|
|
(r) -> r.getFilter() instanceof ResourceUrlEncodingFilter)
|
|
|
|
EnumSet.of(DispatcherType.INCLUDE));
|
|
|
|
.findFirst().get();
|
|
|
|
|
|
|
|
assertThat(registration).hasFieldOrPropertyWithValue(
|
|
|
|
|
|
|
|
"dispatcherTypes", EnumSet.of(DispatcherType.INCLUDE));
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void layoutDialectCanBeCustomized() {
|
|
|
|
public void layoutDialectCanBeCustomized() {
|
|
|
|
load(LayoutDialectConfiguration.class);
|
|
|
|
this.contextRunner.withUserConfiguration(LayoutDialectConfiguration.class)
|
|
|
|
LayoutDialect layoutDialect = this.context.getBean(LayoutDialect.class);
|
|
|
|
.run((context) -> assertThat(ReflectionTestUtils.getField(
|
|
|
|
assertThat(ReflectionTestUtils.getField(layoutDialect, "sortingStrategy"))
|
|
|
|
context.getBean(LayoutDialect.class), "sortingStrategy"))
|
|
|
|
.isInstanceOf(GroupingStrategy.class);
|
|
|
|
.isInstanceOf(GroupingStrategy.class));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
@Test
|
|
|
|
public void cachingCanBeDisabled() {
|
|
|
|
public void cachingCanBeDisabled() {
|
|
|
|
load(BaseConfiguration.class, "spring.thymeleaf.cache:false");
|
|
|
|
this.contextRunner.withPropertyValues("spring.thymeleaf.cache:false")
|
|
|
|
assertThat(this.context.getBean(ThymeleafViewResolver.class).isCache()).isFalse();
|
|
|
|
.run((context) -> {
|
|
|
|
SpringResourceTemplateResolver templateResolver = this.context
|
|
|
|
assertThat(context.getBean(ThymeleafViewResolver.class).isCache())
|
|
|
|
.getBean(SpringResourceTemplateResolver.class);
|
|
|
|
.isFalse();
|
|
|
|
assertThat(templateResolver.isCacheable()).isFalse();
|
|
|
|
SpringResourceTemplateResolver templateResolver = 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 {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration(proxyBeanMethods = false)
|
|
|
|
@Configuration(proxyBeanMethods = false)
|
|
|
|
@Import(BaseConfiguration.class)
|
|
|
|
|
|
|
|
static class LayoutDialectConfiguration {
|
|
|
|
static class LayoutDialectConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
@Bean
|
|
|
@ -357,7 +375,6 @@ public class ThymeleafServletAutoConfigurationTests {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration(proxyBeanMethods = false)
|
|
|
|
@Configuration(proxyBeanMethods = false)
|
|
|
|
@Import(BaseConfiguration.class)
|
|
|
|
|
|
|
|
static class FilterRegistrationResourceConfiguration {
|
|
|
|
static class FilterRegistrationResourceConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
@Bean
|
|
|
@ -371,7 +388,6 @@ public class ThymeleafServletAutoConfigurationTests {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Configuration(proxyBeanMethods = false)
|
|
|
|
@Configuration(proxyBeanMethods = false)
|
|
|
|
@Import(BaseConfiguration.class)
|
|
|
|
|
|
|
|
static class FilterRegistrationOtherConfiguration {
|
|
|
|
static class FilterRegistrationOtherConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
@Bean
|
|
|
|