Polish FreeMarker macro support in spring-webflux

See gh-23002
This commit is contained in:
Sam Brannen 2019-06-10 16:08:04 +03:00
parent ac28de0dc1
commit 2f640fe205
8 changed files with 234 additions and 130 deletions

View File

@ -10,14 +10,15 @@
* all macros within it available to any application using Spring's
* FreeMarkerConfigurer.
*
* To take advantage of these macros, the "exposeSpringMacroHelpers" property
* of the FreeMarker class needs to be set to "true". This will expose a
* RequestContext under the name "springMacroRequestContext", as needed by
* the macros in this library.
* To take advantage of these macros, the "requestContextAttribute" property of
* the FreeMarkerView class must be set to "springMacroRequestContext". This will
* expose a RequestContext under the name "springMacroRequestContext", as needed
* by the macros in this library.
*
* @author Darren Davison
* @author Juergen Hoeller
* @author Issam El-atif
* @author Sam Brannen
* @since 5.2
-->
@ -71,7 +72,7 @@
* RequestContext. This can be customized by calling "setDefaultHtmlEscape"
* on the "springMacroRequestContext" context variable, or via the
* "defaultHtmlEscape" context-param in web.xml (same as for the JSP bind tag).
* Also regards a "htmlEscape" variable in the namespace of this library.
* Also regards an "htmlEscape" variable in the namespace of this library.
*
* Producing no output, the following context variable will be available
* each time this macro is referenced (assuming you import this library in
@ -173,8 +174,7 @@
-->
<#macro formTextarea path attributes="">
<@bind path/>
<textarea id="${status.expression?replace('[','')?replace(']','')}" name="${status.expression}" ${attributes?no_esc}>
${stringStatusValue}</textarea>
<textarea id="${status.expression?replace('[','')?replace(']','')}" name="${status.expression}" ${attributes?no_esc}>${stringStatusValue}</textarea>
</#macro>
<#--
@ -320,10 +320,10 @@ ${stringStatusValue}</textarea>
*
* @param value the current value in a list iteration
-->
<#macro checkSelected value>
<#if stringStatusValue?is_number && stringStatusValue == value?number>selected="selected"</#if>
<#if stringStatusValue?is_string && stringStatusValue == value>selected="selected"</#if>
</#macro>
<#macro checkSelected value><#--
--><#if stringStatusValue?is_number && stringStatusValue == value?number> selected="selected"</#if><#--
--><#if stringStatusValue?is_string && stringStatusValue == value> selected="selected"</#if><#--
--></#macro>
<#--
* contains

View File

@ -25,12 +25,12 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriTemplate;
/**
* Dummy request context used for VTL and FTL macro tests.
* Dummy request context used for FreeMarker macro tests.
*
* @author Darren Davison
* @author Juergen Hoeller
* @author Issam El-atif
*
* @since 5.2
* @see org.springframework.web.reactive.result.view.RequestContext
*/
public class DummyMacroRequestContext {
@ -115,14 +115,14 @@ public class DummyMacroRequestContext {
* @see org.springframework.web.reactive.result.view.RequestContext#getBindStatus(String)
*/
public BindStatus getBindStatus(String path) throws IllegalStateException {
return new BindStatus(new RequestContext(this.exchange, this.model, this.context), path, false);
return getBindStatus(path, false);
}
/**
* @see org.springframework.web.reactive.result.view.RequestContext#getBindStatus(String, boolean)
*/
public BindStatus getBindStatus(String path, boolean htmlEscape) throws IllegalStateException {
return new BindStatus(new RequestContext(this.exchange, this.model, this.context), path, true);
return new BindStatus(new RequestContext(this.exchange, this.model, this.context), path, htmlEscape);
}
}

View File

@ -16,7 +16,6 @@
package org.springframework.web.reactive.result.view.freemarker;
import java.io.IOException;
import java.util.HashMap;
import java.util.Properties;
@ -24,13 +23,9 @@ import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@ -43,34 +38,34 @@ import static org.assertj.core.api.Assertions.assertThatIOException;
/**
* @author Juergen Hoeller
* @author Issam El-atif
* @author Sam Brannen
* @since 5.2
*/
public class FreeMarkerConfigurerTests {
private final FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
@Test
public void freeMarkerConfigurerDefaultEncoding() throws IOException, TemplateException {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.afterPropertiesSet();
Configuration cfg = configurer.getConfiguration();
public void freeMarkerConfigurerDefaultEncoding() throws Exception {
freeMarkerConfigurer.afterPropertiesSet();
Configuration cfg = freeMarkerConfigurer.getConfiguration();
assertThat(cfg.getDefaultEncoding()).isEqualTo("UTF-8");
}
@Test
public void freeMarkerConfigurerWithConfigLocation() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setConfigLocation(new FileSystemResource("myprops.properties"));
freeMarkerConfigurer.setConfigLocation(new FileSystemResource("myprops.properties"));
Properties props = new Properties();
props.setProperty("myprop", "/mydir");
configurer.setFreemarkerSettings(props);
assertThatIOException().isThrownBy(
configurer::afterPropertiesSet);
freeMarkerConfigurer.setFreemarkerSettings(props);
assertThatIOException().isThrownBy(freeMarkerConfigurer::afterPropertiesSet);
}
@Test
public void freeMarkerConfigurerWithResourceLoaderPath() throws Exception {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("file:/mydir");
configurer.afterPropertiesSet();
Configuration cfg = configurer.getConfiguration();
freeMarkerConfigurer.setTemplateLoaderPath("file:/mydir");
freeMarkerConfigurer.afterPropertiesSet();
Configuration cfg = freeMarkerConfigurer.getConfiguration();
assertThat(cfg.getTemplateLoader()).isInstanceOf(MultiTemplateLoader.class);
MultiTemplateLoader multiTemplateLoader = (MultiTemplateLoader)cfg.getTemplateLoader();
assertThat(multiTemplateLoader.getTemplateLoader(0)).isInstanceOf(SpringTemplateLoader.class);
@ -80,12 +75,11 @@ public class FreeMarkerConfigurerTests {
@Test
@SuppressWarnings("rawtypes")
public void freeMarkerConfigurerWithNonFileResourceLoaderPath() throws Exception {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("file:/mydir");
freeMarkerConfigurer.setTemplateLoaderPath("file:/mydir");
Properties settings = new Properties();
settings.setProperty("localized_lookup", "false");
configurer.setFreemarkerSettings(settings);
configurer.setResourceLoader(new ResourceLoader() {
freeMarkerConfigurer.setFreemarkerSettings(settings);
freeMarkerConfigurer.setResourceLoader(new ResourceLoader() {
@Override
public Resource getResource(String location) {
if (!("file:/mydir".equals(location) || "file:/mydir/test".equals(location))) {
@ -98,23 +92,11 @@ public class FreeMarkerConfigurerTests {
return getClass().getClassLoader();
}
});
configurer.afterPropertiesSet();
assertThat(configurer.getConfiguration()).isInstanceOf(Configuration.class);
Configuration fc = configurer.getConfiguration();
freeMarkerConfigurer.afterPropertiesSet();
assertThat(freeMarkerConfigurer.getConfiguration()).isInstanceOf(Configuration.class);
Configuration fc = freeMarkerConfigurer.getConfiguration();
Template ft = fc.getTemplate("test");
assertThat(FreeMarkerTemplateUtils.processTemplateIntoString(ft, new HashMap())).isEqualTo("test");
}
@Test // SPR-12448
public void freeMarkerConfigurationAsBean() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition loaderDef = new RootBeanDefinition(SpringTemplateLoader.class);
loaderDef.getConstructorArgumentValues().addGenericArgumentValue(new DefaultResourceLoader());
loaderDef.getConstructorArgumentValues().addGenericArgumentValue("/freemarker");
RootBeanDefinition configDef = new RootBeanDefinition(Configuration.class);
configDef.getPropertyValues().add("templateLoader", loaderDef);
beanFactory.registerBeanDefinition("freeMarkerConfig", configDef);
beanFactory.getBean(Configuration.class);
}
}

View File

@ -17,17 +17,22 @@
package org.springframework.web.reactive.result.view.freemarker;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import freemarker.template.Configuration;
import org.junit.Before;
import org.junit.Test;
import reactor.core.publisher.Mono;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.web.test.server.MockServerWebExchange;
import org.springframework.tests.sample.beans.TestBean;
@ -35,150 +40,260 @@ import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.ModelMap;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.reactive.result.view.BindStatus;
import org.springframework.web.reactive.result.view.DummyMacroRequestContext;
import org.springframework.web.reactive.result.view.RequestContext;
import org.springframework.web.server.ServerWebExchange;
import static java.util.Collections.singletonMap;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Darren Davison
* @author Juergen Hoeller
* @author Issam El-atif
* @author Sam Brannen
* @since 5.2
*/
public class FreeMarkerMacroTests {
private MockServerWebExchange exchange;
private static final String SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE = "springMacroRequestContext";
private static final String TEMPLATE_FILE = "test-macro.ftl";
private final MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/path"));
private Configuration freeMarkerConfig;
@Before
public void setUp() throws Exception {
this.exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/path"));
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPaths("classpath:/", "file://" + System.getProperty("java.io.tmpdir"));
this.freeMarkerConfig = configurer.createConfiguration();
}
@Test
public void testName() throws Exception {
assertThat(getMacroOutput("NAME")).isEqualTo("Darren");
public void exposeRequestContextAsModelAttribute() throws Exception {
storeTemplateInTempDir("<@spring.bind \"testBean.name\"/>\nHi ${spring.status.value}");
FreeMarkerView view = new FreeMarkerView() {
@Override
protected Mono<Void> renderInternal(Map<String, Object> renderAttributes,
MediaType contentType, ServerWebExchange exchange) {
Object value = renderAttributes.get(SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE);
assertThat(value).isInstanceOf(RequestContext.class);
BindStatus status = ((RequestContext) value).getBindStatus("testBean.name");
assertThat(status.getExpression()).isEqualTo("name");
assertThat(status.getValue()).isEqualTo("Dilbert");
return super.renderInternal(renderAttributes, contentType, exchange);
}
};
StaticWebApplicationContext wac = new StaticWebApplicationContext();
wac.refresh();
view.setApplicationContext(wac);
view.setRequestContextAttribute(SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE);
view.setBeanName("myView");
view.setUrl("tmp.ftl");
view.setConfiguration(this.freeMarkerConfig);
view.render(singletonMap("testBean", new TestBean("Dilbert", 99)), null, this.exchange).subscribe();
assertThat(getOutput()).containsExactly("Hi Dilbert");
}
@Test
public void testAge() throws Exception {
assertThat(getMacroOutput("AGE")).isEqualTo("99");
public void name() throws Exception {
assertThat(getMacroOutput("NAME")).containsExactly("Darren");
}
@Test
public void testMessage() throws Exception {
assertThat(getMacroOutput("MESSAGE")).isEqualTo("Howdy Mundo");
public void age() throws Exception {
assertThat(getMacroOutput("AGE")).containsExactly("99");
}
@Test
public void testDefaultMessage() throws Exception {
assertThat(getMacroOutput("DEFAULTMESSAGE")).isEqualTo("hi planet");
public void message() throws Exception {
assertThat(getMacroOutput("MESSAGE")).containsExactly("Howdy Mundo");
}
@Test
public void testMessageArgs() throws Exception {
assertThat(getMacroOutput("MESSAGEARGS")).isEqualTo("Howdy[World]");
public void defaultMessage() throws Exception {
assertThat(getMacroOutput("DEFAULTMESSAGE")).containsExactly("hi planet");
}
@Test
public void testMessageArgsWithDefaultMessage() throws Exception {
assertThat(getMacroOutput("MESSAGEARGSWITHDEFAULTMESSAGE")).isEqualTo("Hi");
public void messageArgs() throws Exception {
assertThat(getMacroOutput("MESSAGEARGS")).containsExactly("Howdy[World]");
}
@Test
public void testUrl() throws Exception {
assertThat(getMacroOutput("URL")).isEqualTo("/springtest/aftercontext.html");
public void messageArgsWithDefaultMessage() throws Exception {
assertThat(getMacroOutput("MESSAGEARGSWITHDEFAULTMESSAGE")).containsExactly("Hi");
}
@Test
public void testUrlParams() throws Exception {
assertThat(getMacroOutput("URLPARAMS")).isEqualTo("/springtest/aftercontext/bar?spam=bucket");
public void url() throws Exception {
assertThat(getMacroOutput("URL")).containsExactly("/springtest/aftercontext.html");
}
@Test
public void testForm1() throws Exception {
assertThat(getMacroOutput("FORM1")).isEqualTo("<input type=\"text\" id=\"name\" name=\"name\" value=\"Darren\" >");
public void urlParams() throws Exception {
assertThat(getMacroOutput("URLPARAMS")).containsExactly(
"/springtest/aftercontext/bar?spam=bucket");
}
@Test
public void testForm2() throws Exception {
assertThat(getMacroOutput("FORM2")).isEqualTo("<input type=\"text\" id=\"name\" name=\"name\" value=\"Darren\" class=\"myCssClass\" >");
public void formInput() throws Exception {
assertThat(getMacroOutput("FORM1")).containsExactly(
"<input type=\"text\" id=\"name\" name=\"name\" value=\"Darren\" >");
}
@Test
public void testForm3() throws Exception {
assertThat(getMacroOutput("FORM3")).isEqualTo("<textarea id=\"name\" name=\"name\" >\nDarren</textarea>");
public void formInputWithCss() throws Exception {
assertThat(getMacroOutput("FORM2")).containsExactly(
"<input type=\"text\" id=\"name\" name=\"name\" value=\"Darren\" class=\"myCssClass\" >");
}
@Test
public void testForm4() throws Exception {
assertThat(getMacroOutput("FORM4")).isEqualTo("<textarea id=\"name\" name=\"name\" rows=10 cols=30>\nDarren</textarea>");
public void formTextarea() throws Exception {
assertThat(getMacroOutput("FORM3")).containsExactly(
"<textarea id=\"name\" name=\"name\" >Darren</textarea>");
}
@Test
public void testForm9() throws Exception {
assertThat(getMacroOutput("FORM9")).isEqualTo("<input type=\"password\" id=\"name\" name=\"name\" value=\"\" >");
public void formTextareaWithCustomRowsAndColumns() throws Exception {
assertThat(getMacroOutput("FORM4")).containsExactly(
"<textarea id=\"name\" name=\"name\" rows=10 cols=30>Darren</textarea>");
}
@Test
public void testForm10() throws Exception {
assertThat(getMacroOutput("FORM10")).isEqualTo("<input type=\"hidden\" id=\"name\" name=\"name\" value=\"Darren\" >");
public void formSingleSelectFromMap() throws Exception {
assertThat(getMacroOutput("FORM5")).containsExactly(
"<select id=\"name\" name=\"name\" >", //
"<option value=\"Rob&amp;Harrop\">Rob Harrop</option>", //
"<option value=\"John\">John Doe</option>", //
"<option value=\"Fred\">Fred Bloggs</option>", //
"<option value=\"Darren\" selected=\"selected\">Darren Davison</option>", //
"</select>");
}
@Test
public void testForm11() throws Exception {
assertThat(getMacroOutput("FORM11")).isEqualTo("<input type=\"text\" id=\"name\" name=\"name\" value=\"Darren\" >");
public void formSingleSelectFromList() throws Exception {
assertThat(getMacroOutput("FORM14")).containsExactly(
"<select id=\"name\" name=\"name\" >", //
"<option value=\"Rob Harrop\">Rob Harrop</option>", //
"<option value=\"Darren Davison\">Darren Davison</option>", //
"<option value=\"John Doe\">John Doe</option>", //
"<option value=\"Fred Bloggs\">Fred Bloggs</option>", //
"</select>");
}
@Test
public void testForm12() throws Exception {
assertThat(getMacroOutput("FORM12")).isEqualTo("<input type=\"hidden\" id=\"name\" name=\"name\" value=\"Darren\" >");
public void formMultiSelect() throws Exception {
assertThat(getMacroOutput("FORM6")).containsExactly(
"<select multiple=\"multiple\" id=\"spouses\" name=\"spouses\" >", //
"<option value=\"Rob&amp;Harrop\">Rob Harrop</option>", //
"<option value=\"John\">John Doe</option>", //
"<option value=\"Fred\" selected=\"selected\">Fred Bloggs</option>", //
"<option value=\"Darren\">Darren Davison</option>", //
"</select>");
}
@Test
public void testForm13() throws Exception {
assertThat(getMacroOutput("FORM13")).isEqualTo("<input type=\"password\" id=\"name\" name=\"name\" value=\"\" >");
public void formRadioButtons() throws Exception {
assertThat(getMacroOutput("FORM7")).containsExactly(
"<input type=\"radio\" id=\"name0\" name=\"name\" value=\"Rob&amp;Harrop\" >", //
"<label for=\"name0\">Rob Harrop</label>", //
"<input type=\"radio\" id=\"name1\" name=\"name\" value=\"John\" >", //
"<label for=\"name1\">John Doe</label>", //
"<input type=\"radio\" id=\"name2\" name=\"name\" value=\"Fred\" >", //
"<label for=\"name2\">Fred Bloggs</label>", //
"<input type=\"radio\" id=\"name3\" name=\"name\" value=\"Darren\" checked=\"checked\" >", //
"<label for=\"name3\">Darren Davison</label>");
}
@Test
public void testForm15() throws Exception {
String output = getMacroOutput("FORM15");
assertThat(output.startsWith("<input type=\"hidden\" name=\"_name\" value=\"on\"/>")).as("Wrong output: " + output).isTrue();
assertThat(output.contains("<input type=\"checkbox\" id=\"name\" name=\"name\" />")).as("Wrong output: " + output).isTrue();
public void formCheckboxForStringProperty() throws Exception {
assertThat(getMacroOutput("FORM15")).containsExactly(
"<input type=\"hidden\" name=\"_name\" value=\"on\"/>",
"<input type=\"checkbox\" id=\"name\" name=\"name\" />");
}
@Test
public void testForm16() throws Exception {
String output = getMacroOutput("FORM16");
assertThat(output.startsWith(
"<input type=\"hidden\" name=\"_jedi\" value=\"on\"/>")).as("Wrong output: " + output).isTrue();
assertThat(output.contains(
"<input type=\"checkbox\" id=\"jedi\" name=\"jedi\" checked=\"checked\" />")).as("Wrong output: " + output).isTrue();
public void formCheckboxForBooleanProperty() throws Exception {
assertThat(getMacroOutput("FORM16")).containsExactly(
"<input type=\"hidden\" name=\"_jedi\" value=\"on\"/>",
"<input type=\"checkbox\" id=\"jedi\" name=\"jedi\" checked=\"checked\" />");
}
@Test
public void testForm17() throws Exception {
assertThat(getMacroOutput("FORM17")).isEqualTo("<input type=\"text\" id=\"spouses0.name\" name=\"spouses[0].name\" value=\"Fred\" >");
public void formCheckboxForNestedPath() throws Exception {
assertThat(getMacroOutput("FORM18")).containsExactly(
"<input type=\"hidden\" name=\"_spouses[0].jedi\" value=\"on\"/>",
"<input type=\"checkbox\" id=\"spouses0.jedi\" name=\"spouses[0].jedi\" checked=\"checked\" />");
}
@Test
public void testForm18() throws Exception {
String output = getMacroOutput("FORM18");
assertThat(output.startsWith(
"<input type=\"hidden\" name=\"_spouses[0].jedi\" value=\"on\"/>")).as("Wrong output: " + output).isTrue();
assertThat(output.contains(
"<input type=\"checkbox\" id=\"spouses0.jedi\" name=\"spouses[0].jedi\" checked=\"checked\" />")).as("Wrong output: " + output).isTrue();
public void formCheckboxForStringArray() throws Exception {
assertThat(getMacroOutput("FORM8")).containsExactly(
"<input type=\"checkbox\" id=\"stringArray0\" name=\"stringArray\" value=\"Rob&amp;Harrop\" >", //
"<label for=\"stringArray0\">Rob Harrop</label>", //
"<input type=\"checkbox\" id=\"stringArray1\" name=\"stringArray\" value=\"John\" checked=\"checked\" >", //
"<label for=\"stringArray1\">John Doe</label>", //
"<input type=\"checkbox\" id=\"stringArray2\" name=\"stringArray\" value=\"Fred\" checked=\"checked\" >", //
"<label for=\"stringArray2\">Fred Bloggs</label>", //
"<input type=\"checkbox\" id=\"stringArray3\" name=\"stringArray\" value=\"Darren\" >", //
"<label for=\"stringArray3\">Darren Davison</label>", //
"<input type=\"hidden\" name=\"_stringArray\" value=\"on\"/>");
}
private String getMacroOutput(String name) throws Exception {
@Test
public void formPasswordInput() throws Exception {
assertThat(getMacroOutput("FORM9")).containsExactly(
"<input type=\"password\" id=\"name\" name=\"name\" value=\"\" >");
}
@Test
public void formHiddenInput() throws Exception {
assertThat(getMacroOutput("FORM10")).containsExactly(
"<input type=\"hidden\" id=\"name\" name=\"name\" value=\"Darren\" >");
}
@Test
public void formInputText() throws Exception {
assertThat(getMacroOutput("FORM11")).containsExactly(
"<input type=\"text\" id=\"name\" name=\"name\" value=\"Darren\" >");
}
@Test
public void formInputHidden() throws Exception {
assertThat(getMacroOutput("FORM12")).containsExactly(
"<input type=\"hidden\" id=\"name\" name=\"name\" value=\"Darren\" >");
}
@Test
public void formInputPassword() throws Exception {
assertThat(getMacroOutput("FORM13")).containsExactly(
"<input type=\"password\" id=\"name\" name=\"name\" value=\"\" >");
}
@Test
public void forInputWithNestedPath() throws Exception {
assertThat(getMacroOutput("FORM17")).containsExactly(
"<input type=\"text\" id=\"spouses0.name\" name=\"spouses[0].name\" value=\"Fred\" >");
}
private List<String> getMacroOutput(String name) throws Exception {
String macro = fetchMacro(name);
assertThat(macro).isNotNull();
FileSystemResource resource = new FileSystemResource(System.getProperty("java.io.tmpdir") + "/tmp.ftl");
FileCopyUtils.copy("<#import \"spring.ftl\" as spring />\n" + macro, new FileWriter(resource.getPath()));
storeTemplateInTempDir(macro);
Map<String, String> msgMap = new HashMap<>();
msgMap.put("hello", "Howdy");
@ -189,7 +304,7 @@ public class FreeMarkerMacroTests {
fred.setJedi(true);
darren.setSpouse(fred);
darren.setJedi(true);
darren.setStringArray(new String[] {"John", "Fred"});
darren.setStringArray(new String[] { "John", "Fred" });
Map<String, String> names = new HashMap<>();
names.put("Darren", "Darren Davison");
@ -198,7 +313,8 @@ public class FreeMarkerMacroTests {
names.put("Rob&Harrop", "Rob Harrop");
ModelMap model = new ExtendedModelMap();
DummyMacroRequestContext rc = new DummyMacroRequestContext(this.exchange, model, new GenericApplicationContext());
DummyMacroRequestContext rc = new DummyMacroRequestContext(this.exchange, model,
new GenericApplicationContext());
rc.setMessageMap(msgMap);
rc.setContextPath("/springtest");
@ -215,14 +331,11 @@ public class FreeMarkerMacroTests {
view.render(model, null, this.exchange).subscribe();
// tokenize output and ignore whitespace
String output = this.exchange.getResponse().getBodyAsString().block();
output = output.replace("\r\n", "\n");
return output.trim();
return getOutput();
}
private String fetchMacro(String name) throws Exception {
ClassPathResource resource = new ClassPathResource("test-macro.ftl", getClass());
ClassPathResource resource = new ClassPathResource(TEMPLATE_FILE, getClass());
assertThat(resource.exists()).isTrue();
String all = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream()));
all = all.replace("\r\n", "\n");
@ -235,4 +348,15 @@ public class FreeMarkerMacroTests {
return null;
}
private void storeTemplateInTempDir(String macro) throws IOException {
FileSystemResource resource = new FileSystemResource(System.getProperty("java.io.tmpdir") + "/tmp.ftl");
FileCopyUtils.copy("<#import \"spring.ftl\" as spring />\n" + macro, new FileWriter(resource.getPath()));
}
private List<String> getOutput() {
String output = this.exchange.getResponse().getBodyAsString().block();
String[] lines = output.replace("\r\n", "\n").replaceAll(" +"," ").split("\n");
return Arrays.stream(lines).map(String::trim).filter(line -> !line.isEmpty()).collect(toList());
}
}

View File

@ -1,5 +1,5 @@
<#--
test template for FreeMarker macro test class
test template for FreeMarker macro support
-->
<#import "spring.ftl" as spring />
@ -79,4 +79,4 @@ FORM17
<@spring.formInput "command.spouses[0].name", ""/>
FORM18
<@spring.formCheckbox "command.spouses[0].jedi" />
<@spring.formCheckbox "command.spouses[0].jedi" />

View File

@ -25,7 +25,7 @@ import org.springframework.web.servlet.support.RequestContext;
import org.springframework.web.util.UriTemplate;
/**
* Dummy request context used for VTL and FTL macro tests.
* Dummy request context used for FreeMarker macro tests.
*
* @author Darren Davison
* @author Juergen Hoeller
@ -34,7 +34,7 @@ import org.springframework.web.util.UriTemplate;
*/
public class DummyMacroRequestContext {
private HttpServletRequest request;
private final HttpServletRequest request;
private Map<String, String> messageMap;
@ -147,14 +147,14 @@ public class DummyMacroRequestContext {
* @see org.springframework.web.servlet.support.RequestContext#getBindStatus(String)
*/
public BindStatus getBindStatus(String path) throws IllegalStateException {
return new BindStatus(new RequestContext(this.request), path, false);
return getBindStatus(path, false);
}
/**
* @see org.springframework.web.servlet.support.RequestContext#getBindStatus(String, boolean)
*/
public BindStatus getBindStatus(String path, boolean htmlEscape) throws IllegalStateException {
return new BindStatus(new RequestContext(this.request), path, true);
return new BindStatus(new RequestContext(this.request), path, htmlEscape);
}
}

View File

@ -45,7 +45,7 @@ public class FreeMarkerConfigurerTests {
private final FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
@Test
public void freeMarkerConfigurerWithConfigLocation() throws Exception {
public void freeMarkerConfigurerWithConfigLocation() {
freeMarkerConfigurer.setConfigLocation(new FileSystemResource("myprops.properties"));
Properties props = new Properties();
props.setProperty("myprop", "/mydir");

View File

@ -98,8 +98,7 @@ public class FreeMarkerMacroTests {
protected void processTemplate(Template template, SimpleHash fmModel, HttpServletResponse response)
throws TemplateException {
Map model = fmModel.toMap();
boolean condition = model.get(FreeMarkerView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE) instanceof RequestContext;
assertThat(condition).isTrue();
assertThat(model.get(FreeMarkerView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE)).isInstanceOf(RequestContext.class);
RequestContext rc = (RequestContext) model.get(FreeMarkerView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE);
BindStatus status = rc.getBindStatus("tb.name");
assertThat(status.getExpression()).isEqualTo("name");
@ -136,9 +135,8 @@ public class FreeMarkerMacroTests {
fv.render(model, request, response);
}
catch (Exception ex) {
boolean condition = ex instanceof ServletException;
assertThat(condition).isTrue();
assertThat(ex.getMessage().contains(FreeMarkerView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE)).isTrue();
assertThat(ex).isInstanceOf(ServletException.class);
assertThat(ex.getMessage()).contains(FreeMarkerView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE);
}
}
@ -222,7 +220,7 @@ public class FreeMarkerMacroTests {
assertThat(getMacroOutput("FORM4")).isEqualTo("<textarea id=\"name\" name=\"name\" rows=10 cols=30>\nDarren</textarea>");
}
// TODO verify remaining output (fix whitespace)
// TODO verify remaining output for forms 5, 6, 7, 8, and 14 (fix whitespace)
@Test
public void testForm9() throws Exception {