View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.shared.context.flash;
20  
21  import java.util.Arrays;
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.Map;
26  
27  import javax.faces.application.FacesMessage;
28  import javax.faces.event.PhaseId;
29  import javax.servlet.ServletContext;
30  import javax.servlet.http.Cookie;
31  import javax.servlet.http.HttpServletRequest;
32  import javax.servlet.http.HttpServletResponse;
33  import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
34  
35  import org.apache.myfaces.test.mock.MockExternalContext20;
36  import org.apache.myfaces.test.mock.MockFacesContext20;
37  import org.apache.myfaces.test.mock.MockHttpServletRequest;
38  import org.apache.myfaces.test.mock.MockHttpServletResponse;
39  import org.junit.Assert;
40  import org.junit.Test;
41  
42  /**
43   * Tests for FlashImpl.
44   */
45  public class FlashImplTest extends AbstractJsfTestCase
46  {
47      
48      private FlashImpl _flash;
49  
50      public FlashImplTest()
51      {
52      }
53  
54      @Override
55      protected void setUpFacesContext() throws Exception
56      {
57          super.setUpFacesContext();
58  
59          // Unfortunately, setUpExternalContext() does not work, b/c MockFacesContext20 overwrites it!
60          externalContext = new MockExternalContext21(servletContext, request, response);
61          facesContext.setExternalContext(externalContext);
62      }
63  
64      @Override
65      public void setUp() throws Exception
66      {
67          super.setUp();
68          
69          _flash = (FlashImpl) FlashImpl.getCurrentInstance(externalContext);
70      }
71  
72      @Override
73      public void tearDown() throws Exception
74      {
75          _flash = null;
76          
77          super.tearDown();
78      }
79  
80      /**
81       * Tests if FlashImpl uses the sessionMap as base for the SubKeyMap
82       * and correctly stores the values in it.
83       * @throws Exception
84       */
85      @Test
86      public void testSessionMapWrapperSubKeyMap() throws Exception
87      {
88          // set phase to RESTORE_VIEW to create the flash tokens on doPrePhaseActions()
89          facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
90          _flash.doPrePhaseActions(facesContext);
91          
92          // put the value in the scope an keep() it!
93          _flash.putNow("testkey1", "testvalue1");
94          _flash.keep("testkey1");
95          
96          // set phase to RENDER_RESPONSE --> now renderMap will be used
97          facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
98          
99          // get the token for the render FlashMap (FlashImpl internals)
100         final String renderToken = (String) externalContext
101                 .getRequestMap().get(FlashImpl.FLASH_RENDER_MAP_TOKEN);
102         final String sessionMapKey = FlashImpl.FLASH_SESSION_MAP_SUBKEY_PREFIX + 
103                 FlashImpl.SEPARATOR_CHAR + renderToken + FlashImpl.SEPARATOR_CHAR + "testkey1";
104         
105         // Assertion
106         Assert.assertEquals("The render FlashMap must use the session Map to store the values.",
107                 "testvalue1", session.getAttribute(sessionMapKey));     
108     }
109     
110     /**
111      * Tests the functionality of keep() in a normal postback scenario.
112      * @throws Exception
113      */
114     @SuppressWarnings("unchecked")
115     @Test
116     public void testKeepValueNormalPostback() throws Exception
117     {
118         // simulate JSF lifecycle:
119         // note that doPrePhaseActions() only performs tasks on RESTORE_VIEW
120         // and doPostPhaseActions() only on the last phase.
121         
122         // initial request ----------------------------------------------------
123         
124         // this request is a normal GET request, and thus not a postback
125         ((MockFacesContext20) facesContext).setPostback(false);
126         
127         // simulate JSF lifecycle
128         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
129         _flash.doPrePhaseActions(facesContext);
130         
131         // simulate JSF lifecycle
132         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
133         _flash.doPostPhaseActions(facesContext);
134         
135         // first postback -----------------------------------------------------
136         
137         // simulate a new request
138         _simulateNewRequest();
139         
140         // this request should be a postback
141         ((MockFacesContext20) facesContext).setPostback(true);
142         
143         // simulate JSF lifecycle
144         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
145         _flash.doPrePhaseActions(facesContext);
146         
147         // simulate JSF lifecycle
148         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
149         
150         // put the value in the scope an keep() it!
151         _flash.putNow("flashkey", "flashvalue");
152         _flash.keep("flashkey");
153         
154         // simulate JSF lifecycle
155         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
156         _flash.doPostPhaseActions(facesContext);
157         
158         // second postback ----------------------------------------------------
159         
160         // simulate a new request
161         _simulateNewRequest();
162         
163         // this request should be a postback
164         ((MockFacesContext20) facesContext).setPostback(true);
165         
166         // simulate JSF lifecycle
167         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
168         _flash.doPrePhaseActions(facesContext);
169         
170         // simulate JSF lifecycle
171         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
172         
173         // _flash.get() will ask the execute FlashMap for the value
174         // and this must be the render FlashMap of the previous request,
175         // thus it must contain the value from the previous request.
176         Assert.assertEquals("flashvalue", _flash.get("flashkey"));
177         
178         // simulate JSF lifecycle
179         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
180         _flash.doPostPhaseActions(facesContext);
181         
182         // _flash.get() also references to the execute FlashMap, but
183         // this one has to be cleared by now, thus it must be null.
184         Assert.assertNull("Execute FlashMap must have been cleared", _flash.get("flashkey"));
185         
186         // get the execute Map of the second postback (FlashImpl internals)
187         Map<String, Object> executeMap = (Map<String, Object>) externalContext
188                 .getRequestMap().get(FlashImpl.FLASH_EXECUTE_MAP);
189         
190         // must be empty
191         Assert.assertTrue("The execute Map of the second postback must have been cleared",
192                 executeMap.isEmpty());
193     }
194     
195     /**
196      * Tests the functionality of keep() in a POST-REDIRECT-GET scenario.
197      * @throws Exception
198      */
199     @SuppressWarnings("unchecked")
200     @Test
201     public void testKeepValuePostRedirectGet() throws Exception
202     {
203         // simulate JSF lifecycle:
204         // note that doPrePhaseActions() only performs tasks on RESTORE_VIEW
205         // and doPostPhaseActions() only on the last phase.
206         
207         // initial request ----------------------------------------------------
208         
209         // this request is a normal GET request, and thus not a postback
210         ((MockFacesContext20) facesContext).setPostback(false);
211         
212         // simulate JSF lifecycle
213         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
214         _flash.doPrePhaseActions(facesContext);
215         
216         // simulate JSF lifecycle
217         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
218         _flash.doPostPhaseActions(facesContext);
219         
220         // first postback (POST of POST-REDIRECT-GET) -------------------------
221         
222         // simulate a new request
223         _simulateNewRequest();
224         
225         // this request should be a postback
226         ((MockFacesContext20) facesContext).setPostback(true);
227         
228         // simulate JSF lifecycle
229         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
230         _flash.doPrePhaseActions(facesContext);
231         
232         // simulate JSF lifecycle
233         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
234         
235         // put the value in the scope an keep() it!
236         _flash.put("flashkey", "flashvalue");
237         _flash.keep("flashkey");
238         
239         // set redirect to true, this happens by the NavigationHandler in phase 5
240         _flash.setRedirect(true);
241         
242         Assert.assertTrue("setRedirect(true) was just called, thus isRedirect() must be true",
243                 _flash.isRedirect());
244         
245         // note that setRedirect(true) was called, thus the cleanup happens
246         // in phase 5, because doPostPhaseActions() won't be called on phase 6.
247         _flash.doPostPhaseActions(facesContext);
248         
249         // GET request of POST-REDIRECT-GET -----------------------------------
250         
251         // simulate a new request
252         _simulateNewRequest();
253         
254         // this request is not a postback
255         ((MockFacesContext20) facesContext).setPostback(false);
256         
257         // simulate JSF lifecycle
258         // Note that doPrePhaseActions() is called on RESTORE_VIEW even
259         // though this request is not a postback.
260         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
261         _flash.doPrePhaseActions(facesContext);
262         
263         // check isRedirect();
264         Assert.assertTrue("setRedirect(true) was called on the previous request, "
265                 + " and we are in the execute portion of the lifecycle, "
266                 + " thus isRedirect() must be true.",
267                 _flash.isRedirect());
268         
269         // simulate JSF lifecycle - JSF will immediately jump to phase 6
270         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
271         
272         // check isRedirect();
273         Assert.assertFalse("setRedirect(true) was called on the previous request, "
274                 + " but we are already in the render portion of the lifecycle, "
275                 + " thus isRedirect() must be false.",
276                 _flash.isRedirect());
277         
278         // _flash.get() will ask the execute FlashMap and this one
279         // must contain the key used in keep()
280         Assert.assertEquals("flashvalue", _flash.get("flashkey"));
281         
282         _flash.doPostPhaseActions(facesContext);
283         
284         // second postback (after POST-REDIRECT-GET) --------------------------
285         
286         // simulate a new request
287         _simulateNewRequest();
288         
289         // this request should be a postback
290         ((MockFacesContext20) facesContext).setPostback(true);
291         
292         // simulate JSF lifecycle
293         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
294         _flash.doPrePhaseActions(facesContext);
295         
296         // simulate JSF lifecycle
297         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
298         
299         // check isRedirect();
300         Assert.assertFalse("setRedirect(true) was called on the pre-previous request, "
301                 + " thus isRedirect() must be false again.",
302                 _flash.isRedirect());
303         
304         // _flash.get() will ask the execute FlashMap for the value
305         // and this must be the render FlashMap of the previous (GET) request,
306         // thus it must not contain the value from the previous request,
307         // because the value was on the previous request's execute FlashMap
308         // and not on the previous request's render FlashMap.
309         Assert.assertNull(_flash.get("flashkey"));
310         
311         // simulate JSF lifecycle
312         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
313         _flash.doPostPhaseActions(facesContext);
314         
315         // get the execute Map of the second postback (FlashImpl internals)
316         Map<String, Object> executeMap = (Map<String, Object>) externalContext
317                 .getRequestMap().get(FlashImpl.FLASH_EXECUTE_MAP);
318         
319         // must be empty
320         Assert.assertTrue("The execute Map of the second postback must have been cleared",
321                 executeMap.isEmpty());
322     }
323     
324     /**
325      * Tests the functionality of keepMessages in a normal postback scenario.
326      * @throws Exception
327      */
328     @Test
329     public void testKeepMessagesNormalPostback() throws Exception
330     {
331         // simulate JSF lifecycle:
332         // note that doPrePhaseActions() only performs tasks on RESTORE_VIEW
333         // and doPostPhaseActions() only on the last phase.
334         
335         // initial request ----------------------------------------------------
336         
337         // this request is a normal GET request, and thus not a postback
338         ((MockFacesContext20) facesContext).setPostback(false);
339         
340         // simulate JSF lifecycle
341         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
342         _flash.doPrePhaseActions(facesContext);
343         
344         // simulate JSF lifecycle
345         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
346         _flash.doPostPhaseActions(facesContext);
347         
348         // first postback -----------------------------------------------------
349         
350         // simulate a new request
351         _simulateNewRequest();
352         
353         // this request should be a postback
354         ((MockFacesContext20) facesContext).setPostback(true);
355         
356         // simulate JSF lifecycle
357         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
358         _flash.doPrePhaseActions(facesContext);
359         
360         // simulate JSF lifecycle
361         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
362         
363         // add FacesMessages to the facesContext
364         FacesMessage messageClientId = new FacesMessage("message for clientId");
365         facesContext.addMessage("clientId", messageClientId);
366         FacesMessage messageNoClientId = new FacesMessage("message without clientId");
367         facesContext.addMessage(null, messageNoClientId);
368         
369         // now the FacesContext must contain 2 messages
370         Assert.assertEquals(2, facesContext.getMessageList().size());
371         
372         // keep messages
373         _flash.setKeepMessages(true);
374         
375         Assert.assertTrue("setKeepMessages(true) was just called, thus isKeepMessages() "
376                 + "must be true.", _flash.isKeepMessages());
377         
378         // simulate JSF lifecycle
379         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
380         _flash.doPostPhaseActions(facesContext);
381         
382         // second postback ----------------------------------------------------
383         
384         // simulate a new request
385         _simulateNewRequest();
386         
387         // this request should be a postback
388         ((MockFacesContext20) facesContext).setPostback(true);
389         
390         // now the FacesContext must contain 0 messages (new request, new FacesContext)
391         Assert.assertEquals(0, facesContext.getMessageList().size());
392         
393         // simulate JSF lifecycle
394         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
395         _flash.doPrePhaseActions(facesContext);
396         
397         // now the messages must be here again
398         Assert.assertEquals(2, facesContext.getMessageList().size());
399         Assert.assertEquals(Arrays.asList(messageClientId), facesContext.getMessageList("clientId"));
400         Assert.assertEquals(Arrays.asList(messageNoClientId), facesContext.getMessageList(null));
401         
402         Assert.assertFalse("setKeepMessages(true) was not called on this request, thus "
403                 + "isKeepMessages() must be false.", _flash.isKeepMessages());
404         
405         // simulate JSF lifecycle
406         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
407         _flash.doPostPhaseActions(facesContext);
408         
409         // third postback ----------------------------------------------------
410         
411         // simulate a new request
412         _simulateNewRequest();
413         
414         // this request should be a postback
415         ((MockFacesContext20) facesContext).setPostback(true);
416         
417         // now the FacesContext must contain 0 messages (new request, new FacesContext)
418         Assert.assertEquals(0, facesContext.getMessageList().size());
419         
420         // simulate JSF lifecycle
421         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
422         _flash.doPrePhaseActions(facesContext);
423         
424         // the messages must still be gone here, because setKeepMessages(true)
425         // was not called on the previous request
426         Assert.assertEquals(0, facesContext.getMessageList().size());
427         
428         // simulate JSF lifecycle
429         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
430         _flash.doPostPhaseActions(facesContext); 
431     }
432     
433     /**
434      * Tests the functionality of keepMessages in a POST-REDIRECT-GET scenario.
435      * In this test case the messages are only shipped from the POST to the GET and
436      * then not from the GET to the next postback.
437      * @throws Exception
438      */
439     @Test
440     public void testKeepMessagesPostRedirectGet() throws Exception
441     {
442         // simulate JSF lifecycle:
443         // note that doPrePhaseActions() only performs tasks on RESTORE_VIEW
444         // and doPostPhaseActions() only on the last phase.
445         
446         // initial request ----------------------------------------------------
447         
448         // this request is a normal GET request, and thus not a postback
449         ((MockFacesContext20) facesContext).setPostback(false);
450         
451         // simulate JSF lifecycle
452         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
453         _flash.doPrePhaseActions(facesContext);
454         
455         // simulate JSF lifecycle
456         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
457         _flash.doPostPhaseActions(facesContext);
458         
459         // first postback (POST of POST-REDIRECT-GET) -------------------------
460         
461         // simulate a new request
462         _simulateNewRequest();
463         
464         // this request should be a postback
465         ((MockFacesContext20) facesContext).setPostback(true);
466         
467         // simulate JSF lifecycle
468         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
469         _flash.doPrePhaseActions(facesContext);
470         
471         // simulate JSF lifecycle
472         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
473         
474         // add FacesMessages to the facesContext
475         FacesMessage messageClientId = new FacesMessage("message for clientId");
476         facesContext.addMessage("clientId", messageClientId);
477         FacesMessage messageNoClientId = new FacesMessage("message without clientId");
478         facesContext.addMessage(null, messageNoClientId);
479         
480         // now the FacesContext must contain 2 messages
481         Assert.assertEquals(2, facesContext.getMessageList().size());
482         
483         // keep messages
484         _flash.setKeepMessages(true);
485         Assert.assertTrue("setKeepMessages(true) was just called, thus isKeepMessages() "
486                 + "must be true.", _flash.isKeepMessages());
487         
488         // set redirect to true, this happens by the NavigationHandler in phase 5
489         _flash.setRedirect(true);
490         Assert.assertTrue("setRedirect(true) was just called, thus isRedirect() must be true",
491                 _flash.isRedirect());
492         // The redirect cause responseComplete() method to be called.
493         facesContext.responseComplete();
494         // note that setRedirect(true) was called, thus the cleanup happens
495         // in phase 5, because doPostPhaseActions() won't be called on phase 6.
496         _flash.doPostPhaseActions(facesContext);
497         
498         // GET request of POST-REDIRECT-GET -----------------------------------
499         
500         // simulate a new request
501         _simulateNewRequest();
502         
503         // this request is not a postback
504         ((MockFacesContext20) facesContext).setPostback(false);
505         
506         // now the FacesContext must contain 0 messages (new request, new FacesContext)
507         Assert.assertEquals(0, facesContext.getMessageList().size());
508         
509         // simulate JSF lifecycle
510         // Note that doPrePhaseActions() is called on RESTORE_VIEW even
511         // though this request is not a postback.
512         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
513         _flash.doPrePhaseActions(facesContext);
514         
515         // simulate JSF lifecycle - JSF will immediately jump to phase 6
516         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
517         
518         // now the messages must be here again
519         Assert.assertEquals(2, facesContext.getMessageList().size());
520         Assert.assertEquals(Arrays.asList(messageClientId), facesContext.getMessageList("clientId"));
521         Assert.assertEquals(Arrays.asList(messageNoClientId), facesContext.getMessageList(null));
522         
523         // check isKeepMessages()
524         Assert.assertFalse("setKeepMessages(true) was not called on this request, thus "
525                 + "isKeepMessages() must be false.", _flash.isKeepMessages());
526         
527         _flash.doPostPhaseActions(facesContext);
528         
529         // second postback (after POST-REDIRECT-GET) --------------------------
530         
531         // simulate a new request
532         _simulateNewRequest();
533         
534         // this request should be a postback
535         ((MockFacesContext20) facesContext).setPostback(true);
536         
537         // now the FacesContext must contain 0 messages (new request, new FacesContext)
538         Assert.assertEquals(0, facesContext.getMessageList().size());
539         
540         // simulate JSF lifecycle
541         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
542         _flash.doPrePhaseActions(facesContext);
543         
544         // simulate JSF lifecycle
545         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
546         
547         // now the FacesContext must contain 0 messages, because 
548         // setKeepMessages(true) was not called on the GET-request
549         Assert.assertEquals(0, facesContext.getMessageList().size());
550         
551         // simulate JSF lifecycle
552         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
553         _flash.doPostPhaseActions(facesContext);
554     }
555     
556     /**
557      * Tests the functionality of keepMessages in a POST-REDIRECT-GET scenario.
558      * In this test case the messages are shipped from the POST to the GET and
559      * then also from the GET to the next postback.
560      * @throws Exception
561      */
562     @Test
563     public void testKeepMessagesPostRedirectGetTwoTimes() throws Exception
564     {
565         // simulate JSF lifecycle:
566         // note that doPrePhaseActions() only performs tasks on RESTORE_VIEW
567         // and doPostPhaseActions() only on the last phase.
568         
569         // initial request ----------------------------------------------------
570         
571         // this request is a normal GET request, and thus not a postback
572         ((MockFacesContext20) facesContext).setPostback(false);
573         
574         // simulate JSF lifecycle
575         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
576         _flash.doPrePhaseActions(facesContext);
577         
578         // simulate JSF lifecycle
579         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
580         _flash.doPostPhaseActions(facesContext);
581         
582         // first postback (POST of POST-REDIRECT-GET) -------------------------
583         
584         // simulate a new request
585         _simulateNewRequest();
586         
587         // this request should be a postback
588         ((MockFacesContext20) facesContext).setPostback(true);
589         
590         // simulate JSF lifecycle
591         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
592         _flash.doPrePhaseActions(facesContext);
593         
594         // simulate JSF lifecycle
595         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
596         
597         // add FacesMessages to the facesContext
598         FacesMessage messageClientId = new FacesMessage("message for clientId");
599         facesContext.addMessage("clientId", messageClientId);
600         FacesMessage messageNoClientId = new FacesMessage("message without clientId");
601         facesContext.addMessage(null, messageNoClientId);
602         
603         // now the FacesContext must contain 2 messages
604         Assert.assertEquals(2, facesContext.getMessageList().size());
605         
606         // keep messages
607         _flash.setKeepMessages(true);
608         Assert.assertTrue("setKeepMessages(true) was just called, thus isKeepMessages() "
609                 + "must be true.", _flash.isKeepMessages());
610         
611         // set redirect to true, this happens by the NavigationHandler in phase 5
612         _flash.setRedirect(true);
613         Assert.assertTrue("setRedirect(true) was just called, thus isRedirect() must be true",
614                 _flash.isRedirect());
615         // The redirect cause responseComplete() method to be called.
616         facesContext.responseComplete();
617         
618         // note that setRedirect(true) was called, thus the cleanup happens
619         // in phase 5, because doPostPhaseActions() won't be called on phase 6.
620         _flash.doPostPhaseActions(facesContext);
621         
622         // GET request of POST-REDIRECT-GET -----------------------------------
623         
624         // simulate a new request
625         _simulateNewRequest();
626         
627         // this request is not a postback
628         ((MockFacesContext20) facesContext).setPostback(false);
629         
630         // now the FacesContext must contain 0 messages (new request, new FacesContext)
631         Assert.assertEquals(0, facesContext.getMessageList().size());
632         
633         // simulate JSF lifecycle
634         // Note that doPrePhaseActions() is called on RESTORE_VIEW even
635         // though this request is not a postback.
636         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
637         _flash.doPrePhaseActions(facesContext);
638         
639         // simulate JSF lifecycle - JSF will immediately jump to phase 6
640         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
641         
642         // now the messages must be here again
643         Assert.assertEquals(2, facesContext.getMessageList().size());
644         Assert.assertEquals(Arrays.asList(messageClientId), facesContext.getMessageList("clientId"));
645         Assert.assertEquals(Arrays.asList(messageNoClientId), facesContext.getMessageList(null));
646         
647         // check isKeepMessages()
648         Assert.assertFalse("setKeepMessages(true) was not called on this request, thus "
649                 + "isKeepMessages() must be false.", _flash.isKeepMessages());
650         
651         // keep messages - again
652         _flash.setKeepMessages(true);
653         Assert.assertTrue("setKeepMessages(true) was just called, thus isKeepMessages() "
654                 + "must be true.", _flash.isKeepMessages());
655         // The redirect cause responseComplete() method to be called.
656         facesContext.responseComplete();
657         
658         _flash.doPostPhaseActions(facesContext);
659         
660         // second postback (after POST-REDIRECT-GET) --------------------------
661         
662         // simulate a new request
663         _simulateNewRequest();
664         
665         // this request should be a postback
666         ((MockFacesContext20) facesContext).setPostback(true);
667         
668         // now the FacesContext must contain 0 messages (new request, new FacesContext)
669         Assert.assertEquals(0, facesContext.getMessageList().size());
670         
671         // simulate JSF lifecycle
672         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
673         _flash.doPrePhaseActions(facesContext);
674         
675         // simulate JSF lifecycle
676         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
677         
678         // now the messages must be here again
679         Assert.assertEquals(2, facesContext.getMessageList().size());
680         Assert.assertEquals(Arrays.asList(messageClientId), facesContext.getMessageList("clientId"));
681         Assert.assertEquals(Arrays.asList(messageNoClientId), facesContext.getMessageList(null));
682         
683         // simulate JSF lifecycle
684         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
685         _flash.doPostPhaseActions(facesContext);
686         
687         // third postback -----------------------------------------------------
688         
689         // simulate a new request
690         _simulateNewRequest();
691         
692         // this request should be a postback
693         ((MockFacesContext20) facesContext).setPostback(true);
694         
695         // now the FacesContext must contain 0 messages (new request, new FacesContext)
696         Assert.assertEquals(0, facesContext.getMessageList().size());
697         
698         // simulate JSF lifecycle
699         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
700         _flash.doPrePhaseActions(facesContext);
701         
702         // simulate JSF lifecycle
703         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
704         
705         // now the FacesContext must contain 0 messages, because 
706         // setKeepMessages(true) was not called on the previous postback
707         Assert.assertEquals(0, facesContext.getMessageList().size());
708         
709         // simulate JSF lifecycle
710         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
711         _flash.doPostPhaseActions(facesContext);
712     }
713     
714     /**
715      * Test if setRedirect(true) works via _flash.put("redirect", true)
716      * and if isRedirect() is equal to _flash.get("redirect").
717      */
718     @Test
719     public void testSetRedirect()
720     {
721         Assert.assertFalse(_flash.isRedirect());
722         Assert.assertFalse((Boolean) _flash.get("redirect"));
723         
724         _flash.put("redirect", true);
725         
726         Assert.assertTrue(_flash.isRedirect());
727         Assert.assertTrue((Boolean) _flash.get("redirect"));
728     }
729     
730     /**
731      * Test if setKeepMessages(true) works via _flash.put("keepMessages", true)
732      * and if isKeepMessages() is equal to _flash.get("keepMessages").
733      */
734     @Test
735     public void testSetKeepMessages()
736     {
737         Assert.assertFalse(_flash.isKeepMessages());
738         Assert.assertFalse((Boolean) _flash.get("keepMessages"));
739         
740         _flash.put("keepMessages", true);
741         
742         Assert.assertTrue(_flash.isKeepMessages());
743         Assert.assertTrue((Boolean) _flash.get("keepMessages"));
744     }
745     
746     /**
747      * Tests the functionality of putNow().
748      */
749     @SuppressWarnings("unchecked")
750     @Test
751     public void testPutNow()
752     {
753         Map<String, Object> requestMap = externalContext.getRequestMap();
754         
755         // requestMap must NOT contain the key
756         Assert.assertNull(requestMap.get("flashkey"));
757         
758         _flash.putNow("flashkey", "flashvalue");
759         
760         // requestMap must contain the key
761         Assert.assertEquals("flashvalue", requestMap.get("flashkey"));
762     }
763     
764     /**
765      * Tests keep()
766      * @throws Exception
767      */
768     @Test
769     public void testKeep() throws Exception
770     {
771         // simulate JSF lifecycle:
772         // note that doPrePhaseActions() only performs tasks on RESTORE_VIEW
773         // and doPostPhaseActions() only on the last phase.
774         
775         // initial request ----------------------------------------------------
776         
777         // this request is a normal GET request, and thus not a postback
778         ((MockFacesContext20) facesContext).setPostback(false);
779         
780         // simulate JSF lifecycle
781         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
782         _flash.doPrePhaseActions(facesContext);
783         
784         // simulate JSF lifecycle
785         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
786         _flash.doPostPhaseActions(facesContext);
787         
788         // first postback -----------------------------------------------------
789         
790         // simulate a new request
791         _simulateNewRequest();
792         
793         // this request should be a postback
794         ((MockFacesContext20) facesContext).setPostback(true);
795         
796         // simulate JSF lifecycle
797         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
798         _flash.doPrePhaseActions(facesContext);
799         
800         // simulate JSF lifecycle
801         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
802         
803         // put a value into the request FlashMap
804         _flash.putNow("flashkey", "flashvalue");
805         
806         // and keep() it
807         _flash.keep("flashkey");
808         
809         // simulate JSF lifecycle
810         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
811         
812         // cleanup flash
813         _flash.doPostPhaseActions(facesContext);
814         
815         // second postback ----------------------------------------------------
816         
817         // simulate a new request
818         _simulateNewRequest();
819         
820         // this request should be a postback
821         ((MockFacesContext20) facesContext).setPostback(true);
822         
823         // simulate JSF lifecycle
824         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
825         _flash.doPrePhaseActions(facesContext);
826         
827         // simulate JSF lifecycle
828         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
829      
830         // the value must be in the executeMap
831         Assert.assertEquals("flashvalue", _flash.get("flashkey"));
832         
833         // simulate JSF lifecycle
834         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
835         
836         // cleanup flash
837         _flash.doPostPhaseActions(facesContext);
838     }
839     
840     /**
841      * Like testKeep(), but without calling keep() to keep the value.
842      * @throws Exception
843      */
844     @Test
845     public void testNotKeep() throws Exception
846     {
847         // simulate JSF lifecycle:
848         // note that doPrePhaseActions() only performs tasks on RESTORE_VIEW
849         // and doPostPhaseActions() only on RENDER_RESPONSE.
850         
851         // initial request ----------------------------------------------------
852         
853         // this request is a normal GET request, and thus not a postback
854         ((MockFacesContext20) facesContext).setPostback(false);
855         
856         // simulate JSF lifecycle
857         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
858         _flash.doPrePhaseActions(facesContext);
859         
860         // simulate JSF lifecycle
861         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
862         _flash.doPostPhaseActions(facesContext);
863         
864         // first postback -----------------------------------------------------
865         
866         // simulate a new request
867         _simulateNewRequest();
868         
869         // this request should be a postback
870         ((MockFacesContext20) facesContext).setPostback(true);
871         
872         // simulate JSF lifecycle
873         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
874         _flash.doPrePhaseActions(facesContext);
875         
876         // simulate JSF lifecycle
877         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
878         
879         // put a value into the request FlashMap
880         _flash.putNow("flashkey", "flashvalue");
881         
882         // and do NOT keep it.
883         
884         // simulate JSF lifecycle
885         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
886         
887         _flash.doPostPhaseActions(facesContext);
888         
889         // second postback ----------------------------------------------------
890         
891         // simulate a new request
892         _simulateNewRequest();
893         
894         // this request should be a postback
895         ((MockFacesContext20) facesContext).setPostback(true);
896         
897         // simulate JSF lifecycle
898         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
899         _flash.doPrePhaseActions(facesContext);
900         
901         // simulate JSF lifecycle
902         facesContext.setCurrentPhaseId(PhaseId.INVOKE_APPLICATION);
903      
904         // render FlashMap must be empty
905         Assert.assertNull(_flash.get("flashkey"));
906         
907         // simulate JSF lifecycle
908         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
909         
910         // cleanup flash
911         _flash.doPostPhaseActions(facesContext);
912     }
913     
914     /**
915      * Tests if the reading functions use _getFlashMapForReading()
916      * and if the writing functions use _getFlashMapForWriting().
917      */
918     @Test
919     public void testMapMethodsUseDifferentMaps() throws Exception
920     {
921         // simulate JSF lifecycle:
922         // note that doPrePhaseActions() only performs tasks on RESTORE_VIEW
923         // and doPostPhaseActions() only on RENDER_RESPONSE.
924         
925         // initial request ----------------------------------------------------
926         
927         // this request is a normal GET request, and thus not a postback
928         ((MockFacesContext20) facesContext).setPostback(false);
929         
930         // simulate JSF lifecycle
931         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
932         _flash.doPrePhaseActions(facesContext);
933         
934         // simulate JSF lifecycle
935         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
936         _flash.doPostPhaseActions(facesContext);
937         
938         // first postback -----------------------------------------------------
939         
940         // simulate a new request
941         _simulateNewRequest();
942         
943         // this request should be a postback
944         ((MockFacesContext20) facesContext).setPostback(true);
945         
946         // simulate JSF lifecycle
947         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
948         _flash.doPrePhaseActions(facesContext);
949         
950         // simulate JSF lifecycle
951         facesContext.setCurrentPhaseId(PhaseId.RENDER_RESPONSE);
952         
953         // in this configuration put() and get() are executed on different maps
954         
955         // there must not be a value with the key "flashkey"
956         Assert.assertNull(_flash.get("flashkey"));
957         
958         // put() always references the active FlashMap,
959         // which is the render FlashMap in this case (phase is render response)
960         _flash.put("flashkey", "flashvalue");
961         
962         // there must still not be a value with the key "flashkey"
963         // NOTE that get still references the execute FlashMap
964         Assert.assertNull(_flash.get("flashkey"));
965         
966         _flash.doPostPhaseActions(facesContext);
967     }
968     
969     /**
970      * Tests the implementation of the methods from the java.util.Map interface.
971      */
972     @Test
973     public void testMapMethods()
974     {
975         // ensure that _getActiveFlashMap() returns the execute FlashMap
976         facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
977         
978         // run assertions for an empty FlashMap
979         _noElementAssertions();
980         
981         // use put() to put a value into the map
982         _flash.put("flashkey", "flashvalue");
983         
984         // run assertions for the FlashMap with one element
985         _oneElementAssertions();
986         
987         // remove the key using remove();
988         _flash.remove("flashkey");
989         
990         _noElementAssertions();
991 
992         // use putAll() to put a value into the map
993         Map<String, Object> map = new HashMap<String, Object>();
994         map.put("flashkey", "flashvalue");
995         _flash.putAll(map);
996         
997         _oneElementAssertions();
998         
999         // use clear() to remove the value from the map
1000         _flash.clear();
1001         
1002         _noElementAssertions();
1003         
1004         // put the value into the map again
1005         _flash.put("flashkey", "flashvalue");
1006         
1007         _oneElementAssertions();
1008         
1009         // use the keySet to clear the map
1010         _flash.keySet().clear();
1011         
1012         _noElementAssertions();
1013     }
1014     
1015     /**
1016      * Utility method used by testMapMethods()
1017      */
1018     private void _noElementAssertions()
1019     {
1020         Assert.assertTrue(_flash.isEmpty());
1021         Assert.assertEquals(0, _flash.size());
1022         Assert.assertFalse(_flash.containsKey("flashkey"));
1023         Assert.assertFalse(_flash.containsValue("flashvalue"));
1024         Assert.assertEquals(Collections.emptySet(), _flash.keySet());
1025         Assert.assertNull(_flash.get("flashkey"));
1026         Assert.assertTrue(_flash.values().isEmpty());
1027     }
1028     
1029     /**
1030      * Utility method used by testMapMethods()
1031      */
1032     private void _oneElementAssertions()
1033     {
1034         Assert.assertFalse(_flash.isEmpty());
1035         Assert.assertEquals(1, _flash.size());
1036         Assert.assertTrue(_flash.containsKey("flashkey"));
1037         Assert.assertTrue(_flash.containsValue("flashvalue"));
1038         Assert.assertEquals(new HashSet<String>(Arrays.asList("flashkey")), _flash.keySet());
1039         Assert.assertEquals("flashvalue", _flash.get("flashkey"));
1040         Assert.assertTrue(_flash.values().contains("flashvalue"));
1041     }
1042     
1043     /**
1044      * Create new request, response, ExternalContext and FacesContext
1045      * to simulate a new request. Also resend any Cookies added to the
1046      * current request by the Flash implementation.
1047      * 
1048      * @throws Exception
1049      */
1050     private void _simulateNewRequest() throws Exception
1051     {
1052         // we will now have a cookie with the token for the new request
1053         Cookie renderTokenCookie = response.getCookie(FlashImpl.FLASH_RENDER_MAP_TOKEN);
1054         
1055         // the Cookie must exist
1056         Assert.assertNotNull(renderTokenCookie);
1057         
1058         // check for the redirect-cookie
1059         Cookie redirectCookie = response.getCookie(FlashImpl.FLASH_REDIRECT);
1060         
1061         // create new request, response, ExternalContext and FacesContext
1062         // to simulate a new request
1063         request = new MockHttpServletRequest(session);
1064         request.setServletContext(servletContext);
1065         response = new MockHttpServletResponse();
1066         setUpExternalContext();
1067         setUpFacesContext();
1068         
1069         facesContext.setApplication(application);
1070         
1071         // add the cookie to the new request
1072         request.addCookie(renderTokenCookie);
1073         
1074         // add the redirect-cookie to the new request, if exists
1075         if (redirectCookie != null)
1076         {
1077             // maxage == 0 means remove the cookie
1078             if (redirectCookie.getMaxAge() != 0)
1079             {
1080                 request.addCookie(redirectCookie);
1081             }
1082         }
1083     }
1084 
1085     /**
1086      * Adds isSecure() implementation to MockExternalContext20.
1087      *
1088      * TODO remove this one as soon as MyFaces-Test provides MockExternalContext21.
1089      */
1090     private static class MockExternalContext21 extends MockExternalContext20
1091     {
1092 
1093         private boolean secure = false;
1094 
1095         private MockExternalContext21(ServletContext context, HttpServletRequest request, HttpServletResponse response)
1096         {
1097             super(context, request, response);
1098         }
1099 
1100         @Override
1101         public boolean isSecure()
1102         {
1103             return secure;
1104         }
1105 
1106         public void setSecure(boolean secure)
1107         {
1108             this.secure = secure;
1109         }
1110     }
1111 
1112 }