Package org.jboss.seam.mock

Source Code of org.jboss.seam.mock.SeamTest$Request

/*
�* JBoss, Home of Professional Open Source
�*
�* Distributable under LGPL license.
�* See terms of license at gnu.org.
�*/
package org.jboss.seam.mock;

import java.lang.reflect.Field;
import java.util.AbstractSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.transaction.UserTransaction;

import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.jboss.seam.Component;
import org.jboss.seam.Model;
import org.jboss.seam.actionparam.ActionParamMethodBinding;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.Lifecycle;
import org.jboss.seam.core.Expressions;
import org.jboss.seam.core.FacesMessages;
import org.jboss.seam.core.Init;
import org.jboss.seam.core.Manager;
import org.jboss.seam.core.Pageflow;
import org.jboss.seam.init.Initialization;
import org.jboss.seam.jsf.AbstractSeamPhaseListener;
import org.jboss.seam.jsf.SeamApplication11;
import org.jboss.seam.jsf.SeamNavigationHandler;
import org.jboss.seam.jsf.SeamPhaseListener;
import org.jboss.seam.jsf.SeamStateManager;
import org.jboss.seam.servlet.ServletSessionImpl;
import org.jboss.seam.util.Naming;
import org.jboss.seam.util.Reflections;
import org.jboss.seam.util.Transactions;
import org.testng.annotations.Configuration;

/**
* Superclass for TestNG integration tests for JSF/Seam applications.
*
* @author Gavin King
* @author <a href="mailto:theute@jboss.org">Thomas Heute</a>
* @version $Revision: 1.65 $
*/
public class SeamTest
{

   private MockExternalContext externalContext;
   private MockServletContext servletContext;
   private MockApplication application;
   private AbstractSeamPhaseListener phases;
   private MockHttpSession session;
   private Map<String, Map> conversationViewRootAttributes;
   private Map<String, Object> pageParameters = new HashMap<String, Object>();
  
   protected void setParameter(String name, String value)
   {
      getParameters().put( name, new String[] {value} );
   }
  
   protected void setPageParameter(String name, Object value)
   {
      pageParameters.put(name, value);
   }
  
   protected Map<String, String[]> getParameters()
   {
      return ( (MockHttpServletRequest) externalContext.getRequest() ).getParameters();
   }
  
   protected Map<String, String[]> getHeaders()
   {
      return ( (MockHttpServletRequest) externalContext.getRequest() ).getHeaders();
   }
  
   protected HttpSession getSession()
   {
      return (HttpSession) externalContext.getSession(true);
   }
  
   protected boolean isSessionInvalid()
   {
      return ( (MockHttpSession) getSession() ).isInvalid();
   }
  
   /**
    * Helper method for resolving components in
    * the test script.
    */
   protected Object getInstance(Class clazz)
   {
      return Component.getInstance(clazz);
   }
  
   /**
    * Helper method for resolving components in
    * the test script.
    */
   protected Object getInstance(String name)
   {
      return Component.getInstance(name);
   }
  
   /**
    * Is there a long running conversation associated
    * with the current request?
    */
   protected boolean isLongRunningConversation() {
      return Manager.instance().isLongRunningConversation();
   }
  
   /**
    * Search in all contexts
    */
   public Object lookup(String name) {
      return Contexts.lookupInStatefulContexts(name);
   }
  
   /**
    * @deprecated use FacesRequest or NonFacesRequest
    * @author Gavin King
    */
   public abstract class Script extends Request {
      public Script() {}
      public Script(String conversationId)
      {
         super(conversationId);
      }
   }
  
   /**
    * Script is an abstract superclass for usually anonymous 
    * inner classes that test JSF interactions.
    *
    * @author Gavin King
    */
   abstract class Request
   {
      private String conversationId;
      private String outcome;
      private boolean validationFailed;
      private MockFacesContext facesContext;
      private String viewId;
      private boolean renderResponseBegun;
      private boolean renderResponseComplete;
      private boolean invokeApplicationBegun;
      private boolean invokeApplicationComplete;
      private Application application;
     
      /**
       * Override to define the name of the current principal
       *
       * @return "gavin" by default
       */
      public String getPrincipalName()
      {
         return "gavin";
      }
     
      /**
       * Override to define the roles assigned to the current principal
       *
       * @return a Set of all roles by default
       */
      public Set<String> getPrincipalRoles()
      {
         return new AbstractSet<String>() {
            @Override
            public boolean contains(Object o)
            {
               return true;
            }
            @Override
            public Iterator<String> iterator()
            {
               throw new UnsupportedOperationException();
            }
            @Override
            public int size()
            {
               throw new UnsupportedOperationException();
            }
         };
      }
     
      public List<Cookie> getCookies()
      {
         return Collections.EMPTY_LIST;
      }
     
