View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.demo.travel.application;
17  
18  import org.junit.Ignore;
19  import org.junit.Test;
20  import org.kuali.rice.kew.api.action.ActionRequestType;
21  import org.kuali.rice.testtools.selenium.WebDriverLegacyITBase;
22  import org.kuali.rice.testtools.selenium.WebDriverUtils;
23  import org.openqa.selenium.By;
24  
25  /**
26   * Tests the pessimistic locking feature in a transactional document.
27   *
28   * @author Kuali Rice Team (rice.collab@kuali.org)
29   */
30  public class DemoTravelAuthorizationPessimisticLockingAft extends WebDriverLegacyITBase {
31  
32      /**
33       * /kr-krad/approval?methodToCall=docHandler&command=initiate&docTypeName=TravelAuthorization
34       */
35      public static final String BOOKMARK_URL = "/kr-krad/approval?methodToCall=docHandler&command=initiate&docTypeName=TravelAuthorization";
36  
37      private static final String DOC_HANDLER_URL = "/kew/DocHandler.do?command=displayDocSearchView&docId=";
38  
39      private static final String APPROVER_PRINCIPAL_NAME_VALUE = "edna";
40      private static final String EDITOR_PRINCIPAL_NAME_VALUE = "dev1";
41  
42      private static final String DOCUMENT_DESCRIPTION_FIELD = "document.documentHeader.documentDescription";
43      private static final String CONTACT_NUMBER_FIELD = "document.cellPhoneNumber";
44  
45      private static final String DOCUMENT_DESCRIPTION_VALUE = "Test Pessimistic Locking";
46      private static final String CONTACT_NUMBER_VALUE = "555-555-5555";
47  
48      @Override
49      protected String getBookmarkUrl() {
50          return BOOKMARK_URL;
51      }
52  
53      @Override
54      protected void navigate() throws Exception {
55          waitAndClickDemoLink();
56          waitAndClickByLinkText("Travel Authorization Document");
57      }
58  
59      @Override
60      public String getUserName() {
61          return "admin";
62      }
63  
64      /**
65       * Tests whether a document is locked for editing for any other user opening it before it has been routed.
66       *
67       * @throws Exception for any test exceptions
68       */
69      protected void testPessimisticLockingOnSave() throws Exception {
70          String documentNumber = createTravelAuthorization();
71  
72          openTravelAuthorization(documentNumber, EDITOR_PRINCIPAL_NAME_VALUE);
73  
74          waitForTextPresent("This document currently has a full lock");
75          waitForElementNotPresent(By.cssSelector("input[name = '" + DOCUMENT_DESCRIPTION_FIELD + "']"));
76          waitForElementNotPresent(By.cssSelector("input[name = '" + CONTACT_NUMBER_FIELD + "']"));
77  
78          waitForElementNotPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"save\\\"}']"));
79          waitForElementNotPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"route\\\"}']"));
80          waitForElementNotPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"cancel\\\"}']"));
81  
82          openTravelAuthorization(documentNumber, getUserName());
83  
84          waitForTextNotPresent("This document currently has a full lock");
85          assertElementPresent(By.cssSelector("input[name = '" + DOCUMENT_DESCRIPTION_FIELD + "']"));
86          assertElementPresent(By.cssSelector("input[name = '" + CONTACT_NUMBER_FIELD + "']"));
87  
88          assertElementPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"save\\\"}']"), "Save button not found");
89          assertElementPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"route\\\"}']"), "Submit button not found");
90          assertElementPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"cancel\\\"}']"), "Cancel button not found");
91  
92          waitAndClickCloseByText();
93          waitAndClickConfirmSaveOnClose();
94          openTravelAuthorization(documentNumber, EDITOR_PRINCIPAL_NAME_VALUE);
95  
96          waitForTextNotPresent("This document currently has a full lock");
97          assertElementPresent(By.cssSelector("input[name = '" + DOCUMENT_DESCRIPTION_FIELD + "']"));
98          assertElementPresent(By.cssSelector("input[name = '" + CONTACT_NUMBER_FIELD + "']"));
99  
100         assertElementPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"save\\\"}']"), "Save button not found");
101         assertElementPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"route\\\"}']"), "Submit button not found");
102         assertElementPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"cancel\\\"}']"), "Cancel button not found");
103 
104         openTravelAuthorization(documentNumber, getUserName());
105 
106         waitForTextPresent("This document currently has a full lock");
107         waitForElementNotPresent(By.cssSelector("input[name = '" + DOCUMENT_DESCRIPTION_FIELD + "']"));
108         waitForElementNotPresent(By.cssSelector("input[name = '" + CONTACT_NUMBER_FIELD + "']"));
109 
110         waitForElementNotPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"save\\\"}']"));
111         waitForElementNotPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"route\\\"}']"));
112         waitForElementNotPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"cancel\\\"}']"));
113     }
114 
115     /**
116      * Tests whether a document is locked for editing for any other user opening it after it has been routed.
117      *
118      * @throws Exception for any test exceptions
119      */
120     protected void testPessimisticLockingOnRoute() throws Exception {
121         String documentNumber = createTravelAuthorization();
122 
123         addAdHocRecipient(ActionRequestType.APPROVE.name(), APPROVER_PRINCIPAL_NAME_VALUE, getUserName());
124 
125         submitSuccessfully();
126 
127         openTravelAuthorization(documentNumber, APPROVER_PRINCIPAL_NAME_VALUE);
128 
129         waitForTextPresent("This document currently has a full lock");
130         waitForElementNotPresent(By.cssSelector("input[name = '" + DOCUMENT_DESCRIPTION_FIELD + "']"));
131         waitForElementNotPresent(By.cssSelector("input[name = '" + CONTACT_NUMBER_FIELD + "']"));
132 
133         waitForElementNotPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"blanketApprove\\\"}']"));
134 
135         openTravelAuthorization(documentNumber, getUserName());
136 
137         waitForTextNotPresent("This document currently has a full lock");
138         assertElementPresent(By.cssSelector("input[name = '" + DOCUMENT_DESCRIPTION_FIELD + "']"));
139         assertElementPresent(By.cssSelector("input[name = '" + CONTACT_NUMBER_FIELD + "']"));
140 
141         assertElementPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"blanketApprove\\\"}']"), "Blanket Approve not found");
142 
143         waitAndClickCloseByText();
144 
145         openTravelAuthorization(documentNumber, APPROVER_PRINCIPAL_NAME_VALUE);
146 
147         waitForTextNotPresent("This document currently has a full lock");
148         assertElementPresent(By.cssSelector("input[name = '" + DOCUMENT_DESCRIPTION_FIELD + "']"));
149         assertElementPresent(By.cssSelector("input[name = '" + CONTACT_NUMBER_FIELD + "']"));
150 
151         waitForElementNotPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"blanketApprove\\\"}']"));
152 
153         openTravelAuthorization(documentNumber, getUserName());
154 
155         waitForTextPresent("This document currently has a full lock");
156         waitForElementNotPresent(By.cssSelector("input[name = '" + DOCUMENT_DESCRIPTION_FIELD + "']"));
157         waitForElementNotPresent(By.cssSelector("input[name = '" + CONTACT_NUMBER_FIELD + "']"));
158 
159         waitForElementNotPresent(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"blanketApprove\\\"}']"));
160     }
161 
162     /**
163      * Tests whether a document is unlocked when routed.
164      *
165      * @throws Exception for any test exceptions
166      */
167     protected void testPessimisticLockingUnlockingOnRoute() throws Exception {
168         String documentNumber = createTravelAuthorization();
169 
170         addAdHocRecipient(ActionRequestType.APPROVE.name(), APPROVER_PRINCIPAL_NAME_VALUE);
171 
172         submitSuccessfully(WebDriverUtils.configuredImplicityWait() * 5);
173 
174         waitAndClickCloseByText();
175 
176         openTravelAuthorization(documentNumber, EDITOR_PRINCIPAL_NAME_VALUE);
177 
178         waitForTextNotPresent("This document currently has a full lock");
179     }
180 
181     /**
182      * Tests whether a document is unlocked when approved.
183      *
184      * @throws Exception for any test exceptions
185      */
186     protected void testPessimisticLockingUnlockingOnApprove() throws Exception {
187         String documentNumber = createTravelAuthorization();
188 
189         addAdHocRecipient(ActionRequestType.APPROVE.name(), APPROVER_PRINCIPAL_NAME_VALUE);
190 
191         submitSuccessfully();
192 
193         waitAndClickCloseByText();
194 
195         openTravelAuthorization(documentNumber, APPROVER_PRINCIPAL_NAME_VALUE);
196 
197         waitAndClickApproveByText();
198 
199         openTravelAuthorization(documentNumber, EDITOR_PRINCIPAL_NAME_VALUE);
200 
201         waitForTextNotPresent("This document currently has a full lock");
202     }
203 
204     /**
205      * Tests whether a document is unlocked when disapproved.
206      *
207      * @throws Exception for any test exceptions
208      */
209     protected void testPessimisticLockingUnlockingOnDisapprove() throws Exception {
210         String documentNumber = createTravelAuthorization();
211 
212         addAdHocRecipient(ActionRequestType.APPROVE.name(), APPROVER_PRINCIPAL_NAME_VALUE);
213 
214         submitSuccessfully();
215 
216         waitAndClickCloseByText();
217 
218         openTravelAuthorization(documentNumber, APPROVER_PRINCIPAL_NAME_VALUE);
219 
220         waitAndClickDisapproveByText();
221         waitAndType(By.cssSelector("div[data-parent = 'DisapproveExplanationDialog'] textarea"), "Document incomplete");
222         waitAndClick(By.cssSelector("div[data-parent = 'DisapproveExplanationDialog'] button[data-response = 'true']"));
223         acceptAlertIfPresent();
224 
225         openTravelAuthorization(documentNumber, EDITOR_PRINCIPAL_NAME_VALUE);
226 
227         waitForTextNotPresent("This document currently has a full lock");
228     }
229 
230     /**
231      * Tests whether a document is unlocked when cancelled.
232      *
233      * @throws Exception for any test exceptions
234      */
235     protected void testPessimisticLockingUnlockingOnCancel() throws Exception {
236         String documentNumber = createTravelAuthorization();
237         waitAndClick(By.cssSelector("button[data-submit_data = '{\\\"methodToCall\\\":\\\"cancel\\\"}']"));
238         waitAndClick(By.cssSelector("div[data-parent = 'ConfirmCancelDialog'] button[data-response = 'true']"));
239 
240         openTravelAuthorization(documentNumber, EDITOR_PRINCIPAL_NAME_VALUE);
241 
242         waitForTextNotPresent("This document currently has a full lock");
243     }
244 
245     /**
246      * Tests whether a document is unlocked when acknowledged.
247      *
248      * @throws Exception for any test exceptions
249      */
250     protected void testPessimisticLockingUnlockingOnAcknowledge() throws Exception {
251         String documentNumber = createTravelAuthorization();
252 
253         addAdHocRecipient(ActionRequestType.ACKNOWLEDGE.name(), APPROVER_PRINCIPAL_NAME_VALUE);
254 
255         submitSuccessfully();
256 
257         waitAndClickCloseByText();
258 
259         openTravelAuthorization(documentNumber, APPROVER_PRINCIPAL_NAME_VALUE);
260 
261         waitAndClickAcknowledgeByText();
262 
263         openTravelAuthorization(documentNumber, EDITOR_PRINCIPAL_NAME_VALUE);
264 
265         waitForTextNotPresent("This document currently has a full lock");
266     }
267 
268     private String createTravelAuthorization() throws Exception {
269         String documentNumber = waitForDocIdKrad();
270 
271         waitAndTypeByName(DOCUMENT_DESCRIPTION_FIELD, DOCUMENT_DESCRIPTION_VALUE);
272 
273         waitAndTypeByName(CONTACT_NUMBER_FIELD, CONTACT_NUMBER_VALUE);
274 
275         waitAndClick(By.cssSelector("div[data-label = 'Primary Destination Id'] button"));
276         gotoLightBox();
277         waitAndClickButtonByText(SEARCH);
278         waitAndClickByLinkText(RETURN_VALUE_LINK_TEXT);
279 
280         saveSuccessfully();
281 
282         return documentNumber;
283     }
284 
285     private void addAdHocRecipient(String actionRequested, String... principalNames) throws Exception {
286         waitAndClickByLinkText("Ad Hoc Recipients");
287 
288         for (String principalName : principalNames) {
289             waitAndSelectByName("newCollectionLines['document.adHocRoutePersons'].actionRequested", actionRequested);
290             waitAndTypeByName("newCollectionLines['document.adHocRoutePersons'].id", principalName);
291             waitAndClickById("Uif-AdHocPersonCollection_add");
292         }
293 
294         waitAndClickByLinkText("Ad Hoc Recipients");
295     }
296 
297     private void openTravelAuthorization(String documentNumber, String principalName) throws Exception {
298         open(getBaseUrlString() + "/portal.do");
299 
300         acceptAlertIfPresent();
301 
302         impersonateUser(principalName);
303 
304         open(getBaseUrlString() + DOC_HANDLER_URL + documentNumber);
305     }
306 
307     @Test
308     public void testPessimisticLockingOnSaveBookmark() throws Exception {
309         testPessimisticLockingOnSave();
310         passed();
311     }
312 
313     @Test
314     public void testPessimisticLockingOnSaveNav() throws Exception {
315         testPessimisticLockingOnSave();
316         passed();
317     }
318 
319     @Ignore("https://jira.kuali.org/browse/KULRICE-13330 AFT Failure DemoTravelAuthorizationPessimisticLockingAft.testPessimisticLockingOnRoute full lock is not present in CI")
320     @Test
321     public void testPessimisticLockingOnRouteBookmark() throws Exception {
322         testPessimisticLockingOnRoute();
323         passed();
324     }
325 
326     @Ignore("https://jira.kuali.org/browse/KULRICE-13330 AFT Failure DemoTravelAuthorizationPessimisticLockingAft.testPessimisticLockingOnRoute full lock is not present in CI")
327     @Test
328     public void testPessimisticLockingOnRouteNav() throws Exception {
329         testPessimisticLockingOnRoute();
330         passed();
331     }
332 
333     @Ignore ("https://jira.kuali.org/browse/KULRICE-13357 AFT Failures Dialogs on CI")
334     @Test
335     public void testPessimisticLockingUnlockingOnRouteBookmark() throws Exception {
336         testPessimisticLockingUnlockingOnRoute();
337         passed();
338     }
339 
340     @Test
341     public void testPessimisticLockingUnlockingOnRouteNav() throws Exception {
342         testPessimisticLockingUnlockingOnRoute();
343         passed();
344     }
345 
346     @Ignore ("https://jira.kuali.org/browse/KULRICE-13357 AFT Failures Dialogs on CI")
347     @Test
348     public void testPessimisticLockingUnlockingOnApproveBookmark() throws Exception {
349         testPessimisticLockingUnlockingOnApprove();
350         passed();
351     }
352 
353     @Test
354     public void testPessimisticLockingUnlockingOnApproveNav() throws Exception {
355         testPessimisticLockingUnlockingOnApprove();
356         passed();
357     }
358 
359     @Ignore ("https://jira.kuali.org/browse/KULRICE-13357 AFT Failures Dialogs on CI")
360     @Test
361     public void testPessimisticLockingUnlockingOnDisapproveBookmark() throws Exception {
362         testPessimisticLockingUnlockingOnDisapprove();
363         passed();
364     }
365 
366     @Test
367     public void testPessimisticLockingUnlockingOnDisapproveNav() throws Exception {
368         testPessimisticLockingUnlockingOnDisapprove();
369         passed();
370     }
371 
372     @Test
373     public void testPessimisticLockingUnlockingOnCancelBookmark() throws Exception {
374         testPessimisticLockingUnlockingOnCancel();
375         passed();
376     }
377 
378     @Test
379     public void testPessimisticLockingUnlockingOnCancelNav() throws Exception {
380         testPessimisticLockingUnlockingOnCancel();
381         passed();
382     }
383 
384     @Ignore ("https://jira.kuali.org/browse/KULRICE-13357 AFT Failures Dialogs on CI")
385     @Test
386     public void testPessimisticLockingUnlockingOnAcknowledgeBookmark() throws Exception {
387         testPessimisticLockingUnlockingOnAcknowledge();
388         passed();
389     }
390 
391     @Ignore ("https://jira.kuali.org/browse/KULRICE-13357 AFT Failures Dialogs on CI")
392     @Test
393     public void testPessimisticLockingUnlockingOnAcknowledgeNav() throws Exception {
394         testPessimisticLockingUnlockingOnAcknowledge();
395         passed();
396     }
397 
398 }