1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.servlet.view;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import javax.servlet.http.HttpServletRequest;
24 import javax.servlet.http.HttpServletResponse;
25
26 import org.junit.Test;
27
28 import org.springframework.http.HttpStatus;
29 import org.springframework.mock.web.test.MockHttpServletRequest;
30 import org.springframework.mock.web.test.MockHttpServletResponse;
31 import org.springframework.mock.web.test.MockServletContext;
32 import org.springframework.tests.sample.beans.TestBean;
33 import org.springframework.ui.ModelMap;
34 import org.springframework.web.context.ContextLoader;
35 import org.springframework.web.context.support.StaticWebApplicationContext;
36 import org.springframework.web.servlet.DispatcherServlet;
37 import org.springframework.web.servlet.FlashMap;
38 import org.springframework.web.servlet.FlashMapManager;
39 import org.springframework.web.servlet.View;
40 import org.springframework.web.servlet.support.RequestDataValueProcessor;
41 import org.springframework.web.servlet.support.RequestDataValueProcessorWrapper;
42 import org.springframework.web.servlet.support.SessionFlashMapManager;
43 import org.springframework.web.util.WebUtils;
44
45 import static org.junit.Assert.*;
46 import static org.mockito.BDDMockito.*;
47
48
49
50
51
52
53
54
55
56
57
58 public class RedirectViewTests {
59
60 @Test(expected = IllegalArgumentException.class)
61 public void noUrlSet() throws Exception {
62 RedirectView rv = new RedirectView();
63 rv.afterPropertiesSet();
64 }
65
66 @Test
67 public void http11() throws Exception {
68 RedirectView rv = new RedirectView();
69 rv.setUrl("http://url.somewhere.com");
70 rv.setHttp10Compatible(false);
71 MockHttpServletRequest request = createRequest();
72 MockHttpServletResponse response = new MockHttpServletResponse();
73 request.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
74 request.setAttribute(DispatcherServlet.FLASH_MAP_MANAGER_ATTRIBUTE, new SessionFlashMapManager());
75 rv.render(new HashMap<String, Object>(), request, response);
76 assertEquals(303, response.getStatus());
77 assertEquals("http://url.somewhere.com", response.getHeader("Location"));
78 }
79
80 private MockHttpServletRequest createRequest() {
81 MockHttpServletRequest request = new MockHttpServletRequest();
82 request.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
83 request.setAttribute(DispatcherServlet.FLASH_MAP_MANAGER_ATTRIBUTE, new SessionFlashMapManager());
84 return request;
85 }
86
87 @Test
88 public void explicitStatusCodeHttp11() throws Exception {
89 RedirectView rv = new RedirectView();
90 rv.setUrl("http://url.somewhere.com");
91 rv.setHttp10Compatible(false);
92 rv.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
93 MockHttpServletRequest request = createRequest();
94 MockHttpServletResponse response = new MockHttpServletResponse();
95 rv.render(new HashMap<String, Object>(), request, response);
96 assertEquals(301, response.getStatus());
97 assertEquals("http://url.somewhere.com", response.getHeader("Location"));
98 }
99
100 @Test
101 public void explicitStatusCodeHttp10() throws Exception {
102 RedirectView rv = new RedirectView();
103 rv.setUrl("http://url.somewhere.com");
104 rv.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
105 MockHttpServletRequest request = createRequest();
106 MockHttpServletResponse response = new MockHttpServletResponse();
107 rv.render(new HashMap<String, Object>(), request, response);
108 assertEquals(301, response.getStatus());
109 assertEquals("http://url.somewhere.com", response.getHeader("Location"));
110 }
111
112 @Test
113 public void attributeStatusCodeHttp11() throws Exception {
114 RedirectView rv = new RedirectView();
115 rv.setUrl("http://url.somewhere.com");
116 rv.setHttp10Compatible(false);
117 MockHttpServletRequest request = createRequest();
118 request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.CREATED);
119 MockHttpServletResponse response = new MockHttpServletResponse();
120 rv.render(new HashMap<String, Object>(), request, response);
121 assertEquals(201, response.getStatus());
122 assertEquals("http://url.somewhere.com", response.getHeader("Location"));
123 }
124
125 @Test
126 public void flashMap() throws Exception {
127 RedirectView rv = new RedirectView();
128 rv.setUrl("http://url.somewhere.com/path");
129 rv.setHttp10Compatible(false);
130 MockHttpServletRequest request = createRequest();
131 HttpServletResponse response = new MockHttpServletResponse();
132 FlashMap flashMap = new FlashMap();
133 flashMap.put("successMessage", "yay!");
134 request.setAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
135 ModelMap model = new ModelMap("id", "1");
136 rv.render(model, request, response);
137 assertEquals(303, response.getStatus());
138 assertEquals("http://url.somewhere.com/path?id=1", response.getHeader("Location"));
139
140 assertEquals("/path", flashMap.getTargetRequestPath());
141 assertEquals(model, flashMap.getTargetRequestParams().toSingleValueMap());
142 }
143
144 @Test
145 public void updateTargetUrl() throws Exception {
146 StaticWebApplicationContext wac = new StaticWebApplicationContext();
147 wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class);
148 wac.setServletContext(new MockServletContext());
149 wac.refresh();
150
151 RequestDataValueProcessor mockProcessor = mock(RequestDataValueProcessor.class);
152 wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor);
153
154 RedirectView rv = new RedirectView();
155 rv.setApplicationContext(wac);
156 rv.setUrl("/path");
157
158 MockHttpServletRequest request = createRequest();
159 request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);
160 HttpServletResponse response = new MockHttpServletResponse();
161
162 given(mockProcessor.processUrl(request, "/path")).willReturn("/path?key=123");
163
164 rv.render(new ModelMap(), request, response);
165
166 verify(mockProcessor).processUrl(request, "/path");
167 }
168
169
170 @Test
171 public void updateTargetUrlWithContextLoader() throws Exception {
172 StaticWebApplicationContext wac = new StaticWebApplicationContext();
173 wac.registerSingleton("requestDataValueProcessor", RequestDataValueProcessorWrapper.class);
174
175 MockServletContext servletContext = new MockServletContext();
176 ContextLoader contextLoader = new ContextLoader(wac);
177 contextLoader.initWebApplicationContext(servletContext);
178
179 try {
180 RequestDataValueProcessor mockProcessor = mock(RequestDataValueProcessor.class);
181 wac.getBean(RequestDataValueProcessorWrapper.class).setRequestDataValueProcessor(mockProcessor);
182
183 RedirectView rv = new RedirectView();
184 rv.setUrl("/path");
185
186 MockHttpServletRequest request = createRequest();
187 HttpServletResponse response = new MockHttpServletResponse();
188
189 given(mockProcessor.processUrl(request, "/path")).willReturn("/path?key=123");
190
191 rv.render(new ModelMap(), request, response);
192
193 verify(mockProcessor).processUrl(request, "/path");
194 }
195 finally {
196 contextLoader.closeWebApplicationContext(servletContext);
197 }
198 }
199
200 @Test
201 public void emptyMap() throws Exception {
202 String url = "/myUrl";
203 doTest(new HashMap<String, Object>(), url, false, url);
204 }
205
206 @Test
207 public void emptyMapWithContextRelative() throws Exception {
208 String url = "/myUrl";
209 doTest(new HashMap<String, Object>(), url, true, url);
210 }
211
212 @Test
213 public void singleParam() throws Exception {
214 String url = "http://url.somewhere.com";
215 String key = "foo";
216 String val = "bar";
217 Map<String, String> model = new HashMap<String, String>();
218 model.put(key, val);
219 String expectedUrlForEncoding = url + "?" + key + "=" + val;
220 doTest(model, url, false, expectedUrlForEncoding);
221 }
222
223 @Test
224 public void singleParamWithoutExposingModelAttributes() throws Exception {
225 String url = "http://url.somewhere.com";
226 String key = "foo";
227 String val = "bar";
228 Map<String, String> model = new HashMap<String, String>();
229 model.put(key, val);
230 String expectedUrlForEncoding = url;
231 doTest(model, url, false, false, expectedUrlForEncoding);
232 }
233
234 @Test
235 public void paramWithAnchor() throws Exception {
236 String url = "http://url.somewhere.com/test.htm#myAnchor";
237 String key = "foo";
238 String val = "bar";
239 Map<String, String> model = new HashMap<String, String>();
240 model.put(key, val);
241 String expectedUrlForEncoding = "http://url.somewhere.com/test.htm" + "?" + key + "=" + val + "#myAnchor";
242 doTest(model, url, false, expectedUrlForEncoding);
243 }
244
245 @Test
246 public void contextRelativeQueryParam() throws Exception {
247 String url = "/test.html?id=1";
248 doTest(new HashMap<String, Object>(), url, true, url);
249 }
250
251 @Test
252 public void twoParams() throws Exception {
253 String url = "http://url.somewhere.com";
254 String key = "foo";
255 String val = "bar";
256 String key2 = "thisIsKey2";
257 String val2 = "andThisIsVal2";
258 Map<String, String> model = new HashMap<String, String>();
259 model.put(key, val);
260 model.put(key2, val2);
261 try {
262 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val + "&" + key2 + "=" + val2;
263 doTest(model, url, false, expectedUrlForEncoding);
264 }
265 catch (AssertionError err) {
266
267 String expectedUrlForEncoding = "http://url.somewhere.com?" + key2 + "=" + val2 + "&" + key + "=" + val;
268 doTest(model, url, false, expectedUrlForEncoding);
269 }
270 }
271
272 @Test
273 public void arrayParam() throws Exception {
274 String url = "http://url.somewhere.com";
275 String key = "foo";
276 String[] val = new String[] {"bar", "baz"};
277 Map<String, String[]> model = new HashMap<String, String[]>();
278 model.put(key, val);
279 try {
280 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val[0] + "&" + key + "=" + val[1];
281 doTest(model, url, false, expectedUrlForEncoding);
282 }
283 catch (AssertionError err) {
284
285 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val[1] + "&" + key + "=" + val[0];
286 doTest(model, url, false, expectedUrlForEncoding);
287 }
288 }
289
290 @Test
291 public void collectionParam() throws Exception {
292 String url = "http://url.somewhere.com";
293 String key = "foo";
294 List<String> val = new ArrayList<String>();
295 val.add("bar");
296 val.add("baz");
297 Map<String, List<String>> model = new HashMap<String, List<String>>();
298 model.put(key, val);
299 try {
300 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val.get(0) + "&" + key + "=" + val.get(1);
301 doTest(model, url, false, expectedUrlForEncoding);
302 }
303 catch (AssertionError err) {
304
305 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val.get(1) + "&" + key + "=" + val.get(0);
306 doTest(model, url, false, expectedUrlForEncoding);
307 }
308 }
309
310 @Test
311 public void objectConversion() throws Exception {
312 String url = "http://url.somewhere.com";
313 String key = "foo";
314 String val = "bar";
315 String key2 = "int2";
316 Object val2 = new Long(611);
317 String key3 = "tb";
318 Object val3 = new TestBean();
319 Map<String, Object> model = new HashMap<String, Object>();
320 model.put(key, val);
321 model.put(key2, val2);
322 model.put(key3, val3);
323 String expectedUrlForEncoding = "http://url.somewhere.com?" + key + "=" + val + "&" + key2 + "=" + val2;
324 doTest(model, url, false, expectedUrlForEncoding);
325 }
326
327 @Test
328 public void propagateQueryParams() throws Exception {
329 RedirectView rv = new RedirectView();
330 rv.setPropagateQueryParams(true);
331 rv.setUrl("http://url.somewhere.com?foo=bar#bazz");
332 MockHttpServletRequest request = createRequest();
333 MockHttpServletResponse response = new MockHttpServletResponse();
334 request.setQueryString("a=b&c=d");
335 rv.render(new HashMap<String, Object>(), request, response);
336 assertEquals(302, response.getStatus());
337 assertEquals("http://url.somewhere.com?foo=bar&a=b&c=d#bazz", response.getHeader("Location"));
338 }
339
340 private void doTest(Map<String, ?> map, String url, boolean contextRelative, String expectedUrlForEncoding)
341 throws Exception {
342 doTest(map, url, contextRelative, true, expectedUrlForEncoding);
343 }
344
345 private void doTest(final Map<String, ?> map, final String url, final boolean contextRelative,
346 final boolean exposeModelAttributes, String expectedUrlForEncoding) throws Exception {
347
348 class TestRedirectView extends RedirectView {
349
350 public boolean queryPropertiesCalled = false;
351
352
353
354
355 @Override
356 protected Map<String, Object> queryProperties(Map<String, Object> model) {
357
358 assertTrue("Map and model must be equal.", map.equals(model));
359 this.queryPropertiesCalled = true;
360 return super.queryProperties(model);
361 }
362 }
363
364 TestRedirectView rv = new TestRedirectView();
365 rv.setUrl(url);
366 rv.setContextRelative(contextRelative);
367 rv.setExposeModelAttributes(exposeModelAttributes);
368
369 HttpServletRequest request = mock(HttpServletRequest.class, "request");
370 if (exposeModelAttributes) {
371 given(request.getCharacterEncoding()).willReturn(WebUtils.DEFAULT_CHARACTER_ENCODING);
372 }
373 if (contextRelative) {
374 expectedUrlForEncoding = "/context" + expectedUrlForEncoding;
375 given(request.getContextPath()).willReturn("/context");
376 }
377
378 given(request.getAttribute(DispatcherServlet.OUTPUT_FLASH_MAP_ATTRIBUTE)).willReturn(new FlashMap());
379
380 FlashMapManager flashMapManager = new SessionFlashMapManager();
381 given(request.getAttribute(DispatcherServlet.FLASH_MAP_MANAGER_ATTRIBUTE)).willReturn(flashMapManager);
382
383 HttpServletResponse response = mock(HttpServletResponse.class, "response");
384 given(response.encodeRedirectURL(expectedUrlForEncoding)).willReturn(expectedUrlForEncoding);
385 response.sendRedirect(expectedUrlForEncoding);
386
387 rv.render(map, request, response);
388 if (exposeModelAttributes) {
389 assertTrue("queryProperties() should have been called.", rv.queryPropertiesCalled);
390 }
391 }
392
393 }