      /**
       * A script for a JSF interaction with
       * no existing long-running conversation.
       */
      protected Request() {}
     
      /**
       * A script for a JSF interaction in the
       * scope of an existing long-running
       * conversation.
       */
      protected Request(String conversationId)
      {
         this.conversationId = conversationId;
      }
     
      /**
       * Is this a non-faces request? Override
       * if it is.
       *
       * @return false by default
       */
      protected boolean isGetRequest()
      {
         return false;
      }
     
      /**
       * The JSF view id of the form that is being submitted
       * or of the page that is being rendered in a non-faces
       * request.
       * (override if you need page actions to be called,
       * and page parameters applied)
       */
      protected String getViewId()
      {
         return viewId;
      }
     
      protected void setViewId(String viewId)
      {
         this.viewId = viewId;
      }
     
      /**
       * Override to implement the interactions between
       * the JSF page and your components that occurs
       * during the apply request values phase.
       */
      protected void applyRequestValues() throws Exception {}
      /**
       * Override to implement the interactions between
       * the JSF page and your components that occurs
       * during the process validations phase.
       */
      protected void processValidations() throws Exception {}
      /**
       * Override to implement the interactions between
       * the JSF page and your components that occurs
       * during the update model values phase.
       */
      protected void updateModelValues() throws Exception {}
      /**
       * Override to implement the interactions between
       * the JSF page and your components that occurs
       * during the invoke application phase.
       */
      protected void invokeApplication() throws Exception {}
      /**
       * Set the outcome of the INVOKE_APPLICATION phase
       */
      protected void setOutcome(String outcome) { this.outcome = outcome; }
      /**
       * Get the outcome of the INVOKE_APPLICATION phase
       */
      protected String getInvokeApplicationOutcome() { return outcome; }
      /**
       * Override to implement the interactions between
       * the JSF page and your components that occurs
       * during the render response phase.
       */
      protected void renderResponse() throws Exception {}
      /**
       * Override to set up any request parameters for
       * the request.
       *
       * @deprecated use beforeRequest()
       */
      protected void setup() {}
      /**
       * Make some assertions, after the end of the request.
       */
      protected void afterRequest() {}
      /**
       * Do anything you like, after the start of the request.
       * Especially, set up any request parameters for the
       * request.
       */
      protected void beforeRequest() {
         setup();
      }
      /**
       * Get the view id to be rendered
       *
       * @return the JSF view id
       */
      protected String getRenderedViewId()
      {
         if ( Init.instance().isJbpmInstalled() && Pageflow.instance().isInProcess() )
         {
            return Pageflow.instance().getPageViewId();
         }
         else
         {
            //TODO: not working right now, 'cos no mock navigation handler!
            return getFacesContext().getViewRoot().getViewId();
         }
      }
     
      /**
       * @deprecated use validateValue()
       */
      protected void validate(Class modelClass, String property, Object value)
      {
         ClassValidator validator = Model.forClass(modelClass).getValidator();
         InvalidValue[] ivs = validator.getPotentialInvalidValues(property, value);
         if (ivs.length>0)
         {
            validationFailed = true;
            FacesMessage message = FacesMessages.createFacesMessage( FacesMessage.SEVERITY_WARN, ivs[0].getMessage() );
            FacesContext.getCurrentInstance().addMessage( property, /*TODO*/ message );
            FacesContext.getCurrentInstance().renderResponse();
         }
      }
     
      /**
       * Did a validation failure occur during a call to validate()?
       */
      protected boolean isValidationFailure()
      {
         return validationFailed;
      }
     
      protected FacesContext getFacesContext()
      {
         return facesContext;
      }
     
      protected String getConversationId()
      {
         return conversationId;
      }
     
      /**
       * Evaluate (get) a value binding
       */
      protected Object getValue(String valueExpression)
      {
         return application.createValueBinding(valueExpression).getValue(facesContext);
      }

      /**
       * Set a value binding
       */
      protected void setValue(String valueExpression, Object value)
      {
         application.createValueBinding(valueExpression).setValue(facesContext, value);
      }
     
      /**
       * Validate the value against model-based constraints
       * return true if the value is valid
       */
      protected boolean validateValue(String valueExpression, Object value)
      {
         InvalidValue[] ivs = Expressions.instance().validate(valueExpression, value);
         if (ivs.length>0)
         {
            validationFailed = true;
            facesContext.addMessage( null, FacesMessages.createFacesMessage( FacesMessage.SEVERITY_WARN, ivs[0].getMessage() ) );
            return false;
         }
         else
         {
            return true;
         }
      }

      /**
       * Call a method binding
       */
      protected Object invokeMethod(String methodExpression)
      {
         return new ActionParamMethodBinding(application, methodExpression).invoke(facesContext, null);
      }

