001/** 002 * Copyright 2004-2015 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 */ 016package org.kuali.hr.time.roles.web; 017 018import com.gargoylesoftware.htmlunit.html.DomElement; 019import com.gargoylesoftware.htmlunit.html.HtmlForm; 020import com.gargoylesoftware.htmlunit.html.HtmlPage; 021import org.apache.commons.collections.CollectionUtils; 022import org.apache.log4j.Logger; 023import org.joda.time.DateTime; 024import org.joda.time.DateTimeZone; 025import org.json.simple.JSONArray; 026import org.json.simple.JSONObject; 027import org.json.simple.JSONValue; 028import org.junit.Assert; 029import org.junit.Test; 030import org.kuali.hr.time.util.TimeDetailTestUtils; 031import org.kuali.hr.time.workflow.TimesheetWebTestBase; 032import org.kuali.hr.util.HtmlUnitUtil; 033import org.kuali.kpme.core.FunctionalTest; 034import org.kuali.kpme.core.api.assignment.Assignment; 035import org.kuali.kpme.core.api.calendar.entry.CalendarEntry; 036import org.kuali.kpme.core.api.earncode.EarnCode; 037import org.kuali.kpme.core.role.KPMERole; 038import org.kuali.kpme.core.service.HrServiceLocator; 039import org.kuali.kpme.core.util.HrContext; 040import org.kuali.kpme.core.util.TKUtils; 041import org.kuali.kpme.tklm.time.detail.web.TimeDetailActionFormBase; 042import org.kuali.kpme.tklm.time.service.TkServiceLocator; 043import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument; 044 045import java.util.ArrayList; 046import java.util.HashMap; 047import java.util.List; 048import java.util.Map; 049 050/** 051 * See: https://wiki.kuali.org/display/KPME/Role+Security+Grid 052 */ 053@FunctionalTest 054public class RoleTimesheetWebIntegrationTest extends TimesheetWebTestBase { 055 056 private static final Logger LOG = Logger.getLogger(RoleTimesheetWebIntegrationTest.class); 057 058 // Non Time Entry users (for this test) who have some access to 'fred's' 059 // Time Sheet. 060 private List<String> VALID_NON_ENTRY_USERS = new ArrayList<String>() {{ 061 //add fred too. 062 /*add("testuser6");*/ add("frank"); add("fran"); add("edna"); add("fred"); }}; 063 064 // Users with incorrect Department or Work Area for Time Sheet privilege. 065 private List<String> INVALID_NON_ENTRY_USERS = new ArrayList<String>(){{ 066 add("testuser1"); add("testuser2"); add("testuser3"); add("testuser4"); }}; 067 068 private TimesheetDocument fredsDocument = null; 069 DateTime asOfDate = new DateTime(2011, 3, 1, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 070 071 @Override 072 /** 073 * This code is called before each test below - allows us to control how far 074 * into the routing process we are for any given level of testing. 075 */ 076 public void setUp() throws Exception { 077 super.setUp(); 078 079 String userId = "fred"; 080 DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone(userId)); 081 082 CalendarEntry pcd = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates(userId, asOfDate); 083 Assert.assertNotNull("No PayCalendarDates", pcd); 084 fredsDocument = TkServiceLocator.getTimesheetService().openTimesheetDocument(userId, pcd); 085 String tdocId = fredsDocument.getDocumentId(); 086 087 // Verify the non time entry logins. 088 verifyLogins(fredsDocument); 089 090 // Verify Fred, and Add Timeblocks 091 HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true); 092 Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011")); 093 094 HtmlForm form = page.getFormByName("TimeDetailActionForm"); 095 Assert.assertNotNull(form); 096 List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments(userId, JAN_AS_OF_DATE.toLocalDate()); 097 Assignment assignment = assignments.get(0); 098 099 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}