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 }