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