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.extensions.validator.test;
20  
21  import java.io.StringWriter;
22  import java.net.URL;
23  import java.net.URLClassLoader;
24  import java.util.Iterator;
25  
26  import javax.faces.FactoryFinder;
27  import javax.faces.el.ValueBinding;
28  import javax.faces.application.ApplicationFactory;
29  import javax.faces.component.UIViewRoot;
30  import javax.faces.component.UIInput;
31  import javax.faces.context.FacesContext;
32  import javax.faces.event.PhaseEvent;
33  import javax.faces.event.PhaseId;
34  import javax.faces.render.RenderKit;
35  import javax.faces.render.RenderKitFactory;
36  
37  import junit.framework.TestCase;
38  
39  import org.apache.myfaces.extensions.validator.core.renderkit.DefaultRenderKitWrapperFactory;
40  import org.apache.myfaces.extensions.validator.core.startup.ExtValStartupListener;
41  import org.apache.myfaces.extensions.validator.crossval.CrossValidationPhaseListener;
42  import org.apache.myfaces.extensions.validator.test.crossval.MockValidationStrategyFactory;
43  import org.apache.myfaces.extensions.validator.test.util.TestUtils;
44  import org.apache.myfaces.extensions.validator.util.ExtValUtils;
45  import org.apache.myfaces.extensions.validator.ExtValInformation;
46  import org.apache.myfaces.extensions.validator.PropertyValidationModuleStartupListener;
47  import org.apache.myfaces.shared_impl.config.MyfacesConfig;
48  import org.apache.shale.test.mock.MockApplication;
49  import org.apache.shale.test.mock.MockExternalContext;
50  import org.apache.shale.test.mock.MockFacesContext;
51  import org.apache.shale.test.mock.MockFacesContextFactory;
52  import org.apache.shale.test.mock.MockHttpServletRequest;
53  import org.apache.shale.test.mock.MockHttpServletResponse;
54  import org.apache.shale.test.mock.MockHttpSession;
55  import org.apache.shale.test.mock.MockLifecycle;
56  import org.apache.shale.test.mock.MockLifecycleFactory;
57  import org.apache.shale.test.mock.MockRenderKit;
58  import org.apache.shale.test.mock.MockResponseWriter;
59  import org.apache.shale.test.mock.MockServletConfig;
60  import org.apache.shale.test.mock.MockServletContext;
61  
62  /**
63   * Abstract Shale Test base class, which sets up the JSF environment.  If the test
64   * overrides <code>setUp()</code> and/or <code>tearDown()</code>, then those
65   * methods but call the overwitten method to insure a valid test environment.
66   */
67  public abstract class AbstractExValViewControllerTestCase extends TestCase
68  {
69      protected MockApplication application;
70      protected MockServletConfig config;
71      protected MockExternalContext externalContext;
72      protected MockFacesContext facesContext;
73      protected MockFacesContextFactory facesContextFactory;
74      protected MockLifecycle lifecycle;
75      protected MockLifecycleFactory lifecycleFactory;
76      protected RenderKit renderKit;
77      protected MockHttpServletRequest request;
78      protected MockHttpServletResponse response;
79      protected MockServletContext servletContext;
80      protected MockHttpSession session;
81      private ClassLoader threadContextClassLoader;
82          
83      /** Response Writer */
84      private MockResponseWriter writer;
85  
86      /**
87       * Construct a new instance of the test.
88       * 
89       * @param name Name of the test.
90       */
91      public AbstractExValViewControllerTestCase(String name)
92      {
93          super(name);
94          application = null;
95          config = null;
96          externalContext = null;
97          facesContext = null;
98          facesContextFactory = null;
99          lifecycle = null;
100         lifecycleFactory = null;
101         renderKit = null;
102         request = null;
103         response = null;
104         servletContext = null;
105         session = null;
106         threadContextClassLoader = null;
107     }
108 
109     /**
110      *  Setup the test environment, including the following:
111      *  <ul>
112      *  <li>Set the Application Map.</li>
113      *  <li>Set a response writer</li>
114      *  <li>Add Tomahawk's renderers to the faces context.</li>
115      *  </ul> 
116      */
117     protected void setUp() throws Exception
118     {
119         threadContextClassLoader = Thread.currentThread().getContextClassLoader();
120         Thread.currentThread().setContextClassLoader(new URLClassLoader(new URL[0], getClass().getClassLoader()));
121         servletContext = new MockServletContext();
122         //for testing the fallback
123         //servletContext.addInitParameter(ExtValInformation.WEBXML_PARAM_PREFIX + ".DEACTIVATE_EL_RESOLVER", "true");
124         servletContext.addInitParameter(ExtValInformation.WEBXML_PARAM_PREFIX + ".CUSTOM_VALIDATION_STRATEGY_FACTORY", MockValidationStrategyFactory.class.getName());
125         config = new MockServletConfig(servletContext);
126         session = new MockHttpSession();
127         session.setServletContext(servletContext);
128         request = new MockHttpServletRequest(session);
129         request.setServletContext(servletContext);
130         response = new MockHttpServletResponse();
131         FactoryFinder.releaseFactories();
132         FactoryFinder.setFactory("javax.faces.application.ApplicationFactory", "org.apache.shale.test.mock.MockApplicationFactory");
133         FactoryFinder.setFactory("javax.faces.context.FacesContextFactory", "org.apache.shale.test.mock.MockFacesContextFactory");
134         FactoryFinder.setFactory("javax.faces.lifecycle.LifecycleFactory", "org.apache.shale.test.mock.MockLifecycleFactory");
135         FactoryFinder.setFactory("javax.faces.render.RenderKitFactory", "org.apache.shale.test.mock.MockRenderKitFactory");
136         externalContext = new MockExternalContext(servletContext, request, response);
137         lifecycleFactory = (MockLifecycleFactory)FactoryFinder.getFactory("javax.faces.lifecycle.LifecycleFactory");
138         lifecycle = (MockLifecycle)lifecycleFactory.getLifecycle("DEFAULT");
139         facesContextFactory = (MockFacesContextFactory)FactoryFinder.getFactory("javax.faces.context.FacesContextFactory");
140         facesContext = (MockFacesContext)facesContextFactory.getFacesContext(servletContext, request, response, lifecycle);
141         externalContext = (MockExternalContext)facesContext.getExternalContext();
142         UIViewRoot root = new UIViewRoot();
143         root.setViewId("/viewId");
144         root.setRenderKitId("HTML_BASIC");
145         facesContext.setViewRoot(root);
146         ApplicationFactory applicationFactory = (ApplicationFactory)FactoryFinder.getFactory("javax.faces.application.ApplicationFactory");
147         application = (MockApplication)applicationFactory.getApplication();
148         facesContext.setApplication(application);
149         RenderKitFactory renderKitFactory = (RenderKitFactory)FactoryFinder.getFactory("javax.faces.render.RenderKitFactory");
150         //Wrap renderers with proper exval wrapper
151         renderKit = new DefaultRenderKitWrapperFactory().create(new MockRenderKit());
152         renderKitFactory.addRenderKit("HTML_BASIC", renderKit);        
153         
154         // additional setup not provided automatically by the shale mock stuff
155         facesContext.getExternalContext().getApplicationMap().put(MyfacesConfig.class.getName(), new MyfacesConfig());
156         writer = new MockResponseWriter(new StringWriter(), null, null);
157         facesContext.setResponseWriter(writer);
158 
159         TestUtils.addDefaultRenderers(facesContext);
160         TestUtils.addDefaultValidators(facesContext);
161 
162         //execute startup listener
163         new ExtValStartupListener() {
164             @Override
165             protected void init()
166             {
167                 super.init();
168             }
169         }.init();
170 
171         new PropertyValidationModuleStartupListener(){
172             @Override
173             protected void init()
174             {
175                 super.init();
176             }
177         }.init();
178     }
179 
180     /**
181      * Tear down the test environment.
182      */
183     protected void tearDown() throws Exception
184     {
185         application = null;
186         config = null;
187         externalContext = null;
188         facesContext.release();
189         facesContext = null;
190         lifecycle = null;
191         lifecycleFactory = null;
192         renderKit = null;
193         request = null;
194         response = null;
195         servletContext = null;
196         session = null;
197         FactoryFinder.releaseFactories();
198         Thread.currentThread().setContextClassLoader(threadContextClassLoader);
199         threadContextClassLoader = null;
200     }
201     
202     protected void processCrossValValidation()
203     {
204         new CrossValidationPhaseListener().afterPhase(new PhaseEvent((FacesContext)facesContext,PhaseId.ANY_PHASE,lifecycle));
205     }
206     
207     protected void checkMessageCount(int expected)
208     {
209         int actual = 0;
210         for(Iterator messages = facesContext.getMessages(); messages.hasNext();)
211         {
212             messages.next();
213             actual++;
214         }
215 
216         assertEquals("Complete message count", expected, actual);
217     }
218 
219     protected void checkMessageCount(String clientId, int expected)
220     {
221         int actual = 0;
222         for(Iterator messages = facesContext.getMessages(clientId); messages.hasNext();)
223         {
224             messages.next();
225             actual++;
226         }
227 
228         assertEquals("Complete message count", expected, actual);
229     }
230     
231     /**
232      * Verify the following:
233      * <ul>
234      * <li>id is not null</li>
235      * <li>Response is complete</li>
236      * <li>Responce contains the id</li>
237      * </ul>
238      * 
239      * @param id ID to verify
240      */
241     protected void assertIdExists(String id)
242     {
243         assertNotNull("ID is not null", id);
244         assertTrue("Response Complete", facesContext.getResponseComplete());
245         String output = writer.getWriter().toString();
246         assertNotNull("Has output", output);
247         assertTrue("Contains id '" + id + "'", output.indexOf(id) != -1);
248     }
249 
250     protected void createValueBinding(UIInput uiInput, String name, String expression)
251     {
252         ValueBinding valueBinding = application.createValueBinding(expression);
253 
254         if(uiInput != null)
255         {
256             uiInput.setValueBinding(name, valueBinding);
257         }
258     }
259 
260     protected void createRequestScopedBean(String name, Object instance)
261     {
262         createValueBinding(null, "value", "#{" + name + "}");
263         facesContext.getExternalContext().getRequestMap().put(name, instance);
264     }
265 
266     protected <T> T resolveBean(String name, Class<T> targetClass)
267     {
268         return (T) ExtValUtils.getELHelper().getBean(name);
269     }
270 }