|
22 | 22 |
|
23 | 23 | import nz.net.ultraq.thymeleaf.LayoutDialect;
|
24 | 24 | import nz.net.ultraq.thymeleaf.decorators.strategies.GroupingStrategy;
|
25 |
| -import org.junit.After; |
26 | 25 | import org.junit.Rule;
|
27 | 26 | import org.junit.Test;
|
28 | 27 | import org.thymeleaf.TemplateEngine;
|
|
36 | 35 | import org.thymeleaf.spring5.view.reactive.ThymeleafReactiveViewResolver;
|
37 | 36 | import org.thymeleaf.templateresolver.ITemplateResolver;
|
38 | 37 |
|
39 |
| -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; |
40 |
| -import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; |
| 38 | +import org.springframework.boot.autoconfigure.AutoConfigurations; |
| 39 | +import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; |
41 | 40 | import org.springframework.boot.test.rule.OutputCapture;
|
42 |
| -import org.springframework.boot.test.util.TestPropertyValues; |
43 |
| -import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext; |
44 | 41 | import org.springframework.context.annotation.Bean;
|
45 | 42 | import org.springframework.context.annotation.Configuration;
|
46 |
| -import org.springframework.context.annotation.Import; |
47 | 43 | import org.springframework.http.MediaType;
|
48 | 44 | import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
49 | 45 | import org.springframework.mock.web.server.MockServerWebExchange;
|
|
60 | 56 | *
|
61 | 57 | * @author Brian Clozel
|
62 | 58 | * @author Kazuki Shimizu
|
| 59 | + * @author Stephane Nicoll |
63 | 60 | */
|
64 | 61 | public class ThymeleafReactiveAutoConfigurationTests {
|
65 | 62 |
|
66 | 63 | @Rule
|
67 | 64 | public OutputCapture output = new OutputCapture();
|
68 | 65 |
|
69 |
| - private AnnotationConfigReactiveWebApplicationContext context; |
70 |
| - |
71 |
| - @After |
72 |
| - public void close() { |
73 |
| - if (this.context != null) { |
74 |
| - this.context.close(); |
75 |
| - } |
76 |
| - } |
| 66 | + private ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner() |
| 67 | + .withConfiguration(AutoConfigurations.of(ThymeleafAutoConfiguration.class)); |
77 | 68 |
|
78 | 69 | @Test
|
79 | 70 | public void createFromConfigClass() {
|
80 |
| - load(BaseConfiguration.class, "spring.thymeleaf.suffix:.html"); |
81 |
| - TemplateEngine engine = this.context.getBean(TemplateEngine.class); |
82 |
| - Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); |
83 |
| - String result = engine.process("template", attrs); |
84 |
| - assertThat(result).isEqualTo("<html>bar</html>"); |
| 71 | + this.contextRunner.withPropertyValues("spring.thymeleaf.suffix:.html") |
| 72 | + .run((context) -> { |
| 73 | + TemplateEngine engine = context.getBean(TemplateEngine.class); |
| 74 | + Context attrs = new Context(Locale.UK, |
| 75 | + Collections.singletonMap("foo", "bar")); |
| 76 | + String result = engine.process("template", attrs); |
| 77 | + assertThat(result).isEqualTo("<html>bar</html>"); |
| 78 | + }); |
85 | 79 | }
|
86 | 80 |
|
87 | 81 | @Test
|
88 | 82 | public void overrideCharacterEncoding() {
|
89 |
| - load(BaseConfiguration.class, "spring.thymeleaf.encoding:UTF-16"); |
90 |
| - ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class); |
91 |
| - assertThat(resolver instanceof SpringResourceTemplateResolver).isTrue(); |
92 |
| - assertThat(((SpringResourceTemplateResolver) resolver).getCharacterEncoding()) |
93 |
| - .isEqualTo("UTF-16"); |
94 |
| - ThymeleafReactiveViewResolver views = this.context |
95 |
| - .getBean(ThymeleafReactiveViewResolver.class); |
96 |
| - assertThat(views.getDefaultCharset().name()).isEqualTo("UTF-16"); |
| 83 | + this.contextRunner.withPropertyValues("spring.thymeleaf.encoding:UTF-16") |
| 84 | + .run((context) -> { |
| 85 | + ITemplateResolver resolver = context.getBean(ITemplateResolver.class); |
| 86 | + assertThat(resolver) |
| 87 | + .isInstanceOf(SpringResourceTemplateResolver.class); |
| 88 | + assertThat(((SpringResourceTemplateResolver) resolver) |
| 89 | + .getCharacterEncoding()).isEqualTo("UTF-16"); |
| 90 | + ThymeleafReactiveViewResolver views = context |
| 91 | + .getBean(ThymeleafReactiveViewResolver.class); |
| 92 | + assertThat(views.getDefaultCharset().name()).isEqualTo("UTF-16"); |
| 93 | + }); |
97 | 94 | }
|
98 | 95 |
|
99 | 96 | @Test
|
100 | 97 | public void overrideMediaTypes() {
|
101 |
| - load(BaseConfiguration.class, |
102 |
| - "spring.thymeleaf.reactive.media-types:text/html,text/plain"); |
103 |
| - ThymeleafReactiveViewResolver views = this.context |
104 |
| - .getBean(ThymeleafReactiveViewResolver.class); |
105 |
| - assertThat(views.getSupportedMediaTypes()).contains(MediaType.TEXT_HTML, |
106 |
| - MediaType.TEXT_PLAIN); |
| 98 | + this.contextRunner |
| 99 | + .withPropertyValues( |
| 100 | + "spring.thymeleaf.reactive.media-types:text/html,text/plain") |
| 101 | + .run((context) -> assertThat( |
| 102 | + context.getBean(ThymeleafReactiveViewResolver.class) |
| 103 | + .getSupportedMediaTypes()).contains(MediaType.TEXT_HTML, |
| 104 | + MediaType.TEXT_PLAIN)); |
107 | 105 | }
|
108 | 106 |
|
109 | 107 | @Test
|
110 | 108 | public void overrideTemplateResolverOrder() {
|
111 |
| - load(BaseConfiguration.class, "spring.thymeleaf.templateResolverOrder:25"); |
112 |
| - ITemplateResolver resolver = this.context.getBean(ITemplateResolver.class); |
113 |
| - assertThat(resolver.getOrder()).isEqualTo(Integer.valueOf(25)); |
| 109 | + this.contextRunner.withPropertyValues("spring.thymeleaf.templateResolverOrder:25") |
| 110 | + .run((context) -> assertThat( |
| 111 | + context.getBean(ITemplateResolver.class).getOrder()) |
| 112 | + .isEqualTo(Integer.valueOf(25))); |
114 | 113 | }
|
115 | 114 |
|
116 | 115 | @Test
|
117 | 116 | public void overrideViewNames() {
|
118 |
| - load(BaseConfiguration.class, "spring.thymeleaf.viewNames:foo,bar"); |
119 |
| - ThymeleafReactiveViewResolver views = this.context |
120 |
| - .getBean(ThymeleafReactiveViewResolver.class); |
121 |
| - assertThat(views.getViewNames()).isEqualTo(new String[] { "foo", "bar" }); |
| 117 | + this.contextRunner.withPropertyValues("spring.thymeleaf.viewNames:foo,bar") |
| 118 | + .run((context) -> assertThat(context |
| 119 | + .getBean(ThymeleafReactiveViewResolver.class).getViewNames()) |
| 120 | + .isEqualTo(new String[] { "foo", "bar" })); |
122 | 121 | }
|
123 | 122 |
|
124 | 123 | @Test
|
125 | 124 | public void overrideMaxChunkSize() {
|
126 |
| - load(BaseConfiguration.class, "spring.thymeleaf.reactive.maxChunkSize:8KB"); |
127 |
| - ThymeleafReactiveViewResolver views = this.context |
128 |
| - .getBean(ThymeleafReactiveViewResolver.class); |
129 |
| - assertThat(views.getResponseMaxChunkSizeBytes()).isEqualTo(Integer.valueOf(8192)); |
| 125 | + this.contextRunner |
| 126 | + .withPropertyValues("spring.thymeleaf.reactive.maxChunkSize:8KB") |
| 127 | + .run((context) -> assertThat( |
| 128 | + context.getBean(ThymeleafReactiveViewResolver.class) |
| 129 | + .getResponseMaxChunkSizeBytes()) |
| 130 | + .isEqualTo(Integer.valueOf(8192))); |
130 | 131 | }
|
131 | 132 |
|
132 | 133 | @Test
|
133 | 134 | public void overrideFullModeViewNames() {
|
134 |
| - load(BaseConfiguration.class, |
135 |
| - "spring.thymeleaf.reactive.fullModeViewNames:foo,bar"); |
136 |
| - ThymeleafReactiveViewResolver views = this.context |
137 |
| - .getBean(ThymeleafReactiveViewResolver.class); |
138 |
| - assertThat(views.getFullModeViewNames()).isEqualTo(new String[] { "foo", "bar" }); |
| 135 | + this.contextRunner |
| 136 | + .withPropertyValues("spring.thymeleaf.reactive.fullModeViewNames:foo,bar") |
| 137 | + .run((context) -> assertThat( |
| 138 | + context.getBean(ThymeleafReactiveViewResolver.class) |
| 139 | + .getFullModeViewNames()) |
| 140 | + .isEqualTo(new String[] { "foo", "bar" })); |
139 | 141 | }
|
140 | 142 |
|
141 | 143 | @Test
|
142 | 144 | public void overrideChunkedModeViewNames() {
|
143 |
| - load(BaseConfiguration.class, |
144 |
| - "spring.thymeleaf.reactive.chunkedModeViewNames:foo,bar"); |
145 |
| - ThymeleafReactiveViewResolver views = this.context |
146 |
| - .getBean(ThymeleafReactiveViewResolver.class); |
147 |
| - assertThat(views.getChunkedModeViewNames()) |
148 |
| - .isEqualTo(new String[] { "foo", "bar" }); |
| 145 | + this.contextRunner |
| 146 | + .withPropertyValues( |
| 147 | + "spring.thymeleaf.reactive.chunkedModeViewNames:foo,bar") |
| 148 | + .run((context) -> assertThat( |
| 149 | + context.getBean(ThymeleafReactiveViewResolver.class) |
| 150 | + .getChunkedModeViewNames()) |
| 151 | + .isEqualTo(new String[] { "foo", "bar" })); |
149 | 152 | }
|
150 | 153 |
|
151 | 154 | @Test
|
152 | 155 | public void overrideEnableSpringElCompiler() {
|
153 |
| - load(BaseConfiguration.class, "spring.thymeleaf.enable-spring-el-compiler:true"); |
154 |
| - assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class) |
155 |
| - .getEnableSpringELCompiler()).isTrue(); |
| 156 | + this.contextRunner |
| 157 | + .withPropertyValues("spring.thymeleaf.enable-spring-el-compiler:true") |
| 158 | + .run((context) -> assertThat( |
| 159 | + context.getBean(SpringWebFluxTemplateEngine.class) |
| 160 | + .getEnableSpringELCompiler()).isTrue()); |
156 | 161 | }
|
157 | 162 |
|
158 | 163 | @Test
|
159 | 164 | public void enableSpringElCompilerIsDisabledByDefault() {
|
160 |
| - load(BaseConfiguration.class); |
161 |
| - assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class) |
162 |
| - .getEnableSpringELCompiler()).isFalse(); |
| 165 | + this.contextRunner.run( |
| 166 | + (context) -> assertThat(context.getBean(SpringWebFluxTemplateEngine.class) |
| 167 | + .getEnableSpringELCompiler()).isFalse()); |
163 | 168 | }
|
164 | 169 |
|
165 | 170 | @Test
|
166 | 171 | public void overrideRenderHiddenMarkersBeforeCheckboxes() {
|
167 |
| - load(BaseConfiguration.class, |
168 |
| - "spring.thymeleaf.render-hidden-markers-before-checkboxes:true"); |
169 |
| - assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class) |
170 |
| - .getRenderHiddenMarkersBeforeCheckboxes()).isTrue(); |
| 172 | + this.contextRunner |
| 173 | + .withPropertyValues( |
| 174 | + "spring.thymeleaf.render-hidden-markers-before-checkboxes:true") |
| 175 | + .run((context) -> assertThat( |
| 176 | + context.getBean(SpringWebFluxTemplateEngine.class) |
| 177 | + .getRenderHiddenMarkersBeforeCheckboxes()).isTrue()); |
171 | 178 | }
|
172 | 179 |
|
173 | 180 | @Test
|
174 | 181 | public void enableRenderHiddenMarkersBeforeCheckboxesIsDisabledByDefault() {
|
175 |
| - load(BaseConfiguration.class); |
176 |
| - assertThat(this.context.getBean(SpringWebFluxTemplateEngine.class) |
177 |
| - .getRenderHiddenMarkersBeforeCheckboxes()).isFalse(); |
| 182 | + this.contextRunner.run( |
| 183 | + (context) -> assertThat(context.getBean(SpringWebFluxTemplateEngine.class) |
| 184 | + .getRenderHiddenMarkersBeforeCheckboxes()).isFalse()); |
178 | 185 | }
|
179 | 186 |
|
180 | 187 | @Test
|
181 | 188 | public void templateLocationDoesNotExist() {
|
182 |
| - load(BaseConfiguration.class, |
183 |
| - "spring.thymeleaf.prefix:classpath:/no-such-directory/"); |
184 |
| - this.output.expect(containsString("Cannot find template location")); |
| 189 | + this.contextRunner |
| 190 | + .withPropertyValues( |
| 191 | + "spring.thymeleaf.prefix:classpath:/no-such-directory/") |
| 192 | + .run((context) -> this.output |
| 193 | + .expect(containsString("Cannot find template location"))); |
185 | 194 | }
|
186 | 195 |
|
187 | 196 | @Test
|
188 | 197 | public void templateLocationEmpty() {
|
189 | 198 | new File("target/test-classes/templates/empty-directory").mkdir();
|
190 |
| - load(BaseConfiguration.class, |
191 |
| - "spring.thymeleaf.prefix:classpath:/templates/empty-directory/"); |
192 |
| - this.output.expect(not(containsString("Cannot find template location"))); |
| 199 | + this.contextRunner |
| 200 | + .withPropertyValues( |
| 201 | + "spring.thymeleaf.prefix:classpath:/templates/empty-directory/") |
| 202 | + .run((context) -> this.output |
| 203 | + .expect(not(containsString("Cannot find template location")))); |
193 | 204 | }
|
194 | 205 |
|
195 | 206 | @Test
|
196 | 207 | public void useDataDialect() {
|
197 |
| - load(BaseConfiguration.class); |
198 |
| - ISpringWebFluxTemplateEngine engine = this.context |
199 |
| - .getBean(ISpringWebFluxTemplateEngine.class); |
200 |
| - Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); |
201 |
| - String result = engine.process("data-dialect", attrs); |
202 |
| - assertThat(result).isEqualTo("<html><body data-foo=\"bar\"></body></html>"); |
| 208 | + this.contextRunner.run((context) -> { |
| 209 | + ISpringWebFluxTemplateEngine engine = context |
| 210 | + .getBean(ISpringWebFluxTemplateEngine.class); |
| 211 | + Context attrs = new Context(Locale.UK, |
| 212 | + Collections.singletonMap("foo", "bar")); |
| 213 | + String result = engine.process("data-dialect", attrs); |
| 214 | + assertThat(result).isEqualTo("<html><body data-foo=\"bar\"></body></html>"); |
| 215 | + }); |
203 | 216 | }
|
204 | 217 |
|
205 | 218 | @Test
|
206 | 219 | public void useJava8TimeDialect() {
|
207 |
| - load(BaseConfiguration.class); |
208 |
| - ISpringWebFluxTemplateEngine engine = this.context |
209 |
| - .getBean(ISpringWebFluxTemplateEngine.class); |
210 |
| - Context attrs = new Context(Locale.UK); |
211 |
| - String result = engine.process("java8time-dialect", attrs); |
212 |
| - assertThat(result).isEqualTo("<html><body>2015-11-24</body></html>"); |
| 220 | + this.contextRunner.run((context) -> { |
| 221 | + ISpringWebFluxTemplateEngine engine = context |
| 222 | + .getBean(ISpringWebFluxTemplateEngine.class); |
| 223 | + Context attrs = new Context(Locale.UK); |
| 224 | + String result = engine.process("java8time-dialect", attrs); |
| 225 | + assertThat(result).isEqualTo("<html><body>2015-11-24</body></html>"); |
| 226 | + }); |
213 | 227 | }
|
214 | 228 |
|
215 | 229 | @Test
|
216 | 230 | public void useSecurityDialect() {
|
217 |
| - load(BaseConfiguration.class); |
218 |
| - ISpringWebFluxTemplateEngine engine = this.context |
219 |
| - .getBean(ISpringWebFluxTemplateEngine.class); |
220 |
| - MockServerWebExchange exchange = MockServerWebExchange |
221 |
| - .from(MockServerHttpRequest.get("/test").build()); |
222 |
| - exchange.getAttributes().put( |
223 |
| - SpringSecurityContextUtils.SECURITY_CONTEXT_MODEL_ATTRIBUTE_NAME, |
224 |
| - new SecurityContextImpl( |
225 |
| - new TestingAuthenticationToken("alice", "admin"))); |
226 |
| - IContext attrs = new SpringWebFluxContext(exchange); |
227 |
| - String result = engine.process("security-dialect", attrs); |
228 |
| - assertThat(result).isEqualTo( |
229 |
| - "<html><body><div>alice</div></body></html>" + System.lineSeparator()); |
| 231 | + this.contextRunner.run((context) -> { |
| 232 | + ISpringWebFluxTemplateEngine engine = context |
| 233 | + .getBean(ISpringWebFluxTemplateEngine.class); |
| 234 | + MockServerWebExchange exchange = MockServerWebExchange |
| 235 | + .from(MockServerHttpRequest.get("/test").build()); |
| 236 | + exchange.getAttributes().put( |
| 237 | + SpringSecurityContextUtils.SECURITY_CONTEXT_MODEL_ATTRIBUTE_NAME, |
| 238 | + new SecurityContextImpl( |
| 239 | + new TestingAuthenticationToken("alice", "admin"))); |
| 240 | + IContext attrs = new SpringWebFluxContext(exchange); |
| 241 | + String result = engine.process("security-dialect", attrs); |
| 242 | + assertThat(result).isEqualTo("<html><body><div>alice</div></body></html>" |
| 243 | + + System.lineSeparator()); |
| 244 | + }); |
230 | 245 | }
|
231 | 246 |
|
232 | 247 | @Test
|
233 | 248 | public void renderTemplate() {
|
234 |
| - load(BaseConfiguration.class); |
235 |
| - ISpringWebFluxTemplateEngine engine = this.context |
236 |
| - .getBean(ISpringWebFluxTemplateEngine.class); |
237 |
| - Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); |
238 |
| - String result = engine.process("home", attrs); |
239 |
| - assertThat(result).isEqualTo("<html><body>bar</body></html>"); |
| 249 | + this.contextRunner.run((context) -> { |
| 250 | + ISpringWebFluxTemplateEngine engine = context |
| 251 | + .getBean(ISpringWebFluxTemplateEngine.class); |
| 252 | + Context attrs = new Context(Locale.UK, |
| 253 | + Collections.singletonMap("foo", "bar")); |
| 254 | + String result = engine.process("home", attrs); |
| 255 | + assertThat(result).isEqualTo("<html><body>bar</body></html>"); |
| 256 | + }); |
240 | 257 | }
|
241 | 258 |
|
242 | 259 | @Test
|
243 | 260 | public void layoutDialectCanBeCustomized() {
|
244 |
| - load(LayoutDialectConfiguration.class); |
245 |
| - LayoutDialect layoutDialect = this.context.getBean(LayoutDialect.class); |
246 |
| - assertThat(ReflectionTestUtils.getField(layoutDialect, "sortingStrategy")) |
247 |
| - .isInstanceOf(GroupingStrategy.class); |
248 |
| - } |
249 |
| - |
250 |
| - private void load(Class<?> config, String... envVariables) { |
251 |
| - this.context = new AnnotationConfigReactiveWebApplicationContext(); |
252 |
| - TestPropertyValues.of(envVariables).applyTo(this.context); |
253 |
| - if (config != null) { |
254 |
| - this.context.register(config); |
255 |
| - } |
256 |
| - this.context.register(config); |
257 |
| - this.context.refresh(); |
258 |
| - } |
259 |
| - |
260 |
| - @Configuration |
261 |
| - @ImportAutoConfiguration({ ThymeleafAutoConfiguration.class, |
262 |
| - PropertyPlaceholderAutoConfiguration.class }) |
263 |
| - protected static class BaseConfiguration { |
264 |
| - |
| 261 | + this.contextRunner.withUserConfiguration(LayoutDialectConfiguration.class) |
| 262 | + .run((context) -> assertThat(ReflectionTestUtils.getField( |
| 263 | + context.getBean(LayoutDialect.class), "sortingStrategy")) |
| 264 | + .isInstanceOf(GroupingStrategy.class)); |
265 | 265 | }
|
266 | 266 |
|
267 | 267 | @Configuration
|
268 |
| - @Import(BaseConfiguration.class) |
269 | 268 | static class LayoutDialectConfiguration {
|
270 | 269 |
|
271 | 270 | @Bean
|
|
0 commit comments