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 }