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    }