Merging of SWF-367 back into trunk. This has all of the SWF 2.0 goodies.

This commit is contained in:
Ben Hale
2007-10-11 01:16:37 +00:00
parent b9513cd42b
commit 58d1ea3acc
984 changed files with 11849 additions and 39596 deletions

View File

@@ -0,0 +1,92 @@
package org.springframework.faces.ui.resource;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import java.io.IOException;
import java.io.StringWriter;
import junit.framework.TestCase;
import org.apache.shale.test.mock.MockResponseWriter;
import org.easymock.EasyMock;
import org.springframework.faces.webflow.JSFMockHelper;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.context.FlowDefinitionRequestInfo;
import org.springframework.webflow.context.RequestPath;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
public class FlowResourceHelperTests extends TestCase {
RequestContext requestContext = createMock(RequestContext.class);
ExternalContext externalContext = createMock(ExternalContext.class);
FlowResourceHelper resourceHelper = new FlowResourceHelper();
StringWriter writer = new StringWriter();
JSFMockHelper jsf = new JSFMockHelper();
protected void setUp() throws Exception {
jsf.setUp();
jsf.facesContext().setResponseWriter(new MockResponseWriter(writer, "text/html", "UTF-8"));
expect(requestContext.getExternalContext()).andStubReturn(externalContext);
RequestContextHolder.setRequestContext(requestContext);
}
protected void tearDown() throws Exception {
jsf.tearDown();
}
public final void testRenderScriptLink() throws IOException {
String scriptPath = "/dojo/dojo.js";
String expectedUrl = "/context/spring/resources/dojo/dojo.js";
FlowDefinitionRequestInfo expectedRequest = new FlowDefinitionRequestInfo("resources", new RequestPath(
scriptPath), null, null);
expect(externalContext.buildFlowDefinitionUrl(requestInfoMatches(expectedRequest))).andReturn(expectedUrl);
replay(new Object[] { requestContext, externalContext });
resourceHelper.renderScriptLink(jsf.facesContext(), scriptPath);
resourceHelper.renderScriptLink(jsf.facesContext(), scriptPath);
verify(new Object[] { externalContext });
String expectedOutput = "<script type=\"text/javascript\" src=\"" + expectedUrl + "\"/>";
assertEquals(expectedOutput, writer.toString());
}
public final void testRenderStyleLink() throws IOException {
String scriptPath = "/dijit/themes/dijit.css";
String expectedUrl = "/context/spring/resources/dijit/themes/dijit.css";
FlowDefinitionRequestInfo expectedRequest = new FlowDefinitionRequestInfo("resources", new RequestPath(
scriptPath), null, null);
expect(externalContext.buildFlowDefinitionUrl(requestInfoMatches(expectedRequest))).andReturn(expectedUrl);
replay(new Object[] { requestContext, externalContext });
resourceHelper.renderStyleLink(jsf.facesContext(), scriptPath);
resourceHelper.renderStyleLink(jsf.facesContext(), scriptPath);
verify(new Object[] { externalContext });
String expectedOutput = "<link type=\"text/css\" rel=\"stylesheet\" href=\"" + expectedUrl + "\"/>";
assertEquals(expectedOutput, writer.toString());
}
static FlowDefinitionRequestInfo requestInfoMatches(FlowDefinitionRequestInfo info) {
EasyMock.reportMatcher(new RequestInfoMatcher(info));
return null;
}
}

View File

@@ -0,0 +1,23 @@
package org.springframework.faces.ui.resource;
import org.easymock.IArgumentMatcher;
import org.springframework.webflow.context.FlowDefinitionRequestInfo;
class RequestInfoMatcher implements IArgumentMatcher {
private FlowDefinitionRequestInfo expected;
public RequestInfoMatcher(FlowDefinitionRequestInfo expected) {
this.expected = expected;
}
public void appendTo(StringBuffer buffer) {
buffer.append("/" + expected.getFlowDefinitionId() + expected.getRequestPath());
}
public boolean matches(Object actual) {
FlowDefinitionRequestInfo actualRequest = (FlowDefinitionRequestInfo) actual;
return expected.getFlowDefinitionId().equals(actualRequest.getFlowDefinitionId())
&& expected.getRequestPath().equals(actualRequest.getRequestPath());
}
}

View File

@@ -0,0 +1,61 @@
package org.springframework.faces.ui.resource;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.ServletContext;
import junit.framework.TestCase;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.context.RequestPath;
import org.springframework.webflow.execution.RequestContext;
public class ResolveAndRenderResourceActionTests extends TestCase {
ExternalContext externalContext = createMock(ExternalContext.class);
RequestContext requestContext = createMock(RequestContext.class);
ServletContext servletContext = new MimeAwareMockServletContext();
MockHttpServletResponse response = new MockHttpServletResponse();
MockHttpServletRequest request = new MockHttpServletRequest();
RequestPath requestPath;
String[] requestElements;
ResolveAndRenderResourceAction action;
protected void setUp() throws Exception {
action = new ResolveAndRenderResourceAction();
expect(requestContext.getExternalContext()).andStubReturn(externalContext);
expect(externalContext.getContext()).andStubReturn(servletContext);
expect(externalContext.getResponse()).andStubReturn(response);
expect(externalContext.getRequest()).andStubReturn(request);
expect(externalContext.getResponseWriter()).andStubReturn(new PrintWriter(new StringWriter()));
}
public final void testExecute() throws Exception {
requestPath = new RequestPath("/ext/ext.js");
expect(externalContext.getRequestPath()).andStubReturn(requestPath);
replay(new Object[] { requestContext, externalContext });
action.execute(requestContext);
}
private class MimeAwareMockServletContext extends MockServletContext {
public String getMimeType(String filePath) {
return null;
}
}
}

View File

@@ -0,0 +1,73 @@
package org.springframework.faces.webflow;
import javax.faces.component.UICommand;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.MethodBinding;
import javax.faces.el.MethodNotFoundException;
import javax.faces.event.ActionEvent;
import junit.framework.TestCase;
public class FlowActionListenerTests extends TestCase {
FlowActionListener listener = new FlowActionListener();
JSFMockHelper jsfMock = new JSFMockHelper();
protected void setUp() throws Exception {
jsfMock.setUp();
}
protected void tearDown() throws Exception {
jsfMock.tearDown();
}
public final void testProcessAction() {
String outcome = "foo";
MethodBinding binding = new MethodBindingStub(outcome);
UICommand commandButton = new UICommand();
commandButton.setAction(binding);
ActionEvent event = new ActionEvent(commandButton);
listener.processAction(event);
assertTrue("The event was not signaled", jsfMock.externalContext().getRequestMap().containsKey(
JsfView.EVENT_KEY));
assertEquals("The event should be " + outcome, outcome, jsfMock.externalContext().getRequestMap().get(
JsfView.EVENT_KEY));
}
public final void testProcessAction_NullOutcome() {
String outcome = null;
MethodBinding binding = new MethodBindingStub(outcome);
UICommand commandButton = new UICommand();
commandButton.setAction(binding);
ActionEvent event = new ActionEvent(commandButton);
listener.processAction(event);
assertFalse("An unexpected event was signaled", jsfMock.externalContext().getRequestMap().containsKey(
JsfView.EVENT_KEY));
}
private class MethodBindingStub extends MethodBinding {
String result;
public MethodBindingStub(String result) {
this.result = result;
}
public Class getType(FacesContext context) throws MethodNotFoundException {
return String.class;
}
public Object invoke(FacesContext context, Object[] args) throws EvaluationException, MethodNotFoundException {
return this.result;
}
}
}

