1 /* 2 * Copyright 2002-2008 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.web.servlet.tags.form; 18 19 import java.beans.PropertyEditor; 20 import java.io.StringReader; 21 import java.util.ArrayList; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 26 import javax.servlet.http.HttpServletRequest; 27 import javax.servlet.jsp.tagext.BodyTag; 28 import javax.servlet.jsp.tagext.Tag; 29 30 import org.dom4j.Document; 31 import org.dom4j.Element; 32 import org.dom4j.Node; 33 import org.dom4j.io.SAXReader; 34 import org.springframework.beans.TestBean; 35 import org.springframework.mock.web.MockHttpServletRequest; 36 import org.springframework.mock.web.MockPageContext; 37 import org.springframework.validation.BeanPropertyBindingResult; 38 import org.springframework.validation.BindingResult; 39 import org.springframework.validation.Errors; 40 import org.springframework.web.servlet.support.BindStatus; 41 import org.springframework.web.servlet.support.RequestContext; 42 import org.springframework.web.servlet.tags.RequestContextAwareTag; 43 44 /** 45 * @author Rob Harrop 46 * @author Juergen Hoeller 47 * @author Scott Andrews 48 * @author Jeremy Grelle 49 */ 50 public final class OptionsTagTests extends AbstractHtmlElementTagTests { 51 52 private static final String COMMAND_NAME = "testBean"; 53 54 private SelectTag selectTag; 55 private OptionsTag tag; 56 onSetUp()57 protected void onSetUp() { 58 this.tag = new OptionsTag() { 59 protected TagWriter createTagWriter() { 60 return new TagWriter(getWriter()); 61 } 62 }; 63 selectTag = new SelectTag() { 64 protected TagWriter createTagWriter() { 65 return new TagWriter(getWriter()); 66 } 67 public String getName() { 68 // Should not be used other than to delegate to 69 // RequestDataValueDataProcessor 70 return "testName"; 71 } 72 }; 73 selectTag.setPageContext(getPageContext()); 74 this.tag.setParent(selectTag); 75 this.tag.setPageContext(getPageContext()); 76 } 77 testWithCollection()78 public void testWithCollection() throws Exception { 79 getPageContext().setAttribute( 80 SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.country", false)); 81 82 this.tag.setItems("${countries}"); 83 this.tag.setItemValue("isoCode"); 84 this.tag.setItemLabel("name"); 85 this.tag.setId("myOption"); 86 this.tag.setCssClass("myClass"); 87 this.tag.setOnclick("CLICK"); 88 int result = this.tag.doStartTag(); 89 assertEquals(Tag.SKIP_BODY, result); 90 String output = getOutput(); 91 output = "<doc>" + output + "</doc>"; 92 93 SAXReader reader = new SAXReader(); 94 Document document = reader.read(new StringReader(output)); 95 Element rootElement = document.getRootElement(); 96 97 List children = rootElement.elements(); 98 assertEquals("Incorrect number of children", 4, children.size()); 99 100 Element element = (Element) rootElement.selectSingleNode("option[@value = 'UK']"); 101 assertEquals("UK node not selected", "selected", element.attribute("selected").getValue()); 102 assertEquals("myOption3", element.attribute("id").getValue()); 103 assertEquals("myClass", element.attribute("class").getValue()); 104 assertEquals("CLICK", element.attribute("onclick").getValue()); 105 } 106 testWithCollectionAndDynamicAttributes()107 public void testWithCollectionAndDynamicAttributes() throws Exception { 108 String dynamicAttribute1 = "attr1"; 109 String dynamicAttribute2 = "attr2"; 110 111 getPageContext().setAttribute( 112 SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.country", false)); 113 114 this.tag.setItems("${countries}"); 115 this.tag.setItemValue("isoCode"); 116 this.tag.setItemLabel("name"); 117 this.tag.setId("myOption"); 118 this.tag.setCssClass("myClass"); 119 this.tag.setOnclick("CLICK"); 120 this.tag.setDynamicAttribute(null, dynamicAttribute1, dynamicAttribute1); 121 this.tag.setDynamicAttribute(null, dynamicAttribute2, dynamicAttribute2); 122 123 int result = this.tag.doStartTag(); 124 assertEquals(Tag.SKIP_BODY, result); 125 String output = getOutput(); 126 output = "<doc>" + output + "</doc>"; 127 128 SAXReader reader = new SAXReader(); 129 Document document = reader.read(new StringReader(output)); 130 Element rootElement = document.getRootElement(); 131 132 List children = rootElement.elements(); 133 assertEquals("Incorrect number of children", 4, children.size()); 134 135 Element element = (Element) rootElement.selectSingleNode("option[@value = 'UK']"); 136 assertEquals("UK node not selected", "selected", element.attribute("selected").getValue()); 137 assertEquals("myOption3", element.attribute("id").getValue()); 138 assertEquals("myClass", element.attribute("class").getValue()); 139 assertEquals("CLICK", element.attribute("onclick").getValue()); 140 assertEquals(dynamicAttribute1, element.attribute(dynamicAttribute1).getValue()); 141 assertEquals(dynamicAttribute2, element.attribute(dynamicAttribute2).getValue()); 142 } 143 testWithCollectionAndCustomEditor()144 public void testWithCollectionAndCustomEditor() throws Exception { 145 PropertyEditor propertyEditor = new SimpleFloatEditor(); 146 147 TestBean target = new TestBean(); 148 target.setMyFloat(new Float("12.34")); 149 150 BeanPropertyBindingResult errors = new BeanPropertyBindingResult(target, COMMAND_NAME); 151 errors.getPropertyAccessor().registerCustomEditor(Float.class, propertyEditor); 152 exposeBindingResult(errors); 153 154 getPageContext().setAttribute( 155 SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.myFloat", false)); 156 157 this.tag.setItems("${floats}"); 158 int result = this.tag.doStartTag(); 159 assertEquals(Tag.SKIP_BODY, result); 160 String output = getOutput(); 161 output = "<doc>" + output + "</doc>"; 162 163 SAXReader reader = new SAXReader(); 164 Document document = reader.read(new StringReader(output)); 165 Element rootElement = document.getRootElement(); 166 167 List children = rootElement.elements(); 168 assertEquals("Incorrect number of children", 6, children.size()); 169 170 Element element = (Element) rootElement.selectSingleNode("option[text() = '12.34f']"); 171 assertNotNull("Option node should not be null", element); 172 assertEquals("12.34 node not selected", "selected", element.attribute("selected").getValue()); 173 assertNull("No id rendered", element.attribute("id")); 174 175 element = (Element) rootElement.selectSingleNode("option[text() = '12.35f']"); 176 assertNotNull("Option node should not be null", element); 177 assertNull("12.35 node incorrectly selected", element.attribute("selected")); 178 assertNull("No id rendered", element.attribute("id")); 179 } 180 testWithItemsNullReference()181 public void testWithItemsNullReference() throws Exception { 182 getPageContext().getRequest().removeAttribute("countries"); 183 getPageContext().setAttribute( 184 SelectTag.LIST_VALUE_PAGE_ATTRIBUTE, new BindStatus(getRequestContext(), "testBean.country", false)); 185 186 this.tag.setItems("${countries}"); 187 this.tag.setItemValue("isoCode"); 188 this.tag.setItemLabel("name"); 189 int result = this.tag.doStartTag(); 190 assertEquals(Tag.SKIP_BODY, result); 191 String output = getOutput(); 192 output = "<doc>" + output + "</doc>"; 193 194 SAXReader reader = new SAXReader(); 195 Document document = reader.read(new StringReader(output)); 196 Element rootElement = document.getRootElement(); 197 198 List children = rootElement.elements(); 199 assertEquals("Incorrect number of children", 0, children.size()); 200 } 201 testWithoutItems()202 public void testWithoutItems() throws Exception { 203 this.tag.setItemValue("isoCode"); 204 this.tag.setItemLabel("name"); 205 this.selectTag.setPath("testBean"); 206 207 this.selectTag.doStartTag(); 208 int result = this.tag.doStartTag(); 209 assertEquals(Tag.SKIP_BODY, result); 210 this.tag.doEndTag(); 211 this.selectTag.doEndTag(); 212 213 String output = getOutput(); 214 SAXReader reader = new SAXReader(); 215 Document document = reader.read(new StringReader(output)); 216 Element rootElement = document.getRootElement(); 217 218 List children = rootElement.elements(); 219 assertEquals("Incorrect number of children", 0, children.size()); 220 } 221 testWithoutItemsEnumParent()222 public void testWithoutItemsEnumParent() throws Exception { 223 BeanWithEnum testBean = new BeanWithEnum(); 224 testBean.setTestEnum(TestEnum.VALUE_2); 225 getPageContext().getRequest().setAttribute("testBean", testBean); 226 227 this.selectTag.setPath("testBean.testEnum"); 228 229 this.selectTag.doStartTag(); 230 int result = this.tag.doStartTag(); 231 assertEquals(BodyTag.SKIP_BODY, result); 232 result = this.tag.doEndTag(); 233 assertEquals(Tag.EVAL_PAGE, result); 234 this.selectTag.doEndTag(); 235 236 String output = getWriter().toString(); 237 SAXReader reader = new SAXReader(); 238 Document document = reader.read(new StringReader(output)); 239 Element rootElement = document.getRootElement(); 240 241 assertEquals(2, rootElement.elements().size()); 242 Node value1 = rootElement.selectSingleNode("option[@value = 'VALUE_1']"); 243 Node value2 = rootElement.selectSingleNode("option[@value = 'VALUE_2']"); 244 assertEquals("TestEnum: VALUE_1", value1.getText()); 245 assertEquals("TestEnum: VALUE_2", value2.getText()); 246 assertEquals(value2, rootElement.selectSingleNode("option[@selected]")); 247 } 248 testWithoutItemsEnumParentWithExplicitLabelsAndValues()249 public void testWithoutItemsEnumParentWithExplicitLabelsAndValues() throws Exception { 250 BeanWithEnum testBean = new BeanWithEnum(); 251 testBean.setTestEnum(TestEnum.VALUE_2); 252 getPageContext().getRequest().setAttribute("testBean", testBean); 253 254 this.selectTag.setPath("testBean.testEnum"); 255 this.tag.setItemLabel("enumLabel"); 256 this.tag.setItemValue("enumValue"); 257 258 this.selectTag.doStartTag(); 259 int result = this.tag.doStartTag(); 260 assertEquals(BodyTag.SKIP_BODY, result); 261 result = this.tag.doEndTag(); 262 assertEquals(Tag.EVAL_PAGE, result); 263 this.selectTag.doEndTag(); 264 265 String output = getWriter().toString(); 266 SAXReader reader = new SAXReader(); 267 Document document = reader.read(new StringReader(output)); 268 Element rootElement = document.getRootElement(); 269 270 assertEquals(2, rootElement.elements().size()); 271 Node value1 = rootElement.selectSingleNode("option[@value = 'Value: VALUE_1']"); 272 Node value2 = rootElement.selectSingleNode("option[@value = 'Value: VALUE_2']"); 273 assertEquals("Label: VALUE_1", value1.getText()); 274 assertEquals("Label: VALUE_2", value2.getText()); 275 assertEquals(value2, rootElement.selectSingleNode("option[@selected]")); 276 } 277 extendRequest(MockHttpServletRequest request)278 protected void extendRequest(MockHttpServletRequest request) { 279 TestBean bean = new TestBean(); 280 bean.setName("foo"); 281 bean.setCountry("UK"); 282 bean.setMyFloat(new Float("12.34")); 283 request.setAttribute(COMMAND_NAME, bean); 284 request.setAttribute("countries", Country.getCountries()); 285 286 List floats = new ArrayList(); 287 floats.add(new Float("12.30")); 288 floats.add(new Float("12.31")); 289 floats.add(new Float("12.32")); 290 floats.add(new Float("12.33")); 291 floats.add(new Float("12.34")); 292 floats.add(new Float("12.35")); 293 294 request.setAttribute("floats", floats); 295 } 296 exposeBindingResult(Errors errors)297 protected void exposeBindingResult(Errors errors) { 298 // wrap errors in a Model 299 Map model = new HashMap(); 300 model.put(BindingResult.MODEL_KEY_PREFIX + COMMAND_NAME, errors); 301 302 // replace the request context with one containing the errors 303 MockPageContext pageContext = getPageContext(); 304 RequestContext context = new RequestContext((HttpServletRequest) pageContext.getRequest(), model); 305 pageContext.setAttribute(RequestContextAwareTag.REQUEST_CONTEXT_PAGE_ATTRIBUTE, context); 306 } 307 308 } 309