mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Support response encoding in select and options JSP form tags
Prior to this commit, Spring Framework's JSP form tags supported the response encoding in most places; however, <form:select> and <form:options> still did not support the response character encoding. To address that, this commit updates SelectTag, OptionsTag, and OptionWriter to provide support for response character encoding in the `select` and `options` JSP form tags. See gh-33023 Closes gh-35783
This commit is contained in:
+82
@@ -21,6 +21,7 @@ import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -50,6 +51,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Juergen Hoeller
|
||||
* @author Scott Andrews
|
||||
* @author Jeremy Grelle
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
class OptionsTagTests extends AbstractHtmlElementTagTests {
|
||||
@@ -114,6 +116,86 @@ class OptionsTagTests extends AbstractHtmlElementTagTests {
|
||||
assertThat(element.attribute("onclick").getValue()).isEqualTo("CLICK");
|
||||
}
|
||||
|
||||
@Test // gh-35783
|
||||
void withListWithHtmlEscaping() throws Exception {
|
||||
getPageContext().setAttribute(
|
||||
SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.country", false));
|
||||
|
||||
this.tag.setItems(List.of("café", "Jane \"I Love Cafés\" Smith"));
|
||||
this.tag.setId("myOption");
|
||||
|
||||
var expectedOutput = """
|
||||
<option id="myOption1" value="café">café</option>
|
||||
<option id="myOption2" value="Jane "I Love Cafés" Smith">Jane "I Love Cafés" Smith</option>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test // gh-35783
|
||||
void withListWithHtmlEscapingAndCharacterEncoding() throws Exception {
|
||||
this.getPageContext().getResponse().setCharacterEncoding("UTF-8");
|
||||
|
||||
getPageContext().setAttribute(
|
||||
SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.country", false));
|
||||
|
||||
this.tag.setItems(List.of("café", "Jane \"I Love Cafés\" Smith"));
|
||||
this.tag.setId("myOption");
|
||||
|
||||
var expectedOutput = """
|
||||
<option id="myOption1" value="café">café</option>
|
||||
<option id="myOption2" value="Jane "I Love Cafés" Smith">Jane "I Love Cafés" Smith</option>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test // gh-35783
|
||||
void withMapWithHtmlEscaping() throws Exception {
|
||||
getPageContext().setAttribute(
|
||||
SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.country", false));
|
||||
|
||||
var map = new LinkedHashMap<String, String>();
|
||||
map.put("one", "Jane \"I Love Cafés\" Smith");
|
||||
map.put("two", "Joe Café");
|
||||
|
||||
this.tag.setItems(map);
|
||||
this.tag.setId("myOption");
|
||||
|
||||
var expectedOutput = """
|
||||
<option id="myOption1" value="one">Jane "I Love Cafés" Smith</option>
|
||||
<option id="myOption2" value="two">Joe Café</option>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test // gh-35783
|
||||
void withMapWithHtmlEscapingAndCharacterEncoding() throws Exception {
|
||||
this.getPageContext().getResponse().setCharacterEncoding("UTF-8");
|
||||
|
||||
getPageContext().setAttribute(
|
||||
SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.country", false));
|
||||
|
||||
var map = new LinkedHashMap<String, String>();
|
||||
map.put("one", "Jane \"I Love Cafés\" Smith");
|
||||
map.put("two", "Joe Café");
|
||||
|
||||
this.tag.setItems(map);
|
||||
this.tag.setId("myOption");
|
||||
|
||||
var expectedOutput = """
|
||||
<option id="myOption1" value="one">Jane "I Love Cafés" Smith</option>
|
||||
<option id="myOption2" value="two">Joe Café</option>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test
|
||||
void withCollectionAndDynamicAttributes() throws Exception {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
|
||||
+139
-14
@@ -23,6 +23,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -54,6 +55,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
* @author Juergen Hoeller
|
||||
* @author Jeremy Grelle
|
||||
* @author Dave Syer
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class SelectTagTests extends AbstractFormTagTests {
|
||||
@@ -77,6 +79,18 @@ public class SelectTagTests extends AbstractFormTagTests {
|
||||
this.tag.setPageContext(getPageContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TestBean createTestBean() {
|
||||
this.bean = new TestBeanWithRealCountry();
|
||||
this.bean.setName("Rob");
|
||||
this.bean.setCountry("UK");
|
||||
this.bean.setSex("M");
|
||||
this.bean.setMyFloat(Float.valueOf("12.34"));
|
||||
this.bean.setSomeIntegerArray(new Integer[]{12, 34});
|
||||
return this.bean;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void dynamicAttributes() throws JspException {
|
||||
String dynamicAttribute1 = "attr1";
|
||||
@@ -132,6 +146,78 @@ public class SelectTagTests extends AbstractFormTagTests {
|
||||
assertList(true);
|
||||
}
|
||||
|
||||
@Test // gh-33023
|
||||
void withListWithHtmlEscapingInPath() throws Exception {
|
||||
this.tag.setPath("favoriteCafé");
|
||||
this.tag.setItems(List.of("Cup of Joe", "Jane's Coffee Shop"));
|
||||
this.tag.setSize("2");
|
||||
|
||||
var expectedOutput = """
|
||||
<select id="favoriteCafé" name="favoriteCafé" size="2">
|
||||
<option value="Cup of Joe">Cup of Joe</option>
|
||||
<option value="Jane's Coffee Shop">Jane's Coffee Shop</option>
|
||||
</select>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test // gh-33023
|
||||
void withListWithHtmlEscapingAndCharacterEncodingInPath() throws Exception {
|
||||
this.getPageContext().getResponse().setCharacterEncoding("UTF-8");
|
||||
|
||||
this.tag.setPath("favoriteCafé");
|
||||
this.tag.setItems(List.of("Cup of Joe", "Jane's Coffee Shop"));
|
||||
this.tag.setSize("2");
|
||||
|
||||
var expectedOutput = """
|
||||
<select id="favoriteCafé" name="favoriteCafé" size="2">
|
||||
<option value="Cup of Joe">Cup of Joe</option>
|
||||
<option value="Jane's Coffee Shop">Jane's Coffee Shop</option>
|
||||
</select>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test // gh-35783
|
||||
void withListWithHtmlEscapingInOptions() throws Exception {
|
||||
this.tag.setPath("name");
|
||||
this.tag.setItems(List.of("café", "Jane \"I Love Cafés\" Smith"));
|
||||
this.tag.setSize("2");
|
||||
|
||||
var expectedOutput = """
|
||||
<select id="name" name="name" size="2">
|
||||
<option value="café">café</option>
|
||||
<option value="Jane "I Love Cafés" Smith">Jane "I Love Cafés" Smith</option>
|
||||
</select>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test // gh-35783
|
||||
void withListWithHtmlEscapingAndCharacterEncodingInOptions() throws Exception {
|
||||
this.getPageContext().getResponse().setCharacterEncoding("UTF-8");
|
||||
|
||||
this.tag.setPath("name");
|
||||
this.tag.setItems(List.of("café", "Jane \"I Love Cafés\" Smith"));
|
||||
this.tag.setSize("2");
|
||||
|
||||
var expectedOutput = """
|
||||
<select id="name" name="name" size="2">
|
||||
<option value="café">café</option>
|
||||
<option value="Jane "I Love Cafés" Smith">Jane "I Love Cafés" Smith</option>
|
||||
</select>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test
|
||||
void withResolvedList() throws Exception {
|
||||
this.tag.setPath("country");
|
||||
@@ -335,8 +421,58 @@ public class SelectTagTests extends AbstractFormTagTests {
|
||||
void withMap() throws Exception {
|
||||
this.tag.setPath("sex");
|
||||
this.tag.setItems(getSexes());
|
||||
int result = this.tag.doStartTag();
|
||||
assertThat(result).isEqualTo(Tag.SKIP_BODY);
|
||||
|
||||
var expectedOutput = """
|
||||
<select id="sex" name="sex">
|
||||
<option value="F">Female</option>
|
||||
<option value="M" selected="selected">Male</option>
|
||||
</select>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test // gh-35783
|
||||
void withMapWithHtmlEscapingInOptions() throws Exception {
|
||||
var map = new LinkedHashMap<String, String>();
|
||||
map.put("F", "Jane \"I Love Cafés\" Smith");
|
||||
map.put("M", "Joe Café");
|
||||
|
||||
this.tag.setPath("sex");
|
||||
this.tag.setItems(map);
|
||||
|
||||
var expectedOutput = """
|
||||
<select id="sex" name="sex">
|
||||
<option value="F">Jane "I Love Cafés" Smith</option>
|
||||
<option value="M" selected="selected">Joe Café</option>
|
||||
</select>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test // gh-35783
|
||||
void withMapWithHtmlEscapingAndCharacterEncodingInOptions() throws Exception {
|
||||
this.getPageContext().getResponse().setCharacterEncoding("UTF-8");
|
||||
|
||||
var map = new LinkedHashMap<String, String>();
|
||||
map.put("F", "Jane \"I Love Cafés\" Smith");
|
||||
map.put("M", "Joe Café");
|
||||
|
||||
this.tag.setPath("sex");
|
||||
this.tag.setItems(map);
|
||||
|
||||
var expectedOutput = """
|
||||
<select id="sex" name="sex">
|
||||
<option value="F">Jane "I Love Cafés" Smith</option>
|
||||
<option value="M" selected="selected">Joe Café</option>
|
||||
</select>
|
||||
""".replace("\n", "");
|
||||
|
||||
assertThat(this.tag.doStartTag()).isEqualTo(Tag.SKIP_BODY);
|
||||
assertThat(getOutput()).isEqualTo(expectedOutput);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -958,7 +1094,7 @@ public class SelectTagTests extends AbstractFormTagTests {
|
||||
}
|
||||
|
||||
private Map getSexes() {
|
||||
Map<String, String> sexes = new HashMap<>();
|
||||
Map<String, String> sexes = new LinkedHashMap<>();
|
||||
sexes.put("F", "Female");
|
||||
sexes.put("M", "Male");
|
||||
return sexes;
|
||||
@@ -996,17 +1132,6 @@ public class SelectTagTests extends AbstractFormTagTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TestBean createTestBean() {
|
||||
this.bean = new TestBeanWithRealCountry();
|
||||
this.bean.setName("Rob");
|
||||
this.bean.setCountry("UK");
|
||||
this.bean.setSex("M");
|
||||
this.bean.setMyFloat(Float.valueOf("12.34"));
|
||||
this.bean.setSomeIntegerArray(new Integer[]{12, 34});
|
||||
return this.bean;
|
||||
}
|
||||
|
||||
private TestBean getTestBean() {
|
||||
return (TestBean) getPageContext().getRequest().getAttribute(COMMAND_NAME);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user