View File

@@ -0,0 +1,158 @@
package org.springframework.faces.webflow;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import java.util.Iterator;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import junit.framework.TestCase;
import org.springframework.binding.message.Message;
import org.springframework.binding.message.MessageContext;
import org.springframework.binding.message.MessageResolver;
import org.springframework.binding.message.Severity;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
public class FlowFacesContextTests extends TestCase {
JSFMockHelper jsf = new JSFMockHelper();
FacesContext facesContext;
RequestContext requestContext = createMock(RequestContext.class);
MessageContext messageContext;
protected void setUp() throws Exception {
jsf.setUp();
facesContext = new FlowFacesContext(jsf.facesContext());
RequestContextHolder.setRequestContext(requestContext);
}
protected void tearDown() throws Exception {
jsf.tearDown();
}
public final void testCurrentInstance() {
assertSame(FacesContext.getCurrentInstance(), facesContext);
}
public final void testAddMessage() {
messageContext = new TestAddMessageContext();
expect(requestContext.getMessageContext()).andStubReturn(messageContext);
replay(new Object[] { requestContext });
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "foo", "foo"));
assertEquals("Message count is incorrect", 1, ((TestAddMessageContext) messageContext).messageCount);
}
public final void testGetMessages() {
messageContext = new TestGetMessagesContext();
expect(requestContext.getMessageContext()).andStubReturn(messageContext);
replay(new Object[] { requestContext });
int iterationCount = 0;
Iterator<FacesMessage> i = facesContext.getMessages();
while (i.hasNext()) {
assertNotNull(i.next());
iterationCount++;
}
assertEquals(3, iterationCount);
}
public final void testGetMessagesByClientId() {
messageContext = new TestGetMessagesContext();
expect(requestContext.getMessageContext()).andStubReturn(messageContext);
replay(new Object[] { requestContext });
int iterationCount = 0;
Iterator<FacesMessage> i = facesContext.getMessages("componentId");
while (i.hasNext()) {
assertNotNull(i.next());
iterationCount++;
}
assertEquals(1, iterationCount);
}
public final void testGetClientIdsWithMessages() {
messageContext = new TestGetMessagesContext();
expect(requestContext.getMessageContext()).andStubReturn(messageContext);
replay(new Object[] { requestContext });
int iterationCount = 0;
Iterator<String> i = facesContext.getClientIdsWithMessages();
while (i.hasNext()) {
String id = i.next();
assertEquals("componentId", id);
iterationCount++;
}
assertEquals(1, iterationCount);
}
public final void testGetMaximumSeverity() {
messageContext = new TestGetMessagesContext();
expect(requestContext.getMessageContext()).andStubReturn(messageContext);
replay(new Object[] { requestContext });
assertEquals(FacesMessage.SEVERITY_ERROR, facesContext.getMaximumSeverity());
}
private class TestAddMessageContext implements MessageContext {
int messageCount = 0;
public void addMessage(MessageResolver messageResolver) {
messageCount++;
}
public Message[] getMessages() {
return null;
}
public Message[] getMessages(Object source) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Auto-generated method stub");
}
public void clearMessages() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Auto-generated method stub");
}
}
private class TestGetMessagesContext implements MessageContext {
Message[] messages;
TestGetMessagesContext() {
messages = new Message[3];
messages[0] = new Message(null, "foo", Severity.INFO);
messages[1] = new Message("componentId", "bar", Severity.WARNING);
messages[2] = new Message(null, "baz", Severity.ERROR);
}
public void addMessage(MessageResolver messageResolver) {
}
public Message[] getMessages() {
return messages;
}
public Message[] getMessages(Object source) {
return new Message[] { messages[1] };
}
public void clearMessages() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Auto-generated method stub");
}
}
}

View File

@@ -1,60 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.faces.webflow;
import junit.framework.TestCase;
import org.springframework.faces.webflow.FlowNavigationHandlerArgumentExtractor;
import org.springframework.faces.webflow.JsfExternalContext;
import org.springframework.webflow.executor.support.FlowExecutorArgumentExtractionException;
public class FlowNavigationHandlerArgumentExtractorTests extends TestCase {
private FlowNavigationHandlerArgumentExtractor extractor;
private MockFacesContext facesContext;
protected void setUp() throws Exception {
extractor = new FlowNavigationHandlerArgumentExtractor();
facesContext = new MockFacesContext();
facesContext.setExternalContext(new MockJsfExternalContext());
}
public void testExtractFlowId() {
JsfExternalContext context = new JsfExternalContext(facesContext);
context.handleNavigationCalled("action", "flowId:foo");
String flowId = extractor.extractFlowId(context);
assertEquals("Wrong flow id", "foo", flowId);
}
public void testExtractFlowIdWrongFormat() {
JsfExternalContext context = new JsfExternalContext(facesContext);
context.handleNavigationCalled("action", "bogus:foo");
try {
extractor.extractFlowId(context);
fail();
} catch (FlowExecutorArgumentExtractionException e) {
// expected
}
}
public void testExtractEventId() {
JsfExternalContext context = new JsfExternalContext(facesContext);
context.handleNavigationCalled("action", "submit");
String eventId = extractor.extractEventId(context);
assertEquals("Wrong event id", "submit", eventId);
}
}

View File

@@ -1,135 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.faces.webflow;
import javax.faces.el.EvaluationException;
import javax.faces.el.PropertyNotFoundException;
import javax.faces.el.PropertyResolver;
import javax.faces.el.ReferenceSyntaxException;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.springframework.faces.webflow.el.FlowPropertyResolver;
import org.springframework.webflow.execution.FlowExecution;
import org.springframework.webflow.test.MockFlowSession;
/**
* @author Colin Sampaleanu
* @since 1.0
*/
public class FlowPropertyResolverTests extends TestCase {
private FlowPropertyResolver resolver;
private FlowExecution flowEx;
protected void setUp() throws Exception {
resolver = new FlowPropertyResolver(new OriginalPropertyResolver());
flowEx = (FlowExecution) EasyMock.createMock(FlowExecution.class);
}
protected void tearDown() throws Exception {
resolver = null;
}
public void testGetTypeBaseIndex() {
Class type = resolver.getType(flowEx, 22);
assertNull("can't get property from flow via index", type);
}
public void testGetTypeBaseProperty() {
MockFlowSession flowSession = new MockFlowSession();
flowSession.getScope().put("name", "joe");
flowEx.getActiveSession();
EasyMock.expectLastCall().andReturn(flowSession);
EasyMock.replay(new Object[] { flowEx });
Class type = resolver.getType(flowEx, "name");
assertTrue("returned type must match property type", type.equals(String.class));
}
public void testGetValueBaseIndex() {
try {
resolver.getValue(flowEx, 2);
fail("not legal to get flow property by index");
} catch (ReferenceSyntaxException e) {
// expected
}
}
public void testGetValueBaseProperty() {
MockFlowSession flowSession = new MockFlowSession();
flowSession.getScope().put("name", "joe");
flowEx.getActiveSession();
EasyMock.expectLastCall().andReturn(flowSession);
EasyMock.replay(new Object[] { flowEx });
Object value = resolver.getValue(flowEx, "name");
assertTrue("must return expected property", value.equals("joe"));
}
public void testSetValueBaseIndex() {
try {
resolver.setValue(flowEx, 2, "whatever");
fail("not legal to set flow property by index");
} catch (ReferenceSyntaxException e) {
// expected
}
}
public void testSetValueBaseProperty() {
MockFlowSession flowSession = new MockFlowSession();
flowEx.getActiveSession();
EasyMock.expectLastCall().andReturn(flowSession);
EasyMock.replay(new Object[] { flowEx });
resolver.setValue(flowEx, "name", "joe");
assertTrue(flowSession.getScope().get("name").equals("joe"));
}
private static class OriginalPropertyResolver extends PropertyResolver {
public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException {
return Object.class;
}
public Class getType(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
return Object.class;
}
public Object getValue(Object base, int index) throws EvaluationException, PropertyNotFoundException {
return new String("Some value");
}
public Object getValue(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
return new String("Some value");
}
public boolean isReadOnly(Object base, int index) throws EvaluationException, PropertyNotFoundException {
return false;
}
public boolean isReadOnly(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
return false;
}
public void setValue(Object base, int index, Object value) throws EvaluationException,
PropertyNotFoundException {
}
public void setValue(Object base, Object property, Object value) throws EvaluationException,
PropertyNotFoundException {
}
}
}

