001 /**
002 * Copyright 2004-2014 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 }