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(getWebClient(), baseUrl); 110 Assert.assertNotNull(page); 111 Assert.assertTrue("Clock Page contains Distribute Button", page.asText().contains("Distribute Time Blocks")); 112 this.createTB(); 113 updateWebClient(); 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(getWebClient(), 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(getWebClient(), 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 updateWebClient(); 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 updateWebClient() { 155 WebClient webClient = getWebClient(); 156 webClient.setJavaScriptEnabled(true); 157 webClient.setThrowExceptionOnScriptError(false); 158 webClient.setAjaxController(new NicelyResynchronizingAjaxController()); 159 webClient.waitForBackgroundJavaScript(10000); 160 } 161 162 /** 163 * This test is to : 164 * 1) make sure the seconds on clockTimestamp and timestamp are preserved when there is no grace period rule. 165 * 2) the clock in / out button is correctly rendered 166 * 167 * @throws Exception 168 */ 169 @Test 170 public void testClockActionWithoutGracePeriodRule() throws Exception { 171 // Make sure there is no active grace period rule 172 GracePeriodRule gpr = TkServiceLocator.getGracePeriodService().getGracePeriodRule(TKUtils.getCurrentDate()); 173 if (gpr != null && gpr.isActive()) { 174 gpr.setActive(false); 175 KRADServiceLocator.getBusinessObjectService().save(gpr); 176 } 177 178 // Clock in 179 clockIn(); 180 // Make sure clock out button is rendered 181 ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin"); 182 // Make sure both timestamps preserve seconds 183 Assert.assertTrue("The seconds on clock timestamp should be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() != 0); 184 Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0); 185 186 // Clock out 187 clockOut(); 188 // Make sure both timestamps preserve seconds 189 lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin"); 190 Assert.assertTrue("The seconds on clock timestamp should be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() != 0); 191 Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0); 192 } 193 194 @Test 195 public void testClockActionWithGracePeriodRule() throws Exception { 196 //clean clock logs 197 KRADServiceLocator.getBusinessObjectService().deleteMatching(ClockLog.class, Collections.singletonMap("principalId", "admin")); 198 GracePeriodRule gpr = new GracePeriodRule(); 199 //gpr.setTkGracePeriodRuleId("1"); 200 gpr.setEffectiveDate(TKUtils.createDate(1, 1, 2010, 0, 0, 0)); 201 gpr.setHourFactor(new BigDecimal(3)); 202 gpr.setTimestamp(new Timestamp(System.currentTimeMillis())); 203 204 gpr.setActive(true); 205 KRADServiceLocator.getBusinessObjectService().save(gpr); 206 207 // Clock in 208 clockIn(); 209 // Make sure clock out button is rendered 210 ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin"); 211 // Make sure both timestamps preserve seconds 212 Assert.assertTrue("The seconds on clock timestamp should NOT be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() == 0); 213 Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0); 214 215 // Clock out 216 clockOut(); 217 // Make sure both timestamps preserve seconds 218 lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin"); 219 Assert.assertTrue("The seconds on clock timestamp should NOT be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() == 0); 220 Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0); 221 222 223 } 224 225 private HtmlPage clockIn() throws Exception { 226 227 // Clock in 228 HtmlPage page = clockAction(TkConstants.CLOCK_IN); 229 230 // Make sure clock in button is rendered 231 HtmlUnitUtil.createTempFile(page); 232 Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Clock Out")); 233 Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Take Lunch")); 234 235 return page; 236 } 237 238 private HtmlPage clockOut() throws Exception { 239 DateTime dateTime = new DateTime(); 240 if (dateTime.getSecondOfMinute() >= 58 241 || dateTime.getSecondOfMinute() == 0) { 242 Thread.sleep(4000); 243 } 244 // Clock out 245 HtmlPage page = clockAction(TkConstants.CLOCK_OUT); 246 247 // Make sure clock in button is rendered 248 HtmlUnitUtil.createTempFile(page); 249 Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Clock In")); 250 251 return page; 252 } 253 254 /** 255 * This method is used for clocking in and out. 256 * For some reason, htmlunit couldn't click the clock action button correctly. 257 * It's probably because we bind a onClick event to the button instead of submitting the form. 258 * 259 * @param clockAction 260 * @return HtmlPage page 261 */ 262 private HtmlPage clockAction(String clockAction) throws Exception { 263 DateTime dateTime = new DateTime(); 264 if (dateTime.getSecondOfMinute() >= 58 265 || dateTime.getSecondOfMinute() == 0) { 266 Thread.sleep(4000); 267 } 268 String baseUrl = TkTestConstants.Urls.CLOCK_URL; 269 String actionUrl = baseUrl + "?methodToCall=clockAction&selectedAssignment=30_30_30¤tClockAction=" + clockAction; 270 HtmlPage page = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), actionUrl); 271 Assert.assertNotNull("The login page shouldn't be null", page); 272 Thread.sleep(3000); 273 return page; 274 } 275 276 277 }