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