View File

@@ -1,102 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.faces.webflow;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import junit.framework.TestCase;
import org.springframework.faces.webflow.FlowExecutionHolder;
import org.springframework.faces.webflow.FlowSystemCleanupFilter;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.webflow.context.ExternalContextHolder;
import org.springframework.webflow.engine.impl.FlowExecutionImpl;
import org.springframework.webflow.execution.FlowExecutionContextHolder;
import org.springframework.webflow.test.MockExternalContext;
public class FlowSystemCleanupFilterTests extends TestCase {
private FlowSystemCleanupFilter filter;
private ServletRequest request;
private ServletResponse response;
private FilterChain chain;
protected void setUp() throws Exception {
filter = new FlowSystemCleanupFilter();
request = new MockHttpServletRequest();
request.setAttribute(getFlowExecutionHolderKey(), new FlowExecutionHolder(new FlowExecutionImpl()));
response = new MockHttpServletResponse();
chain = new MockFilterChain();
FlowExecutionContextHolder.setFlowExecutionContext(new FlowExecutionImpl());
ExternalContextHolder.setExternalContext(new MockExternalContext());
}
public void testCleanup() throws ServletException, IOException {
filter.doFilter(request, response, chain);
assertNull("Should have cleaned up the flow execution", request.getAttribute(getFlowExecutionHolderKey()));
try {
FlowExecutionContextHolder.getFlowExecutionContext();
fail("Should have an empty holder");
} catch (IllegalStateException e) {
}
try {
ExternalContextHolder.getExternalContext();
fail("Should have an empty holder");
} catch (IllegalStateException e) {
}
}
public void testExceptionThrown() throws ServletException, IOException {
try {
filter.doFilter(request, response, new ExceptionThrowingMockFilterChain());
} catch (RuntimeException e) {
assertNull("Should have cleaned up the flow execution", request.getAttribute(getFlowExecutionHolderKey()));
try {
FlowExecutionContextHolder.getFlowExecutionContext();
fail("Should have an empty holder");
} catch (IllegalStateException e1) {
}
try {
ExternalContextHolder.getExternalContext();
fail("Should have an empty holder");
} catch (IllegalStateException e1) {
}
}
}
private static String getFlowExecutionHolderKey() {
return FlowExecutionHolder.class.getName();
}
private class ExceptionThrowingMockFilterChain extends MockFilterChain {
public void doFilter(ServletRequest request, ServletResponse response) {
throw new RuntimeException();
}
}
}

View File

@@ -1,95 +0,0 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.faces.webflow;
import javax.faces.context.FacesContext;
import javax.faces.el.EvaluationException;
import javax.faces.el.VariableResolver;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.springframework.faces.webflow.FlowExecutionHolder;
import org.springframework.faces.webflow.FlowExecutionHolderUtils;
import org.springframework.faces.webflow.el.FlowVariableResolver;
import org.springframework.webflow.execution.FlowExecution;
import org.springframework.webflow.execution.repository.FlowExecutionKey;
/**
* Unit tests for the FlowVariableResolver class.
*
* @author Ulrik Sandberg
*/
public class FlowVariableResolverTests extends TestCase {
private FlowVariableResolver tested;
private TestableVariableResolver variableResolver;
private MockFacesContext mockFacesContext;
private MockJsfExternalContext mockJsfExternalContext;
protected void setUp() throws Exception {
super.setUp();
mockFacesContext = new MockFacesContext();
mockJsfExternalContext = new MockJsfExternalContext();
mockFacesContext.setExternalContext(mockJsfExternalContext);
variableResolver = new TestableVariableResolver();
tested = new FlowVariableResolver(variableResolver);
}
public void testResolveVariableNotFlowScope() {
Object result = tested.resolveVariable(mockFacesContext, "some name");
assertTrue("not resolved using delegate", variableResolver.resolvedUsingDelegate);
assertSame(variableResolver.expected, result);
}
public void testResolveVariableFlowScopeWithNoThreadLocal() {
try {
tested.resolveVariable(mockFacesContext, "flowScope");
fail("EvaluationException expected");
} catch (EvaluationException expected) {
}
assertFalse("resolved using delegate", variableResolver.resolvedUsingDelegate);
}
public void testResolveVariableFlowScopeWithThreadLocal() {
FlowExecution flowExecutionMock = (FlowExecution) EasyMock.createMock(FlowExecution.class);
FlowExecutionKey key = null;
FlowExecutionHolder holder = new FlowExecutionHolder(key, flowExecutionMock, null);
FlowExecutionHolderUtils.setFlowExecutionHolder(holder, mockFacesContext);
EasyMock.replay(new Object[] { flowExecutionMock });
Object result = tested.resolveVariable(mockFacesContext, "flowScope");
EasyMock.verify(new Object[] { flowExecutionMock });
assertFalse("resolved using delegate", variableResolver.resolvedUsingDelegate);
assertSame(flowExecutionMock, result);
}
private static class TestableVariableResolver extends VariableResolver {
private boolean resolvedUsingDelegate;
private Object expected = new Object();
public Object resolveVariable(FacesContext arg0, String arg1) throws EvaluationException {
resolvedUsingDelegate = true;
return expected;
}
}
}

View File