      /**
       * @return the conversation id
       * @throws Exception to fail the test
       */
      public String run() throws Exception
      {  
         HttpServletRequest request = new MockHttpServletRequest( session, getPrincipalName(), getPrincipalRoles(), getCookies().toArray( new Cookie[]{} ) );
         externalContext = new MockExternalContext(servletContext, request);
         application = new SeamApplication11(SeamTest.this.application);
         facesContext = new MockFacesContext( externalContext, application );
         facesContext.setCurrent();
        
         beforeRequest();

         phases.beforePhase( new PhaseEvent(facesContext, PhaseId.RESTORE_VIEW, MockLifecycle.INSTANCE) );
        
         UIViewRoot viewRoot = facesContext.getApplication().getViewHandler().createView( facesContext, getViewId() );
         facesContext.setViewRoot(viewRoot);
         Map restoredViewRootAttributes = facesContext.getViewRoot().getAttributes();
         if ( conversationId!=null )
         {
            if ( isGetRequest() )
            {
               setParameter( Manager.instance().getConversationIdParameter(), conversationId );
               //TODO: what about conversationIsLongRunning????
            }
            else
            {
               if ( conversationViewRootAttributes.containsKey(conversationId) )
               {
                  //should really only do this if the view id matches (not really possible to implement)
                  Map state = conversationViewRootAttributes.get(conversationId);
                  restoredViewRootAttributes.putAll(state);
               }
            }
         }
         if ( !isGetRequest() )
         {
            restoredViewRootAttributes.putAll(pageParameters);
         }
        
         updateConversationId();
        
         phases.afterPhase( new PhaseEvent(facesContext, PhaseId.RESTORE_VIEW, MockLifecycle.INSTANCE) );
        
         if ( !isGetRequest() && !skipToRender() )
         {
        
            phases.beforePhase( new PhaseEvent(facesContext, PhaseId.APPLY_REQUEST_VALUES, MockLifecycle.INSTANCE) );
           
            applyRequestValues();
           
            updateConversationId();
     
            phases.afterPhase( new PhaseEvent(facesContext, PhaseId.APPLY_REQUEST_VALUES, MockLifecycle.INSTANCE) );
           
            if ( !skipToRender() )
            {
           
               phases.beforePhase( new PhaseEvent(facesContext, PhaseId.PROCESS_VALIDATIONS, MockLifecycle.INSTANCE) );
              
               processValidations();
              
               updateConversationId();
              
               phases.afterPhase( new PhaseEvent(facesContext, PhaseId.PROCESS_VALIDATIONS, MockLifecycle.INSTANCE) );
  
               if ( !skipToRender() )
               {
           
                  phases.beforePhase( new PhaseEvent(facesContext, PhaseId.UPDATE_MODEL_VALUES, MockLifecycle.INSTANCE) );
                 
                  updateModelValues();
                 
                  updateConversationId();
           
                  phases.afterPhase( new PhaseEvent(facesContext, PhaseId.UPDATE_MODEL_VALUES, MockLifecycle.INSTANCE) );
  
                  if ( !skipToRender() )
                  {
              
                     phases.beforePhase( new PhaseEvent(facesContext, PhaseId.INVOKE_APPLICATION, MockLifecycle.INSTANCE) );
                 
                     invokeApplicationBegun = true;
                    
                     invokeApplication();
                    
                     invokeApplicationComplete = true;
                 
                     String outcome = getInvokeApplicationOutcome();
                     facesContext.getApplication().getNavigationHandler().handleNavigation(facesContext, null, outcome);
                    
                     viewId = getRenderedViewId();
           
                     updateConversationId();
                    
                     phases.afterPhase( new PhaseEvent(facesContext, PhaseId.INVOKE_APPLICATION, MockLifecycle.INSTANCE) );
                    
                  }
                 
               }
              
            }
           
         }
        
         if ( skipRender() )
         {
            //we really should look at redirect parameters here!
         }
         else
         {
        
            phases.beforePhase( new PhaseEvent(facesContext, PhaseId.RENDER_RESPONSE, MockLifecycle.INSTANCE) );
           
            renderResponseBegun = true;
           
            renderResponse();
           
            renderResponseComplete = true;
           
            facesContext.getApplication().getStateManager().saveSerializedView(facesContext);
           
            updateConversationId();

            phases.afterPhase( new PhaseEvent(facesContext, PhaseId.RENDER_RESPONSE, MockLifecycle.INSTANCE) );
           
            Map renderedViewRootAttributes = facesContext.getViewRoot().getAttributes();
            if (renderedViewRootAttributes!=null)
            {
               Map conversationState = new HashMap();
               conversationState.putAll(renderedViewRootAttributes);
               conversationViewRootAttributes.put(conversationId, conversationState);
            }

         }
        
         afterRequest();

         return conversationId;
      }
     
