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.lm.leaveCalendar; 017 018 import static org.junit.Assert.assertTrue; 019 020 import java.util.ArrayList; 021 import java.util.HashMap; 022 import java.util.List; 023 import java.util.Map; 024 025 import org.apache.commons.lang.StringUtils; 026 import org.joda.time.DateTime; 027 import org.json.simple.JSONArray; 028 import org.json.simple.JSONObject; 029 import org.json.simple.JSONValue; 030 import org.junit.Assert; 031 import org.junit.Ignore; 032 import org.junit.Test; 033 import org.kuali.hr.TestAutoLoginFilter; 034 import org.kuali.hr.util.HtmlUnitUtil; 035 import org.kuali.kpme.core.FunctionalTest; 036 import org.kuali.kpme.core.assignment.Assignment; 037 import org.kuali.kpme.core.assignment.AssignmentDescriptionKey; 038 import org.kuali.kpme.core.calendar.entry.CalendarEntry; 039 import org.kuali.kpme.core.earncode.EarnCode; 040 import org.kuali.kpme.core.service.HrServiceLocator; 041 import org.kuali.kpme.core.util.HrContext; 042 import org.kuali.kpme.core.util.TKUtils; 043 import org.kuali.kpme.tklm.leave.calendar.LeaveCalendarDocument; 044 import org.kuali.kpme.tklm.leave.calendar.web.LeaveCalendarWSForm; 045 import org.kuali.kpme.tklm.leave.service.LmServiceLocator; 046 047 import com.gargoylesoftware.htmlunit.html.HtmlButtonInput; 048 import com.gargoylesoftware.htmlunit.html.HtmlElement; 049 import com.gargoylesoftware.htmlunit.html.HtmlForm; 050 import com.gargoylesoftware.htmlunit.html.HtmlPage; 051 052 @FunctionalTest 053 public class LeaveCalendarWorkflowIntegrationTest extends LeaveCalendarWebTestBase { 054 055 public static final String USER_PRINCIPAL_ID = "admin"; 056 private DateTime JAN_AS_OF_DATE = new DateTime(2010, 1, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 057 058 @Ignore 059 @Test 060 /** 061 * - create timesheet 062 * - add two 8 hour time blocks 063 * - submit timesheet for routing 064 * - ## login as approver 065 * - look for approval button 066 * - approve timeblock 067 * - verify approval button gone 068 * - ## login as original user 069 * - verify submit for routing button gone 070 */ 071 public void testLeaveCalendarSubmissionIntegration() throws Exception { 072 DateTime asOfDate = new DateTime(2011, 3, 1, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 073 CalendarEntry pcd = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDatesForLeaveCalendar(USER_PRINCIPAL_ID, asOfDate); 074 Assert.assertNotNull("No CalendarEntry", pcd); 075 LeaveCalendarDocument tdoc = LmServiceLocator.getLeaveCalendarService().openLeaveCalendarDocument(USER_PRINCIPAL_ID, pcd); 076 String tdocId = tdoc.getDocumentId(); 077 HtmlPage page = loginAndGetLeaveCalendarHtmlPage("admin", tdocId, true); 078 079 // 1. Obtain User Data 080 Assignment assignment = HrServiceLocator.getAssignmentService().getAssignment(HrContext.getPrincipalId(), AssignmentDescriptionKey.get("30_30_30"), JAN_AS_OF_DATE.toLocalDate()); 081 EarnCode earnCode = HrServiceLocator.getEarnCodeService().getEarnCode("VAC", JAN_AS_OF_DATE.toLocalDate()); 082 083 // 2. Set Timeblock Start and End time 084 // 3/02/2011 - 8:00a to 4:00pm 085 DateTime start = new DateTime(2011, 3, 2, 8, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 086 DateTime end = new DateTime(2011, 3, 2, 16, 0, 0, 0, TKUtils.getSystemDateTimeZone()); 087 088 HtmlForm form = page.getFormByName("LeaveCalendarForm"); 089 Assert.assertNotNull(form); 090 091 // Build an action form - we're using it as a POJO, it ties into the 092 // existing TK validation setup 093 LeaveCalendarWSForm tdaf = LeaveCalendarTestUtils.buildLeaveCalendarForm(tdoc, assignment, earnCode, start, end, null, true); 094 LeaveCalendarTestUtils.setTimeBlockFormDetails(form, tdaf); 095 page = LeaveCalendarTestUtils.submitLeaveCalendar(getWebClient(), getLeaveCalendarUrl(tdocId), tdaf); 096 Assert.assertNotNull(page); 097 HtmlUnitUtil.createTempFile(page, "LeaveBlockPresent"); 098 099 // Verify block present on rendered page. 100 String pageAsText = page.asText(); 101 102 // JSON 103 // 104 // 105 // Grab the leaveBlock data from the text area. We can check specifics there 106 // to be more fine grained in our validation. 107 String dataText = page.getElementById("leaveBlockString").getFirstChild().getNodeValue(); 108 JSONArray jsonData = (JSONArray)JSONValue.parse(dataText); 109 final JSONObject jsonDataObject = (JSONObject) jsonData.get(0); 110 Assert.assertTrue("leaveBlock Data Missing.", checkJSONValues(new JSONObject() {{ put("outer", jsonDataObject); }}, 111 new ArrayList<Map<String, Object>>() {{ 112 add(new HashMap<String, Object>() {{ 113 put("earnCode", "VAC"); 114 put("leaveAmount", "-8"); 115 put("earnCode", "VAC"); 116 put("leaveDate", "03/02/2011"); 117 //put("endNoTz", "2011-03-02T16:00:00"); 118 put("title", "SDR1 Work Area"); 119 put("assignment", "30_30_30"); 120 }}); 121 }}, 122 new HashMap<String, Object>() {{ }} 123 )); 124 125 // Check the Display Rendered Text for Time Block, Quick Check 126 Assert.assertTrue("TimeBlock not Present.", pageAsText.contains("SDR1 Work Area-SDR1 task")); 127 Assert.assertTrue("TimeBlock not Present.", pageAsText.contains("VAC (-8)")); 128 129 // 130 // Route Timesheet 131 // 132 // Routing is initiated via javascript, we need to extract the routing 133 // action from the button element to perform this action. 134 HtmlButtonInput routeButton = (HtmlButtonInput)page.getElementById("ts-route-button"); 135 String routeHref = HtmlUnitUtil.getOnClickHref(routeButton); 136 // The 'only' way to do the button click. 137 page = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), getBaseURL() + "/" + routeHref); 138 //HtmlUnitUtil.createTempFile(page, "RouteClicked"); 139 pageAsText = page.asText(); 140 // Verify Route Status via UI 141 Assert.assertTrue("Wrong Document Loaded.", pageAsText.contains(tdocId)); 142 Assert.assertTrue("Document not routed.", pageAsText.contains("Enroute")); 143 routeButton = (HtmlButtonInput)page.getElementById("ts-route-button"); 144 Assert.assertNull("Route button should not be present.", routeButton); 145 HtmlElement approveButton = (HtmlButtonInput)page.getElementById("ts-approve-button"); 146 Assert.assertNull("Approval button should not be present.", approveButton); 147 148 // 149 // Login as Approver, who is not 'admin' 150 page = loginAndGetLeaveCalendarHtmlPage("eric", tdocId, true); 151 //HtmlUnitUtil.createTempFile(page, "2ndLogin"); 152 pageAsText = page.asText(); 153 Assert.assertTrue("Document not routed.", pageAsText.contains("Enroute")); 154 approveButton = (HtmlButtonInput)page.getElementById("ts-approve-button"); 155 Assert.assertNotNull("No approval button present.", approveButton); 156 157 // Click Approve 158 // And Verify 159 // 160 routeHref = HtmlUnitUtil.getOnClickHref(approveButton); 161 TestAutoLoginFilter.OVERRIDE_ID = "eric"; 162 page = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), getBaseURL() + "/" + routeHref); 163 TestAutoLoginFilter.OVERRIDE_ID = ""; 164 //HtmlUnitUtil.createTempFile(page, "ApproveClicked"); 165 pageAsText = page.asText(); 166 Assert.assertTrue("Wrong Document Loaded.", pageAsText.contains(tdocId)); 167 Assert.assertTrue("Login info not present.", pageAsText.contains("Employee Id:")); 168 Assert.assertTrue("Login info not present.", pageAsText.contains("eric, eric")); 169 Assert.assertTrue("Document not routed.", pageAsText.contains("Final")); 170 approveButton = (HtmlElement)page.getElementById("ts-approve-button"); 171 Assert.assertNull("Approval button should not be present.", approveButton); 172 } 173 174 @Ignore 175 @Test 176 public void testRedirectionForBalanceTransferOnLeaveApprove() throws Exception { 177 //Create a leave summary with a single row containing an accrual category that has exceeded max balance limit. 178 /* LeaveSummary ls = new LeaveSummary(); 179 List<LeaveSummaryRow> leaveSummaryRows = new ArrayList<LeaveSummaryRow>(); 180 //A leave summary row for an accrual category over max balance. 181 LeaveSummaryRow lsr = new LeaveSummaryRow(); 182 lsr.setAccrualCategory("debitAC1"); 183 lsr.setAccrualCategoryId("10055"); 184 lsr.setAccrualCategoryRuleId("3000"); 185 lsr.setLeaveBalance(new BigDecimal(500)); 186 //debitAC1 accrual category has a max balance of 100. 187 leaveSummaryRows.add(lsr); 188 //A leave summary row for an accrual category to accept transfers. 189 lsr = new LeaveSummaryRow(); 190 lsr.setAccrualCategory("creditAC1"); 191 lsr.setAccrualCategoryId("10056"); 192 lsr.setAccrualCategoryRuleId("3001"); 193 lsr.setLeaveBalance(BigDecimal.ZERO); 194 195 leaveSummaryRows.add(lsr); 196 ls.setLeaveSummaryRows(leaveSummaryRows); 197 setBaseDetailURL(TkTestConstants.Urls.LEAVE_CALENDAR_SUBMIT_URL + "?documentId="); 198 Date asOfDate = new Date((new DateTime(2011, 3, 1, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone())).getMillis()); 199 CalendarEntry pcd = HrServiceLocator.getCalendarService().getCurrentCalendarDatesForLeaveCalendar(USER_PRINCIPAL_ID, asOfDate); 200 Assert.assertNotNull("No CalendarEntry", pcd); 201 LeaveCalendarDocument tdoc = LmServiceLocator.getLeaveCalendarService().openLeaveCalendarDocument(USER_PRINCIPAL_ID, pcd); 202 String tdocId = tdoc.getDocumentId(); 203 204 // Build an action form - we're using it as a POJO, it ties into the 205 // existing TK validation setup 206 LeaveCalendarWSForm tdaf = LeaveCalendarTestUtils.buildLeaveCalendarFormForSubmission(tdoc, ls); 207 208 HtmlPage page = LeaveCalendarTestUtils.submitLeaveCalendar2(getLeaveCalendarUrl(tdocId), tdaf); 209 Assert.assertNotNull(page); 210 HtmlUnitUtil.createTempFile(page, "LeaveBlockPresent"); 211 212 // Verify block present on rendered page. 213 String pageAsText = page.asText(); 214 System.out.print(pageAsText); 215 216 */ 217 //LeaveCalendarWSForm mockForm = LeaveCalendarTestUtils.buildLeaveCalendarForm(tdoc, assignment, earnCode, start, end, null, true); 218 //Attach leave summary to relevant object (leavecalendardocument?) 219 //load LeaveCalendarDocument into web container 220 //leave calendar document must have status "initiated" 221 //mock the submit action on behalf of the principal who owns the leave calendar. 222 //redirect should occur, which loads the balance transfer document. 223 //balance transfer document should have all fields locked except for transfer amount. 224 //mock transfer action on behalf of the principal. 225 //verify leave block creation 226 assertTrue("Dummy assertion 2", true); 227 228 } 229 230 231 /** 232 * Examines the JSON structure that is written to each output TimeDetails 233 * page. 234 * @param json The JSON Object to examine 235 * @param thdList The (optional) list of Time Hour Details values 236 * @param checkValues The list of values to check for in the JSON object 237 * @return true if the JSON object contains the required values, false otherwise. 238 */ 239 public static boolean checkJSONValues(JSONObject json, List<Map<String,Object>> thdList, Map<String,Object> checkValues) { 240 boolean contains = false; 241 242 for(Object eso : json.entrySet()) { 243 // This is the outer TimeBlock ID -> Time Block Data mapping 244 Map.Entry e = (Map.Entry)eso; 245 JSONObject innerMap = (JSONObject)e.getValue(); // the values we actually care about. 246 boolean localContains = true; 247 for (Map.Entry<String,Object> cve : checkValues.entrySet()) { 248 Object joValue = innerMap.get(cve.getKey()); 249 Object cvValue = cve.getValue(); 250 251 // Null Checks.. 252 if (cvValue == null && joValue == null) 253 localContains &= true; 254 else if (joValue == null || cvValue == null) 255 localContains = false; 256 else 257 localContains &= StringUtils.equals(joValue.toString(), cvValue.toString()); 258 } 259 260 contains |= localContains; 261 } 262 263 return contains; 264 } 265 266 public static boolean checkJSONValues(String json, List<Map<String,Object>> thdList, Map<String,Object> checkValues) { 267 return checkJSONValues((JSONObject)JSONValue.parse(json), thdList, checkValues); 268 } 269 }