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.view.facelets.tag.ui.template;
20  
21  import java.io.StringWriter;
22  
23  import javax.faces.component.UIViewRoot;
24  
25  import org.apache.myfaces.test.mock.MockResponseWriter;
26  import org.apache.myfaces.view.facelets.FaceletTestCase;
27  import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
28  import org.junit.Assert;
29  import org.junit.Test;
30  
31  public class DecorateTestCase extends FaceletTestCase {
32  
33      @Override
34      protected void setUpServletObjects() throws Exception
35      {
36          super.setUpServletObjects();
37          servletContext.addInitParameter(FaceletViewDeclarationLanguage.PARAM_SKIP_COMMENTS, "true");
38      }
39  
40      @Test
41      public void testDecorate1() throws Exception {
42          UIViewRoot root = facesContext.getViewRoot();
43          vdl.buildView(facesContext, root, "decorate1.xhtml");
44          
45          StringWriter sw = new StringWriter();
46          MockResponseWriter mrw = new MockResponseWriter(sw);
47          facesContext.setResponseWriter(mrw);
48          root.encodeAll(facesContext);
49          sw.flush();
50          
51          String response = sw.toString();
52          Assert.assertTrue(response.contains("fragmentNumber1"));
53          Assert.assertTrue(response.contains("decorateContent"));
54          Assert.assertFalse(response.contains("This fragment will not be inserted"));
55          Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED"));
56          Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED TOO"));
57      }
58      
59      @Test
60      public void testDecorate2EmptyDecorate() throws Exception {
61          UIViewRoot root = facesContext.getViewRoot();
62          vdl.buildView(facesContext, root, "decorate2.xhtml");
63          
64          StringWriter sw = new StringWriter();
65          MockResponseWriter mrw = new MockResponseWriter(sw);
66          facesContext.setResponseWriter(mrw);
67          root.encodeAll(facesContext);
68          sw.flush();
69          
70          String response = sw.toString();
71          Assert.assertFalse(response.contains("This fragment will not be inserted"));
72          Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED"));
73          Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED TOO"));
74      }
75      
76      @Test
77      public void testDecorate3EmptyDecorate() throws Exception {
78          UIViewRoot root = facesContext.getViewRoot();
79          vdl.buildView(facesContext, root, "decorate3.xhtml");
80          
81          StringWriter sw = new StringWriter();
82          MockResponseWriter mrw = new MockResponseWriter(sw);
83          facesContext.setResponseWriter(mrw);
84          root.encodeAll(facesContext);
85          sw.flush();
86          
87          String response = sw.toString();
88          Assert.assertFalse(response.contains("This fragment will not be inserted"));
89          Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED"));
90          Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED TOO"));
91      }
92      
93      @Test
94      public void testDecorate4DefineOverInsert() throws Exception {
95          UIViewRoot root = facesContext.getViewRoot();
96          vdl.buildView(facesContext, root, "decorate4.xhtml");
97          
98          StringWriter sw = new StringWriter();
99          MockResponseWriter mrw = new MockResponseWriter(sw);
100         facesContext.setResponseWriter(mrw);
101         root.encodeAll(facesContext);
102         sw.flush();
103         
104         String response = sw.toString();
105         Assert.assertTrue(response.contains("fragmentNumber1"));
106         Assert.assertFalse(response.contains("This fragment will not be inserted"));
107         Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED"));
108         Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED TOO"));
109     }
110     
111     /**
112      * Based on
113      * 
114      * https://facelets.dev.java.net/issues/show_bug.cgi?id=256
115      * 
116      * In few words it says how two nested ui:decorate tags should be resolved.
117      * Note the difference between ui:composition and ui:decorate. Since the first one
118      * trims everything above and below, the page author can only use once per view, but
119      * with ui:decorate you can use more than once per view. Additionally, an ui:insert
120      * inside a ui:decorate, should take into account the outer one first.
121      * 
122      * @throws Exception
123      */
124     @Test
125     public void testDecorate5() throws Exception 
126     {
127         /*
128         decorate5.xhtml
129 
130         <ui:decorate template="/decorate5_1.xhtml">
131         decorate5Content
132         </ui:decorate>
133 
134         decorate5_1.xhtml
135 
136         <ui:composition>
137             start first decoration
138             <ui:decorate template="/decorate5_2.xhtml">
139               start inner text
140               <ui:insert />
141               end inner text
142             </ui:decorate>
143             end first decoration
144         </ui:composition>
145 
146         decorate5_2.xhtml
147 
148         <ui:composition>      
149             start second decoration
150             <ui:insert/>
151             end second decoration
152         </ui:composition>
153 
154         Result
155 
156             start first decoration
157              start second decoration
158               start inner text
159                decorate5Content
160               end inner text
161              end second decoration
162             end first decoration
163         */
164 
165         UIViewRoot root = facesContext.getViewRoot();
166         vdl.buildView(facesContext, root, "decorate5.xhtml");
167         
168         StringWriter sw = new StringWriter();
169         MockResponseWriter mrw = new MockResponseWriter(sw);
170         facesContext.setResponseWriter(mrw);
171         root.encodeAll(facesContext);
172         sw.flush();
173         
174         String response = sw.toString();
175 
176         Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED"));
177         Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED TOO"));
178         
179         response = checkStringInOrder(response, "start first decoration");
180         response = checkStringInOrder(response, "start second decoration");
181         response = checkStringInOrder(response, "start inner text");
182         response = checkStringInOrder(response, "decorate5Content");
183         response = checkStringInOrder(response, "end inner text");
184         response = checkStringInOrder(response, "end second decoration");
185         response = checkStringInOrder(response, "end first decoration");
186     }
187     
188     private String checkStringInOrder(String response, String token)
189     {
190         int pos = response.indexOf(token);
191         Assert.assertTrue(pos > -1);
192         return response.substring(pos+token.length());
193     }
194 
195     /**
196      * An outer ui:decorate definition takes precedence over an inner
197      * ui:composition definition.
198      * 
199      * @throws Exception
200      */
201     @Test
202     public void testDecorateNested1() throws Exception {
203         /*
204         decorate4.xhtml
205 
206         <ui:decorate template="/composition4.xhtml">
207           <ui:define name="fragment1">
208             fragmentNumber2
209           </ui:define>
210         fragmentNumber3
211         </ui:decorate>
212 
213         composition4.xhtml
214 
215         <ui:composition template="/template1.xhtml">
216           <ui:define name="fragment1">
217             fragmentNumber1
218           </ui:define>
219         </ui:composition>
220 
221         template1.xhtml
222 
223         <ui:composition>
224           <ui:insert>
225             This fragment will not be inserted
226           </ui:insert>
227           <ui:insert name="fragment1">
228             fragmentNumber1
229           </ui:insert>
230         </ui:composition>
231 
232         Response
233 
234             fragmentNumber3
235             fragmentNumber2
236 
237         */
238 
239         UIViewRoot root = facesContext.getViewRoot();
240         vdl.buildView(facesContext, root, "decorateNested1.xhtml");
241         
242         StringWriter sw = new StringWriter();
243         MockResponseWriter mrw = new MockResponseWriter(sw);
244         facesContext.setResponseWriter(mrw);
245         root.encodeAll(facesContext);
246         sw.flush();
247         
248         String response = sw.toString();
249         Assert.assertTrue(response.contains("fragmentNumber3"));
250         Assert.assertTrue(response.contains("fragmentNumber2"));
251         Assert.assertFalse(response.contains("fragmentNumber1"));
252         Assert.assertFalse(response.contains("This fragment will not be inserted"));
253         Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED"));
254         Assert.assertTrue(response.contains("THIS SHOULD BE RENDERED TOO"));
255     }
256     
257     
258     @Test
259     public void testDecorateNested2() throws Exception
260     {
261         /*
262         decorateNested2.xhtml
263         
264         <ui:composition>
265           <ui:decorate template="/decorateNested2_1.xhtml">
266             <ui:define name="fragment1">
267               decorateNested2Content
268             </ui:define>
269           </ui:decorate>
270         </ui:composition>
271       
272         decorateNested2_1.xhtml
273         
274         <ui:composition>
275             start first decoration
276             <ui:decorate template="/decorateNested2_2.xhtml">
277               <ui:define name="fragment1">
278                 start inner text
279                   <ui:insert name="fragment1"/>
280                 end inner text
281               </ui:define>
282             </ui:decorate>
283             end first decoration
284         </ui:composition>
285         
286         decorateNested2_2.xhtml
287     
288         <ui:composition>
289             start second composition
290             <ui:insert name="fragment1"/>
291             end second composition
292         </ui:composition>
293         
294         Response
295         
296         start first decoration
297         start second composition
298         start inner text
299         decorateNested2Content
300         end inner text
301         end second composition
302         end first decoration
303         
304         */
305         
306         UIViewRoot root = facesContext.getViewRoot();
307         vdl.buildView(facesContext, root, "decorateNested2.xhtml");
308         
309         StringWriter sw = new StringWriter();
310         MockResponseWriter mrw = new MockResponseWriter(sw);
311         facesContext.setResponseWriter(mrw);
312         root.encodeAll(facesContext);
313         sw.flush();
314         
315         String response = sw.toString();
316 
317         response = checkStringInOrder(response, "start first decoration");
318         response = checkStringInOrder(response, "start second composition");
319         response = checkStringInOrder(response, "start inner text");
320         response = checkStringInOrder(response, "decorateNested2Content");
321         response = checkStringInOrder(response, "end inner text");
322         response = checkStringInOrder(response, "end second composition");
323         response = checkStringInOrder(response, "end first decoration");
324     }
325 }