1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.time.test;
17
18 import java.math.BigDecimal;
19 import java.sql.Date;
20 import java.sql.Timestamp;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Calendar;
24 import java.util.GregorianCalendar;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.LinkedList;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31
32 import org.apache.log4j.Logger;
33 import org.joda.time.DateTime;
34 import org.joda.time.DateTimeZone;
35 import org.joda.time.Days;
36 import org.joda.time.Duration;
37 import org.junit.Assert;
38 import org.kuali.hr.job.Job;
39 import org.kuali.hr.time.assignment.Assignment;
40 import org.kuali.hr.time.flsa.FlsaDay;
41 import org.kuali.hr.time.flsa.FlsaWeek;
42 import org.kuali.hr.time.service.base.TkServiceLocator;
43 import org.kuali.hr.time.timeblock.TimeBlock;
44 import org.kuali.hr.time.timeblock.TimeHourDetail;
45 import org.kuali.hr.time.timeblock.service.TimeBlockService;
46 import org.kuali.hr.time.timesheet.TimesheetDocument;
47 import org.kuali.hr.time.util.TKContext;
48 import org.kuali.hr.time.util.TKUser;
49 import org.kuali.hr.time.util.TkConstants;
50 import org.kuali.hr.time.util.TkTimeBlockAggregate;
51 import org.kuali.rice.kew.api.exception.WorkflowException;
52 import org.w3c.dom.NamedNodeMap;
53 import org.w3c.dom.Node;
54
55 import com.gargoylesoftware.htmlunit.html.HtmlCheckBoxInput;
56 import com.gargoylesoftware.htmlunit.html.HtmlElement;
57 import com.gargoylesoftware.htmlunit.html.HtmlForm;
58 import com.gargoylesoftware.htmlunit.html.HtmlInput;
59 import com.gargoylesoftware.htmlunit.html.HtmlPage;
60 import com.gargoylesoftware.htmlunit.html.HtmlSelect;
61 import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
62 import com.gargoylesoftware.htmlunit.html.HtmlTextArea;
63
64 public class TkTestUtils {
65
66 private static final Logger LOG = Logger.getLogger(TkTestUtils.class);
67
68 public static TimesheetDocument populateBlankTimesheetDocument(Date calDate) {
69 try {
70 TimesheetDocument timesheet = TkServiceLocator.getTimesheetService().openTimesheetDocument(TKUser.getCurrentTargetPerson().getPrincipalId(),
71 TkServiceLocator.getCalendarService().getCurrentCalendarDates(TKUser.getCurrentTargetPerson().getPrincipalId(),
72 calDate));
73 for(TimeBlock timeBlock : timesheet.getTimeBlocks()){
74 TkServiceLocator.getTimeBlockService().deleteTimeBlock(timeBlock);
75 }
76
77 return timesheet;
78 } catch (WorkflowException e) {
79 throw new RuntimeException("Problem fetching document");
80 }
81 }
82
83 public static TimesheetDocument populateTimesheetDocument(Date calDate) {
84 try {
85 TimesheetDocument timesheet = TkServiceLocator.getTimesheetService().openTimesheetDocument(TKUser.getCurrentTargetPerson().getPrincipalId(),
86 TkServiceLocator.getCalendarService().getCurrentCalendarDates(TKUser.getCurrentTargetPerson().getPrincipalId(),
87 calDate));
88 for(TimeBlock timeBlock : timesheet.getTimeBlocks()){
89 TkServiceLocator.getTimeBlockService().deleteTimeBlock(timeBlock);
90 }
91
92
93 timesheet = TkServiceLocator.getTimesheetService().openTimesheetDocument(TKUser.getCurrentTargetPerson().getPrincipalId(),
94 TkServiceLocator.getCalendarService().getCurrentCalendarDates(TKUser.getCurrentTargetPerson().getPrincipalId(),
95 calDate));
96 List<TimeBlock> timeBlocks = new LinkedList<TimeBlock>();
97 for(int i = 0;i<5;i++){
98 TimeBlock timeBlock = createTimeBlock(timesheet, i+1, 10);
99 timeBlocks.add(timeBlock);
100 timesheet.setTimeBlocks(timeBlocks);
101 }
102
103
104 TimeBlock timeBlock = createTimeBlock(timesheet, 1, 4,"TEX");
105 timeBlocks.add(timeBlock);
106 timesheet.setTimeBlocks(timeBlocks);
107 return timesheet;
108
109 } catch (WorkflowException e) {
110 throw new RuntimeException("Problem fetching document");
111 }
112 }
113
114
115 public static void createEarnGroup(String earnGroup, List<String> earnCodes, Date asOfDate){
116
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130 public static List<TimeBlock> createUniformTimeBlocks(DateTime start, int days, BigDecimal hours, String earnCode, Long jobNumber, Long workArea) {
131 return TkTestUtils.createUniformTimeBlocks(start, days, hours, earnCode, jobNumber, workArea, null);
132 }
133
134 public static List<TimeBlock> createUniformTimeBlocks(DateTime start, int days, BigDecimal hours, String earnCode, Long jobNumber, Long workArea, Long task) {
135 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
136
137 for (int i=0; i<days; i++) {
138 DateTime ci = start.plusDays(i);
139 DateTime co = ci.plusHours(hours.intValue());
140 TimeBlock block = TkTestUtils.createDummyTimeBlock(ci, co, hours, earnCode, jobNumber, workArea);
141 block.setTask(task);
142 blocks.add(block);
143 }
144
145 return blocks;
146 }
147
148 public static TimeBlock createDummyTimeBlock(DateTime clockIn, DateTime clockOut, BigDecimal hours, String earnCode) {
149 return TkTestUtils.createDummyTimeBlock(clockIn, clockOut, hours, earnCode, -1L, -1L);
150 }
151
152 public static TimeBlock createDummyTimeBlock(DateTime clockIn, DateTime clockOut, BigDecimal hours, String earnCode, Long jobNumber, Long workArea) {
153 TimeBlock block = new TimeBlock();
154 Timestamp ci = new Timestamp(clockIn.getMillis());
155 Timestamp co = new Timestamp(clockOut.getMillis());
156 block.setBeginTimestamp(ci);
157 block.setEndTimestamp(co);
158 block.setHours(hours);
159 block.setEarnCode(earnCode);
160 block.setJobNumber(jobNumber);
161 block.setWorkArea(workArea);
162
163 TimeHourDetail thd = new TimeHourDetail();
164 thd.setHours(hours);
165 thd.setEarnCode(earnCode);
166 List<TimeHourDetail> timeHourDetails = new ArrayList<TimeHourDetail>();
167 timeHourDetails.add(thd);
168 block.setTimeHourDetails(timeHourDetails);
169
170 return block;
171 }
172
173 public static TimeBlock createTimeBlock(TimesheetDocument timesheetDocument, int dayInPeriod, int numHours){
174 return createTimeBlock(timesheetDocument, dayInPeriod, numHours,"RGN");
175 }
176 public static TimeBlock createTimeBlock(TimesheetDocument timesheetDocument, int dayInPeriod, int numHours, String earnCode){
177 TimeBlock timeBlock = new TimeBlock();
178 Calendar cal = GregorianCalendar.getInstance();
179 cal.setTimeInMillis(timesheetDocument.getPayCalendarEntry().getBeginPeriodDateTime().getTime());
180 for(int i = 1; i< dayInPeriod;i++){
181 cal.add(Calendar.DAY_OF_MONTH, 1);
182 }
183 cal.set(Calendar.HOUR, 8);
184 cal.set(Calendar.MINUTE, 0);
185
186 timeBlock.setDocumentId(timesheetDocument.getDocumentId());
187 timeBlock.setBeginTimeDisplay(new DateTime(cal.getTimeInMillis()));
188
189 timeBlock.setBeginTimestamp(new Timestamp(cal.getTimeInMillis()));
190 timeBlock.setBeginTimestampTimezone("EST");
191 timeBlock.setEarnCode(earnCode);
192 timeBlock.setJobNumber(1L);
193 timeBlock.setWorkArea(1234L);
194 timeBlock.setHours((new BigDecimal(numHours)).setScale(TkConstants.BIG_DECIMAL_SCALE, TkConstants.BIG_DECIMAL_SCALE_ROUNDING));
195 cal.add(Calendar.HOUR, numHours);
196 timeBlock.setEndTimestamp(new Timestamp(cal.getTimeInMillis()));
197 timeBlock.setEndTimeDisplay(new DateTime(cal.getTimeInMillis()));
198
199 return timeBlock;
200 }
201
202 public static List<Job> getJobs(Date calDate){
203 return TkServiceLocator.getJobService().getJobs(TKContext.getPrincipalId(), calDate);
204 }
205
206
207
208
209
210
211
212 public static HtmlPage fillOutForm(HtmlPage page, Map<String, Object> criteria) throws Exception {
213 HtmlForm lookupForm = HtmlUnitUtil.getDefaultForm(page);
214 String formFieldPrefix = "";
215 HtmlPage resultPage = null;
216 HtmlSelect select = null;
217 HtmlInput input = null;
218 HtmlCheckBoxInput checkBox = null;
219 HtmlTextArea textArea = null;
220
221
222
223
224 HtmlElement htmlBasicInput = null;
225
226 Set<Map.Entry<String, Object>> entries = criteria.entrySet();
227 Iterator<Map.Entry<String, Object>> it = entries.iterator();
228
229 while (it.hasNext()) {
230 Map.Entry<String,Object> entry = it.next();
231
232
233 if(entry.getValue() instanceof String[]) {
234 String key = Arrays.asList((String[])entry.getValue()).get(0).toString();
235 String value = Arrays.asList((String[])entry.getValue()).get(1).toString();
236
237
238 if(key.equals(TkTestConstants.FormElementTypes.DROPDOWN)) {
239
240 try {
241 select = (HtmlSelect) lookupForm.getSelectByName(formFieldPrefix + entry.getKey());
242 } catch (Exception e) {
243 select = (HtmlSelect) lookupForm.getElementById(formFieldPrefix + entry.getKey());
244 }
245
246 resultPage = (HtmlPage) select.getOptionByValue((String)value).setSelected(true);
247 }
248
249 else if(key.equals(TkTestConstants.FormElementTypes.CHECKBOX)) {
250 try {
251 checkBox = page.getHtmlElementById(formFieldPrefix + entry.getKey());
252 }
253 catch(Exception e) {
254 checkBox = page.getElementByName(formFieldPrefix + entry.getKey());
255 }
256 resultPage = (HtmlPage) checkBox.setChecked(Boolean.parseBoolean(value));
257 }
258
259 else if(key.equals(TkTestConstants.FormElementTypes.TEXTAREA)) {
260 try {
261 textArea = page.getHtmlElementById(formFieldPrefix + entry.getKey());
262 } catch (Exception e){
263 textArea = page.getElementByName(formFieldPrefix + entry.getKey());
264 }
265 textArea.setText(Arrays.asList((String[])entry.getValue()).get(1).toString());
266 }
267 } else {
268 try {
269 htmlBasicInput = page.getHtmlElementById(formFieldPrefix + entry.getKey());
270 if (htmlBasicInput instanceof HtmlTextArea) {
271 textArea = (HtmlTextArea)htmlBasicInput;
272 textArea.setText(entry.getValue().toString());
273 resultPage = (HtmlPage) textArea.getPage();
274 } else if (htmlBasicInput instanceof HtmlInput) {
275 input = (HtmlInput)htmlBasicInput;
276 resultPage = (HtmlPage) input.setValueAttribute(entry.getValue().toString());
277 } else {
278 LOG.error("Request to populate a non-input html form field.");
279 }
280 } catch (Exception e) {
281 htmlBasicInput = page.getElementByName(formFieldPrefix + entry.getKey());
282
283 if (htmlBasicInput instanceof HtmlTextArea) {
284 textArea = (HtmlTextArea)htmlBasicInput;
285 textArea.setText(entry.getValue().toString());
286 resultPage = (HtmlPage) textArea.getPage();
287 } else if (htmlBasicInput instanceof HtmlInput) {
288 input = (HtmlInput)htmlBasicInput;
289 resultPage = (HtmlPage) input.setValueAttribute(entry.getValue().toString());
290 } else {
291 LOG.error("Request to populate a non-input html form field.");
292 }
293 }
294 }
295 }
296 HtmlUnitUtil.createTempFile(resultPage);
297 return resultPage;
298 }
299
300
301
302
303
304
305
306
307 public static HtmlPage clickButton(HtmlPage page, String name) throws Exception {
308 HtmlForm form = HtmlUnitUtil.getDefaultForm(page);
309 HtmlSubmitInput input = form.getInputByName(name);
310 return (HtmlPage) input.click();
311 }
312
313 public static HtmlPage clickClockInOrOutButton(HtmlPage page) throws Exception {
314 HtmlForm form = HtmlUnitUtil.getDefaultForm(page);
315
316 HtmlSubmitInput input = form.getInputByName("clockAction");
317 form.getInputByName("methodToCall").setValueAttribute("clockAction");
318 return (HtmlPage) input.click();
319 }
320
321 public static HtmlPage clickLunchInOrOutButton(HtmlPage page, String lunchAction) throws Exception {
322 HtmlForm form = HtmlUnitUtil.getDefaultForm(page);
323
324 HtmlSubmitInput input = form.getInputByName("clockAction");
325 form.getInputByName("methodToCall").setValueAttribute("clockAction");
326 form.getInputByName("currentClockAction").setValueAttribute(lunchAction);
327 return (HtmlPage) input.click();
328 }
329
330 @SuppressWarnings("serial")
331 public static void verifyAggregateHourSumsFlatList(String msg, final Map<String,BigDecimal> ecToHoursMap, TkTimeBlockAggregate aggregate) {
332
333
334 Map<String,BigDecimal> ecToSumMap = new HashMap<String,BigDecimal>() {{ for (String ec : ecToHoursMap.keySet()) { put(ec, BigDecimal.ZERO); }}};
335
336 for (TimeBlock bl : aggregate.getFlattenedTimeBlockList())
337 for (TimeHourDetail thd : bl.getTimeHourDetails())
338 if (ecToSumMap.containsKey(thd.getEarnCode()))
339 ecToSumMap.put(thd.getEarnCode(), ecToSumMap.get(thd.getEarnCode()).add(thd.getHours()));
340
341
342 for (String key : ecToHoursMap.keySet())
343 Assert.assertEquals(
344 msg + " >> ("+key+") Wrong number of hours expected: " + ecToHoursMap.get(key) + " found: " + ecToSumMap.get(key) + " :: ",
345 0,
346 ecToHoursMap.get(key).compareTo(ecToSumMap.get(key)));
347 }
348
349
350
351
352
353
354
355
356
357
358
359 @SuppressWarnings("serial")
360 public static void verifyAggregateHourSums(String msg, final Map<String,BigDecimal> ecToHoursMap, TkTimeBlockAggregate aggregate, int flsaWeek) {
361
362
363 Map<String,BigDecimal> ecToSumMap = new HashMap<String,BigDecimal>() {{ for (String ec : ecToHoursMap.keySet()) { put(ec, BigDecimal.ZERO); }}};
364
365 List<FlsaWeek> flsaWeeks = aggregate.getFlsaWeeks(DateTimeZone.forID(TkServiceLocator.getTimezoneService().getUserTimezone()));
366 Assert.assertTrue(msg + " >> Not enough FLSA weeks to verify aggregate hours, max: " + (flsaWeeks.size() - 1), flsaWeeks.size() > flsaWeek);
367
368
369 FlsaWeek week = flsaWeeks.get(flsaWeek);
370 List<FlsaDay> flsaDays = week.getFlsaDays();
371 for (FlsaDay day : flsaDays)
372 for (TimeBlock bl : day.getAppliedTimeBlocks())
373 for (TimeHourDetail thd : bl.getTimeHourDetails())
374 if (ecToSumMap.containsKey(thd.getEarnCode()))
375 ecToSumMap.put(thd.getEarnCode(), ecToSumMap.get(thd.getEarnCode()).add(thd.getHours()));
376
377
378 for (String key : ecToHoursMap.keySet())
379 Assert.assertEquals(
380 msg + " >> ("+key+") Wrong number of hours expected: " + ecToHoursMap.get(key) + " found: " + ecToSumMap.get(key) + " :: ",
381 0,
382 ecToHoursMap.get(key).compareTo(ecToSumMap.get(key)));
383 }
384 public static void verifyAggregateHourSums(final Map<String,BigDecimal> ecToHoursMap, TkTimeBlockAggregate aggregate, int flsaWeek) {
385 TkTestUtils.verifyAggregateHourSums("", ecToHoursMap, aggregate, flsaWeek);
386 }
387
388
389
390
391
392
393 public static List<TimeBlock> createUniformActualTimeBlocks(TimesheetDocument timesheetDocument, Assignment assignment, String earnCode, DateTime start, int days, BigDecimal hours, BigDecimal amount) {
394 TimeBlockService service = TkServiceLocator.getTimeBlockService();
395 List<TimeBlock> blocks = new ArrayList<TimeBlock>();
396
397 for (int i=0; i<days; i++) {
398 DateTime ci = start.plusDays(i);
399 DateTime co = ci.plusHours(hours.intValue());
400 Timestamp tsin = new Timestamp(ci.getMillis());
401 Timestamp tsout = new Timestamp(co.getMillis());
402
403 blocks.addAll(service.buildTimeBlocks(assignment, earnCode, timesheetDocument, tsin, tsout, hours, amount, false, false));
404 }
405
406 return blocks;
407 }
408
409 public static Map<Timestamp, BigDecimal> getDateToHoursMap(TimeBlock timeBlock, TimeHourDetail timeHourDetail) {
410 Map<Timestamp, BigDecimal> dateToHoursMap = new HashMap<Timestamp, BigDecimal>();
411 DateTime beginTime = new DateTime(timeBlock.getBeginTimestamp());
412 DateTime endTime = new DateTime(timeBlock.getEndTimestamp());
413
414 Days d = Days.daysBetween(beginTime, endTime);
415 int numberOfDays = d.getDays();
416 if (numberOfDays < 1) {
417 dateToHoursMap.put(timeBlock.getBeginTimestamp(), timeHourDetail.getHours());
418 return dateToHoursMap;
419 }
420 DateTime currentTime = beginTime;
421 for (int i = 0; i < numberOfDays; i++) {
422 DateTime nextDayAtMidnight = new DateTime(currentTime.plusDays(1).getMillis());
423 nextDayAtMidnight = nextDayAtMidnight.hourOfDay().setCopy(12);
424 nextDayAtMidnight = nextDayAtMidnight.minuteOfDay().setCopy(0);
425 nextDayAtMidnight = nextDayAtMidnight.secondOfDay().setCopy(0);
426 nextDayAtMidnight = nextDayAtMidnight.millisOfSecond().setCopy(0);
427 Duration dur = new Duration(currentTime, nextDayAtMidnight);
428 long duration = dur.getStandardSeconds();
429 BigDecimal hrs = new BigDecimal(duration / 3600, TkConstants.MATH_CONTEXT);
430 dateToHoursMap.put(new Timestamp(currentTime.getMillis()), hrs);
431 currentTime = nextDayAtMidnight;
432 }
433 Duration dur = new Duration(currentTime, endTime);
434 long duration = dur.getStandardSeconds();
435 BigDecimal hrs = new BigDecimal(duration / 3600, TkConstants.MATH_CONTEXT);
436 dateToHoursMap.put(new Timestamp(currentTime.getMillis()), hrs);
437
438 return dateToHoursMap;
439 }
440
441 public static Date createDate(int month, int day, int year, int hours, int minutes, int seconds){
442 DateTime dt = new DateTime(year, month, day, hours, minutes, seconds, 0);
443 return new Date(dt.getMillis());
444 }
445
446
447
448
449
450
451
452 public static String getOnClickHref(HtmlElement button) {
453 NamedNodeMap attributes = button.getAttributes();
454 Node node = attributes.getNamedItem("onclick");
455
456
457 String hrefRaw = node.getNodeValue();
458 int sidx = hrefRaw.indexOf("='");
459
460 return hrefRaw.substring(sidx+2, hrefRaw.length() - 1);
461 }
462
463 }