@@ -1,142 +0,0 @@
package org.springframework.faces.webflow;
import java.io.FileNotFoundException;
import javax.faces.el.ValueBinding;
import org.easymock.EasyMock;
import org.jboss.el.ExpressionFactoryImpl;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.faces.el.Jsf11ELExpressionParser;
import org.springframework.faces.webflow.el.DelegatingFlowVariableResolver;
import org.springframework.faces.webflow.el.FlowPropertyResolver;
import org.springframework.faces.webflow.el.FlowVariableResolver;
import org.springframework.util.ResourceUtils;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.jsf.DelegatingVariableResolver;
import org.springframework.webflow.definition.registry.FlowDefinitionResource;
import org.springframework.webflow.execution.FlowExecutionException;
import org.springframework.webflow.execution.ViewSelection;
import org.springframework.webflow.test.MockFlowServiceLocator;
import org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests;
public class JSF11ManagedBeanAccessTests extends AbstractXmlFlowExecutionTests {
JSFMockHelper jsf;
JSFManagedBean jsfBean;
JSFModel jsfModel;
FlowPhaseListener flowPhaseListener;
FlowNavigationHandler flowNavigationHandler;
MockService service;
GenericWebApplicationContext ctx;
protected void setUp() throws Exception {
super.setUp();
service = (MockService) EasyMock.createMock(MockService.class);
jsf = new JSFMockHelper();
jsf.setUp();
configureJSFForSWF();
}
private void configureJSFForSWF() {
DelegatingVariableResolver dvr = new DelegatingVariableResolver(jsf.application().getVariableResolver());
DelegatingFlowVariableResolver dfvr = new DelegatingFlowVariableResolver(dvr);
FlowVariableResolver fvr = new FlowVariableResolver(dfvr);
jsf.application().setVariableResolver(fvr);
FlowPropertyResolver fpr = new FlowPropertyResolver(jsf.application().getPropertyResolver());
jsf.application().setPropertyResolver(fpr);
flowNavigationHandler = new FlowNavigationHandler(jsf.application().getNavigationHandler());
jsf.application().setNavigationHandler(flowNavigationHandler);
jsf.externalContext().getRequestMap().put("JsfBean", new JSFManagedBean());
}
protected void tearDown() throws Exception {
super.tearDown();
jsf.tearDown();
}
public void testManagedBeanExpression() {
ValueBinding vb = jsf.application().createValueBinding("#{JsfBean}");
jsfBean = (JSFManagedBean) vb.getValue(jsf.facesContext());
assertNotNull(jsfBean);
}
public void testSWFExplicitlyScopedPropertyInjection() {
testManagedBeanExpression();
startFlow();
ValueBinding propBinding = jsf.application().createValueBinding("#{flowScope.jsfModel}");
jsfModel = (JSFModel) propBinding.getValue(jsf.facesContext());
assertNotNull(jsfModel);
}
public void testManagedBeanPropertyAsArgument() {
testManagedBeanExpression();
jsfBean.setProp1("arg");
service.doSomething(jsfBean.getProp1());
EasyMock.replay(new Object[] { service });
startFlow();
signalEvent("event1");
EasyMock.verify(new Object[] { service });
assertCurrentStateEquals("viewState2");
}
public void testEvalManagedBeanMethod() {
testManagedBeanExpression();
startFlow();
ValueBinding propBinding = jsf.application().createValueBinding("#{flowScope.jsfModel}");
jsfModel = (JSFModel) propBinding.getValue(jsf.facesContext());
assertNotNull(jsfModel);
jsfModel.setValue("foo");
signalEvent("event2");
assertFalse(jsfBean.getValues().isEmpty());
String addedValue = jsfBean.getValues().get(0).toString();
assertEquals(jsfModel.getValue(), addedValue);
assertCurrentStateEquals("viewState2");
}
public void testSWFScopedPropertyInjection() {
startFlow();
ValueBinding propBinding = jsf.application().createValueBinding("#{flowScopedModel}");
jsfModel = (JSFModel) propBinding.getValue(jsf.facesContext());
assertNotNull("This test won't pass until custom scopes are implemented.", jsfModel);
}
protected ViewSelection startFlow() throws FlowExecutionException {
ViewSelection view = super.startFlow();
FlowExecutionHolder holder = new FlowExecutionHolder(getFlowExecution());
FlowExecutionHolderUtils.setFlowExecutionHolder(holder, jsf.facesContext());
holder.setViewSelection(view);
return view;
}
protected FlowDefinitionResource getFlowDefinitionResource() {
try {
return createFlowDefinitionResource(ResourceUtils.getFile(
"classpath:org/springframework/faces/webflow/jsf-flow.xml").getPath());
} catch (FileNotFoundException e) {
fail(e.getMessage());
return null;
}
}
protected void registerMockServices(MockFlowServiceLocator serviceRegistry) {
serviceRegistry.setExpressionParser(new Jsf11ELExpressionParser(new ExpressionFactoryImpl()));
serviceRegistry.registerBean("serviceBean", service);
ctx = new GenericWebApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new ClassPathResource("org/springframework/faces/webflow/jsf-flow-beans.xml"));
ctx.refresh();
jsf.externalContext().getApplicationMap().put(
GenericWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx);
}
}

View File

@@ -1,25 +0,0 @@
package org.springframework.faces.webflow;
import org.jboss.el.ExpressionFactoryImpl;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.faces.el.Jsf12ELExpressionParser;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.webflow.test.MockFlowServiceLocator;
public class JSF12ManagedBeanAccessTests extends JSF11ManagedBeanAccessTests {
protected void registerMockServices(MockFlowServiceLocator serviceRegistry) {
serviceRegistry.setExpressionParser(new Jsf12ELExpressionParser(new ExpressionFactoryImpl()));
serviceRegistry.registerBean("serviceBean", service);
ctx = new GenericWebApplicationContext();
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
xmlReader.loadBeanDefinitions(new ClassPathResource("org/springframework/faces/webflow/jsf-flow-beans.xml"));
ctx.refresh();
jsf.externalContext().getApplicationMap().put(
GenericWebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx);
}
}

View File

