001 /**
002 * Copyright 2005-2014 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kew.actions;
017
018 import org.junit.Test;
019 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
020 import org.kuali.rice.kew.api.KewApiServiceLocator;
021 import org.kuali.rice.kew.api.WorkflowDocument;
022 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
023 import org.kuali.rice.kew.api.action.MovePoint;
024 import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
025 import org.kuali.rice.kew.api.document.WorkflowDocumentService;
026 import org.kuali.rice.kew.service.KEWServiceLocator;
027 import org.kuali.rice.kew.test.KEWTestCase;
028 import org.kuali.rice.kew.test.TestUtilities;
029
030 import java.util.List;
031 import java.util.Set;
032
033 import static org.junit.Assert.*;
034
035 public class MoveDocumentTest extends KEWTestCase {
036
037 protected void loadTestData() throws Exception {
038 loadXmlFile("ActionsConfig.xml");
039 }
040
041 /**
042 * Tests that we can move a sequential document forward and backward.
043 *
044 */
045 @Test public void testMoveDocumentSequential() throws Exception {
046 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), SeqSetup.DOCUMENT_TYPE_NAME);
047 document.route("");
048
049 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
050 assertTrue("Bmcgough should have an approve.", document.isApprovalRequested());
051 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
052 assertTrue("Rkirkend should have an approve.", document.isApprovalRequested());
053 assertEquals("Should be at the WorkflowDocument Node.", SeqSetup.WORKFLOW_DOCUMENT_NODE, document.getNodeNames().iterator().next());
054
055 // move the document forward one node
056 document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_NODE, 1), "");
057
058 List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
059 assertEquals("Should be only 1 pending approve request to pmckown.", 1, actionRequests.size());
060 assertEquals("Should be at the WorkflowDocument2 Node.", SeqSetup.WORKFLOW_DOCUMENT_2_NODE, document.getNodeNames().iterator().next());
061
062 // after moving the document forward, bmcgough and rkirkend should no longer have requests, but phil should
063 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
064 assertFalse("Bmcgough should NOT have an approve.", document.isApprovalRequested());
065 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
066 assertFalse("Rkirkend should NOT have an approve.", document.isApprovalRequested());
067
068 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("pmckown"), document.getDocumentId());
069 assertTrue("Pmckown should have an approve.", document.isApprovalRequested());
070 ActionRequestValue pmckownRequest = (ActionRequestValue)actionRequests.get(0);
071
072 // now try moving it to itself, effectively refreshing the node
073 document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_2_NODE, 0), "");
074 assertTrue("Pmckown should still have an approve.", document.isApprovalRequested());
075 actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
076 assertEquals("Should be only 1 pending approve request to pmckown.", 1, actionRequests.size());
077 assertEquals("Should be at the WorkflowDocument2 Node.", SeqSetup.WORKFLOW_DOCUMENT_2_NODE, document.getNodeNames().iterator().next());
078
079 // since this should have invoked a refresh, let's ensure that the action request ids are different after the move
080 assertFalse("Action request ids should be different.", pmckownRequest.getActionRequestId().equals(((ActionRequestValue)actionRequests.get(0)).getActionRequestId()));
081
082 // now try moving it back
083 document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_2_NODE, -1), "");
084
085 // document should now be back at the WorkflowDocumentNode with requests to rkirkend and brian
086 actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
087 assertEquals("Should be 2 pending requests.", 2, actionRequests.size());
088
089 assertEquals("Should be at the WorkflowDocument Node.", SeqSetup.WORKFLOW_DOCUMENT_NODE, document.getNodeNames().iterator().next());
090 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
091 assertTrue("Bmcgough should have an approve.", document.isApprovalRequested());
092 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
093 assertTrue("Rkirkend should have an approve.", document.isApprovalRequested());
094
095
096 // Let's do a sanity check to make sure we're still ENROUTE and move the doc to an ack node, rendering it PROCESSED,
097 // also, we'll check that there are no permissions enforced on the move document action by moving as a random user
098 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("xqi"), document.getDocumentId());
099 assertTrue("Doc should be ENROUTE.", document.isEnroute());
100 document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_NODE, 2), "");
101 assertTrue("Doc should be PROCESSED.", document.isProcessed());
102 }
103
104 /**
105 * This tests that we can invoke the move document command inside of a sub process.
106 */
107 @Test public void testMoveDocumentInsideProcess() throws Exception {
108 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "MoveInProcessTest");
109 document.route("");
110
111 // approve as bmcgough and rkirkend to move into process
112 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("bmcgough"), document.getDocumentId());
113 assertTrue("bmcgough should have approve", document.isApprovalRequested());
114 document.approve("");
115 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), document.getDocumentId());
116 assertTrue("rkirkend should have approve", document.isApprovalRequested());
117 document.approve("");
118
119 WorkflowDocumentService workflowDocumentService = KewApiServiceLocator.getWorkflowDocumentService();
120 List<RouteNodeInstance> activeNodeInstances = workflowDocumentService.getActiveRouteNodeInstances(document.getDocumentId());
121 assertEquals("Should be 1 active node instance.", 1, activeNodeInstances.size());
122 RouteNodeInstance node2 = activeNodeInstances.get(0);
123 assertEquals("Should be at the WorkflowDocument2 node.", SeqSetup.WORKFLOW_DOCUMENT_2_NODE, node2.getName());
124 assertTrue("Node should be in a process.", node2.getProcessId() != null);
125
126 // now try to move the document forward one which will keep us inside the subprocess
127 document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_2_NODE, 1), "");
128
129 activeNodeInstances = workflowDocumentService.getActiveRouteNodeInstances(document.getDocumentId());
130 RouteNodeInstance node3 = activeNodeInstances.get(0);
131 assertEquals("Should be at the WorkflowDocument3 node.", SeqSetup.WORKFLOW_DOCUMENT_3_NODE, node3.getName());
132 assertTrue("Node should be in a process.", node3.getProcessId() != null);
133 assertEquals("Node 2 and 3 should be in the same process.", node2.getProcessId(), node3.getProcessId());
134
135 document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_3_NODE, 0), "");
136
137 document.move(MovePoint.create(SeqSetup.WORKFLOW_DOCUMENT_3_NODE, -1), "");
138 }
139
140 @Test public void testMoveDocumentParallel() throws Exception {
141 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), ParallelSetup.DOCUMENT_TYPE_NAME);
142 document.blanketApprove("", new String[] { ParallelSetup.WORKFLOW_DOCUMENT_2_B2_NODE, ParallelSetup.WORKFLOW_DOCUMENT_3_B1_NODE, ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE });
143 Set nodeNames = TestUtilities.createNodeInstanceNameSet(KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()));
144 assertEquals("There should be 3 active nodes.", 3, nodeNames.size());
145 assertTrue("Should be at WorkflowDocument3-B1", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_3_B1_NODE));
146 assertTrue("Should be at WorkflowDocument2-B2", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_2_B2_NODE));
147 assertTrue("Should be at WorkflowDocument4-B3", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE));
148
149 // try to move the document from WorkflowDocument3-B1 to WorkflowDocument2-B1
150 document.move(MovePoint.create(ParallelSetup.WORKFLOW_DOCUMENT_3_B1_NODE, -1), "");
151 nodeNames = TestUtilities.createNodeInstanceNameSet(KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()));
152 assertEquals("There should be 3 active nodes.", 3, nodeNames.size());
153 assertTrue("Should be at WorkflowDocument2-B1", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_2_B1_NODE));
154 assertTrue("Should be at WorkflowDocument2-B2", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_2_B2_NODE));
155 assertTrue("Should be at WorkflowDocument4-B3", nodeNames.contains(ParallelSetup.WORKFLOW_DOCUMENT_4_B3_NODE));
156 }
157
158 private class SeqSetup {
159
160 public static final String DOCUMENT_TYPE_NAME = "MoveSequentialTest";
161 public static final String ADHOC_NODE = "AdHoc";
162 public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
163 public static final String WORKFLOW_DOCUMENT_2_NODE = "WorkflowDocument2";
164 public static final String WORKFLOW_DOCUMENT_3_NODE = "WorkflowDocument3";
165 public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
166 public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
167
168 }
169
170 private class ParallelSetup {
171
172 public static final String DOCUMENT_TYPE_NAME = "BlanketApproveParallelTest";
173 public static final String ADHOC_NODE = "AdHoc";
174 public static final String WORKFLOW_DOCUMENT_NODE = "WorkflowDocument";
175 public static final String WORKFLOW_DOCUMENT_2_B1_NODE = "WorkflowDocument2-B1";
176 public static final String WORKFLOW_DOCUMENT_2_B2_NODE = "WorkflowDocument2-B2";
177 public static final String WORKFLOW_DOCUMENT_3_B1_NODE = "WorkflowDocument3-B1";
178 public static final String WORKFLOW_DOCUMENT_3_B2_NODE = "WorkflowDocument3-B2";
179 public static final String WORKFLOW_DOCUMENT_4_B3_NODE = "WorkflowDocument4-B3";
180 public static final String ACKNOWLEDGE_1_NODE = "Acknowledge1";
181 public static final String ACKNOWLEDGE_2_NODE = "Acknowledge2";
182 public static final String JOIN_NODE = "Join";
183 public static final String SPLIT_NODE = "Split";
184 public static final String WORKFLOW_DOCUMENT_FINAL_NODE = "WorkflowDocumentFinal";
185
186 }
187
188 }