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