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 */
016package org.kuali.hr.time.util;
017
018import com.gargoylesoftware.htmlunit.WebClient;
019import com.gargoylesoftware.htmlunit.html.HtmlButton;
020import com.gargoylesoftware.htmlunit.html.HtmlForm;
021import com.gargoylesoftware.htmlunit.html.HtmlPage;
022import org.apache.log4j.Logger;
023import org.joda.time.DateTime;
024import org.joda.time.Interval;
025import org.kuali.hr.TestAutoLoginFilter;
026import org.kuali.hr.util.HtmlUnitUtil;
027import org.kuali.kpme.core.api.assignment.Assignment;
028import org.kuali.kpme.core.api.assignment.AssignmentDescriptionKey;
029import org.kuali.kpme.core.api.earncode.EarnCode;
030import org.kuali.kpme.core.util.TKUtils;
031import org.kuali.kpme.tklm.leave.transfer.BalanceTransfer;
032import org.kuali.kpme.tklm.time.detail.validation.TimeDetailValidationUtil;
033import org.kuali.kpme.tklm.time.detail.web.TimeDetailActionFormBase;
034import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
035
036import java.math.BigDecimal;
037import java.net.URLEncoder;
038import java.util.List;
039
040public class TimeDetailTestUtils {
041
042    private static final Logger LOG = Logger.getLogger(TimeDetailTestUtils.class);
043
044    /**
045     * From the provided set of parameters, build an action form suitable for
046     * submitting to the TimeDetailAction servlet. In our case, we are mostly
047     * using it in a mock type of situation.
048     * @param timeshetDocument
049     * @param assignment
050     * @param earnCode
051     * @param start
052     * @param end
053     * @param amount
054     * @param acrossDays
055     * @param timeblockId
056     *
057     * @return A populated TimeDetailActionFormBase object.
058     */
059    public static TimeDetailActionFormBase buildDetailActionForm(TimesheetDocument timeshetDocument, Assignment assignment, EarnCode earnCode, DateTime start, DateTime end, BigDecimal amount, boolean acrossDays, String timeblockId, boolean spanningWeeks, String outputString, List<String> warnings, String overtimePref, String leaveBlockId, BigDecimal leaveAmount, List<BalanceTransfer> forfeitures) {
060        TimeDetailActionFormBase tdaf = new TimeDetailActionFormBase();
061        /**
062         * 
063         * 
064         * 
065         */
066        BigDecimal hours = null;
067        String startTimeS = null;
068        String endTimeS = null;
069        String startDateS;
070        String endDateS;
071        String selectedEarnCode;
072        String selectedAssignment;
073
074        if (hours == null) {
075            if (start != null && end != null) {
076                Interval se_i = new Interval(start, end);
077                hours = TKUtils.convertMillisToHours(se_i.toDurationMillis());
078            }
079
080            // the date/time format is defined in tk.calendar.js. For now, the format is 11/17/2010 8:0
081            startTimeS = start.toString("H:mm");
082            endTimeS = end.toString("H:mm");
083        }
084
085        startDateS = start.toString("MM/dd/YYYY");
086        endDateS = end.toString("MM/dd/YYYY");
087
088        AssignmentDescriptionKey adk = new AssignmentDescriptionKey(assignment);
089        selectedAssignment = adk.toAssignmentKeyString();
090
091        selectedEarnCode = earnCode.getEarnCode();
092
093        tdaf.setAcrossDays(acrossDays ? "y" : "n");
094//        tdaf.setSpanningWeeks(spanningWeeks ? "y" : "n"); // KPME-1446
095        tdaf.setAmount(amount);
096        tdaf.setHours(hours);
097        tdaf.setStartTime(startTimeS);
098        tdaf.setEndTime(endTimeS);
099        tdaf.setStartDate(startDateS);
100        tdaf.setEndDate(endDateS);
101        tdaf.setTkTimeBlockId(timeblockId);
102        tdaf.setTimesheetDocument(timeshetDocument);
103        tdaf.setSelectedAssignment(selectedAssignment);
104        tdaf.setSelectedEarnCode(selectedEarnCode);
105        tdaf.setOvertimePref(overtimePref);
106        tdaf.setOutputString(outputString);
107        tdaf.setForfeitures(forfeitures);
108        tdaf.setWarnings(warnings);
109        tdaf.setLmLeaveBlockId(leaveBlockId);
110        tdaf.setLeaveAmount(leaveAmount);
111        //tdaf.setPrincipalId(principalId);
112        tdaf.setMethodToCall("addTimeBlock");
113
114        return tdaf;
115    }
116
117    /**
118     * Set the attributes on the provided html form to the values found in the provided
119     * ActionForm. Errors are returned in the List<String> object.
120     *
121     * @param form The HtmlForm to populate.
122     * @param tdaf The ActionForm with values we will use to populate.
123     *
124     * @return A list of string error messages from the validation call.
125     */
126    public static List<String> setTimeBlockFormDetails(HtmlForm form, TimeDetailActionFormBase tdaf) {
127        // Validation -- the same call the WS makes. (should already be valid...)
128        List<String> errors = TimeDetailValidationUtil.validateTimeEntryDetails(tdaf);
129/*        errors = new ArrayList<String>();*/
130        // If validation passes, we can add the time block.
131        if (errors.size() == 0) {
132            if (tdaf.getTkTimeBlockId() != null) {
133                form.setAttribute("tkTimeBlockId", tdaf.getTkTimeBlockId().toString());
134            }
135            form.setAttribute("startDate", tdaf.getStartDate());
136            form.setAttribute("endDate", tdaf.getEndDate());
137
138            if (tdaf.getAmount() != null) {
139                form.setAttribute("amount", tdaf.getAmount().toString());
140            } else {
141                form.setAttribute("startTime", tdaf.getStartTime());
142                form.setAttribute("endTime", tdaf.getEndTime());
143                form.setAttribute("hours", tdaf.getHours().toString());
144            }
145
146            form.setAttribute("selectedEarnCode", tdaf.getSelectedEarnCode());
147            form.setAttribute("selectedAssignment", tdaf.getSelectedAssignment());
148            form.setAttribute("acrossDays", tdaf.getAcrossDays());
149            form.setAttribute("methodToCall", tdaf.getMethodToCall());
150            //form.setAttribute("principalId", tdaf.getPrincipalId());
151        }
152
153        return errors;
154    }
155
156    /**
157     * This is a 'hacker' method to get around the fact that in HtmlUnit you
158     * can no longer directly submit forms if there are no buttons. We
159     * simply add a button to the form, and click it!
160     *
161     * @param page The HtmlPage the form came from.
162     * @param form The HtmlForm you wish to submit.
163     * @return The return results from clicking .submit()
164     */
165    private static HtmlPage submitTimeDetailsDep(HtmlPage page, HtmlForm form) {
166        HtmlButton submitButton = null;
167
168        //ScriptResult sr = page.executeJavaScript("document.forms[\"TimeDetailActionForm\"].submit();");
169
170        if (submitButton == null) {
171            submitButton = (HtmlButton)page.createElement("button");
172            submitButton.setAttribute("type", "submit");
173            form.appendChild(submitButton);
174        }
175
176        HtmlPage newPage = null;
177        try {
178            submitButton.click();
179        } catch (Exception e) {
180            LOG.error("While submitting time detail form", e);
181        }
182
183        return newPage;
184    }
185
186
187    /**
188     * A method to wrap the submission of the time details.
189     * @param baseUrl
190     * @param tdaf
191     * @return
192     */
193    public static HtmlPage submitTimeDetails(WebClient webClient, String baseUrl, TimeDetailActionFormBase tdaf) {
194        // For now, until a more HtmlUnit based click method can be found
195        // workable, we're building a url-encoded string to directly
196        // post to the servlet.
197
198        String url = baseUrl + buildPostFromFormParams(tdaf);
199        HtmlPage page = null;
200
201        try {
202            page = HtmlUnitUtil.gotoPageAndLogin(webClient, url);
203        } catch (Exception e) {
204            LOG.error("Error while submitting form", e);
205        }
206
207        return page;
208    }
209
210    /**
211     * A method to wrap the submission of the time details.
212     * @param baseUrl
213     * @param tdaf
214     * @return
215     */
216    public static HtmlPage submitTimeDetails(WebClient webClient, String principalId, String baseUrl, TimeDetailActionFormBase tdaf) {
217        // For now, until a more HtmlUnit based click method can be found
218        // workable, we're building a url-encoded string to directly
219        // post to the servlet.
220
221        String url = baseUrl + buildPostFromFormParams(tdaf);
222        HtmlPage page = null;
223
224        try {
225            TestAutoLoginFilter.OVERRIDE_ID = principalId;
226            page = HtmlUnitUtil.gotoPageAndLogin(webClient, url);
227            TestAutoLoginFilter.OVERRIDE_ID = "";
228        } catch (Exception e) {
229            LOG.error("Error while submitting form", e);
230        }
231
232        return page;
233    }
234
235    private static String buildPostFromFormParams(TimeDetailActionFormBase tdaf) {
236        StringBuilder builder = new StringBuilder();
237
238        try {
239            builder.append("&methodToCall=").append(URLEncoder.encode(tdaf.getMethodToCall(), "UTF-8"));
240            builder.append("&acrossDays=").append(URLEncoder.encode(tdaf.getAcrossDays(), "UTF-8"));
241            if (tdaf.getAmount() != null) {
242                builder.append("&amount=").append(URLEncoder.encode(tdaf.getAmount().toString(), "UTF-8"));
243            } else {
244                builder.append("&hours=").append(URLEncoder.encode(tdaf.getHours().toString(), "UTF-8"));
245                builder.append("&startTime=").append(URLEncoder.encode(tdaf.getStartTime(), "UTF-8"));
246                builder.append("&endTime=").append(URLEncoder.encode(tdaf.getEndTime(), "UTF-8"));
247            }
248            builder.append("&startDate=").append(URLEncoder.encode(tdaf.getStartDate(), "UTF-8"));
249            builder.append("&endDate=").append(URLEncoder.encode(tdaf.getEndDate(), "UTF-8"));
250            builder.append("&selectedAssignment=").append(URLEncoder.encode(tdaf.getSelectedAssignment(), "UTF-8"));
251            builder.append("&selectedEarnCode=").append(URLEncoder.encode(tdaf.getSelectedEarnCode(), "UTF-8"));
252            //builder.append("&principalId=").append(URLEncoder.encode(tdaf.getPrincipalId(), "UTF-8"));
253            if (tdaf.getTkTimeBlockId() != null) {
254                builder.append("&tkTimeBlockId=").append(URLEncoder.encode(tdaf.getTkTimeBlockId().toString(), "UTF-8"));
255            }
256        } catch (Exception e) {
257            LOG.error("Exception building Post String", e);
258        }
259
260        return builder.toString();
261    }
262}