@@ -0,0 +1,302 @@
package org.springframework.faces.webflow;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.el.CompositeELResolver;
import javax.faces.FacesException;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
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.jboss.el.ExpressionFactoryImpl;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.binding.method.MethodSignature;
import org.springframework.binding.method.Parameter;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.webflow.action.AbstractBeanInvokingAction;
import org.springframework.webflow.action.EvaluateAction;
import org.springframework.webflow.action.SetAction;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.context.ExternalContextHolder;
import org.springframework.webflow.context.servlet.ServletExternalContext;
import org.springframework.webflow.core.expression.el.RequestContextELResolver;
import org.springframework.webflow.core.expression.el.ScopeSearchingELResolver;
import org.springframework.webflow.core.expression.el.WebFlowELExpressionParser;
import org.springframework.webflow.engine.ActionState;
import org.springframework.webflow.engine.EndState;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.TargetStateResolver;
import org.springframework.webflow.engine.Transition;
import org.springframework.webflow.engine.TransitionCriteria;
import org.springframework.webflow.engine.ViewState;
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
import org.springframework.webflow.engine.support.DefaultTargetStateResolver;
import org.springframework.webflow.engine.support.EventIdTransitionCriteria;
import org.springframework.webflow.execution.Action;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.FlowExecution;
import org.springframework.webflow.execution.FlowExecutionKey;
import org.springframework.webflow.execution.FlowExecutionKeyFactory;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.ScopeType;
public class JSFFlowExecutionTests extends TestCase {
JSFMockHelper jsf;
JSFManagedBean jsfBean;
JSFModel jsfModel;
MockViewHandler viewHandler;
MockService service;
GenericWebApplicationContext ctx;
TrackingPhaseListener trackingListener;
Flow flow;
FlowExecution execution;
ExpressionParser parser = new WebFlowELExpressionParser(new ExpressionFactoryImpl());
/**
* TODO - The management of the JSF mocks has gotten rather convoluted now that we are tearing down and rebuilding
* the FacesContext multiple times per request. Consider enhancing JSFMockHelper to manage things more appropriately
* for SWF usage.
*/
protected void setUp() throws Exception {
service = EasyMock.createMock(MockService.class);
trackingListener = new TrackingPhaseListener();
jsfRequestSetup();
flow = Flow.create("jsf-flow", null);
ViewState view1 = new ViewState(flow, "viewState1", new JsfViewFactory(new TestLifecycle(jsf.lifecycle()),
parser.parseExpression("view1", RequestContext.class, String.class, null)));
view1.getTransitionSet().add(new Transition(on("event1"), to("doSomething")));
view1.getTransitionSet().add(new Transition(on("event2"), to("evalSomething")));
ActionState doSomething = new ActionState(flow, "doSomething");
doSomething.getActionList().add(
new StubBeanAction(new MethodSignature("doSomething", new Parameter(String.class, parser
.parseExpression("#{JsfBean.prop1}", RequestContext.class, String.class, null)))));
doSomething.getTransitionSet().add(new Transition(on("success"), to("viewState2")));
ActionState evalSomething = new ActionState(flow, "evalSomething");
evalSomething.getEntryActionList().add(
new SetAction(parser.parseExpression("#{requestContext.flowScope.jsfModel}", RequestContext.class,
String.class, null), ScopeType.FLOW, parser.parseExpression("#{'foo'}", RequestContext.class,
String.class, null)));
evalSomething.getActionList().add(
new EvaluateAction(parser.parseExpression("#{JsfBean.addValue(jsfModel)}", RequestContext.class,
String.class, null)));
evalSomething.getTransitionSet().add(new Transition(on("success"), to("viewState2")));
ViewState viewState2 = new ViewState(flow, "viewState2", new JsfViewFactory(new TestLifecycle(jsf.lifecycle()),
parser.parseExpression("view2", RequestContext.class, String.class, null)));
viewState2.getEntryActionList().add(new ViewState2SetupAction());
viewState2.getTransitionSet().add(new Transition(on("event1"), to("endState1")));
new EndState(flow, "endState1");
FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
factory.setExecutionKeyFactory(new SimpleFlowExecutionKeyFactory());
execution = factory.createFlowExecution(flow);
}
private void jsfRequestSetup() throws Exception {
jsf = new JSFMockHelper();
jsf.tearDown();
jsf.setUp();
FacesContext flowContext = new FlowFacesContext(jsf.facesContext());
org.apache.shale.test.mock.MockFacesContext.setCurrentInstance(flowContext);
viewHandler = new NoRenderViewHandler();
jsf.application().setViewHandler(viewHandler);
trackingListener.reset();
jsf.lifecycle().addPhaseListener(trackingListener);
CompositeELResolver baseResolver = (CompositeELResolver) jsf.facesContext().getELContext().getELResolver();
baseResolver.add(new RequestContextELResolver());
baseResolver.add(new ScopeSearchingELResolver());
jsf.externalContext().getRequestMap().put("JsfBean", new JSFManagedBean());
}
protected void tearDown() throws Exception {
jsf.tearDown();
}
public void testManagedBeanExpression() {
ValueBinding vb = jsf.application().createValueBinding("#{JsfBean}");
jsfBean = (JSFManagedBean) vb.getValue(jsf.facesContext());
assertNotNull(jsfBean);
}
/*
* public void testBeanAction() throws Exception { startFlow();
*
* jsfRequestSetup();
*
* testManagedBeanExpression(); jsfBean.setProp1("arg"); service.doSomething(jsfBean.getProp1());
* EasyMock.replay(new Object[] { service });
*
* jsf.externalContext().getRequestMap().put(JsfView.EVENT_KEY, "event1");
*
* UIViewRoot existingRoot = new UIViewRoot(); existingRoot.setViewId("view1");
* viewHandler.setRestoreView(existingRoot);
*
* execution.resume(getExternalContext());
*
* EasyMock.verify(new Object[] { service });
*
* ViewState currentState = (ViewState) execution.getActiveSession().getState(); assertEquals("viewState2",
* currentState.getId()); }
*
* public void testEvalAction() throws Exception { startFlow();
*
* jsfRequestSetup();
*
* testManagedBeanExpression();
*
* jsf.externalContext().getRequestMap().put(JsfView.EVENT_KEY, "event2");
*
* UIViewRoot existingRoot = new UIViewRoot(); existingRoot.setViewId("view1");
* viewHandler.setRestoreView(existingRoot);
*
* execution.resume(getExternalContext());
*
* assertFalse(jsfBean.getValues().isEmpty()); String addedValue = jsfBean.getValues().get(0).toString();
* assertEquals(addedValue, "foo");
*
* ViewState currentState = (ViewState) execution.getActiveSession().getState(); assertEquals("viewState2",
* currentState.getId()); }
*/
private static TransitionCriteria on(String event) {
return new EventIdTransitionCriteria(event);
}
private static TargetStateResolver to(String stateId) {
return new DefaultTargetStateResolver(stateId);
}
private void startFlow() {
UIViewRoot view = new UIViewRoot();
view.setViewId("view1");
viewHandler.setCreateView(view);
execution.start(getExternalContext());
}
private ExternalContext getExternalContext() {
jsf.request().setPathElements("myApp", "", "/flow", null);
ExternalContext ext = new ServletExternalContext(jsf.servletContext(), jsf.request(), jsf.response());
ExternalContextHolder.setExternalContext(ext);
return ext;
}
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", executed);
super.execute(context);
executed = true;
}
public void reset() {
executed = false;
}
}
private class StubBeanAction extends AbstractBeanInvokingAction {
protected StubBeanAction(MethodSignature methodSignature) {
super(methodSignature);
}
protected Object getBean(RequestContext context) throws Exception {
return service;
}
}
private static class SimpleFlowExecutionKeyFactory implements FlowExecutionKeyFactory {
public FlowExecutionKey getKey(FlowExecution execution) {
return new FlowExecutionKey() {
public String toString() {
return "key";
}
public boolean equals(Object o) {
return true;
}
public int hashCode() {
return 0;
}
};
}
}
private class NoRenderViewHandler extends MockViewHandler {
public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {
// do nothing
}
}
private class TrackingPhaseListener implements PhaseListener {
private List phaseCallbacks = new ArrayList();
public void afterPhase(PhaseEvent event) {
String phaseCallback = "AFTER_" + event.getPhaseId();
assertFalse("Phase callback " + phaseCallback + " already executed.", phaseCallbacks
.contains(phaseCallback));
phaseCallbacks.add(phaseCallback);
}
public void beforePhase(PhaseEvent event) {
String phaseCallback = "BEFORE_" + event.getPhaseId();
assertFalse("Phase callback " + phaseCallback + " already executed.", phaseCallbacks
.contains(phaseCallback));
phaseCallbacks.add(phaseCallback);
}
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
public List getPhaseCallbacks() {
return phaseCallbacks;
}
public void reset() {
phaseCallbacks.clear();
}
}
private class ViewState2SetupAction implements Action {
public Event execute(RequestContext context) throws Exception {
jsfRequestSetup();
UIViewRoot newRoot = new UIViewRoot();
newRoot.setViewId("view2");
viewHandler.setCreateView(newRoot);
return new Event(this, "success");
}
}
}

View File

