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