Create spring-boot-thymeleaf module

This commit is contained in:
Moritz Halbritter 2025-03-25 11:22:30 +01:00 committed by Stéphane Nicoll
parent 452c0f395e
commit ac3f997070
26 changed files with 131 additions and 82 deletions

View File

@ -87,6 +87,7 @@ include "spring-boot-project:spring-boot-test"
include "spring-boot-project:spring-boot-test-autoconfigure"
include "spring-boot-project:spring-boot-test-integration-tests"
include "spring-boot-project:spring-boot-testcontainers"
include "spring-boot-project:spring-boot-thymeleaf"
include "spring-boot-project:spring-boot-tomcat"
include "spring-boot-project:spring-boot-tools:spring-boot-antlib"
include "spring-boot-project:spring-boot-tools:spring-boot-autoconfigure-processor"

View File

@ -103,10 +103,8 @@ dependencies {
optional("org.apiguardian:apiguardian-api")
optional("org.eclipse.angus:angus-mail")
optional("com.github.ben-manes.caffeine:caffeine")
optional("com.github.mxab.thymeleaf.extras:thymeleaf-extras-data-attribute")
optional("com.sendgrid:sendgrid-java")
optional("com.zaxxer:HikariCP")
optional("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
optional("org.aspectj:aspectjweaver")
optional("org.cache2k:cache2k-spring")
optional("org.eclipse.jetty.ee10:jetty-ee10-webapp")
@ -204,9 +202,6 @@ dependencies {
exclude group: "org.eclipse.jetty", module: "jetty-servlet"
exclude group: "jakarta.mail", module: "jakarta.mail-api"
}
optional("org.thymeleaf:thymeleaf")
optional("org.thymeleaf:thymeleaf-spring6")
optional("org.thymeleaf.extras:thymeleaf-extras-springsecurity6")
optional("redis.clients:jedis")
testImplementation(project(":spring-boot-project:spring-boot-freemarker"))
@ -215,6 +210,7 @@ dependencies {
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
testImplementation(project(":spring-boot-project:spring-boot-undertow"))
testImplementation(project(":spring-boot-project:spring-boot-mustache"))
testImplementation(project(":spring-boot-project:spring-boot-thymeleaf"))
testImplementation(testFixtures(project(":spring-boot-project:spring-boot")))
testImplementation(testFixtures(project(":spring-boot-project:spring-boot-autoconfigure")))
testImplementation("ch.qos.logback:logback-classic")

View File

@ -1257,33 +1257,6 @@
"level": "warning"
}
},
{
"name": "spring.thymeleaf.prefix",
"defaultValue": "classpath:/templates/"
},
{
"name": "spring.thymeleaf.reactive.media-types",
"defaultValue": [
"text/html",
"application/xhtml+xml",
"application/xml",
"text/xml",
"application/rss+xml",
"application/atom+xml",
"application/javascript",
"application/ecmascript",
"text/javascript",
"text/ecmascript",
"application/json",
"text/css",
"text/plain",
"text/event-stream"
]
},
{
"name": "spring.thymeleaf.suffix",
"defaultValue": ".html"
},
{
"name": "spring.webflux.hiddenmethod.filter.enabled",
"type": "java.lang.Boolean",

View File

@ -8,7 +8,6 @@ org.springframework.boot.autoconfigure.data.redis.RedisUrlSyntaxFailureAnalyzer
# Template Availability Providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
# Depends on Database Initialization Detectors

View File

@ -70,7 +70,6 @@ org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2Auth
org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2AuthorizationServerJwtAutoConfiguration
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration

View File

@ -22,11 +22,11 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.boot.thymeleaf.autoconfigure.ThymeleafAutoConfiguration;
import org.springframework.boot.tomcat.autoconfigure.servlet.TomcatServletWebServerAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

View File

@ -2065,6 +2065,7 @@ bom {
"spring-boot-test",
"spring-boot-test-autoconfigure",
"spring-boot-testcontainers",
"spring-boot-thymeleaf",
"spring-boot-tomcat",
"spring-boot-tx",
"spring-boot-undertow",

View File

@ -95,6 +95,7 @@ dependencies {
autoConfiguration(project(path: ":spring-boot-project:spring-boot-reactor-netty", configuration: "autoConfigurationMetadata"))
autoConfiguration(project(path: ":spring-boot-project:spring-boot-rsocket", configuration: "autoConfigurationMetadata"))
autoConfiguration(project(path: ":spring-boot-project:spring-boot-testcontainers", configuration: "autoConfigurationMetadata"))
autoConfiguration(project(path: ":spring-boot-project:spring-boot-thymeleaf", configuration: "autoConfigurationMetadata"))
autoConfiguration(project(path: ":spring-boot-project:spring-boot-tomcat", configuration: "autoConfigurationMetadata"))
autoConfiguration(project(path: ":spring-boot-project:spring-boot-tx", configuration: "autoConfigurationMetadata"))
autoConfiguration(project(path: ":spring-boot-project:spring-boot-undertow", configuration: "autoConfigurationMetadata"))
@ -139,6 +140,7 @@ dependencies {
configurationProperties(project(path: ":spring-boot-project:spring-boot-rsocket", configuration: "configurationPropertiesMetadata"))
configurationProperties(project(path: ":spring-boot-project:spring-boot-test-autoconfigure", configuration: "configurationPropertiesMetadata"))
configurationProperties(project(path: ":spring-boot-project:spring-boot-testcontainers", configuration: "configurationPropertiesMetadata"))
configurationProperties(project(path: ":spring-boot-project:spring-boot-thymeleaf", configuration: "configurationPropertiesMetadata"))
configurationProperties(project(path: ":spring-boot-project:spring-boot-tomcat", configuration: "configurationPropertiesMetadata"))
configurationProperties(project(path: ":spring-boot-project:spring-boot-tx", configuration: "configurationPropertiesMetadata"))
configurationProperties(project(path: ":spring-boot-project:spring-boot-undertow", configuration: "configurationPropertiesMetadata"))

View File

@ -6,5 +6,5 @@ description = "Starter for building MVC web applications using Thymeleaf views"
dependencies {
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter"))
api("org.thymeleaf:thymeleaf-spring6")
api(project(":spring-boot-project:spring-boot-thymeleaf"))
}

View File

@ -105,6 +105,7 @@ dependencies {
testImplementation(project(":spring-boot-project:spring-boot-freemarker"))
testImplementation(project(":spring-boot-project:spring-boot-mustache"))
testImplementation(project(":spring-boot-project:spring-boot-testcontainers"))
testImplementation(project(":spring-boot-project:spring-boot-thymeleaf"))
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
testImplementation("ch.qos.logback:logback-classic")
testImplementation("com.fasterxml.jackson.module:jackson-module-parameter-names")

View File

@ -3,7 +3,7 @@ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration
optional:org.springframework.boot.freemarker.autoconfigure.FreeMarkerAutoConfiguration
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration
optional:org.springframework.boot.mustache.autoconfigure.MustacheAutoConfiguration
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
optional:org.springframework.boot.thymeleaf.autoconfigure.ThymeleafAutoConfiguration
optional:org.springframework.boot.validation.autoconfigure.ValidationAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration

View File

@ -6,7 +6,7 @@ org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
optional:org.springframework.boot.mustache.autoconfigure.MustacheAutoConfiguration
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
optional:org.springframework.boot.thymeleaf.autoconfigure.ThymeleafAutoConfiguration
optional:org.springframework.boot.groovy.template.autoconfigure.GroovyTemplateAutoConfiguration
optional:org.springframework.boot.validation.autoconfigure.ValidationAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration

View File

@ -22,11 +22,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
import org.springframework.boot.freemarker.autoconfigure.FreeMarkerAutoConfiguration;
import org.springframework.boot.mustache.autoconfigure.MustacheAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.thymeleaf.autoconfigure.ThymeleafAutoConfiguration;
import org.springframework.boot.validation.autoconfigure.ValidationAutoConfiguration;
import org.springframework.context.ApplicationContext;

View File

@ -22,11 +22,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration;
import org.springframework.boot.freemarker.autoconfigure.FreeMarkerAutoConfiguration;
import org.springframework.boot.groovy.template.autoconfigure.GroovyTemplateAutoConfiguration;
import org.springframework.boot.mustache.autoconfigure.MustacheAutoConfiguration;
import org.springframework.boot.thymeleaf.autoconfigure.ThymeleafAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

View File

@ -0,0 +1,30 @@
plugins {
id "java-library"
id "org.springframework.boot.auto-configuration"
id "org.springframework.boot.configuration-properties"
id "org.springframework.boot.deployed"
id "org.springframework.boot.optional-dependencies"
}
description = "Spring Boot Thymeleaf"
dependencies {
api(project(":spring-boot-project:spring-boot"))
api("org.thymeleaf:thymeleaf-spring6")
api("org.springframework:spring-web")
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
optional("org.springframework.security:spring-security-web")
optional("org.springframework:spring-webmvc")
optional("org.springframework:spring-webflux")
optional("org.thymeleaf:thymeleaf")
optional("org.thymeleaf.extras:thymeleaf-extras-springsecurity6")
optional("com.github.mxab.thymeleaf.extras:thymeleaf-extras-data-attribute")
optional("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
optional("jakarta.servlet:jakarta.servlet-api")
testImplementation(project(":spring-boot-project:spring-boot-test"))
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
testRuntimeOnly("ch.qos.logback:logback-classic")
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.thymeleaf;
package org.springframework.boot.thymeleaf.autoconfigure;
import org.thymeleaf.ITemplateEngine;
import org.thymeleaf.dialect.IDialect;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.thymeleaf;
package org.springframework.boot.thymeleaf.autoconfigure;
import java.util.LinkedHashMap;
@ -40,12 +40,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingFilt
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.template.TemplateLocation;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties.Reactive;
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.thymeleaf.autoconfigure.ThymeleafProperties.Reactive;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@ -69,9 +67,10 @@ import org.springframework.web.servlet.view.AbstractCachingViewResolver;
* @author Daniel Fernández
* @author Kazuki Shimizu
* @author Artsiom Yudovin
* @since 1.0.0
* @since 4.0.0
*/
@AutoConfiguration(after = { WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
@AutoConfiguration(afterName = { "org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration",
"org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration" })
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@Import({ TemplateEngineConfigurations.ReactiveTemplateEngineConfiguration.class,

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.thymeleaf;
package org.springframework.boot.thymeleaf.autoconfigure;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@ -32,7 +32,7 @@ import org.springframework.util.unit.DataSize;
* @author Brian Clozel
* @author Daniel Fernández
* @author Kazuki Shimizu
* @since 1.2.0
* @since 4.0.0
*/
@ConfigurationProperties("spring.thymeleaf")
public class ThymeleafProperties {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.thymeleaf;
package org.springframework.boot.thymeleaf.autoconfigure;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
import org.springframework.core.env.Environment;
@ -27,7 +27,7 @@ import org.springframework.util.ClassUtils;
*
* @author Andy Wilkinson
* @author Madhura Bhave
* @since 1.1.0
* @since 4.0.0
*/
public class ThymeleafTemplateAvailabilityProvider implements TemplateAvailabilityProvider {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,4 +17,4 @@
/**
* Auto-configuration for Thymeleaf.
*/
package org.springframework.boot.autoconfigure.thymeleaf;
package org.springframework.boot.thymeleaf.autoconfigure;

View File

@ -0,0 +1,37 @@
{
"groups": [],
"properties": [
{
"name": "spring.thymeleaf.prefix",
"defaultValue": "classpath:/templates/"
},
{
"name": "spring.thymeleaf.reactive.media-types",
"defaultValue": [
"text/html",
"application/xhtml+xml",
"application/xml",
"text/xml",
"application/rss+xml",
"application/atom+xml",
"application/javascript",
"application/ecmascript",
"text/javascript",
"text/ecmascript",
"application/json",
"text/css",
"text/plain",
"text/event-stream"
]
},
{
"name": "spring.thymeleaf.suffix",
"defaultValue": ".html"
}
],
"hints": [],
"ignored": {
"properties": [
]
}
}

View File

@ -0,0 +1,3 @@
# Template Availability Providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.thymeleaf.autoconfigure.ThymeleafTemplateAvailabilityProvider

View File

@ -0,0 +1 @@
org.springframework.boot.thymeleaf.autoconfigure.ThymeleafAutoConfiguration

View File

@ -14,17 +14,21 @@
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.thymeleaf;
package org.springframework.boot.thymeleaf.autoconfigure;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Locale;
import nz.net.ultraq.thymeleaf.layoutdialect.LayoutDialect;
import nz.net.ultraq.thymeleaf.layoutdialect.decorators.strategies.GroupingStrategy;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.WebContext;
@ -42,7 +46,6 @@ import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.boot.testsupport.classpath.resources.WithResource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -61,12 +64,11 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Brian Clozel
* @author Kazuki Shimizu
* @author Stephane Nicoll
* @author Moritz Halbritter
*/
@ExtendWith(OutputCaptureExtension.class)
class ThymeleafReactiveAutoConfigurationTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ThymeleafAutoConfiguration.class));
@ -88,26 +90,27 @@ class ThymeleafReactiveAutoConfigurationTests {
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");
Assertions.assertThat(views.getDefaultCharset().name()).isEqualTo("UTF-16");
});
}
@Test
void defaultMediaTypes() {
this.contextRunner
.run((context) -> assertThat(context.getBean(ThymeleafReactiveViewResolver.class).getSupportedMediaTypes())
.containsExactly(MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML, MediaType.APPLICATION_XML,
MediaType.TEXT_XML, MediaType.APPLICATION_RSS_XML, MediaType.APPLICATION_ATOM_XML,
new MediaType("application", "javascript"), new MediaType("application", "ecmascript"),
new MediaType("text", "javascript"), new MediaType("text", "ecmascript"),
MediaType.APPLICATION_JSON, new MediaType("text", "css"), MediaType.TEXT_PLAIN,
MediaType.TEXT_EVENT_STREAM));
this.contextRunner.run((context) -> Assertions
.assertThat(context.getBean(ThymeleafReactiveViewResolver.class).getSupportedMediaTypes())
.containsExactly(MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML, MediaType.APPLICATION_XML,
MediaType.TEXT_XML, MediaType.APPLICATION_RSS_XML, MediaType.APPLICATION_ATOM_XML,
new MediaType("application", "javascript"), new MediaType("application", "ecmascript"),
new MediaType("text", "javascript"), new MediaType("text", "ecmascript"),
MediaType.APPLICATION_JSON, new MediaType("text", "css"), MediaType.TEXT_PLAIN,
MediaType.TEXT_EVENT_STREAM));
}
@Test
void overrideMediaTypes() {
this.contextRunner.withPropertyValues("spring.thymeleaf.reactive.media-types:text/html,text/plain")
.run((context) -> assertThat(context.getBean(ThymeleafReactiveViewResolver.class).getSupportedMediaTypes())
.run((context) -> Assertions
.assertThat(context.getBean(ThymeleafReactiveViewResolver.class).getSupportedMediaTypes())
.containsExactly(MediaType.TEXT_HTML, MediaType.TEXT_PLAIN));
}
@ -183,9 +186,10 @@ class ThymeleafReactiveAutoConfigurationTests {
}
@Test
void templateLocationEmpty(CapturedOutput output) {
new File(this.buildOutput.getTestResourcesLocation(), "empty-templates/empty-directory").mkdirs();
this.contextRunner.withPropertyValues("spring.thymeleaf.prefix:classpath:/empty-templates/empty-directory/")
void templateLocationEmpty(CapturedOutput output, @TempDir Path tempDir) throws IOException {
Path directory = tempDir.resolve("empty-templates/empty-directory").toAbsolutePath();
Files.createDirectories(directory);
this.contextRunner.withPropertyValues("spring.thymeleaf.prefix:file:" + directory)
.run((context) -> assertThat(output).doesNotContain("Cannot find template location"));
}

View File

@ -14,9 +14,11 @@
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.thymeleaf;
package org.springframework.boot.thymeleaf.autoconfigure;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Locale;
@ -26,8 +28,10 @@ import jakarta.servlet.DispatcherType;
import jakarta.servlet.ServletContext;
import nz.net.ultraq.thymeleaf.layoutdialect.LayoutDialect;
import nz.net.ultraq.thymeleaf.layoutdialect.decorators.strategies.GroupingStrategy;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.WebContext;
@ -45,7 +49,6 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.boot.testsupport.classpath.resources.WithResource;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
@ -74,12 +77,11 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Brian Clozel
* @author Kazuki Shimizu
* @author Artsiom Yudovin
* @author Moritz Halbritter
*/
@ExtendWith(OutputCaptureExtension.class)
class ThymeleafServletAutoConfigurationTests {
private final BuildOutput buildOutput = new BuildOutput(getClass());
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ThymeleafAutoConfiguration.class));
@ -179,9 +181,10 @@ class ThymeleafServletAutoConfigurationTests {
}
@Test
void templateLocationEmpty(CapturedOutput output) {
new File(this.buildOutput.getTestResourcesLocation(), "empty-templates/empty-directory").mkdirs();
this.contextRunner.withPropertyValues("spring.thymeleaf.prefix:classpath:/empty-templates/empty-directory/")
void templateLocationEmpty(CapturedOutput output, @TempDir Path tempDir) throws IOException {
Path directory = tempDir.resolve("empty-templates/empty-directory").toAbsolutePath();
Files.createDirectories(directory);
this.contextRunner.withPropertyValues("spring.thymeleaf.prefix:file:" + directory)
.run((context) -> assertThat(output).doesNotContain("Cannot find template location"));
}
@ -354,7 +357,7 @@ class ThymeleafServletAutoConfigurationTests {
@Test
void cachingCanBeDisabled() {
this.contextRunner.withPropertyValues("spring.thymeleaf.cache:false").run((context) -> {
assertThat(context.getBean(ThymeleafViewResolver.class).isCache()).isFalse();
Assertions.assertThat(context.getBean(ThymeleafViewResolver.class).isCache()).isFalse();
SpringResourceTemplateResolver templateResolver = context.getBean(SpringResourceTemplateResolver.class);
assertThat(templateResolver.isCacheable()).isFalse();
});

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.thymeleaf;
package org.springframework.boot.thymeleaf.autoconfigure;
import org.junit.jupiter.api.Test;