@@ -1,9 +1,14 @@
package org.springframework.faces.webflow;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.component.UIViewRoot;
import javax.faces.lifecycle.LifecycleFactory;
import javax.faces.render.RenderKitFactory;
import org.apache.shale.test.base.AbstractJsfTestCase;
import org.apache.shale.test.mock.MockApplication;
import org.apache.shale.test.mock.MockExternalContext;
import org.apache.shale.test.mock.MockFacesContextFactory;
import org.apache.shale.test.mock.MockHttpServletRequest;
import org.apache.shale.test.mock.MockHttpServletResponse;
import org.apache.shale.test.mock.MockHttpSession;
@@ -11,7 +16,6 @@ import org.apache.shale.test.mock.MockLifecycle;
import org.apache.shale.test.mock.MockLifecycleFactory;
import org.apache.shale.test.mock.MockRenderKit;
import org.apache.shale.test.mock.MockServletConfig;
import org.apache.shale.test.mock.MockFacesContext;
import org.apache.shale.test.mock.MockServletContext;
/**
@@ -24,7 +28,10 @@ public class JSFMockHelper {
private JSFMock mock = new JSFMock();
public MockApplication application() {
public Application application() {
if (mock.application() == null) {
return mock.facesContext.getApplication();
}
return mock.application();
}
@@ -36,11 +43,11 @@ public class JSFMockHelper {
return mock.externalContext();
}
public MockFacesContext facesContext() {
public FlowFacesContext facesContext() {
return mock.facesContext();
}
public MockFacesContextFactory facesContextFactory() {
public FlowFacesContextFactory facesContextFactory() {
return mock.facesContextFactory();
}
@@ -86,12 +93,70 @@ public class JSFMockHelper {
super("JSFMock");
}
FlowFacesContextFactory facesContextFactory;
FlowFacesContext facesContext;
public void setUp() throws Exception {
super.setUp();
// Thread.currentThread().setContextClassLoader(
// new URLClassLoader(new URL[0], this.getClass().getClassLoader()));
// Set up Servlet API Objects
servletContext = new MockServletContext();
config = new MockServletConfig(servletContext);
session = new MockHttpSession();
session.setServletContext(servletContext);
request = new MockHttpServletRequest(session);
request.setServletContext(servletContext);
response = new MockHttpServletResponse();
// Set up JSF API Objects
FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY,
"org.apache.shale.test.mock.MockApplicationFactory");
FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY,
"org.springframework.faces.webflow.MockBaseFacesContextFactory");
FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY,
"org.springframework.faces.webflow.FlowFacesContextFactory");
FactoryFinder
.setFactory(FactoryFinder.LIFECYCLE_FACTORY, "org.apache.shale.test.mock.MockLifecycleFactory");
FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY,
"org.apache.shale.test.mock.MockRenderKitFactory");
externalContext = new MockExternalContext(servletContext, request, response);
lifecycleFactory = (MockLifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
lifecycle = (MockLifecycle) lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
facesContextFactory = (FlowFacesContextFactory) FactoryFinder
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
facesContext = (FlowFacesContext) facesContextFactory.getFacesContext(servletContext, request, response,
lifecycle);
externalContext = (MockExternalContext) facesContext.getExternalContext();
UIViewRoot root = new UIViewRoot();
root.setViewId("/viewId");
root.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
facesContext.setViewRoot(root);
RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder
.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
renderKit = new MockRenderKit();
renderKitFactory.addRenderKit(RenderKitFactory.HTML_BASIC_RENDER_KIT, renderKit);
}
public void tearDown() throws Exception {
super.tearDown();
application = null;
config = null;
externalContext = null;
if (facesContext != null) {
facesContext.release();
}
facesContext = null;
lifecycle = null;
lifecycleFactory = null;
renderKit = null;
request = null;
response = null;
servletContext = null;
session = null;
FactoryFinder.releaseFactories();
}
public MockApplication application() {
@@ -106,11 +171,11 @@ public class JSFMockHelper {
return externalContext;
}
public MockFacesContext facesContext() {
public FlowFacesContext facesContext() {
return facesContext;
}
public MockFacesContextFactory facesContextFactory() {
public FlowFacesContextFactory facesContextFactory() {
return facesContextFactory;
}

View File

@@ -0,0 +1,147 @@
package org.springframework.faces.webflow;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
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.jboss.el.ExpressionFactoryImpl;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.core.expression.el.WebFlowELExpressionParser;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.execution.ViewFactory;
import org.springframework.webflow.test.MockExternalContext;
public class JsfRenderFinalResponseActionTests extends TestCase {
private static final String VIEW_ID = "testView.xhtml";
private ViewFactory factory;
private JsfRenderFinalResponseAction finalResponseAction;
private JSFMockHelper jsfMock = new JSFMockHelper();
private RequestContext context = EasyMock.createMock(RequestContext.class);
private ViewHandler viewHandler = new NoRenderViewHandler();
private TestLifecycle lifecycle;
private PhaseListener trackingListener;
private StringWriter output = new StringWriter();
ExpressionParser parser = new WebFlowELExpressionParser(new ExpressionFactoryImpl());
protected void setUp() throws Exception {
configureJsf();
}
protected void tearDown() throws Exception {
jsfMock.tearDown();
}
private void configureJsf() throws Exception {
jsfMock.setUp();
trackingListener = new TrackingPhaseListener();
jsfMock.lifecycle().addPhaseListener(trackingListener);
jsfMock.facesContext().setViewRoot(null);
jsfMock.application().setViewHandler(viewHandler);
lifecycle = new TestLifecycle(jsfMock.lifecycle());
factory = new JsfViewFactory(lifecycle, parser.parseExpression("#{'" + VIEW_ID + "'}", RequestContext.class,
String.class, null));
finalResponseAction = new JsfRenderFinalResponseAction(factory);
RequestContextHolder.setRequestContext(context);
ExternalContext ext = new MockExternalContext();
EasyMock.expect(context.getExternalContext()).andStubReturn(ext);
AttributeMap flash = new LocalAttributeMap();
EasyMock.expect(context.getFlashScope()).andStubReturn(flash);
}
public void testRender() throws Exception {
UIViewRoot newRoot = new UIViewRoot();
newRoot.setViewId(VIEW_ID);
newRoot.setRenderKitId("TEST_KIT");
((MockViewHandler) viewHandler).setCreateView(newRoot);
EasyMock.replay(new Object[] { context });
finalResponseAction.execute(context);
assertTrue(newRoot.isTransient());
assertTrue(((NoRenderViewHandler) 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", executed);
super.execute(context);
executed = true;
}
}
private class TrackingPhaseListener implements PhaseListener {
private List<String> phaseCallbacks = new ArrayList<String>();
public void afterPhase(PhaseEvent event) {
String phaseCallback = "AFTER_" + event.getPhaseId();
assertFalse("Phase callback " + phaseCallback + " already executed.", phaseCallbacks
.contains(phaseCallback));
phaseCallbacks.add(phaseCallback);
}
public void beforePhase(PhaseEvent event) {
String phaseCallback = "BEFORE_" + event.getPhaseId();
assertFalse("Phase callback " + phaseCallback + " already executed.", phaseCallbacks
.contains(phaseCallback));
phaseCallbacks.add(phaseCallback);
}
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
public List getPhaseCallbacks() {
return phaseCallbacks;
}
}
private class NoRenderViewHandler extends MockViewHandler {
boolean rendered = false;
public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {
rendered = true;
}
}
}

View File

@@ -0,0 +1,254 @@
package org.springframework.faces.webflow;
import java.util.ArrayList;
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.jboss.el.ExpressionFactoryImpl;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.core.expression.el.WebFlowELExpressionParser;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.execution.View;
import org.springframework.webflow.execution.ViewFactory;
import org.springframework.webflow.test.MockExternalContext;
public class JsfViewFactoryTests extends TestCase {
private static final String VIEW_ID = "testView.xhtml";
private ViewFactory factory;
private JSFMockHelper jsfMock = new JSFMockHelper();
private RequestContext context = EasyMock.createMock(RequestContext.class);
private AttributeMap flashMap = new LocalAttributeMap();
private ViewHandler viewHandler = new MockViewHandler();
private Lifecycle lifecycle;
private PhaseListener trackingListener;
private ExpressionParser parser = new WebFlowELExpressionParser(new ExpressionFactoryImpl());
private ExternalContext extContext = new MockExternalContext();
private String event = "foo";
protected void setUp() throws Exception {
configureJsf();
RequestContextHolder.setRequestContext(context);
EasyMock.expect(context.getFlashScope()).andStubReturn(flashMap);
EasyMock.expect(context.getExternalContext()).andStubReturn(extContext);
EasyMock.replay(new Object[] { context });
}
protected void tearDown() throws Exception {
jsfMock.tearDown();
}
private void configureJsf() throws Exception {
jsfMock.setUp();
trackingListener = new TrackingPhaseListener();
jsfMock.lifecycle().addPhaseListener(trackingListener);
jsfMock.facesContext().setViewRoot(null);
jsfMock.application().setViewHandler(viewHandler);
}
/**
* View has not yet been created
*/
public final void testGetView_Create() {
lifecycle = new NoEventLifecycle(jsfMock.lifecycle());
factory = new JsfViewFactory(lifecycle, parser.parseExpression(VIEW_ID, RequestContext.class, String.class,
null));
UIViewRoot newRoot = new UIViewRoot();
newRoot.setViewId(VIEW_ID);
((MockViewHandler) viewHandler).setCreateView(newRoot);
View newView = factory.getView(context);
assertNotNull("A View was not created", newView);
assertTrue("A JsfView was expected", newView instanceof JsfView);
assertEquals("View name did not match", VIEW_ID, ((JsfView) newView).getViewRoot().getViewId());
assertFalse("An unexpected event was signaled,", newView.eventSignaled());
assertFalse("The lifecycle should not have been invoked", ((NoEventLifecycle) lifecycle).executed);
}
/**
* View already exists in flash scope and must be restored and the lifecycle executed, no event signaled
*/
public final void testGetView_Restore_NoEvent() {
lifecycle = new NoEventLifecycle(jsfMock.lifecycle());
factory = new JsfViewFactory(lifecycle, parser.parseExpression(VIEW_ID, RequestContext.class, String.class,
null));
UIViewRoot existingRoot = new UIViewRoot();
existingRoot.setViewId(VIEW_ID);
((MockViewHandler) viewHandler).setRestoreView(existingRoot);
View restoredView = factory.getView(context);
assertNotNull("A View was not restored", restoredView);
assertTrue("A JsfView was expected", restoredView instanceof JsfView);
assertEquals("View name did not match", VIEW_ID, ((JsfView) restoredView).getViewRoot().getViewId());
assertFalse("An unexpected event was signaled,", restoredView.eventSignaled());
assertTrue("The lifecycle should have been invoked", ((NoEventLifecycle) lifecycle).executed);
}
/**
* View already exists in flowscope and must be restored and the lifecycle executed, an event is signaled
*/
public final void testGetView_Restore_EventSignaled() {
lifecycle = new EventSignalingLifecycle(jsfMock.lifecycle());
factory = new JsfViewFactory(lifecycle, parser.parseExpression(VIEW_ID, RequestContext.class, String.class,
null));
UIViewRoot existingRoot = new UIViewRoot();
existingRoot.setViewId(VIEW_ID);
((MockViewHandler) viewHandler).setRestoreView(existingRoot);
View restoredView = factory.getView(context);
assertNotNull("A View was not restored", restoredView);
assertTrue("A JsfView was expected", restoredView instanceof JsfView);
assertEquals("View name did not match", VIEW_ID, ((JsfView) restoredView).getViewRoot().getViewId());
assertTrue("No event was signaled,", restoredView.eventSignaled());
assertEquals("Event should be " + event, event, restoredView.getEvent().getId());
assertTrue("The lifecycle should have been invoked", ((EventSignalingLifecycle) lifecycle).executed);
}
/**
* View is restored, and then the same view-state is re-entered at the end of the request
* @throws Exception
*/
/*
* public final void testGetView_RestoreTwice() throws Exception {
*
* lifecycle = new EventSignalingLifecycle(jsfMock.lifecycle()); factory = new JsfViewFactory(lifecycle,
* parser.parseExpression(VIEW_ID));
*
* UIViewRoot existingRoot = new UIViewRoot(); existingRoot.setViewId(VIEW_ID); ((MockViewHandler)
* viewHandler).setRestoreView(existingRoot);
*
* View restoredView = factory.getView(context);
*
* assertNull("FacesContext was not released", FacesContext.getCurrentInstance());
*
* configureJsf();
*
* View recursiveView = factory.getView(context);
*
* assertNotNull("A View was not restored", restoredView); assertTrue("A JsfView was expected", restoredView
* instanceof JsfView); assertEquals("View name did not match", VIEW_ID, ((JsfView)
* restoredView).getViewRoot().getViewId()); assertSame("Re-entered view should be the same instance", ((JsfView)
* restoredView).getViewRoot(), ((JsfView) recursiveView).getViewRoot()); assertTrue("No event was signaled,",
* restoredView.eventSignaled()); assertEquals("Event should be " + event, event, restoredView.getEvent().getId());
* assertTrue("The lifecycle should have been invoked", lifecycle.executed); }
*/
/**
* Third party sets the view root before RESTORE_VIEW
*/
public final void testGetView_ExternalViewRoot() {
lifecycle = new NoEventLifecycle(jsfMock.lifecycle());
factory = new JsfViewFactory(lifecycle, parser.parseExpression(VIEW_ID, RequestContext.class, String.class,
null));
UIViewRoot newRoot = new UIViewRoot();
newRoot.setViewId(VIEW_ID);
jsfMock.facesContext().setViewRoot(newRoot);
jsfMock.facesContext().renderResponse();
View newView = factory.getView(context);
assertNotNull("A View was not created", newView);
assertTrue("A JsfView was expected", newView instanceof JsfView);
assertEquals("View name did not match", VIEW_ID, ((JsfView) newView).getViewRoot().getViewId());
assertSame("View root was not the third party instance", newRoot, ((JsfView) newView).getViewRoot());
assertFalse("An unexpected event was signaled,", newView.eventSignaled());
assertFalse("The lifecycle should not have been invoked", ((NoEventLifecycle) lifecycle).executed);
}
private class NoEventLifecycle extends FlowLifecycle {
boolean executed = false;
public NoEventLifecycle(Lifecycle delegate) {
super(delegate);
}
public void execute(FacesContext context) throws FacesException {
assertFalse("Lifecycle executed more than once", executed);
super.execute(context);
executed = true;
}
}
private class EventSignalingLifecycle extends FlowLifecycle {
boolean executed = false;
public EventSignalingLifecycle(Lifecycle delegate) {
super(delegate);
}
@SuppressWarnings("unchecked")
public void execute(FacesContext context) throws FacesException {
assertFalse("Lifecycle executed more than once", executed);
super.execute(context);
extContext.getRequestMap().put(JsfView.EVENT_KEY, event);
executed = true;
}
}
private class TrackingPhaseListener implements PhaseListener {
private List phaseCallbacks = new ArrayList();
public void afterPhase(PhaseEvent event) {
String phaseCallback = "AFTER_" + event.getPhaseId();
assertFalse("Phase callback " + phaseCallback + " already executed.", phaseCallbacks
.contains(phaseCallback));
phaseCallbacks.add(phaseCallback);
}
public void beforePhase(PhaseEvent event) {
String phaseCallback = "BEFORE_" + event.getPhaseId();
assertFalse("Phase callback " + phaseCallback + " already executed.", phaseCallbacks
.contains(phaseCallback));
phaseCallbacks.add(phaseCallback);
}
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
public List getPhaseCallbacks() {
return phaseCallbacks;
}
}
}

