001 /** 002 * Copyright 2004-2013 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.hr.time.roles.web; 017 018 import java.util.ArrayList; 019 import java.util.HashMap; 020 import java.util.List; 021 import java.util.Map; 022 023 import org.apache.log4j.Logger; 024 import org.joda.time.DateTime; 025 import org.joda.time.DateTimeZone; 026 import org.json.simple.JSONArray; 027 import org.json.simple.JSONObject; 028 import org.json.simple.JSONValue; 029 import org.junit.Assert; 030 import org.junit.Test; 031 import org.kuali.hr.time.util.TimeDetailTestUtils; 032 import org.kuali.hr.time.workflow.TimesheetWebTestBase; 033 import org.kuali.hr.util.HtmlUnitUtil; 034 import org.kuali.kpme.core.FunctionalTest; 035 import org.kuali.kpme.core.assignment.Assignment; 036 import org.kuali.kpme.core.calendar.entry.CalendarEntry; 037 import org.kuali.kpme.core.earncode.EarnCode; 038 import org.kuali.kpme.core.service.HrServiceLocator; 039 import org.kuali.kpme.core.util.TKUtils; 040 import org.kuali.kpme.tklm.time.detail.web.TimeDetailActionFormBase; 041 import org.kuali.kpme.tklm.time.service.TkServiceLocator; 042 import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument; 043 import org.kuali.rice.krad.util.GlobalVariables; 044 045 import com.gargoylesoftware.htmlunit.WebRequest; 046 import com.gargoylesoftware.htmlunit.WebResponse; 047 import com.gargoylesoftware.htmlunit.html.DomElement; 048 import com.gargoylesoftware.htmlunit.html.HtmlForm; 049 import com.gargoylesoftware.htmlunit.html.HtmlPage; 050 051 /** 052 * See: https://wiki.kuali.org/display/KPME/Role+Security+Grid 053 */ 054 @FunctionalTest 055 public class RoleTimesheetWebIntegrationTest extends TimesheetWebTestBase { 056 057 private static final Logger LOG = Logger.getLogger(RoleTimesheetWebIntegrationTest.class); 058 059 // Non Time Entry users (for this test) who have some access to 'fred's' 060 // Time Sheet. 061 private List<String> VALID_NON_ENTRY_USERS = new ArrayList<String>() {{ 062 //add fred too. 063 /*add("testuser6");*/ add("frank"); add("fran"); add("edna"); add("fred"); }}; 064 065 // Users with incorrect Department or Work Area for Time Sheet privilege. 066 private List<String> INVALID_NON_ENTRY_USERS = new ArrayList<String>(){{ 067 add("testuser1"); add("testuser2"); add("testuser3"); add("testuser4"); }}; 068 069 private TimesheetDocument fredsDocument = null; 070 DateTime asOfDate = new DateTime(2011, 3, 1, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 071 072 @Override 073 /** 074 * This code is called before each test below - allows us to control how far 075 * into the routing process we are for any given level of testing. 076 */ 077 public void setUp() throws Exception { 078 super.setUp(); 079 080 String userId = "fred"; 081 DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone(userId)); 082 083 CalendarEntry pcd = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates(userId, asOfDate); 084 Assert.assertNotNull("No PayCalendarDates", pcd); 085 fredsDocument = TkServiceLocator.getTimesheetService().openTimesheetDocument(userId, pcd); 086 String tdocId = fredsDocument.getDocumentId(); 087 088 // Verify the non time entry logins. 089 verifyLogins(fredsDocument); 090 091 // Verify Fred, and Add Timeblocks 092 HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true); 093 Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011")); 094 095 HtmlForm form = page.getFormByName("TimeDetailActionForm"); 096 Assert.assertNotNull(form); 097 List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments(userId, JAN_AS_OF_DATE.toLocalDate()); 098 Assignment assignment = assignments.get(0); 099 100 List<EarnCode> earnCodes = TkServiceLocator.getTimesheetService().getEarnCodesForTime(assignment, JAN_AS_OF_DATE.toLocalDate()); 101 EarnCode earnCode = earnCodes.get(0); 102 Assert.assertEquals("There should be no existing time blocks.", 0, fredsDocument.getTimeBlocks().size()); 103 104 // 2. Set Timeblock Start and End time 105 // 3/02/2011 - 8:00a to 6:00pm 106 // OVT - 0 Hrs Expected 107 final DateTime start = new DateTime(2011, 3, 2, 8, 0, 0, 0, dateTimeZone); 108 final DateTime end = new DateTime(2011, 3, 2, 13, 0, 0, 0, dateTimeZone); 109 110 TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(fredsDocument, assignment, earnCode, start, end, null, false, null, true); 111 List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf); 112 113 Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size()); 114 page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), getTimesheetDocumentUrl(tdocId), tdaf); 115 Assert.assertNotNull(page); 116 page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true); 117 118 String pageAsText = page.asText(); 119 DomElement element = page.getElementById("timeBlockString"); 120 Assert.assertNotNull(element); 121 String elementAsText = element.asText(); 122 String dataText = page.getElementById("timeBlockString").getFirstChild().getNodeValue(); 123 JSONArray jsonData = (JSONArray) JSONValue.parse(dataText); 124 final JSONObject jsonDataObject = (JSONObject) jsonData.get(0); 125 Assert.assertTrue("TimeBlock Data Missing.", checkJSONValues(new JSONObject() {{ put("outer", jsonDataObject); }}, 126 new ArrayList<Map<String, Object>>() {{ 127 add(new HashMap<String, Object>() {{ 128 put("earnCode", "RGN"); 129 put("hours", "5.0"); 130 put("amount", null); 131 }}); 132 }}, 133 new HashMap<String, Object>() {{ 134 put("earnCode", "RGN"); 135 start.toString(); 136 put("startNoTz", start.toString("yyyy-MM-dd'T'HH:mm:ss")); 137 put("endNoTz", end.toString("yyyy-MM-dd'T'HH:mm:ss")); 138 put("title", "SDR1 Work Area"); 139 put("assignment", "30_30_30"); 140 }} 141 )); 142 143 // Set freds timesheet to have updated info. 144 fredsDocument = TkServiceLocator.getTimesheetService().openTimesheetDocument(userId, pcd); 145 } 146 147 /* 148 * Tests while Timesheet is in INITIATED state. 149 */ 150 151 @Test 152 public void testInitiatedTimesheetIsVisibleByAll() throws Exception { 153 // test valid users 154 for (String uid : VALID_NON_ENTRY_USERS) { 155 LOG.info("Testing visibility for " + uid); 156 HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), uid, fredsDocument.getDocumentId(), true); 157 Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011")); 158 } 159 } 160 161 @Test 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("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 DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone(userId)); 190 final DateTime start = new DateTime(2011, 3, 2, 13, 0, 0, 0, dateTimeZone); 191 final DateTime end = new DateTime(2011, 3, 2, 18, 0, 0, 0, dateTimeZone); 192 TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(fredsDocument, assignment, earnCode, start, end, null, false, null, true); 193 194 List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf); 195 Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size()); 196 String targetedTimesheetUrl = getTargetedTimesheetDocumentUrl(tdocId,"fred"); 197 page = getWebClient().getPage(targetedTimesheetUrl); 198 Assert.assertNotNull(page); 199 String submitDetailsUrl = BASE_DETAIL_URL + tdocId; 200 //The following page does not contain timeBlockString data after KPME-2959. 201 page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), submitDetailsUrl, tdaf); 202 Assert.assertNotNull(page); 203 //This extra page get was needed for KPME-2959. 204 page = getWebClient().getPage(targetedTimesheetUrl); 205 HtmlUnitUtil.createTempFile(page, "initiatetest"); 206 String dataText = page.getElementById("timeBlockString").getFirstChild().getNodeValue(); 207 JSONArray jsonData = (JSONArray) JSONValue.parse(dataText); 208 final JSONObject jsonDataObject = (JSONObject) jsonData.get(1); 209 Assert.assertTrue("TimeBlock Data Missing.", checkJSONValues(new JSONObject() {{ put("outer", jsonDataObject); }}, 210 new ArrayList<Map<String, Object>>() {{ 211 add(new HashMap<String, Object>() {{ 212 put("earnCode", "RGN"); 213 put("hours", "5.0"); 214 put("amount", null); 215 }}); 216 }}, 217 new HashMap<String, Object>() {{ 218 put("earnCode", "RGN"); 219 put("startNoTz", start.toString("yyyy-MM-dd'T'HH:mm:ss")); 220 put("endNoTz", end.toString("yyyy-MM-dd'T'HH:mm:ss")); 221 put("title", "SDR1 Work Area"); 222 put("assignment", "30_30_30"); 223 }} 224 )); 225 } 226 227 public void testInitiatedTimesheetNotEditable(String userId) throws Exception { 228 // admin, add one timeblock 229 String tdocId = fredsDocument.getDocumentId(); 230 HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true); 231 //HtmlUnitUtil.createTempFile(page, "loggedin"); 232 Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011")); 233 234 HtmlForm form = page.getFormByName("TimeDetailActionForm"); 235 Assert.assertNotNull(form); 236 List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments("fred", JAN_AS_OF_DATE.toLocalDate()); 237 Assignment assignment = assignments.get(0); 238 239 List<EarnCode> earnCodes = TkServiceLocator.getTimesheetService().getEarnCodesForTime(assignment, JAN_AS_OF_DATE.toLocalDate()); 240 EarnCode earnCode = earnCodes.get(0); 241 242 Assert.assertEquals("There should be one existing time block.", 1, fredsDocument.getTimeBlocks().size()); 243 244 DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone(userId)); 245 DateTime start = new DateTime(2011, 3, 4, 8, 0, 0, 0, dateTimeZone); 246 DateTime end = new DateTime(2011, 3, 4, 13, 0, 0, 0, dateTimeZone); 247 TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(fredsDocument, assignment, earnCode, start, end, null, false, null, true); 248 List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf); 249 Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size()); 250 page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), userId, getTimesheetDocumentUrl(tdocId), tdaf); 251 Assert.assertNotNull(page); 252 HtmlUnitUtil.createTempFile(page, "aftertdadd"); 253 Assert.assertTrue("Should not have access", page.asText().contains("You are not authorized to access this portion of the application.")); 254 } 255 256 @Test 257 public void testInitiatedTimesheetIsEditableByAdmin() throws Exception { 258 testInitiatedTimesheetEditable("admin"); 259 } 260 261 @Test 262 public void testInitiatedTimesheetIsEditableByApprover() throws Exception { 263 testInitiatedTimesheetEditable("fran"); 264 } 265 266 @Test 267 public void testInitiatedTimesheetIsEditableByReviewer() throws Exception { 268 testInitiatedTimesheetEditable("frank"); 269 } 270 271 @Test 272 public void testInitiatedTimesheetIs_NOT_EditableByViewOnly() throws Exception { 273 testInitiatedTimesheetNotEditable("edna"); 274 } 275 276 @Test 277 public void testInitiatedTimesheetIs_NOT_EditableByDeptAdmin() throws Exception { 278 testInitiatedTimesheetNotEditable("testuser6"); 279 } 280 281 282 @Test 283 public void testInitiatedTimesheetSubmitUser() throws Exception { 284 // User, 285 // Check for submit button. 286 // Click Button 287 } 288 289 @Test 290 public void testInitiatedTimesheetSubmitAdmin() throws Exception { 291 // Admin 292 // Check for submit button. 293 // Click Button 294 } 295 296 @Test 297 public void testInitiatedTimesheetSubmitApprover() throws Exception { 298 // Approver 299 // Check for submit button. 300 // Click Button 301 } 302 303 304 @Test 305 public void testInitiatedTimesheetIs_NOT_SubmittableByUsers() throws Exception { 306 // DeptAdmin, View Only, Reviewer 307 // Check that submit button is not present. 308 } 309 310 /* 311 * Test for ENROUTE state. 312 */ 313 314 @Test 315 public void testEnrouteTimesheetIsVisibleByAll() throws Exception { 316 // test valid users 317 } 318 319 @Test 320 public void testEnrouteTimesheetIsNotVisible() throws Exception { 321 // make sure invalid users do not have access 322 } 323 324 @Test 325 public void testEnrouteTimesheetIsEditableByAdmin() throws Exception { 326 // admin, add one timeblock 327 } 328 329 @Test 330 public void testEnrouteTimesheetIsEditableByApprover() throws Exception { 331 // approver, add one timeblock 332 } 333 334 @Test 335 public void testEnrouteTimesheetIsEditableByReviewer() throws Exception { 336 // reviewer add one timeblock. 337 } 338 339 @Test 340 public void testEnrouteTimesheetIs_NOT_EditableByViewOnly() throws Exception { 341 } 342 343 @Test 344 public void testEnrouteTimesheetIs_NOT_EditableByDeptAdmin() throws Exception { 345 } 346 347 348 @Test 349 public void testEnrouteTimesheet_NOT_Approvable() throws Exception { 350 // User, Reviewer, View Only, Dept Admin 351 // Check for approve button 352 } 353 354 @Test 355 public void testEnrouteTimesheetApproveAdmin() throws Exception { 356 // Admin 357 // Check for approve button. 358 // Click Button 359 } 360 361 @Test 362 public void testEnrouteTimesheetApproveApprover() throws Exception { 363 // Approver 364 // Check for approve button. 365 // Click Button 366 } 367 368 @Test 369 public void testEnrouteTimesheetIs_NOT_SubmittableByUsers() throws Exception { 370 // DeptAdmin, View Only, Reviewer 371 // Check that submit button is not present. 372 } 373 374 375 /* 376 * Final State 377 */ 378 379 @Test 380 public void testFinalTimesheetIsVisibleByAll() throws Exception { 381 // test valid users 382 } 383 384 @Test 385 public void testFinalTimesheetIsNotVisible() throws Exception { 386 // make sure invalid users do not have access 387 } 388 389 @Test 390 public void testFinalTimesheetIsNotEditable() throws Exception { 391 // by everyone but admin 392 } 393 394 @Test 395 public void testFinalTimesheetIsAdminEditable() throws Exception { 396 // admin, add timeblock. 397 } 398 399 /** 400 * Verifies that each admin/approver/reviewer login is active for this test. 401 */ 402 private void verifyLogins(TimesheetDocument tdoc) throws Exception { 403 for (String userId : VALID_NON_ENTRY_USERS) { 404 String tdocId = tdoc.getDocumentId(); 405 HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true); 406 Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011")); 407 } 408 } 409 410 }