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.clock.web; 017 018 import java.math.BigDecimal; 019 import java.sql.Timestamp; 020 import java.util.*; 021 022 import org.joda.time.DateTime; 023 import org.junit.Assert; 024 import org.junit.Ignore; 025 import org.junit.Test; 026 import org.kuali.hr.test.KPMETestCase; 027 import org.kuali.hr.time.clocklog.ClockLog; 028 import org.kuali.hr.time.graceperiod.rule.GracePeriodRule; 029 import org.kuali.hr.time.service.base.TkServiceLocator; 030 import org.kuali.hr.time.test.HtmlUnitUtil; 031 import org.kuali.hr.time.test.TkTestConstants; 032 import org.kuali.hr.time.timeblock.TimeBlock; 033 import org.kuali.hr.time.timeblock.TimeHourDetail; 034 import org.kuali.hr.time.timesheet.TimesheetDocument; 035 import org.kuali.hr.time.util.TKUtils; 036 import org.kuali.hr.time.util.TkConstants; 037 import org.kuali.hr.time.workflow.TimesheetDocumentHeader; 038 import org.kuali.rice.krad.service.KRADServiceLocator; 039 040 import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController; 041 import com.gargoylesoftware.htmlunit.WebClient; 042 import com.gargoylesoftware.htmlunit.html.HtmlElement; 043 import com.gargoylesoftware.htmlunit.html.HtmlPage; 044 045 046 public class ClockWebTest extends KPMETestCase { 047 048 private String tbId; 049 050 public Long maxDocumentId() { 051 Collection aCol = KRADServiceLocator.getBusinessObjectService().findAll(TimesheetDocumentHeader.class); 052 Long maxId = new Long(-1); 053 Iterator<TimesheetDocumentHeader> itr = aCol.iterator(); 054 while (itr.hasNext()) { 055 TimesheetDocumentHeader tdh = itr.next(); 056 Long temp = new Long(tdh.getDocumentId()); 057 if (temp > maxId) { 058 maxId = temp; 059 } 060 } 061 return maxId; 062 } 063 064 public Long maxTimeBlockId() { 065 Collection aCol = KRADServiceLocator.getBusinessObjectService().findAll(TimeBlock.class); 066 Long maxId = new Long(-1); 067 Iterator<TimeBlock> itr = aCol.iterator(); 068 while (itr.hasNext()) { 069 TimeBlock tb = itr.next(); 070 Long temp = new Long(tb.getTkTimeBlockId()); 071 if (temp > maxId) { 072 maxId = temp; 073 } 074 } 075 return maxId; 076 } 077 078 public void createTB() { 079 TimeBlock timeBlock = new TimeBlock(); 080 timeBlock.setUserPrincipalId("admin"); 081 timeBlock.setJobNumber(2L); 082 timeBlock.setWorkArea(1234L); 083 timeBlock.setTask(1L); 084 timeBlock.setEarnCode("RGN"); 085 Timestamp beginTimestamp = new Timestamp(System.currentTimeMillis()); 086 timeBlock.setBeginTimestamp(beginTimestamp); 087 Timestamp endTimestamp = new Timestamp(System.currentTimeMillis()); 088 timeBlock.setEndTimestamp(endTimestamp); 089 TimeHourDetail timeHourDetail = new TimeHourDetail(); 090 timeHourDetail.setEarnCode("RGN"); 091 timeHourDetail.setHours(new BigDecimal(2.0)); 092 timeBlock.getTimeHourDetails().add(timeHourDetail); 093 timeBlock.setHours(new BigDecimal(2.0)); 094 List<TimeBlock> tbList = new ArrayList<TimeBlock>(); 095 String documentId = this.maxDocumentId().toString(); 096 timeBlock.setDocumentId(documentId); 097 tbList.add(timeBlock); 098 TkServiceLocator.getTimeBlockService().saveTimeBlocks(tbList); 099 100 tbId = timeBlock.getTkTimeBlockId(); 101 TimesheetDocument td = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId); 102 td.setTimeBlocks(tbList); 103 104 } 105 106 @Ignore 107 public void testDistributeTB() throws Exception { 108 String baseUrl = TkTestConstants.Urls.CLOCK_URL; 109 HtmlPage page = HtmlUnitUtil.gotoPageAndLogin(baseUrl); 110 Assert.assertNotNull(page); 111 Assert.assertTrue("Clock Page contains Distribute Button", page.asText().contains("Distribute Time Blocks")); 112 this.createTB(); 113 this.setWebClient(page.getWebClient()); 114 HtmlElement element = page.getElementByName("distributeTime"); 115 Assert.assertNotNull(element); 116 // HtmlPage testPage1 = element.click(); 117 // assertTrue("Distribute Page contains Close button", testPage1.asText().contains("Close")); 118 // assertTrue("Distribute Page contains Close button", testPage1.asText().contains("Edit")); 119 120 // timeDistribute.jsp 121 String distributeUrl = baseUrl + "?methodToCall=distributeTimeBlocks"; 122 HtmlPage page1 = HtmlUnitUtil.gotoPageAndLogin(distributeUrl); 123 Assert.assertTrue("Distribute Page contains Close button", page1.asText().contains("Close")); 124 Assert.assertTrue("Distribute Page contains Close button", page1.asText().contains("Edit")); 125 126 element = page1.getElementByName("editTimeBlock"); 127 Assert.assertNotNull(element); 128 Assert.assertTrue("Onclick attribute of Edit button contains", element.getAttribute("onclick").contains("Clock.do?methodToCall=editTimeBlock&editTimeBlockId=")); 129 130 if (tbId == null) { 131 tbId = this.maxTimeBlockId().toString(); 132 } 133 134 //editTimeBlock.jsp 135 String editUrl = baseUrl + "?methodToCall=editTimeBlock&editTimeBlockId=" + tbId; 136 HtmlPage page3 = HtmlUnitUtil.gotoPageAndLogin(editUrl); 137 138 // editTimeBlock.jsp 139 Assert.assertTrue("Edit Time Blocks Page contains Cancel button", page3.asText().contains("Add")); 140 Assert.assertTrue("Edit Time Blocks Page contains Save button", page3.asText().contains("Save")); 141 Assert.assertTrue("Edit Time Blocks Page contains Cancel button", page3.asText().contains("Cancel")); 142 143 element = page3.getElementByName("addTimeBlock"); 144 Assert.assertNotNull(element); 145 Assert.assertTrue("Onclick attribute of Add button contains", element.getAttribute("onclick").contains("javascript: addTimeBlockRow(this.form);")); 146 147 this.setWebClient(page3.getWebClient()); 148 149 // HtmlPage page4 = element.click(); 150 // assertTrue("Edit Time Blocks Page contains Cancel button", page4.asText().contains("Add")); 151 152 } 153 154 public void setWebClient(WebClient webClient) { 155 webClient.setJavaScriptEnabled(true); 156 webClient.setThrowExceptionOnScriptError(false); 157 webClient.setAjaxController(new NicelyResynchronizingAjaxController()); 158 webClient.waitForBackgroundJavaScript(10000); 159 } 160 161 /** 162 * This test is to : 163 * 1) make sure the seconds on clockTimestamp and timestamp are preserved when there is no grace period rule. 164 * 2) the clock in / out button is correctly rendered 165 * 166 * @throws Exception 167 */ 168 @Test 169 public void testClockActionWithoutGracePeriodRule() throws Exception { 170 // Make sure there is no active grace period rule 171 GracePeriodRule gpr = TkServiceLocator.getGracePeriodService().getGracePeriodRule(TKUtils.getCurrentDate()); 172 if (gpr != null && gpr.isActive()) { 173 gpr.setActive(false); 174 KRADServiceLocator.getBusinessObjectService().save(gpr); 175 } 176 177 // Clock in 178 clockIn(); 179 // Make sure clock out button is rendered 180 ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin"); 181 // Make sure both timestamps preserve seconds 182 Assert.assertTrue("The seconds on clock timestamp should be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() != 0); 183 Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0); 184 185 // Clock out 186 clockOut(); 187 // Make sure both timestamps preserve seconds 188 lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin"); 189 Assert.assertTrue("The seconds on clock timestamp should be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() != 0); 190 Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0); 191 } 192 193 @Test 194 public void testClockActionWithGracePeriodRule() throws Exception { 195 //clean clock logs 196 KRADServiceLocator.getBusinessObjectService().deleteMatching(ClockLog.class, Collections.singletonMap("principalId", "admin")); 197 GracePeriodRule gpr = new GracePeriodRule(); 198 //gpr.setTkGracePeriodRuleId("1"); 199 gpr.setEffectiveDate(TKUtils.createDate(1, 1, 2010, 0, 0, 0)); 200 gpr.setHourFactor(new BigDecimal(3)); 201 gpr.setTimestamp(new Timestamp(System.currentTimeMillis())); 202 203 gpr.setActive(true); 204 KRADServiceLocator.getBusinessObjectService().save(gpr); 205 206 // Clock in 207 clockIn(); 208 // Make sure clock out button is rendered 209 ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin"); 210 // Make sure both timestamps preserve seconds 211 Assert.assertTrue("The seconds on clock timestamp should NOT be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() == 0); 212 Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0); 213 214 // Clock out 215 clockOut(); 216 // Make sure both timestamps preserve seconds 217 lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin"); 218 Assert.assertTrue("The seconds on clock timestamp should NOT be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() == 0); 219 Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0); 220 221 222 } 223 224 private HtmlPage clockIn() throws Exception { 225 226 // Clock in 227 HtmlPage page = clockAction(TkConstants.CLOCK_IN); 228 229 // Make sure clock in button is rendered 230 HtmlUnitUtil.createTempFile(page); 231 Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Clock Out")); 232 Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Take Lunch")); 233 234 return page; 235 } 236 237 private HtmlPage clockOut() throws Exception { 238 DateTime dateTime = new DateTime(); 239 if (dateTime.getSecondOfMinute() >= 58 240 || dateTime.getSecondOfMinute() == 0) { 241 Thread.sleep(4000); 242 } 243 // Clock out 244 HtmlPage page = clockAction(TkConstants.CLOCK_OUT); 245 246 // Make sure clock in button is rendered 247 HtmlUnitUtil.createTempFile(page); 248 Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Clock In")); 249 250 return page; 251 } 252 253 /** 254 * This method is used for clocking in and out. 255 * For some reason, htmlunit couldn't click the clock action button correctly. 256 * It's probably because we bind a onClick event to the button instead of submitting the form. 257 * 258 * @param clockAction 259 * @return HtmlPage page 260 */ 261 private HtmlPage clockAction(String clockAction) throws Exception { 262 DateTime dateTime = new DateTime(); 263 if (dateTime.getSecondOfMinute() >= 58 264 || dateTime.getSecondOfMinute() == 0) { 265 Thread.sleep(4000); 266 } 267 String baseUrl = TkTestConstants.Urls.CLOCK_URL; 268 String actionUrl = baseUrl + "?methodToCall=clockAction&selectedAssignment=30_30_30¤tClockAction=" + clockAction; 269 HtmlPage page = HtmlUnitUtil.gotoPageAndLogin(actionUrl); 270 Assert.assertNotNull("The login page shouldn't be null", page); 271 Thread.sleep(3000); 272 return page; 273 } 274 275 276 }