View File

@@ -0,0 +1,153 @@
package org.springframework.faces.webflow;
import java.io.IOException;
import java.io.StringWriter;
import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.component.UIForm;
import javax.faces.component.UIInput;
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlForm;
import javax.faces.component.html.HtmlInputText;
import javax.faces.context.FacesContext;
import javax.faces.render.RenderKitFactory;
import javax.faces.render.Renderer;
import javax.faces.render.ResponseStateManager;
import junit.framework.TestCase;
import org.apache.shale.test.mock.MockRenderKit;
import org.apache.shale.test.mock.MockResponseWriter;
import org.apache.shale.test.mock.MockStateManager;
import org.easymock.EasyMock;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.execution.FlowExecutionContext;
import org.springframework.webflow.execution.FlowExecutionKey;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
public class JsfViewTests extends TestCase {
private static final String VIEW_ID = "testView.xhtml";
private JsfView view;
private JSFMockHelper jsfMock = new JSFMockHelper();
private StringWriter output = new StringWriter();
private RequestContext requestContext = EasyMock.createMock(RequestContext.class);
private FlowExecutionContext flowExecutionContext = EasyMock.createMock(FlowExecutionContext.class);
private MutableAttributeMap flashMap = EasyMock.createMock(MutableAttributeMap.class);
private FlowExecutionKey key = new FlowExecutionKey() {
public String toString() {
return "MOCK_KEY";
}
public boolean equals(Object o) {
return true;
}
public int hashCode() {
return 0;
}
};
protected void setUp() throws Exception {
jsfMock.setUp();
jsfMock.application().setViewHandler(new MockViewHandler());
jsfMock.application().setStateManager(new TestStateManager());
jsfMock.facesContext().setResponseWriter(new MockResponseWriter(output, null, null));
RenderKitFactory rkf = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
rkf.addRenderKit("TEST_KIT", new TestRenderKit());
UIViewRoot viewToRender = new UIViewRoot();
viewToRender.setRenderKitId("TEST_KIT");
viewToRender.setViewId(VIEW_ID);
jsfMock.facesContext().setViewRoot(viewToRender);
UIForm form = new HtmlForm();
form.setId("myForm");
UIInput input = new HtmlInputText();
input.setId("foo");
form.getChildren().add(input);
viewToRender.getChildren().add(form);
view = new JsfView(viewToRender, jsfMock.lifecycle());
RequestContextHolder.setRequestContext(requestContext);
}
protected void tearDown() throws Exception {
jsfMock.tearDown();
}
public final void testRender() {
EasyMock.expect(requestContext.getFlashScope()).andStubReturn(flashMap);
EasyMock.expect(requestContext.getFlowExecutionContext()).andStubReturn(flowExecutionContext);
EasyMock.expect(flowExecutionContext.getKey()).andStubReturn(key);
EasyMock.expect(flashMap.put(EasyMock.matches(JsfView.STATE_KEY), EasyMock.anyObject())).andStubReturn(null);
EasyMock.expect(flashMap.put(EasyMock.matches("renderResponse"), EasyMock.anyObject())).andStubReturn(null);
EasyMock.expect(flashMap.put(EasyMock.matches("responseComplete"), EasyMock.anyObject())).andStubReturn(null);
EasyMock.replay(new Object[] { requestContext, flowExecutionContext, flashMap });
view.render();
EasyMock.verify(new Object[] { requestContext, flowExecutionContext, flashMap });
assertNull("The FacesContext was not released", FacesContext.getCurrentInstance());
assertTrue(output.getBuffer().toString().contains(key.toString()));
}
public final void testRenderException() {
EasyMock.expect(requestContext.getFlashScope()).andStubReturn(flashMap);
EasyMock.expect(flashMap.put(EasyMock.matches("renderResponse"), EasyMock.anyObject())).andStubReturn(null);
EasyMock.expect(flashMap.put(EasyMock.matches("responseComplete"), EasyMock.anyObject())).andStubReturn(null);
EasyMock.replay(new Object[] { requestContext, flowExecutionContext, flashMap });
jsfMock.application().setViewHandler(new ExceptionalViewHandler());
try {
view.render();
} catch (FacesException ex) {
assertNull("The FacesContext was not released", FacesContext.getCurrentInstance());
}
}
private class ExceptionalViewHandler extends MockViewHandler {
public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {
throw new IOException("Rendering blew up");
}
}
private class TestStateManager extends MockStateManager {
public SerializedView saveSerializedView(FacesContext context) {
SerializedView state = new SerializedView(new Object[] { "tree_state" }, new Object[] { "component_state" });
return state;
}
}
private class TestRenderKit extends MockRenderKit {
Renderer renderer = new Renderer() {
};
public Renderer getRenderer(String family, String rendererType) {
return renderer;
}
public ResponseStateManager getResponseStateManager() {
return new FlowResponseStateManager();
}
}
}

