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 }