      private void updateConversationId()
      {
         conversationId = Manager.instance().getCurrentConversationId();
      }

      private boolean skipRender()
      {
         return FacesContext.getCurrentInstance().getResponseComplete();
      }

      private boolean skipToRender()
      {
         return FacesContext.getCurrentInstance().getRenderResponse() ||
               FacesContext.getCurrentInstance().getResponseComplete();
      }

      protected boolean isInvokeApplicationBegun()
      {
         return invokeApplicationBegun;
      }

      protected boolean isInvokeApplicationComplete()
      {
         return invokeApplicationComplete;
      }

      protected boolean isRenderResponseBegun()
      {
         return renderResponseBegun;
      }

      protected boolean isRenderResponseComplete()
      {
         return renderResponseComplete;
      }
     
   }
  
   public class NonFacesRequest extends Request
   {
      public NonFacesRequest() {}

      /**
       * @param viewId the view id to be rendered
       */
      public NonFacesRequest(String viewId)
      {
         setViewId(viewId);
      }

      /**
       * @param viewId the view id to be rendered
       * @param conversationId the conversation id
       */
      public NonFacesRequest(String viewId, String conversationId)
      {
         super(conversationId);
         setViewId(viewId);
      }

      @Override
      protected final boolean isGetRequest()
      {
         return true;
      }

      @Override
      protected final void applyRequestValues() throws Exception
      {
         throw new UnsupportedOperationException();
      }

      @Override
      protected final void processValidations() throws Exception
      {
         throw new UnsupportedOperationException();
      }

      @Override
      protected final void updateModelValues() throws Exception
      {
         throw new UnsupportedOperationException();
      }

   }

   public class FacesRequest extends Request
   {
     
      public FacesRequest() {}

      /**
       * @param viewId the view id of the form that was submitted
       */
      public FacesRequest(String viewId)
      {
         setViewId(viewId);
      }

      /**
       * @param viewId the view id of the form that was submitted
       * @param conversationId the conversation id
       */
      public FacesRequest(String viewId, String conversationId)
      {
         super(conversationId);
         setViewId(viewId);
      }

      @Override
      protected final boolean isGetRequest()
      {
         return false;
      }

   }

   @Configuration(beforeTestMethod=true)
   public void begin()
   {
      session = new MockHttpSession(servletContext);
   }

   @Configuration(afterTestMethod=true)
   public void end()
   {
      if ( Contexts.isEventContextActive() )
      {
         Lifecycle.endRequest(externalContext);
      }
      Lifecycle.endSession( servletContext, new ServletSessionImpl(session) );
      session = null;
   }
  
   /**
    * Create a SeamPhaseListener by default. Override to use
    * one of the other standard Seam phase listeners.
    */
   protected AbstractSeamPhaseListener createPhaseListener()
   {
    return new SeamPhaseListener();
   }

   @Configuration(beforeTestClass=true)
   public void init() throws Exception
   {
      application = new MockApplication();
      application.setStateManager( new SeamStateManager( application.getStateManager() ) );
      application.setNavigationHandler( new SeamNavigationHandler( application.getNavigationHandler() ) );
      //don't need a SeamVariableResolver, because we don't test the view
      phases = createPhaseListener();
     
      servletContext = new MockServletContext();
      initServletContext( servletContext.getInitParameters() );
      Lifecycle.setServletContext(servletContext);
      new Initialization(servletContext).create().init();

      conversationViewRootAttributes = new HashMap<String, Map>();
   }

   @Configuration(afterTestClass=true)
   public void cleanup() throws Exception
   {
      Lifecycle.endApplication(servletContext);
      externalContext = null;
      conversationViewRootAttributes = null;
   }
  
   /**
    * Override to set up any servlet context attributes.
    */
   public void initServletContext(Map initParams) {}
  
   protected InitialContext getInitialContext() throws NamingException {
      return Naming.getInitialContext();
   }
  
   protected UserTransaction getUserTransaction() throws NamingException
   {
      return Transactions.getUserTransaction();
   }
  
   /**
    * Get the value of an object field, by reflection.
    */
   protected Object getField(Object object, String fieldName)
   {
      Field field = Reflections.getField( object.getClass(), fieldName );
      if ( !field.isAccessible() ) field.setAccessible(true);
      return Reflections.getAndWrap(field, object);
   }
  
   /**
    * Set the value of an object field, by reflection.
    */
   protected void setField(Object object, String fieldName, Object value)
   {
      Field field = Reflections.getField( object.getClass(), fieldName );
      if ( !field.isAccessible() ) field.setAccessible(true);
      Reflections.setAndWrap(field, object, value);
   }

}
TOP

Related Classes of org.jboss.seam.mock.SeamTest$Request

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.