diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java index fc6a3c90..22880e31 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/test/MockExternalContext.java @@ -63,6 +63,8 @@ public class MockExternalContext implements ExternalContext { private boolean ajaxRequest; + private Boolean responseAllowed; + private boolean responseComplete; private boolean flowExecutionRedirectRequested; @@ -152,7 +154,11 @@ public class MockExternalContext implements ExternalContext { } public boolean isResponseAllowed() { - return !responseComplete; + if (responseAllowed != null) { + return responseAllowed.booleanValue(); + } else { + return !responseComplete; + } } public boolean isResponseComplete() { @@ -347,6 +353,14 @@ public class MockExternalContext implements ExternalContext { this.ajaxRequest = ajaxRequest; } + /** + * Set the response allows flag to a value for testing. + * @param responseAllowed true or false + */ + public void setResponseAllowed(boolean responseAllowed) { + this.responseAllowed = Boolean.valueOf(responseAllowed); + } + /** * Returns the implementation of this mock context's response writer. * @return the underlying string writer to use for asserting a specific response was written diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/ViewStateTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/ViewStateTests.java index a8680ecb..44d05ef2 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/ViewStateTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/ViewStateTests.java @@ -32,16 +32,55 @@ import org.springframework.webflow.test.MockRequestControlContext; */ public class ViewStateTests extends TestCase { - public void testEnterViewStateDefaultBehavior() { + public void testEnterViewStateRenderResponse() { Flow flow = new Flow("myFlow"); StubViewFactory viewFactory = new StubViewFactory(); ViewState state = new ViewState(flow, "viewState", viewFactory); MockRequestControlContext context = new MockRequestControlContext(flow); state.enter(context); assertTrue("Render not called", context.getFlowScope().contains("renderCalled")); + assertTrue(context.getExternalContext().isResponseComplete()); assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); } + public void testEnterViewStateRenderNotAllowed() { + Flow flow = new Flow("myFlow"); + StubViewFactory viewFactory = new StubViewFactory(); + ViewState state = new ViewState(flow, "viewState", viewFactory); + MockRequestControlContext context = new MockRequestControlContext(flow); + context.getMockExternalContext().setResponseAllowed(false); + state.enter(context); + assertFalse("Render called", context.getFlowScope().contains("renderCalled")); + assertTrue(context.getExternalContext().isResponseComplete()); + assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); + } + + public void testEnterViewStateResponseAlreadyComplete() { + Flow flow = new Flow("myFlow"); + StubViewFactory viewFactory = new StubViewFactory(); + ViewState state = new ViewState(flow, "viewState", viewFactory); + MockRequestControlContext context = new MockRequestControlContext(flow); + context.getExternalContext().recordResponseComplete(); + context.getFlashScope().put("foo", "bar"); + state.enter(context); + assertFalse("Render called", context.getFlowScope().contains("renderCalled")); + assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); + assertFalse(context.getFlashScope().contains("foo")); + } + + public void testEnterViewStateRedirectResponseAlreadyComplete() { + Flow flow = new Flow("myFlow"); + StubViewFactory viewFactory = new StubViewFactory(); + ViewState state = new ViewState(flow, "viewState", viewFactory); + MockRequestControlContext context = new MockRequestControlContext(flow); + context.getExternalContext().requestFlowExecutionRedirect(); + context.getFlashScope().put("foo", "bar"); + state.enter(context); + assertFalse("Render called", context.getFlowScope().contains("renderCalled")); + assertTrue(context.getMockExternalContext().getFlowExecutionRedirectRequested()); + assertTrue(context.getFlashScope().contains("foo")); + } + public void testEnterViewStateWithVariables() { Flow flow = new Flow("myFlow"); StubViewFactory viewFactory = new StubViewFactory(); @@ -58,6 +97,7 @@ public class ViewStateTests extends TestCase { state.enter(context); assertEquals("bar", context.getViewScope().getString("foo")); assertTrue("Render not called", context.getFlowScope().contains("renderCalled")); + assertTrue(context.getExternalContext().isResponseComplete()); assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); } @@ -107,41 +147,32 @@ public class ViewStateTests extends TestCase { assertTrue(context.getMockExternalContext().getFlowExecutionRedirectRequested()); } - public void testEnterViewStateWithPopup() { - Flow flow = new Flow("myFlow"); - StubViewFactory viewFactory = new StubViewFactory(); - ViewState state = new ViewState(flow, "viewState", viewFactory); - state.setPopup(true); - MockRequestControlContext context = new MockRequestControlContext(flow); - context.setAlwaysRedirectOnPause(true); - state.enter(context); - assertFalse("Render called", context.getFlowScope().contains("renderCalled")); - assertTrue(context.getMockExternalContext().getFlowExecutionRedirectRequested()); - } - - public void testEnterViewStateResponseComplete() { - Flow flow = new Flow("myFlow"); - StubViewFactory viewFactory = new StubViewFactory(); - ViewState state = new ViewState(flow, "viewState", viewFactory); - MockRequestControlContext context = new MockRequestControlContext(flow); - context.setAlwaysRedirectOnPause(true); - context.getExternalContext().recordResponseComplete(); - state.enter(context); - assertFalse("Render called", context.getFlowScope().contains("renderCalled")); - assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); - } - public void testResumeViewStateForRefresh() { Flow flow = new Flow("myFlow"); StubViewFactory viewFactory = new StubViewFactory(); ViewState state = new ViewState(flow, "viewState", viewFactory); - state.getTransitionSet().add(new Transition(on("submit"), to("finish"))); - new EndState(flow, "finish"); MockRequestControlContext context = new MockRequestControlContext(flow); state.enter(context); context = new MockRequestControlContext(context.getFlowExecutionContext()); state.resume(context); assertTrue("Render not called", context.getFlowScope().contains("renderCalled")); + assertTrue(context.getExternalContext().isResponseComplete()); + assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); + } + + public void testResumeViewStateForRefreshResponseNotAllowed() { + Flow flow = new Flow("myFlow"); + StubViewFactory viewFactory = new StubViewFactory(); + ViewState state = new ViewState(flow, "viewState", viewFactory); + MockRequestControlContext context = new MockRequestControlContext(flow); + state.enter(context); + assertTrue("Render called", context.getFlowScope().contains("renderCalled")); + context = new MockRequestControlContext(context.getFlowExecutionContext()); + context.getMockExternalContext().setResponseAllowed(false); + context.getFlowScope().remove("renderCalled"); + state.resume(context); + assertFalse("Render called", context.getFlowScope().contains("renderCalled")); + assertTrue(context.getExternalContext().isResponseComplete()); assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); } @@ -155,10 +186,12 @@ public class ViewStateTests extends TestCase { state.enter(context); context = new MockRequestControlContext(context.getFlowExecutionContext()); context.getFlowScope().remove("renderCalled"); + context.getFlashScope().put("foo", "bar"); context.getExternalContext().recordResponseComplete(); state.resume(context); assertFalse("Render called", context.getFlowScope().contains("renderCalled")); assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); + assertFalse(context.getFlashScope().contains("foo")); } public void testResumeViewStateRestoreVariables() { @@ -183,17 +216,19 @@ public class ViewStateTests extends TestCase { assertEquals("Restored", ((TestBean) context.getViewScope().get("foo")).datum1); } - public void testResumeViewStateForEventWithTransition() { + public void testResumeViewStateForEventWithTransitionStateExited() { Flow flow = new Flow("myFlow"); StubViewFactory viewFactory = new StubViewFactory(); ViewState state = new ViewState(flow, "viewState", viewFactory); state.getTransitionSet().add(new Transition(on("submit"), to("finish"))); - new EndState(flow, "finish"); + EndState end = new EndState(flow, "finish"); + end.setFinalResponseAction(new TestAction()); MockRequestControlContext context = new MockRequestControlContext(flow); state.enter(context); context = new MockRequestControlContext(context.getFlowExecutionContext()); context.putRequestParameter("_eventId", "submit"); state.resume(context); + assertTrue(context.getExternalContext().isResponseComplete()); assertFalse(context.getFlowExecutionContext().isActive()); } @@ -213,10 +248,30 @@ public class ViewStateTests extends TestCase { state.resume(context); assertTrue(context.getFlowExecutionContext().isActive()); assertEquals(1, action.getExecutionCount()); + assertTrue(context.getExternalContext().isResponseComplete()); assertTrue("Render not called", context.getFlowScope().contains("renderCalled")); assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); } + public void testResumeViewStateForEventStateNotExitedNonAjaxResponseNotAllowed() { + Flow flow = new Flow("myFlow"); + StubViewFactory viewFactory = new StubViewFactory(); + ViewState state = new ViewState(flow, "viewState", viewFactory); + Transition t = new Transition(on("submit"), null); + state.getTransitionSet().add(t); + MockRequestControlContext context = new MockRequestControlContext(flow); + state.enter(context); + context = new MockRequestControlContext(context.getFlowExecutionContext()); + context.getFlowScope().remove("renderCalled"); + context.putRequestParameter("_eventId", "submit"); + context.getMockExternalContext().setResponseAllowed(false); + state.resume(context); + assertTrue(context.getFlowExecutionContext().isActive()); + assertTrue(context.getExternalContext().isResponseComplete()); + assertFalse("Render called", context.getFlowScope().contains("renderCalled")); + assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); + } + public void testResumeViewStateForEventStateNotExitedNonAjaxRedirectEnabled() { Flow flow = new Flow("myFlow"); StubViewFactory viewFactory = new StubViewFactory(); @@ -255,10 +310,35 @@ public class ViewStateTests extends TestCase { state.resume(context); assertTrue(context.getFlowExecutionContext().isActive()); assertEquals(1, action.getExecutionCount()); + assertTrue(context.getExternalContext().isResponseComplete()); assertTrue("Render not called", context.getFlowScope().contains("renderCalled")); assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); } + public void testResumeViewStateForEventStateNotExitedAjaxResponseNotAllowed() { + Flow flow = new Flow("myFlow"); + StubViewFactory viewFactory = new StubViewFactory(); + ViewState state = new ViewState(flow, "viewState", viewFactory); + Transition t = new Transition(on("submit"), null); + TestAction action = new TestAction(); + t.setExecutionCriteria(new ActionTransitionCriteria(action)); + state.getTransitionSet().add(t); + MockRequestControlContext context = new MockRequestControlContext(flow); + context.getMockExternalContext().setAjaxRequest(true); + state.enter(context); + context = new MockRequestControlContext(context.getFlowExecutionContext()); + context.putRequestParameter("_eventId", "submit"); + context.getMockExternalContext().setAjaxRequest(true); + context.getMockExternalContext().setResponseAllowed(false); + context.getFlowScope().remove("renderCalled"); + state.resume(context); + assertTrue(context.getFlowExecutionContext().isActive()); + assertEquals(1, action.getExecutionCount()); + assertTrue(context.getExternalContext().isResponseComplete()); + assertFalse("Render called", context.getFlowScope().contains("renderCalled")); + assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); + } + public void testResumeViewStateForEventStateNoExitActionRecordedResponseComplete() { Flow flow = new Flow("myFlow"); StubViewFactory viewFactory = new StubViewFactory(); @@ -279,11 +359,14 @@ public class ViewStateTests extends TestCase { context.getFlowScope().remove("renderCalled"); context = new MockRequestControlContext(context.getFlowExecutionContext()); context.putRequestParameter("_eventId", "submit"); + context.getFlashScope().put("Foo", "bar"); state.resume(context); assertTrue(context.getFlowExecutionContext().isActive()); assertEquals(1, action.getExecutionCount()); + assertTrue(context.getExternalContext().isResponseComplete()); assertFalse("Render called", context.getFlowScope().contains("renderCalled")); assertFalse(context.getMockExternalContext().getFlowExecutionRedirectRequested()); + assertFalse(context.getFlashScope().contains("foo")); } public void testResumeViewStateForEventDestroyVariables() {