001/**
002 * Copyright 2004-2015 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 */
016package org.kuali.hr.time.workflow;
017
018import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
019import com.gargoylesoftware.htmlunit.html.HtmlForm;
020import com.gargoylesoftware.htmlunit.html.HtmlPage;
021import org.joda.time.DateTime;
022import org.json.simple.JSONArray;
023import org.json.simple.JSONObject;
024import org.json.simple.JSONValue;
025import org.junit.Assert;
026import org.junit.Test;
027import org.kuali.hr.TestAutoLoginFilter;
028import org.kuali.hr.time.util.TimeDetailTestUtils;
029import org.kuali.hr.util.HtmlUnitUtil;
030import org.kuali.kpme.core.FunctionalTest;
031import org.kuali.kpme.core.api.assignment.Assignment;
032import org.kuali.kpme.core.api.assignment.AssignmentDescriptionKey;
033import org.kuali.kpme.core.api.calendar.entry.CalendarEntry;
034import org.kuali.kpme.core.api.earncode.EarnCode;
035import org.kuali.kpme.core.calendar.entry.CalendarEntryBo;
036import org.kuali.kpme.core.service.HrServiceLocator;
037import org.kuali.kpme.core.util.HrContext;
038import org.kuali.kpme.core.util.TKUtils;
039import org.kuali.kpme.tklm.time.detail.web.TimeDetailActionFormBase;
040import org.kuali.kpme.tklm.time.service.TkServiceLocator;
041import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
042import org.kuali.rice.kew.api.document.DocumentStatus;
043
044import java.util.ArrayList;
045import java.util.HashMap;
046import java.util.List;
047import java.util.Map;
048
049@FunctionalTest
050public class TimesheetWorkflowIntegrationTest extends TimesheetWebTestBase {
051
052    public static final String USER_PRINCIPAL_ID = "admin";
053        private DateTime JAN_AS_OF_DATE = new DateTime(2010, 1, 1, 0, 0, 0, 0, TKUtils.getSystemDateTimeZone());
054
055
056    /**
057     * @throws Exception
058     */
059    public void setUp() throws Exception {
060        super.setUp();
061        // Data is loaded as part of database loading lifecycle
062        // See: tk-test-data.sql
063        // See: TimesheetWorkflowIntegrationTest.sql
064        // See: TkTestCase.java
065        //
066    }
067
068    public void tearDown() throws Exception {
069        super.tearDown();
070    }
071
072    @Test
073    /**
074     * - create timesheet
075     * - add two 8 hour time blocks
076     * - submit timesheet for routing
077     * - ## login as approver
078     * - look for approval button
079     * - approve timeblock
080     * - verify approval button gone
081     * - ## login as original user
082     * - verify submit for routing button gone
083     */
084    public void testTimesheetSubmissionIntegration() throws Exception {
085        DateTime asOfDate = new DateTime(2011, 3, 1, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone());
086        CalendarEntry pcd =  HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates(USER_PRINCIPAL_ID, asOfDate);
087        Assert.assertNotNull("No PayCalendarDates", pcd);
088        TimesheetDocument tdoc = TkServiceLocator.getTimesheetService().openTimesheetDocument(USER_PRINCIPAL_ID, pcd);
089        String tdocId = tdoc.getDocumentId();
090        HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), "admin", tdocId, true);
091
092        // 1. Obtain User Data
093        Assignment assignment = HrServiceLocator.getAssignmentService().getAssignment(HrContext.getPrincipalId(), AssignmentDescriptionKey.get("IU-IN_30_30_30"), JAN_AS_OF_DATE.toLocalDate());
094        EarnCode earnCode = HrServiceLocator.getEarnCodeService().getEarnCode("RGN", JAN_AS_OF_DATE.toLocalDate());
095
096        // 2. Set Timeblock Start and End time
097        // 3/02/2011 - 8:00a to 4:00pm
098        DateTime start = new DateTime(2011, 3, 2, 8, 0, 0, 0, TKUtils.getSystemDateTimeZone());
099        DateTime end = new DateTime(2011, 3, 2, 16, 0, 0, 0, TKUtils.getSystemDateTimeZone());
100
101        HtmlForm form = page.getFormByName("TimeDetailActionForm");
102        Assert.assertNotNull(form);
103
104        // Build an action form - we're using it as a POJO, it ties into the
105        // existing TK validation setup
106        TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(tdoc, assignment, earnCode, start, end, null, true, null, true, null, null, null, null, null, null);
107        List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf);
108        // Check for errors
109        Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size());
110
111        page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), TimesheetWebTestBase.getTimesheetDocumentUrl(tdocId), tdaf);
112        Assert.assertNotNull(page);
113        page = getWebClient().getPage(TimesheetWebTestBase.getTimesheetDocumentUrl(tdocId));
114        HtmlUnitUtil.createTempFile(page, "TimeBlockPresent");
115        
116        // Verify block present on rendered page.
117        String pageAsText = page.asText();
118        
119        // JSON
120        //
121        //
122        // Grab the timeblock data from the text area. We can check specifics there
123        // to be more fine grained in our validation.
124        String dataText = page.getElementById("timeBlockString").getFirstChild().getNodeValue();
125        JSONArray jsonData = (JSONArray)JSONValue.parse(dataText);
126        final JSONObject jsonDataObject = (JSONObject) jsonData.get(0);
127        Assert.assertTrue("TimeBlock Data Missing.", checkJSONValues(new JSONObject() {{ put("outer", jsonDataObject); }},
128                new ArrayList<Map<String, Object>>() {{
129                    add(new HashMap<String, Object>() {{
130                        put("earnCode", "RGN");
131                        put("hours", "8.0");
132                        put("amount", null);
133                    }});
134                }},
135                new HashMap<String, Object>() {{
136                    put("earnCode", "RGN");
137                    put("startNoTz", "2011-03-02T08:00:00");
138                    put("endNoTz", "2011-03-02T16:00:00");
139                    put("title", "SDR1 Work Area");
140                    put("assignment", "IU-IN_30_30_30");
141                }}
142        ));
143
144        // Check the Display Rendered Text for Time Block, Quick Check
145        Assert.assertTrue("TimeBlock not Present.", pageAsText.contains("08:00 AM - 04:00 PM"));
146        Assert.assertTrue("TimeBlock not Present.", pageAsText.contains("RGN - 8.00 hours"));
147
148        //
149        // Route Timesheet
150        //
151        // Routing is initiated via javascript, we need to extract the routing
152        // action from the button element to perform this action.
153        HtmlButtonInput routeButton = (HtmlButtonInput)page.getElementById("ts-route-button");
154        String routeHref = HtmlUnitUtil.getOnClickHref(routeButton);
155        // The 'only' way to do the button click.
156        page = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), getBaseURL() + "/" + routeHref);
157        //HtmlUnitUtil.createTempFile(page, "RouteClicked");
158        pageAsText = page.asText();
159        // Verify Route Status via UI
160        Assert.assertTrue("Wrong Document Loaded.", pageAsText.contains(tdocId));
161        Assert.assertTrue("Document not routed.", pageAsText.contains(DocumentStatus.ENROUTE.getLabel()));
162        routeButton = (HtmlButtonInput)page.getElementById("ts-route-button");
163        Assert.assertNull("Route button should not be present.", routeButton);
164        HtmlButtonInput approveButton = (HtmlButtonInput)page.getElementById("ts-approve-button");
165        Assert.assertNull("Approval button should not be present.", approveButton);
166
167        //
168        // Login as Approver, who is not 'admin'
169        page = TimesheetWebTestBase.loginAndGetTimeDetailsHtmlPage(getWebClient(), "eric", tdocId, true);
170        //HtmlUnitUtil.createTempFile(page, "2ndLogin");
171        pageAsText = page.asText();
172        Assert.assertTrue("Document not routed.", pageAsText.contains(DocumentStatus.ENROUTE.getLabel()));
173        approveButton = (HtmlButtonInput)page.getElementById("ts-approve-button");
174        Assert.assertNotNull("No approval button present.", approveButton);
175
176        // Click Approve
177        // And Verify
178        //
179        routeHref = HtmlUnitUtil.getOnClickHref(approveButton);
180        TestAutoLoginFilter.OVERRIDE_ID = "eric";
181        page = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), getBaseURL() + "/" + routeHref);
182        TestAutoLoginFilter.OVERRIDE_ID = "";
183        //HtmlUnitUtil.createTempFile(page, "ApproveClicked");
184        pageAsText = page.asText();
185        Assert.assertTrue("Wrong Document Loaded.", pageAsText.contains(tdocId));
186        Assert.assertTrue("Login info not present.", pageAsText.contains("Employee Id:"));
187        Assert.assertTrue("Login info not present.", pageAsText.contains("eric, eric"));
188        Assert.assertTrue("Document not routed.", pageAsText.contains(DocumentStatus.FINAL.getLabel()));
189        approveButton = (HtmlButtonInput)page.getElementById("ts-approve-button");
190        Assert.assertNull("Approval button should not be present.", approveButton);
191    }
192
193}