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.application;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.assertNotNull;
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.Collections;
28  import java.util.HashMap;
29  import java.util.LinkedHashSet;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Set;
33  
34  import javax.faces.FactoryFinder;
35  import javax.faces.application.NavigationCase;
36  
37  import org.apache.myfaces.config.RuntimeConfig;
38  import org.apache.myfaces.config.element.NavigationRule;
39  import org.apache.myfaces.config.impl.digester.DigesterFacesConfigUnmarshallerImpl;
40  import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
41  import org.junit.Assert;
42  import org.junit.Test;
43  import org.xml.sax.SAXException;
44  
45  public class NavigationHandlerImplTest extends AbstractJsfTestCase
46  {
47  
48      private DigesterFacesConfigUnmarshallerImpl _digesterFacesConfigUnmarshaller;
49  
50      public NavigationHandlerImplTest()
51      {
52          super();
53      }
54      
55      @Override
56      public void setUp() throws Exception
57      {
58          super.setUp();
59          _digesterFacesConfigUnmarshaller = new DigesterFacesConfigUnmarshallerImpl(
60                  externalContext);
61      }
62      
63      @Override
64      protected void setFactories() throws Exception
65      {
66          super.setFactories();
67          FactoryFinder.setFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY,
68              "org.apache.myfaces.context.PartialViewContextFactoryImpl");
69      }
70  
71  
72      @Override
73      public void tearDown() throws Exception
74      {
75          _digesterFacesConfigUnmarshaller = null;
76          super.tearDown();
77      }
78  
79      private void loadTextFacesConfig(String file) throws SAXException,
80              IOException
81      {
82          RuntimeConfig runtimeConfig = RuntimeConfig
83                  .getCurrentInstance(externalContext);
84  
85          org.apache.myfaces.config.impl.digester.elements.FacesConfig config = _digesterFacesConfigUnmarshaller
86                  .getFacesConfig(getClass().getResourceAsStream(file), file);
87  
88          for (NavigationRule rule : config.getNavigationRules())
89          {
90              runtimeConfig.addNavigationRule(rule);
91          }
92      }
93  
94      @Test
95      public void testGetSimpleExactMatchRule() throws Exception
96      {
97          loadTextFacesConfig("simple-rules-config.xml");
98  
99          facesContext.getViewRoot().setViewId("/a.jsp");
100         NavigationHandlerImpl nh = new NavigationHandlerImpl();
101 
102         NavigationCase nc = nh.getNavigationCase(facesContext, null, "go");
103 
104         Assert.assertEquals("/b.jsp", nc.getToViewId(facesContext));
105     }
106 
107     @Test
108     public void testHandleSimpleExactMatchRule() throws Exception
109     {
110         loadTextFacesConfig("simple-rules-config.xml");
111 
112         facesContext.getViewRoot().setViewId("/a.jsp");
113         NavigationHandlerImpl nh = new NavigationHandlerImpl();
114 
115         nh.handleNavigation(facesContext, null, "go");
116 
117         Assert.assertEquals("/b.jsp", facesContext.getViewRoot().getViewId());
118     }
119 
120     @Test
121     public void testGetSimpleGlobalExactMatchRule() throws Exception
122     {
123         loadTextFacesConfig("simple-global-rules-config.xml");
124 
125         facesContext.getViewRoot().setViewId("/a.jsp");
126         NavigationHandlerImpl nh = new NavigationHandlerImpl();
127 
128         NavigationCase nc = nh.getNavigationCase(facesContext, null, "go");
129 
130         Assert.assertEquals("/b.jsp", nc.getToViewId(facesContext));
131     }
132 
133     @Test
134     public void testHandleSimpleGlobalExactMatchRule() throws Exception
135     {
136         loadTextFacesConfig("simple-global-rules-config.xml");
137 
138         facesContext.getViewRoot().setViewId("/a.jsp");
139         NavigationHandlerImpl nh = new NavigationHandlerImpl();
140 
141         nh.handleNavigation(facesContext, null, "go");
142 
143         Assert.assertEquals("/b.jsp", facesContext.getViewRoot().getViewId());
144     }
145     
146     @Test
147     public void testGetSimpleMixExactMatchRule() throws Exception
148     {
149         loadTextFacesConfig("simple-mix-rules-config.xml");
150 
151         facesContext.getViewRoot().setViewId("/a.jsp");
152         NavigationHandlerImpl nh = new NavigationHandlerImpl();
153 
154         NavigationCase nc = nh.getNavigationCase(facesContext, null, "go");
155 
156         Assert.assertEquals("/c.jsp", nc.getToViewId(facesContext));
157         
158         facesContext.getViewRoot().setViewId("/z.jsp");
159 
160         nc = nh.getNavigationCase(facesContext, null, "go");
161 
162         Assert.assertEquals("/b.jsp", nc.getToViewId(facesContext));
163     }
164 
165     @Test
166     public void testHandleSimpleMixExactMatchRule() throws Exception
167     {
168         loadTextFacesConfig("simple-mix-rules-config.xml");
169 
170         facesContext.getViewRoot().setViewId("/a.jsp");
171         NavigationHandlerImpl nh = new NavigationHandlerImpl();
172 
173         nh.handleNavigation(facesContext, null, "go");
174 
175         Assert.assertEquals("/c.jsp", facesContext.getViewRoot().getViewId());
176         
177         facesContext.getViewRoot().setViewId("/z.jsp");
178         
179         nh.handleNavigation(facesContext, null, "go");
180         
181         Assert.assertEquals("/b.jsp", facesContext.getViewRoot().getViewId());
182     }
183     
184     @Test
185     public void testGetSimplePartialExactMatchRule() throws Exception
186     {
187         loadTextFacesConfig("simple-partial-rules-config.xml");
188 
189         facesContext.getViewRoot().setViewId("/a.jsp");
190         NavigationHandlerImpl nh = new NavigationHandlerImpl();
191 
192         NavigationCase nc = nh.getNavigationCase(facesContext, null, "go");
193 
194         Assert.assertEquals("/cars/b.jsp", nc.getToViewId(facesContext));
195         
196         facesContext.getViewRoot().setViewId("/cars/z.jsp");
197 
198         nc = nh.getNavigationCase(facesContext, null, "go");
199 
200         Assert.assertEquals("/cars/c.jsp", nc.getToViewId(facesContext));
201     }
202 
203     @Test
204     public void testHandleSimplePartialExactMatchRule() throws Exception
205     {
206         loadTextFacesConfig("simple-partial-rules-config.xml");
207 
208         facesContext.getViewRoot().setViewId("/a.jsp");
209         NavigationHandlerImpl nh = new NavigationHandlerImpl();
210 
211         nh.handleNavigation(facesContext, null, "go");
212 
213         Assert.assertEquals("/cars/b.jsp", facesContext.getViewRoot().getViewId());
214         
215         facesContext.getViewRoot().setViewId("/cars/z.jsp");
216         
217         nh.handleNavigation(facesContext, null, "go");
218         
219         Assert.assertEquals("/cars/c.jsp", facesContext.getViewRoot().getViewId());
220     }
221     
222     @Test
223     public void testGetSimpleELExactMatchRule() throws Exception
224     {
225         loadTextFacesConfig("simple-el-rules-config.xml");
226 
227         facesContext.getViewRoot().setViewId("/a.jsp");
228         
229         NavigationHandlerImpl nh = new NavigationHandlerImpl();
230 
231         NavigationCase nc = nh.getNavigationCase(facesContext, "#{rules.go}", "go");
232 
233         Assert.assertEquals("/b.jsp", nc.getToViewId(facesContext));
234     }
235     
236     @Test
237     public void testGetSimpleELExactMatchRuleFailNullOutcome() throws Exception
238     {
239         loadTextFacesConfig("simple-el-rules-config.xml");
240 
241         facesContext.getViewRoot().setViewId("/a.jsp");
242         
243         NavigationHandlerImpl nh = new NavigationHandlerImpl();
244 
245         NavigationCase nc = nh.getNavigationCase(facesContext, "#{rules.go}", null);
246 
247         Assert.assertNull(nc);
248     }
249     
250     public static class TestBean
251     {
252         public boolean isTrue()
253         {
254             return true;
255         }
256         
257         public boolean isFalse()
258         {
259             return false;
260         }
261     }
262     
263     @Test
264     public void testGetSimpleIfExactMatchRule() throws Exception
265     {
266         loadTextFacesConfig("simple-if-rules-config.xml");
267 
268         externalContext.getRequestMap().put("test", new TestBean());
269         
270         facesContext.getViewRoot().setViewId("/a.jsp");
271         
272         NavigationHandlerImpl nh = new NavigationHandlerImpl();
273 
274         NavigationCase nc = nh.getNavigationCase(facesContext, null, "go");
275 
276         Assert.assertEquals("/b.jsp", nc.getToViewId(facesContext));
277     }
278     
279     @Test
280     public void testGetSimpleIfPreferMathRule() throws Exception
281     {
282         loadTextFacesConfig("simple-if-rules-config-2.xml");
283 
284         externalContext.getRequestMap().put("test", new TestBean());
285         
286         facesContext.getViewRoot().setViewId("/a.jsp");
287         
288         NavigationHandlerImpl nh = new NavigationHandlerImpl();
289 
290         NavigationCase nc = nh.getNavigationCase(facesContext, null, "go");
291 
292         Assert.assertEquals("/b.jsp", nc.getToViewId(facesContext));
293     }
294 
295     @Test
296     public void testGetSimpleNotIfExactMatchRule() throws Exception
297     {
298         loadTextFacesConfig("simple-if-rules-config.xml");
299 
300         externalContext.getRequestMap().put("test", new TestBean());
301         
302         facesContext.getViewRoot().setViewId("/b.jsp");
303         
304         NavigationHandlerImpl nh = new NavigationHandlerImpl();
305 
306         NavigationCase nc = nh.getNavigationCase(facesContext, null, "go");
307 
308         Assert.assertEquals("/d.jsp", nc.getToViewId(facesContext));
309     }
310     
311     @Test
312     public void testGetSimplePreemptiveIfExactMatchRule() throws Exception
313     {
314         loadTextFacesConfig("simple-if-rules-config.xml");
315 
316         externalContext.getRequestMap().put("test", new TestBean());
317         
318         facesContext.getViewRoot().setViewId("/x.jsp");
319         
320         NavigationHandlerImpl nh = new NavigationHandlerImpl();
321 
322         NavigationCase nc = nh.getNavigationCase(facesContext, null, "go");
323 
324         Assert.assertEquals("/go.jsp", nc.getToViewId(facesContext));
325     }    
326     
327     @Test
328     public void testGetSimpleGlobalPreemptiveMatchRule() throws Exception
329     {
330         loadTextFacesConfig("simple-global-preemptive-rules-config.xml");
331 
332         externalContext.getRequestMap().put("test", new TestBean());
333         
334         facesContext.getViewRoot().setViewId("/x.jsp");
335         
336         NavigationHandlerImpl nh = new NavigationHandlerImpl();
337 
338         NavigationCase nc = nh.getNavigationCase(facesContext, null, "go");
339 
340         Assert.assertEquals("/a.jsp", nc.getToViewId(facesContext));
341     }
342     
343     @Test
344     public void testGetSimpleELNoCondMatchRule() throws Exception
345     {
346         loadTextFacesConfig("simple-el-nocond-rules-config.xml");
347 
348         facesContext.getViewRoot().setViewId("/a.jsp");
349         
350         NavigationHandlerImpl nh = new NavigationHandlerImpl();
351 
352         NavigationCase nc = nh.getNavigationCase(facesContext, "#{rules.go}", "go");
353 
354         Assert.assertEquals("/b.jsp", nc.getToViewId(facesContext));
355     }
356     
357     @Test
358     public void testGetSimpleELNoCondNullOutcomeMatchRule() throws Exception
359     {
360         loadTextFacesConfig("simple-el-nocond-rules-config.xml");
361 
362         facesContext.getViewRoot().setViewId("/a.jsp");
363         
364         NavigationHandlerImpl nh = new NavigationHandlerImpl();
365 
366         NavigationCase nc = nh.getNavigationCase(facesContext, "#{rules.go}", null);
367 
368         Assert.assertNull(nc);
369     }
370     
371     @Test
372     public void testActionOutcomePrecendeceMachRule() throws Exception
373     {
374         loadTextFacesConfig("simple-action-outcome-precedence-config.xml");
375 
376         for (int i = 0; i < 2; i++)
377         {
378             final int j = i;
379             facesContext.getViewRoot().setViewId("/a.jsp");
380             
381             NavigationHandlerImpl nh = new NavigationHandlerImpl(){
382     
383                 @Override
384                 public Map<String, Set<NavigationCase>> getNavigationCases()
385                 {
386                     // We have two conditions, this code is for rotate the ordering so we
387                     // test all possible outputs
388                     Map<String, Set<NavigationCase>> map = super.getNavigationCases();
389                     Map<String, Set<NavigationCase>> map2 = new HashMap<String, Set<NavigationCase>>();
390                     
391                     for (Map.Entry<String, Set<NavigationCase>> entry : map.entrySet())
392                     {
393                         LinkedHashSet<NavigationCase> set = new LinkedHashSet<NavigationCase>();
394                         List<NavigationCase> list = new ArrayList<NavigationCase>();
395                         list.addAll(entry.getValue());
396                         Collections.rotate(list, j);
397                         set.addAll(list);
398                         map2.put(entry.getKey(), set);
399                     }
400                     return map2; 
401                 }
402             };
403     
404             NavigationCase nc = nh.getNavigationCase(facesContext, "#{rules.go}", "go");
405     
406             Assert.assertEquals("/b.jsp", nc.getToViewId(facesContext));
407         }
408     }
409     
410     @Test
411     public void testActionOutcomePrecendeceAlternateOutcomeMachRule() throws Exception
412     {
413         loadTextFacesConfig("simple-action-outcome-precedence-config.xml");
414 
415         for (int i = 0; i < 2; i++)
416         {
417             final int j = i;
418             facesContext.getViewRoot().setViewId("/a.jsp");
419             
420             NavigationHandlerImpl nh = new NavigationHandlerImpl(){
421     
422                 @Override
423                 public Map<String, Set<NavigationCase>> getNavigationCases()
424                 {
425                     // We have two conditions, this code is for rotate the ordering so we
426                     // test all possible outputs
427                     Map<String, Set<NavigationCase>> map = super.getNavigationCases();
428                     Map<String, Set<NavigationCase>> map2 = new HashMap<String, Set<NavigationCase>>();
429                     
430                     for (Map.Entry<String, Set<NavigationCase>> entry : map.entrySet())
431                     {
432                         LinkedHashSet<NavigationCase> set = new LinkedHashSet<NavigationCase>();
433                         List<NavigationCase> list = new ArrayList<NavigationCase>();
434                         list.addAll(entry.getValue());
435                         Collections.rotate(list, j);
436                         set.addAll(list);
437                         map2.put(entry.getKey(), set);
438                     }
439                     return map2; 
440                 }
441             };
442     
443             NavigationCase nc = nh.getNavigationCase(facesContext, "#{rules.go}", "nogo");
444     
445             Assert.assertEquals("/c.jsp", nc.getToViewId(facesContext));
446         }
447     }
448 
449     @Test
450     public void testActionOutcomePrecendeceNoOutcomeMachRule() throws Exception
451     {
452         loadTextFacesConfig("simple-action-outcome-precedence-config.xml");
453 
454         for (int i = 0; i < 2; i++)
455         {
456             final int j = i;
457             facesContext.getViewRoot().setViewId("/a.jsp");
458             
459             NavigationHandlerImpl nh = new NavigationHandlerImpl(){
460     
461                 @Override
462                 public Map<String, Set<NavigationCase>> getNavigationCases()
463                 {
464                     // We have two conditions, this code is for rotate the ordering so we
465                     // test all possible outputs
466                     Map<String, Set<NavigationCase>> map = super.getNavigationCases();
467                     Map<String, Set<NavigationCase>> map2 = new HashMap<String, Set<NavigationCase>>();
468                     
469                     for (Map.Entry<String, Set<NavigationCase>> entry : map.entrySet())
470                     {
471                         LinkedHashSet<NavigationCase> set = new LinkedHashSet<NavigationCase>();
472                         List<NavigationCase> list = new ArrayList<NavigationCase>();
473                         list.addAll(entry.getValue());
474                         Collections.rotate(list, j);
475                         set.addAll(list);
476                         map2.put(entry.getKey(), set);
477                     }
478                     return map2; 
479                 }
480             };
481     
482             NavigationCase nc = nh.getNavigationCase(facesContext, "#{rules.go}", null);
483     
484             //If the <if> element is absent, only match a non-null outcome
485             Assert.assertNull(nc);
486         }
487     }
488     
489     @Test
490     public void testActionOutcomePrecendece2MachRule() throws Exception
491     {
492         loadTextFacesConfig("simple-action-outcome-precedence-2-config.xml");
493 
494         for (int i = 0; i < 2; i++)
495         {
496             final int j = i;
497             facesContext.getViewRoot().setViewId("/a.jsp");
498             
499             NavigationHandlerImpl nh = new NavigationHandlerImpl(){
500     
501                 @Override
502                 public Map<String, Set<NavigationCase>> getNavigationCases()
503                 {
504                     // We have two conditions, this code is for rotate the ordering so we
505                     // test all possible outputs
506                     Map<String, Set<NavigationCase>> map = super.getNavigationCases();
507                     Map<String, Set<NavigationCase>> map2 = new HashMap<String, Set<NavigationCase>>();
508                     
509                     for (Map.Entry<String, Set<NavigationCase>> entry : map.entrySet())
510                     {
511                         LinkedHashSet<NavigationCase> set = new LinkedHashSet<NavigationCase>();
512                         List<NavigationCase> list = new ArrayList<NavigationCase>();
513                         list.addAll(entry.getValue());
514                         Collections.rotate(list, j);
515                         set.addAll(list);
516                         map2.put(entry.getKey(), set);
517                     }
518                     return map2; 
519                 }
520             };
521     
522             NavigationCase nc = nh.getNavigationCase(facesContext, "#{rules.go}", "go");
523     
524             Assert.assertEquals("/b.jsp", nc.getToViewId(facesContext));
525         }
526     }
527     
528     /**
529      * Tests if the URL parameters of an outcome are correctly
530      * added to the NavigationCase.
531      */
532     @Test
533     public void testFacesRedirectAddsUrlParameters()
534     {
535         NavigationHandlerImpl nh = new NavigationHandlerImpl();
536         
537         // get the NavigationCase
538         // note that the URL parameters can be separated via & or &amp;
539         NavigationCase navigationCase = nh.getNavigationCase(facesContext, null, 
540                 "test.xhtml?faces-redirect=true&a=b&amp;includeViewParams=true&amp;c=d&e=f");
541         
542         // created the expected parameter map
543         Map<String, List<String>> expected = new HashMap<String, List<String>>();
544         expected.put("a", Arrays.asList("b"));
545         expected.put("c", Arrays.asList("d"));
546         expected.put("e", Arrays.asList("f"));
547         // note that faces-redirect and includeViewParams
548         // should not be added as a parameter
549         
550         Assert.assertEquals(expected, navigationCase.getParameters());
551         Assert.assertTrue("includeViewParams=true in the query String must "
552                 + "set includeViewParams to true.", navigationCase.isIncludeViewParams());
553         Assert.assertTrue("redirect=true in the query String must "
554                 + "set redirect to true.", navigationCase.isRedirect());
555     }
556     
557     /**
558      * Tests if the URL parameters of an outcome are correctly
559      * added to the NavigationCase.
560      * Identically to testFacesRedirectAddsUrlParameters(), except that
561      * it uses faces-include-view-params=true instead of includeViewParams=true.
562      */
563     @Test
564     public void testFacesRedirectAddsUrlParametersFacesIncludeViewParams()
565     {
566         NavigationHandlerImpl nh = new NavigationHandlerImpl();
567         
568         // get the NavigationCase
569         // note that the URL parameters can be separated via & or &amp;
570         NavigationCase navigationCase = nh.getNavigationCase(facesContext, null, 
571                 "test.xhtml?faces-redirect=true&a=b&amp;faces-include-view-params=true&amp;c=d&e=f");
572         
573         // created the expected parameter map
574         Map<String, List<String>> expected = new HashMap<String, List<String>>();
575         expected.put("a", Arrays.asList("b"));
576         expected.put("c", Arrays.asList("d"));
577         expected.put("e", Arrays.asList("f"));
578         // note that faces-redirect and faces-include-view-params
579         // should not be added as a parameter
580         
581         Assert.assertEquals(expected, navigationCase.getParameters());
582         Assert.assertTrue("faces-include-view-params=true in the query String must "
583                 + "set includeViewParams to true.", navigationCase.isIncludeViewParams());
584         Assert.assertTrue("redirect=true in the query String must "
585                 + "set redirect to true.", navigationCase.isRedirect());
586     }
587     
588     /**
589      * Test for MYFACES-3101
590      */
591     @Test
592     public void testHandleViewExpiredExpcetion() throws Exception {
593         NavigationHandlerImpl underTest = new NavigationHandlerImpl();
594         // simulate no available ViewRoot (in case of VEE)
595         facesContext.setViewRoot(null);
596         
597         facesContext.getExternalContext().getRequestMap().put("javax.servlet.include.servlet_path", "/faces/home.xhtml");
598         // test is based on:
599         // http://www.nfjsone.com/blog/ed_burns/2009/09/dealing_gracefully_with_viewexpiredexception_in_jsf2
600         underTest.handleNavigation(facesContext, null, "viewExpired");
601 
602         assertNotNull(facesContext.getViewRoot());
603         assertEquals("/viewExpired.xhtml", facesContext.getViewRoot().getViewId());
604     }
605     
606     @Test
607     public void testHandleViewExpiredExpcetion2() throws Exception {
608         NavigationHandlerImpl underTest = new NavigationHandlerImpl();
609         // simulate no available ViewRoot (in case of VEE)
610         facesContext.setViewRoot(null);
611         
612         facesContext.getExternalContext().getRequestMap().put("javax.servlet.include.servlet_path", "/home.jsf");
613         // test is based on:
614         // http://www.nfjsone.com/blog/ed_burns/2009/09/dealing_gracefully_with_viewexpiredexception_in_jsf2
615         underTest.handleNavigation(facesContext, null, "viewExpired.xhtml");
616 
617         assertNotNull(facesContext.getViewRoot());
618         assertEquals("/viewExpired.xhtml", facesContext.getViewRoot().getViewId());
619         
620     }
621     
622     @Test
623     public void testHandleViewExpiredExpcetion3() throws Exception {
624         NavigationHandlerImpl underTest = new NavigationHandlerImpl();
625         // simulate no available ViewRoot (in case of VEE)
626         facesContext.setViewRoot(null);
627         
628         facesContext.getExternalContext().getRequestMap().put("javax.servlet.include.servlet_path", "/home.jsf");
629         // test is based on:
630         // http://www.nfjsone.com/blog/ed_burns/2009/09/dealing_gracefully_with_viewexpiredexception_in_jsf2
631         underTest.handleNavigation(facesContext, null, "viewExpired");
632 
633         assertNotNull(facesContext.getViewRoot());
634         
635         // In this case, we have /viewExpired.jsf, but note the default ViewHandlerImpl converts the viewId
636         // from /viewExpired.jsf to /viewExpired.xhtml, when deriveViewId() is called.
637         assertEquals("/viewExpired.jsf", facesContext.getViewRoot().getViewId());
638         
639     }
640 
641    @Test
642     public void testHandleViewExpiredExpcetion4() throws Exception {
643         NavigationHandlerImpl underTest = new NavigationHandlerImpl();
644         // simulate no available ViewRoot (in case of VEE)
645         facesContext.setViewRoot(null);
646         // test is based on:
647         // http://www.nfjsone.com/blog/ed_burns/2009/09/dealing_gracefully_with_viewexpiredexception_in_jsf2
648         underTest.handleNavigation(facesContext, null, "viewExpired.xhtml");
649 
650         assertNotNull(facesContext.getViewRoot());
651         assertEquals("/viewExpired.xhtml", facesContext.getViewRoot().getViewId());
652         
653     } 
654     
655     /**
656      * Test for MYFACES-3101 - partial request (without redirect)
657      */
658     @Test
659     public void testHandleViewExpiredExpcetionForPartial() throws Exception {
660         NavigationHandlerImpl underTest = new NavigationHandlerImpl();
661         // simulate no available ViewRoot (in case of VEE)
662         facesContext.setViewRoot(null);
663         facesContext.getPartialViewContext().setPartialRequest(true);
664         
665         underTest.handleNavigation(facesContext, null, "/viewExpired.xhtml");
666         
667         assertNotNull(facesContext.getViewRoot());
668         assertEquals("/viewExpired.xhtml", facesContext.getViewRoot().getViewId());
669     }
670 }