View File

@@ -0,0 +1,35 @@
package org.springframework.faces.webflow;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.context.ExternalContext;
import javax.faces.lifecycle.Lifecycle;
import org.apache.shale.test.mock.MockFacesContext12;
public class MockBaseFacesContext extends MockFacesContext12 {
private Application application;
public MockBaseFacesContext() {
super();
}
public MockBaseFacesContext(ExternalContext externalContext) {
super(externalContext);
}
public MockBaseFacesContext(ExternalContext externalContext, Lifecycle lifecycle) {
super(externalContext, lifecycle);
}
public Application getApplication() {
if (application == null) {
ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder
.getFactory(FactoryFinder.APPLICATION_FACTORY);
application = applicationFactory.getApplication();
}
return application;
}
}

View File

@@ -0,0 +1,25 @@
package org.springframework.faces.webflow;
import javax.faces.FacesException;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shale.test.mock.MockExternalContext;
public class MockBaseFacesContextFactory extends FacesContextFactory {
public FacesContext getFacesContext(Object context, Object request, Object response, Lifecycle lifecycle)
throws FacesException {
ExternalContext ext = new MockExternalContext((ServletContext) context, (HttpServletRequest) request,
(HttpServletResponse) response);
return new MockBaseFacesContext(ext, lifecycle);
}
}

View File

@@ -20,11 +20,14 @@ import java.util.Locale;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.application.StateManager.SerializedView;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
public class MockViewHandler extends ViewHandler {
private UIViewRoot viewRoot;
private UIViewRoot createViewRoot;
private UIViewRoot restoreViewRoot;
public Locale calculateLocale(FacesContext context) {
return null;
@@ -35,15 +38,23 @@ public class MockViewHandler extends ViewHandler {
}
public UIViewRoot createView(FacesContext context, String viewId) {
return viewRoot;
return createViewRoot;
}
/**
* Set the view root that this mpck is supposed to create.
* @param viewRoot the view to set.
* Set the view root that this mock is supposed to create
* @param createViewRoot the view to set.
*/
public void setCreateView(UIViewRoot viewRoot) {
this.viewRoot = viewRoot;
public void setCreateView(UIViewRoot createViewRoot) {
this.createViewRoot = createViewRoot;
}
/**
* Set the view root that this mock is supposed to restore
* @param restoreViewRoot the view to set.
*/
public void setRestoreView(UIViewRoot restoreViewRoot) {
this.restoreViewRoot = restoreViewRoot;
}
public String getActionURL(FacesContext context, String viewId) {
@@ -54,11 +65,17 @@ public class MockViewHandler extends ViewHandler {
return null;
}
/**
* Really simple implementation to exercise rendering and state saving
*/
public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {
context.getViewRoot().encodeAll(context);
SerializedView state = context.getApplication().getStateManager().saveSerializedView(context);
context.getRenderKit().getResponseStateManager().writeState(context, state);
}
public UIViewRoot restoreView(FacesContext context, String viewId) {
return null;
return restoreViewRoot;
}
public void writeState(FacesContext context) throws IOException {