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     */
016    package org.kuali.hr.time.util;
017    
018    import java.math.BigDecimal;
019    import java.net.URLEncoder;
020    import java.util.ArrayList;
021    import java.util.List;
022    
023    import org.apache.log4j.Logger;
024    import org.joda.time.DateTime;
025    import org.joda.time.Interval;
026    import org.kuali.hr.TestAutoLoginFilter;
027    import org.kuali.hr.util.HtmlUnitUtil;
028    import org.kuali.kpme.core.assignment.Assignment;
029    import org.kuali.kpme.core.assignment.AssignmentDescriptionKey;
030    import org.kuali.kpme.core.earncode.EarnCode;
031    import org.kuali.kpme.core.util.TKUtils;
032    import org.kuali.kpme.tklm.time.detail.validation.TimeDetailValidationUtil;
033    import org.kuali.kpme.tklm.time.detail.web.TimeDetailActionFormBase;
034    import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
035    
036    import com.gargoylesoftware.htmlunit.WebClient;
037    import com.gargoylesoftware.htmlunit.html.HtmlButton;
038    import com.gargoylesoftware.htmlunit.html.HtmlForm;
039    import com.gargoylesoftware.htmlunit.html.HtmlPage;
040    
041    public 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    }