001 /** 002 * Copyright 2004-2012 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 }