View Javadoc
1   /**
2    * Copyright 2004-2014 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.hr.time.roles.web;
17  
18  import com.gargoylesoftware.htmlunit.html.DomElement;
19  import com.gargoylesoftware.htmlunit.html.HtmlForm;
20  import com.gargoylesoftware.htmlunit.html.HtmlPage;
21  import org.apache.commons.collections.CollectionUtils;
22  import org.apache.log4j.Logger;
23  import org.joda.time.DateTime;
24  import org.joda.time.DateTimeZone;
25  import org.json.simple.JSONArray;
26  import org.json.simple.JSONObject;
27  import org.json.simple.JSONValue;
28  import org.junit.Assert;
29  import org.junit.Test;
30  import org.kuali.hr.time.util.TimeDetailTestUtils;
31  import org.kuali.hr.time.workflow.TimesheetWebTestBase;
32  import org.kuali.hr.util.HtmlUnitUtil;
33  import org.kuali.kpme.core.FunctionalTest;
34  import org.kuali.kpme.core.api.assignment.Assignment;
35  import org.kuali.kpme.core.api.calendar.entry.CalendarEntry;
36  import org.kuali.kpme.core.api.earncode.EarnCode;
37  import org.kuali.kpme.core.role.KPMERole;
38  import org.kuali.kpme.core.service.HrServiceLocator;
39  import org.kuali.kpme.core.util.HrContext;
40  import org.kuali.kpme.core.util.TKUtils;
41  import org.kuali.kpme.tklm.time.detail.web.TimeDetailActionFormBase;
42  import org.kuali.kpme.tklm.time.service.TkServiceLocator;
43  import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
44  
45  import java.util.ArrayList;
46  import java.util.HashMap;
47  import java.util.List;
48  import java.util.Map;
49  
50  /**
51   * See: https://wiki.kuali.org/display/KPME/Role+Security+Grid
52   */
53  @FunctionalTest
54  public class RoleTimesheetWebIntegrationTest extends TimesheetWebTestBase {
55  
56      private static final Logger LOG = Logger.getLogger(RoleTimesheetWebIntegrationTest.class);
57  
58      // Non Time Entry users (for this test) who have some access to 'fred's'
59      // Time Sheet.
60      private List<String> VALID_NON_ENTRY_USERS = new ArrayList<String>() {{
61      	//add fred too.
62          /*add("testuser6");*/ add("frank"); add("fran"); add("edna"); add("fred"); }};
63  
64      // Users with incorrect Department or Work Area for Time Sheet privilege.
65      private List<String> INVALID_NON_ENTRY_USERS = new ArrayList<String>(){{
66          add("testuser1"); add("testuser2"); add("testuser3"); add("testuser4"); }};
67  
68      private TimesheetDocument fredsDocument = null;
69      DateTime asOfDate = new DateTime(2011, 3, 1, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone());
70  
71      @Override
72      /**
73       * This code is called before each test below - allows us to control how far
74       * into the routing process we are for any given level of testing.
75       */
76      public void setUp() throws Exception {
77          super.setUp();
78  
79          String userId = "fred";
80          DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone(userId));
81          
82          CalendarEntry pcd =  HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates(userId, asOfDate);
83          Assert.assertNotNull("No PayCalendarDates", pcd);
84          fredsDocument = TkServiceLocator.getTimesheetService().openTimesheetDocument(userId, pcd);
85          String tdocId = fredsDocument.getDocumentId();
86  
87          // Verify the non time entry logins.
88          verifyLogins(fredsDocument);
89  
90          // Verify Fred, and Add Timeblocks
91          HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
92          Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
93  
94          HtmlForm form = page.getFormByName("TimeDetailActionForm");
95          Assert.assertNotNull(form);
96          List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments(userId, JAN_AS_OF_DATE.toLocalDate());
97          Assignment assignment = assignments.get(0);
98  
99          List<EarnCode> earnCodes = TkServiceLocator.getTimesheetService().getEarnCodesForTime(assignment, JAN_AS_OF_DATE.toLocalDate());
100         EarnCode earnCode = earnCodes.get(0);
101         Assert.assertEquals("There should be no existing time blocks.", 0, fredsDocument.getTimeBlocks().size());
102 
103         // 2. Set Timeblock Start and End time
104         // 3/02/2011 - 8:00a to 6:00pm
105         // OVT - 0 Hrs Expected
106         final DateTime start = new DateTime(2011, 3, 2, 8, 0, 0, 0, dateTimeZone);
107         final DateTime end = new DateTime(2011, 3, 2, 13, 0, 0, 0, dateTimeZone);
108 
109         TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(fredsDocument, assignment, earnCode, start, end, null, false, null, true, null, null, null, null, null, null);
110         List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf);
111 
112         Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size());
113         page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), getTimesheetDocumentUrl(tdocId), tdaf);
114         Assert.assertNotNull(page);
115         page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
116 
117         String pageAsText = page.asText();
118         DomElement element = page.getElementById("timeBlockString");
119         Assert.assertNotNull(element);
120         String elementAsText = element.asText();
121         String dataText = page.getElementById("timeBlockString").getFirstChild().getNodeValue();
122         JSONArray jsonData = (JSONArray) JSONValue.parse(dataText);
123         final JSONObject jsonDataObject = (JSONObject) jsonData.get(0);
124         Assert.assertTrue("TimeBlock Data Missing.", checkJSONValues(new JSONObject() {{ put("outer", jsonDataObject); }},
125                 new ArrayList<Map<String, Object>>() {{
126                     add(new HashMap<String, Object>() {{
127                         put("earnCode", "RGN");
128                         put("hours", "5.0");
129                         put("amount", null);
130                     }});
131                 }},
132                 new HashMap<String, Object>() {{
133                     put("earnCode", "RGN");
134                     start.toString();
135                     put("startNoTz", start.toString("yyyy-MM-dd'T'HH:mm:ss"));
136                     put("endNoTz", end.toString("yyyy-MM-dd'T'HH:mm:ss"));
137                     put("title", "SDR1 Work Area");
138                     put("assignment", "IU-BL_30_30_30");
139                 }}
140         ));
141 
142         // Set freds timesheet to have updated info.
143         fredsDocument = TkServiceLocator.getTimesheetService().openTimesheetDocument(userId, pcd);
144     }
145 
146     /*
147      * Tests while Timesheet is in INITIATED state.
148      */
149 
150     @Test
151     public void testInitiatedTimesheetIsVisibleByAll() throws Exception {
152         // test valid users
153         for (String uid : VALID_NON_ENTRY_USERS) {
154             LOG.info("Testing visibility for " + uid);
155             HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), uid, fredsDocument.getDocumentId(), true);
156             Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
157         }
158     }
159 
160     @Test
161     //@Ignore
162     public void testInitiatedTimesheetIsNotVisible() throws Exception {
163         for (String uid : INVALID_NON_ENTRY_USERS) {
164             LOG.info("Testing visibility for " + uid);
165             HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), uid, fredsDocument.getDocumentId(), false);
166             //HtmlUnitUtil.createTempFile(page, "badlogin");
167             Assert.assertTrue(uid + " should not have access" , page.asText().contains("You are not authorized to access this portion of the application."));
168         }
169     }
170 
171     public void testInitiatedTimesheetEditable(String userId) throws Exception {
172         // admin, add one timeblock
173         String tdocId = fredsDocument.getDocumentId();
174         HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
175         LOG.debug(page.asText());
176         //HtmlUnitUtil.createTempFile(page, "loggedin");
177         Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
178 
179         HtmlForm form = page.getFormByName("TimeDetailActionForm");
180         Assert.assertNotNull(form);
181         List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments("fred", JAN_AS_OF_DATE.toLocalDate());
182         Assignment assignment = assignments.get(0);
183 
184         List<EarnCode> earnCodes = TkServiceLocator.getTimesheetService().getEarnCodesForTime(assignment, JAN_AS_OF_DATE.toLocalDate());
185         EarnCode earnCode = earnCodes.get(0);
186 
187         Assert.assertEquals("There should be one existing time block.", 1, fredsDocument.getTimeBlocks().size());
188 
189 
190         String targetedTimesheetUrl = getTargetedTimesheetDocumentUrl(tdocId,"fred");
191         HrContext.setTargetPrincipalId("fred");
192         page = getWebClient().getPage(targetedTimesheetUrl);
193         Assert.assertNotNull(page);
194 
195         DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone("fred"));
196         final DateTime start = new DateTime(2011, 3, 2, 13, 0, 0, 0, dateTimeZone);
197         final DateTime end = new DateTime(2011, 3, 2, 18, 0, 0, 0, dateTimeZone);
198         TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(fredsDocument, assignment, earnCode, start, end, null, false, null, true, null, null, null, null, null, null);
199 
200         List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf);
201 
202         if (CollectionUtils.isNotEmpty(errors)) {
203             for (String error : errors) {
204                 LOG.error(error);
205             }
206         }
207         Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size());
208 
209         String submitDetailsUrl = BASE_DETAIL_URL + tdocId;
210         //The following page does not contain timeBlockString data after KPME-2959.
211         page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), submitDetailsUrl, tdaf);
212         Assert.assertNotNull(page);
213         //This extra page get was needed for KPME-2959.
214         page = getWebClient().getPage(targetedTimesheetUrl);
215         HtmlUnitUtil.createTempFile(page, "initiatetest");
216         String dataText = page.getElementById("timeBlockString").getFirstChild().getNodeValue();
217         JSONArray jsonData = (JSONArray) JSONValue.parse(dataText);
218         final JSONObject jsonDataObject = (JSONObject) jsonData.get(1);
219         Assert.assertTrue("TimeBlock Data Missing.", checkJSONValues(new JSONObject() {{ put("outer", jsonDataObject); }},
220                 new ArrayList<Map<String, Object>>() {{
221                     add(new HashMap<String, Object>() {{
222                         put("earnCode", "RGN");
223                         put("hours", "5.0");
224                         put("amount", null);
225                     }});
226                 }},
227                 new HashMap<String, Object>() {{
228                     put("earnCode", "RGN");
229                     put("startNoTz", start.toString("yyyy-MM-dd'T'HH:mm:ss"));
230                     put("endNoTz", end.toString("yyyy-MM-dd'T'HH:mm:ss"));
231                     put("title", "SDR1 Work Area");
232                     put("assignment", "IU-BL_30_30_30");
233                 }}
234         ));
235     }
236 
237     public void testInitiatedTimesheetNotEditable(String userId) throws Exception {
238         // admin, add one timeblock
239         String tdocId = fredsDocument.getDocumentId();
240         HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
241         //HtmlUnitUtil.createTempFile(page, "loggedin");
242         Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
243 
244         HtmlForm form = page.getFormByName("TimeDetailActionForm");
245         Assert.assertNotNull(form);
246         List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments("fred", JAN_AS_OF_DATE.toLocalDate());
247         Assignment assignment = assignments.get(0);
248 
249         List<EarnCode> earnCodes = TkServiceLocator.getTimesheetService().getEarnCodesForTime(assignment, JAN_AS_OF_DATE.toLocalDate());
250         EarnCode earnCode = earnCodes.get(0);
251 
252         Assert.assertEquals("There should be one existing time block.", 1, fredsDocument.getTimeBlocks().size());
253         HrContext.setTargetPrincipalId("fred");
254         DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone("fred"));
255         DateTime start = new DateTime(2011, 3, 4, 8, 0, 0, 0, dateTimeZone);
256         DateTime end = new DateTime(2011, 3, 4, 13, 0, 0, 0, dateTimeZone);
257         TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(fredsDocument, assignment, earnCode, start, end, null, false, null, true, null, null, null, null, null, null);
258         List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf);
259         if (CollectionUtils.isNotEmpty(errors)) {
260             for (String error : errors) {
261                 LOG.error(error);
262             }
263         }
264         KPMERole[] roleNames = KPMERole.values();
265         Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size());
266         page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), userId, getTimesheetDocumentUrl(tdocId), tdaf);
267         Assert.assertNotNull(page);
268         HtmlUnitUtil.createTempFile(page, "aftertdadd");
269         Assert.assertTrue("Should not have access", page.asText().contains("You are not authorized to access this portion of the application."));
270     }
271 
272     @Test
273     public void testInitiatedTimesheetIsEditableByAdmin() throws Exception {
274         testInitiatedTimesheetEditable("admin");
275     }
276 
277     @Test
278     public void testInitiatedTimesheetIsEditableByApprover() throws Exception {
279         testInitiatedTimesheetEditable("fran");
280     }
281 
282     @Test
283     public void testInitiatedTimesheetIsEditableByReviewer() throws Exception {
284         testInitiatedTimesheetEditable("frank");
285     }
286 
287     @Test
288     public void testInitiatedTimesheetIs_NOT_EditableByViewOnly() throws Exception {
289         testInitiatedTimesheetNotEditable("edna");
290     }
291 
292     @Test
293     public void testInitiatedTimesheetIs_NOT_EditableByDeptAdmin() throws Exception {
294         testInitiatedTimesheetNotEditable("testuser6");
295     }
296 
297 
298     @Test
299     public void testInitiatedTimesheetSubmitUser() throws Exception {
300         // User,
301         // Check for submit button.
302         // Click Button
303     }
304 
305     @Test
306     public void testInitiatedTimesheetSubmitAdmin() throws Exception {
307         // Admin
308         // Check for submit button.
309         // Click Button
310     }
311 
312     @Test
313     public void testInitiatedTimesheetSubmitApprover() throws Exception {
314         // Approver
315         // Check for submit button.
316         // Click Button
317     }
318 
319 
320     @Test
321     public void testInitiatedTimesheetIs_NOT_SubmittableByUsers() throws Exception {
322         // DeptAdmin, View Only, Reviewer
323         // Check that submit button is not present.
324     }
325 
326     /*
327      * Test for ENROUTE state.
328      */
329 
330     @Test
331     public void testEnrouteTimesheetIsVisibleByAll() throws Exception {
332         // test valid users
333     }
334 
335     @Test
336     public void testEnrouteTimesheetIsNotVisible() throws Exception {
337         // make sure invalid users do not have access
338     }
339 
340     @Test
341     public void testEnrouteTimesheetIsEditableByAdmin() throws Exception {
342         // admin, add one timeblock
343     }
344 
345     @Test
346     public void testEnrouteTimesheetIsEditableByApprover() throws Exception {
347         // approver, add one timeblock
348     }
349 
350     @Test
351     public void testEnrouteTimesheetIsEditableByReviewer() throws Exception {
352         // reviewer add one timeblock.
353     }
354 
355     @Test
356     public void testEnrouteTimesheetIs_NOT_EditableByViewOnly() throws Exception {
357     }
358 
359     @Test
360     public void testEnrouteTimesheetIs_NOT_EditableByDeptAdmin() throws Exception {
361     }
362 
363 
364     @Test
365     public void testEnrouteTimesheet_NOT_Approvable() throws Exception {
366         // User, Reviewer, View Only, Dept Admin
367         // Check for approve button
368     }
369 
370     @Test
371     public void testEnrouteTimesheetApproveAdmin() throws Exception {
372         // Admin
373         // Check for approve button.
374         // Click Button
375     }
376 
377     @Test
378     public void testEnrouteTimesheetApproveApprover() throws Exception {
379         // Approver
380         // Check for approve button.
381         // Click Button
382     }
383 
384     @Test
385     public void testEnrouteTimesheetIs_NOT_SubmittableByUsers() throws Exception {
386         // DeptAdmin, View Only, Reviewer
387         // Check that submit button is not present.
388     }
389 
390 
391     /*
392      * Final State
393      */
394 
395     @Test
396     public void testFinalTimesheetIsVisibleByAll() throws Exception {
397         // test valid users
398     }
399 
400     @Test
401     public void testFinalTimesheetIsNotVisible() throws Exception {
402         // make sure invalid users do not have access
403     }
404 
405     @Test
406     public void testFinalTimesheetIsNotEditable() throws Exception {
407         // by everyone but admin
408     }
409 
410     @Test
411     public void testFinalTimesheetIsAdminEditable() throws Exception {
412         // admin, add timeblock.
413     }
414 
415     /**
416      * Verifies that each admin/approver/reviewer login is active for this test.
417      */
418     private void verifyLogins(TimesheetDocument tdoc) throws Exception {
419         for (String userId : VALID_NON_ENTRY_USERS) {
420             String tdocId = tdoc.getDocumentId();
421             HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
422             Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
423         }
424     }
425 
426 }