package org.springframework.faces.webflow; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import javax.faces.FacesException; import javax.faces.application.ViewHandler; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.event.PhaseEvent; import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; import javax.faces.lifecycle.Lifecycle; import junit.framework.TestCase; import org.easymock.EasyMock; import org.apache.el.ExpressionFactoryImpl; import org.springframework.binding.expression.ExpressionParser; import org.springframework.binding.expression.support.FluentParserContext; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; import org.springframework.webflow.core.collection.LocalAttributeMap; import org.springframework.webflow.core.collection.LocalParameterMap; import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.RequestContextHolder; import org.springframework.webflow.execution.View; import org.springframework.webflow.expression.el.WebFlowELExpressionParser; import org.springframework.webflow.test.MockExternalContext; public class JsfFinalResponseActionTests extends TestCase { private static final String VIEW_ID = "/testView.xhtml"; private JsfViewFactory factory; private final JSFMockHelper jsfMock = new JSFMockHelper(); private final RequestContext context = EasyMock.createMock(RequestContext.class); private final ViewHandler viewHandler = new NoRenderViewHandler(); private TestLifecycle lifecycle; private PhaseListener trackingListener; ExpressionParser parser = new WebFlowELExpressionParser(new ExpressionFactoryImpl()); protected void setUp() throws Exception { configureJsf(); } protected void tearDown() throws Exception { super.tearDown(); this.jsfMock.tearDown(); RequestContextHolder.setRequestContext(null); } private void configureJsf() throws Exception { this.jsfMock.setUp(); this.trackingListener = new TrackingPhaseListener(); this.jsfMock.lifecycle().addPhaseListener(this.trackingListener); this.jsfMock.facesContext().setViewRoot(null); this.jsfMock.facesContext().getApplication().setViewHandler(this.viewHandler); this.lifecycle = new TestLifecycle(this.jsfMock.lifecycle()); this.factory = new JsfViewFactory(this.parser.parseExpression("#{'" + VIEW_ID + "'}", new FluentParserContext() .template().evaluate(RequestContext.class).expectResult(String.class)), this.lifecycle); RequestContextHolder.setRequestContext(this.context); MockExternalContext ext = new MockExternalContext(); ext.setNativeContext(new MockServletContext()); ext.setNativeRequest(new MockHttpServletRequest()); ext.setNativeResponse(new MockHttpServletResponse()); EasyMock.expect(this.context.getExternalContext()).andStubReturn(ext); LocalAttributeMap<Object> requestMap = new LocalAttributeMap<Object>(); EasyMock.expect(this.context.getFlashScope()).andStubReturn(requestMap); EasyMock.expect(this.context.getRequestParameters()).andStubReturn( new LocalParameterMap(new HashMap<String, Object>())); } public void testRender() throws Exception { UIViewRoot newRoot = new UIViewRoot(); newRoot.setViewId(VIEW_ID); newRoot.setRenderKitId("HTML_BASIC"); ((MockViewHandler) this.viewHandler).setCreateView(newRoot); this.context.inViewState(); EasyMock.expectLastCall().andReturn(false); EasyMock.replay(new Object[] { this.context }); View view = this.factory.getView(this.context); ((JsfView) view).getViewRoot().setTransient(true); view.render(); assertTrue(newRoot.isTransient()); assertTrue(((NoRenderViewHandler) this.viewHandler).rendered); } private class TestLifecycle extends FlowLifecycle { boolean executed = false; public TestLifecycle(Lifecycle delegate) { super(delegate); } public void execute(FacesContext context) throws FacesException { assertFalse("Lifecycle executed more than once", this.executed); super.execute(context); this.executed = true; } } private class TrackingPhaseListener implements PhaseListener { private final List<String> phaseCallbacks = new ArrayList<String>(); public void afterPhase(PhaseEvent event) { String phaseCallback = "AFTER_" + event.getPhaseId(); assertFalse("Phase callback " + phaseCallback + " already executed.", this.phaseCallbacks.contains(phaseCallback)); this.phaseCallbacks.add(phaseCallback); } public void beforePhase(PhaseEvent event) { String phaseCallback = "BEFORE_" + event.getPhaseId(); assertFalse("Phase callback " + phaseCallback + " already executed.", this.phaseCallbacks.contains(phaseCallback)); this.phaseCallbacks.add(phaseCallback); } public PhaseId getPhaseId() { return PhaseId.ANY_PHASE; } } private class NoRenderViewHandler extends MockViewHandler { boolean rendered = false; public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException { this.rendered = true; } } }