View Javadoc
1   /**
2    * Copyright 2004-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.hr.time.clock.web;
17  
18  import java.math.BigDecimal;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.Iterator;
23  import java.util.LinkedHashMap;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.joda.time.DateTime;
28  import org.joda.time.DateTimeZone;
29  import org.joda.time.LocalDate;
30  import org.junit.Assert;
31  import org.junit.Ignore;
32  import org.junit.Test;
33  import org.kuali.hr.KPMEWebTestCase;
34  import org.kuali.hr.util.HtmlUnitUtil;
35  import org.kuali.kpme.core.FunctionalTest;
36  import org.kuali.kpme.core.service.HrServiceLocator;
37  import org.kuali.kpme.core.util.HrTestConstants;
38  import org.kuali.kpme.core.util.TKUtils;
39  import org.kuali.kpme.tklm.common.TkConstants;
40  import org.kuali.kpme.tklm.time.clocklog.ClockLog;
41  import org.kuali.kpme.tklm.time.rules.graceperiod.GracePeriodRule;
42  import org.kuali.kpme.tklm.time.service.TkServiceLocator;
43  import org.kuali.kpme.tklm.time.timeblock.TimeBlock;
44  import org.kuali.kpme.tklm.time.timehourdetail.TimeHourDetail;
45  import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
46  import org.kuali.kpme.tklm.time.workflow.TimesheetDocumentHeader;
47  import org.kuali.kpme.tklm.utils.TkTestConstants;
48  import org.kuali.rice.krad.service.KRADServiceLocator;
49  
50  import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
51  import com.gargoylesoftware.htmlunit.WebClient;
52  import com.gargoylesoftware.htmlunit.html.HtmlElement;
53  import com.gargoylesoftware.htmlunit.html.HtmlPage;
54  
55  
56  @FunctionalTest
57  public class ClockWebTest extends KPMEWebTestCase {
58  
59      private String tbId;
60  
61      public Long maxDocumentId() {
62          Collection aCol = KRADServiceLocator.getBusinessObjectService().findAll(TimesheetDocumentHeader.class);
63          Long maxId = new Long(-1);
64          Iterator<TimesheetDocumentHeader> itr = aCol.iterator();
65          while (itr.hasNext()) {
66              TimesheetDocumentHeader tdh = itr.next();
67              Long temp = new Long(tdh.getDocumentId());
68              if (temp > maxId) {
69                  maxId = temp;
70              }
71          }
72          return maxId;
73      }
74  
75      public Long maxTimeBlockId() {
76          Collection aCol = KRADServiceLocator.getBusinessObjectService().findAll(TimeBlock.class);
77          Long maxId = new Long(-1);
78          Iterator<TimeBlock> itr = aCol.iterator();
79          while (itr.hasNext()) {
80              TimeBlock tb = itr.next();
81              Long temp = new Long(tb.getTkTimeBlockId());
82              if (temp > maxId) {
83                  maxId = temp;
84              }
85          }
86          return maxId;
87      }
88  
89      public void createTB() {
90          TimeBlock timeBlock = new TimeBlock();
91          timeBlock.setUserPrincipalId("admin");
92          timeBlock.setJobNumber(2L);
93          timeBlock.setWorkArea(1234L);
94          timeBlock.setTask(1L);
95          timeBlock.setEarnCode("RGN");
96          timeBlock.setBeginTimestamp(TKUtils.getCurrentTimestamp());
97          timeBlock.setEndTimestamp(TKUtils.getCurrentTimestamp());
98          TimeHourDetail timeHourDetail = new TimeHourDetail();
99          timeHourDetail.setEarnCode("RGN");
100         timeHourDetail.setHours(new BigDecimal(2.0));
101         timeBlock.getTimeHourDetails().add(timeHourDetail);
102         timeBlock.setHours(new BigDecimal(2.0));
103         List<TimeBlock> tbList = new ArrayList<TimeBlock>();
104         String documentId = this.maxDocumentId().toString();
105         timeBlock.setDocumentId(documentId);
106         tbList.add(timeBlock);
107         TkServiceLocator.getTimeBlockService().saveTimeBlocks(tbList);
108 
109         tbId = timeBlock.getTkTimeBlockId();
110         TimesheetDocument td = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
111         td.setTimeBlocks(tbList);
112 
113     }
114 
115     @Ignore
116     public void testDistributeTB() throws Exception {
117         String baseUrl = TkTestConstants.Urls.CLOCK_URL;
118         HtmlPage page = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), baseUrl);
119         Assert.assertNotNull(page);
120         Assert.assertTrue("Clock Page contains Distribute Button", page.asText().contains("Distribute Time Blocks"));
121         this.createTB();
122         updateWebClient();
123         HtmlElement element = page.getElementByName("distributeTime");
124         Assert.assertNotNull(element);
125 //	  	HtmlPage testPage1 = element.click();
126 //	  	assertTrue("Distribute Page contains Close button", testPage1.asText().contains("Close"));
127 //        assertTrue("Distribute Page contains Close button", testPage1.asText().contains("Edit"));
128 
129         // timeDistribute.jsp
130         String distributeUrl = baseUrl + "?methodToCall=distributeTimeBlocks";
131         HtmlPage page1 = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), distributeUrl);
132         Assert.assertTrue("Distribute Page contains Close button", page1.asText().contains("Close"));
133         Assert.assertTrue("Distribute Page contains Close button", page1.asText().contains("Edit"));
134 
135         element = page1.getElementByName("editTimeBlock");
136         Assert.assertNotNull(element);
137         Assert.assertTrue("Onclick attribute of Edit button contains", element.getAttribute("onclick").contains("Clock.do?methodToCall=editTimeBlock&editTimeBlockId="));
138 
139         if (tbId == null) {
140             tbId = this.maxTimeBlockId().toString();
141         }
142 
143         //editTimeBlock.jsp
144         String editUrl = baseUrl + "?methodToCall=editTimeBlock&editTimeBlockId=" + tbId;
145         HtmlPage page3 = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), editUrl);
146 
147         // editTimeBlock.jsp
148         Assert.assertTrue("Edit Time Blocks Page contains Cancel button", page3.asText().contains("Add"));
149         Assert.assertTrue("Edit Time Blocks Page contains Save button", page3.asText().contains("Save"));
150         Assert.assertTrue("Edit Time Blocks Page contains Cancel button", page3.asText().contains("Cancel"));
151 
152         element = page3.getElementByName("addTimeBlock");
153         Assert.assertNotNull(element);
154         Assert.assertTrue("Onclick attribute of Add button contains", element.getAttribute("onclick").contains("javascript: addTimeBlockRow(this.form);"));
155 
156         updateWebClient();
157 
158 //	  	HtmlPage page4 = element.click();
159 //	  	assertTrue("Edit Time Blocks Page contains Cancel button", page4.asText().contains("Add"));
160 
161     }
162 
163     public void updateWebClient() {
164         WebClient webClient = getWebClient();
165         webClient.setJavaScriptEnabled(true);
166         webClient.setThrowExceptionOnScriptError(false);
167         webClient.setAjaxController(new NicelyResynchronizingAjaxController());
168         webClient.waitForBackgroundJavaScript(10000);
169     }
170 
171     /**
172      * This test is to :
173      * 1) make sure the seconds on clockTimestamp and timestamp are preserved when there is no grace period rule.
174      * 2) the clock in / out button is correctly rendered
175      *
176      * @throws Exception
177      */
178     @Test
179     public void testClockActionWithoutGracePeriodRule() throws Exception {
180         // Make sure there is no active grace period rule
181         GracePeriodRule gpr = TkServiceLocator.getGracePeriodService().getGracePeriodRule(LocalDate.now());
182         if (gpr != null && gpr.isActive()) {
183             gpr.setActive(false);
184             KRADServiceLocator.getBusinessObjectService().save(gpr);
185         }
186 
187         // Clock in
188         clockIn();
189         // Make sure clock out button is rendered
190         ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin");
191         // Make sure both timestamps preserve seconds
192         Assert.assertTrue("The seconds on clock timestamp should be preserved", lastClockLog.getClockDateTime().getSecondOfMinute() != 0);
193         Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0);
194 
195         // Clock out
196         clockOut();
197         // Make sure both timestamps preserve seconds
198         lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin");
199         Assert.assertTrue("The seconds on clock timestamp should be preserved", lastClockLog.getClockDateTime().getSecondOfMinute() != 0);
200         Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0);
201     }
202 
203     @Test
204     public void testClockActionWithGracePeriodRule() throws Exception {
205         //clean clock logs
206         KRADServiceLocator.getBusinessObjectService().deleteMatching(ClockLog.class, Collections.singletonMap("principalId", "admin"));
207         GracePeriodRule gpr = new GracePeriodRule();
208         //gpr.setTkGracePeriodRuleId("1");
209         gpr.setEffectiveLocalDate(new LocalDate(2010, 1, 1));
210         gpr.setHourFactor(new BigDecimal(3));
211         gpr.setTimestamp(TKUtils.getCurrentTimestamp());
212         
213         gpr.setActive(true);
214         KRADServiceLocator.getBusinessObjectService().save(gpr);
215 
216         // Clock in
217         clockIn();
218         // Make sure clock out button is rendered
219         ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin");
220         // Make sure both timestamps preserve seconds
221         Assert.assertTrue("The seconds on clock timestamp should NOT be preserved", lastClockLog.getClockDateTime().getSecondOfMinute() == 0);
222         Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0);
223 
224         // Clock out
225         clockOut();
226         // Make sure both timestamps preserve seconds
227         lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin");
228         Assert.assertTrue("The seconds on clock timestamp should NOT be preserved", lastClockLog.getClockDateTime().getSecondOfMinute() == 0);
229         Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0);
230 
231 
232     }
233     
234     
235 	@Test
236 	public void testClockInOutWithTimezone() throws Exception {
237 		HtmlPage page = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), TkTestConstants.Urls.CLOCK_URL,true);
238 		Assert.assertNotNull(page);
239     	
240     	Map<String, Object> criteria = new LinkedHashMap<String, Object>();
241     	criteria.put("selectedAssignment", new String[]{HrTestConstants.FormElementTypes.DROPDOWN, "30_30_30"});
242     	// choose the first assignment from the drop down
243     	page = HtmlUnitUtil.fillOutForm(page, criteria);
244     	Assert.assertNotNull(page);
245     	// clock in
246     	page = HtmlUnitUtil.clickButton(page, "clockAction");
247     	// clock out 
248     	page = HtmlUnitUtil.clickButton(page, "clockAction");
249     	HtmlUnitUtil.createTempFile(page);
250     	
251     	DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone());
252     	DateTime dateTime = new DateTime().withZone(dateTimeZone);
253     	String timeZone = dateTime.toString("zzzz");
254     	Assert.assertTrue("Time zone information is incorrect", page.asText().contains(timeZone));
255 	}
256 
257     private HtmlPage clockIn() throws Exception {
258 
259         // Clock in
260         HtmlPage page = clockAction(TkConstants.CLOCK_IN);
261 
262         // Make sure clock in button is rendered
263         HtmlUnitUtil.createTempFile(page);
264         Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Clock Out"));
265         Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Take Lunch"));
266 
267         return page;
268     }
269 
270     private HtmlPage clockOut() throws Exception {
271         DateTime dateTime = new DateTime();
272         if (dateTime.getSecondOfMinute() >= 58
273                 || dateTime.getSecondOfMinute() == 0) {
274             Thread.sleep(4000);
275         }
276         // Clock out
277         HtmlPage page = clockAction(TkConstants.CLOCK_OUT);
278 
279         // Make sure clock in button is rendered
280         HtmlUnitUtil.createTempFile(page);
281         Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Clock In"));
282 
283         return page;
284     }
285 
286     /**
287      * This method is used for clocking in and out.
288      * For some reason, htmlunit couldn't click the clock action button correctly.
289      * It's probably because we bind a onClick event to the button instead of submitting the form.
290      *
291      * @param clockAction
292      * @return HtmlPage page
293      */
294     private HtmlPage clockAction(String clockAction) throws Exception {
295         DateTime dateTime = new DateTime();
296         if (dateTime.getSecondOfMinute() >= 58
297                 || dateTime.getSecondOfMinute() == 0) {
298             Thread.sleep(4000);
299         }
300         String baseUrl = TkTestConstants.Urls.CLOCK_URL;
301         String actionUrl = baseUrl + "?methodToCall=clockAction&selectedAssignment=30_30_30&currentClockAction=" + clockAction;
302         HtmlPage page = HtmlUnitUtil.gotoPageAndLogin(getWebClient(), actionUrl);
303         Assert.assertNotNull("The login page shouldn't be null", page);
304         Thread.sleep(3000);
305         return page;
306     }
307 
308 
309 }