View Javadoc

1   /**
2    * Copyright 2004-2013 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.sql.Timestamp;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.joda.time.DateTime;
27  import org.junit.Assert;
28  import org.junit.Ignore;
29  import org.junit.Test;
30  import org.kuali.hr.test.KPMETestCase;
31  import org.kuali.hr.time.clocklog.ClockLog;
32  import org.kuali.hr.time.graceperiod.rule.GracePeriodRule;
33  import org.kuali.hr.time.service.base.TkServiceLocator;
34  import org.kuali.hr.time.test.HtmlUnitUtil;
35  import org.kuali.hr.time.test.TkTestConstants;
36  import org.kuali.hr.time.timeblock.TimeBlock;
37  import org.kuali.hr.time.timeblock.TimeHourDetail;
38  import org.kuali.hr.time.timesheet.TimesheetDocument;
39  import org.kuali.hr.time.util.TKUtils;
40  import org.kuali.hr.time.util.TkConstants;
41  import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
42  import org.kuali.rice.krad.service.KRADServiceLocator;
43  
44  import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
45  import com.gargoylesoftware.htmlunit.WebClient;
46  import com.gargoylesoftware.htmlunit.html.HtmlElement;
47  import com.gargoylesoftware.htmlunit.html.HtmlPage;
48  
49  
50  public class ClockWebTest extends KPMETestCase {
51  
52      private String tbId;
53  
54      public Long maxDocumentId() {
55          Collection aCol = KRADServiceLocator.getBusinessObjectService().findAll(TimesheetDocumentHeader.class);
56          Long maxId = new Long(-1);
57          Iterator<TimesheetDocumentHeader> itr = aCol.iterator();
58          while (itr.hasNext()) {
59              TimesheetDocumentHeader tdh = itr.next();
60              Long temp = new Long(tdh.getDocumentId());
61              if (temp > maxId) {
62                  maxId = temp;
63              }
64          }
65          return maxId;
66      }
67  
68      public Long maxTimeBlockId() {
69          Collection aCol = KRADServiceLocator.getBusinessObjectService().findAll(TimeBlock.class);
70          Long maxId = new Long(-1);
71          Iterator<TimeBlock> itr = aCol.iterator();
72          while (itr.hasNext()) {
73              TimeBlock tb = itr.next();
74              Long temp = new Long(tb.getTkTimeBlockId());
75              if (temp > maxId) {
76                  maxId = temp;
77              }
78          }
79          return maxId;
80      }
81  
82      public void createTB() {
83          TimeBlock timeBlock = new TimeBlock();
84          timeBlock.setUserPrincipalId("admin");
85          timeBlock.setJobNumber(2L);
86          timeBlock.setWorkArea(1234L);
87          timeBlock.setTask(1L);
88          timeBlock.setEarnCode("RGN");
89          Timestamp beginTimestamp = new Timestamp(System.currentTimeMillis());
90          timeBlock.setBeginTimestamp(beginTimestamp);
91          Timestamp endTimestamp = new Timestamp(System.currentTimeMillis());
92          timeBlock.setEndTimestamp(endTimestamp);
93          TimeHourDetail timeHourDetail = new TimeHourDetail();
94          timeHourDetail.setEarnCode("RGN");
95          timeHourDetail.setHours(new BigDecimal(2.0));
96          timeBlock.getTimeHourDetails().add(timeHourDetail);
97          timeBlock.setHours(new BigDecimal(2.0));
98          List<TimeBlock> tbList = new ArrayList<TimeBlock>();
99          String documentId = this.maxDocumentId().toString();
100         timeBlock.setDocumentId(documentId);
101         tbList.add(timeBlock);
102         TkServiceLocator.getTimeBlockService().saveTimeBlocks(tbList);
103 
104         tbId = timeBlock.getTkTimeBlockId();
105         TimesheetDocument td = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
106         td.setTimeBlocks(tbList);
107 
108     }
109 
110     @Ignore
111     public void testDistributeTB() throws Exception {
112         String baseUrl = TkTestConstants.Urls.CLOCK_URL;
113         HtmlPage page = HtmlUnitUtil.gotoPageAndLogin(baseUrl);
114         Assert.assertNotNull(page);
115         Assert.assertTrue("Clock Page contains Distribute Button", page.asText().contains("Distribute Time Blocks"));
116         this.createTB();
117         this.setWebClient(page.getWebClient());
118         HtmlElement element = page.getElementByName("distributeTime");
119         Assert.assertNotNull(element);
120 //	  	HtmlPage testPage1 = element.click();
121 //	  	assertTrue("Distribute Page contains Close button", testPage1.asText().contains("Close"));
122 //        assertTrue("Distribute Page contains Close button", testPage1.asText().contains("Edit"));
123 
124         // timeDistribute.jsp
125         String distributeUrl = baseUrl + "?methodToCall=distributeTimeBlocks";
126         HtmlPage page1 = HtmlUnitUtil.gotoPageAndLogin(distributeUrl);
127         Assert.assertTrue("Distribute Page contains Close button", page1.asText().contains("Close"));
128         Assert.assertTrue("Distribute Page contains Close button", page1.asText().contains("Edit"));
129 
130         element = page1.getElementByName("editTimeBlock");
131         Assert.assertNotNull(element);
132         Assert.assertTrue("Onclick attribute of Edit button contains", element.getAttribute("onclick").contains("Clock.do?methodToCall=editTimeBlock&editTimeBlockId="));
133 
134         if (tbId == null) {
135             tbId = this.maxTimeBlockId().toString();
136         }
137 
138         //editTimeBlock.jsp
139         String editUrl = baseUrl + "?methodToCall=editTimeBlock&editTimeBlockId=" + tbId;
140         HtmlPage page3 = HtmlUnitUtil.gotoPageAndLogin(editUrl);
141 
142         // editTimeBlock.jsp
143         Assert.assertTrue("Edit Time Blocks Page contains Cancel button", page3.asText().contains("Add"));
144         Assert.assertTrue("Edit Time Blocks Page contains Save button", page3.asText().contains("Save"));
145         Assert.assertTrue("Edit Time Blocks Page contains Cancel button", page3.asText().contains("Cancel"));
146 
147         element = page3.getElementByName("addTimeBlock");
148         Assert.assertNotNull(element);
149         Assert.assertTrue("Onclick attribute of Add button contains", element.getAttribute("onclick").contains("javascript: addTimeBlockRow(this.form);"));
150 
151         this.setWebClient(page3.getWebClient());
152 
153 //	  	HtmlPage page4 = element.click();
154 //	  	assertTrue("Edit Time Blocks Page contains Cancel button", page4.asText().contains("Add"));
155 
156     }
157 
158     public void setWebClient(WebClient webClient) {
159         webClient.setJavaScriptEnabled(true);
160         webClient.setThrowExceptionOnScriptError(false);
161         webClient.setAjaxController(new NicelyResynchronizingAjaxController());
162         webClient.waitForBackgroundJavaScript(10000);
163     }
164 
165     /**
166      * This test is to :
167      * 1) make sure the seconds on clockTimestamp and timestamp are preserved when there is no grace period rule.
168      * 2) the clock in / out button is correctly rendered
169      *
170      * @throws Exception
171      */
172     @Test
173     public void testClockActionWithoutGracePeriodRule() throws Exception {
174         // Make sure there is no active grace period rule
175         GracePeriodRule gpr = TkServiceLocator.getGracePeriodService().getGracePeriodRule(TKUtils.getCurrentDate());
176         if (gpr != null && gpr.isActive()) {
177             gpr.setActive(false);
178             KRADServiceLocator.getBusinessObjectService().save(gpr);
179         }
180 
181         // Clock in
182         clockIn();
183         // Make sure clock out button is rendered
184         ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin");
185         // Make sure both timestamps preserve seconds
186         Assert.assertTrue("The seconds on clock timestamp should be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() != 0);
187         Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0);
188 
189         // Clock out
190         clockOut();
191         // Make sure both timestamps preserve seconds
192         lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin");
193         Assert.assertTrue("The seconds on clock timestamp should be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() != 0);
194         Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0);
195     }
196 
197     @Test
198     public void testClockActionWithGracePeriodRule() throws Exception {
199         //clean clock logs
200         KRADServiceLocator.getBusinessObjectService().deleteMatching(ClockLog.class, Collections.singletonMap("principalId", "admin"));
201         GracePeriodRule gpr = new GracePeriodRule();
202         //gpr.setTkGracePeriodRuleId("1");
203         gpr.setEffectiveDate(TKUtils.createDate(1, 1, 2010, 0, 0, 0));
204         gpr.setHourFactor(new BigDecimal(3));
205         gpr.setTimestamp(new Timestamp(System.currentTimeMillis()));
206         
207         gpr.setActive(true);
208         KRADServiceLocator.getBusinessObjectService().save(gpr);
209 
210         // Clock in
211         clockIn();
212         // Make sure clock out button is rendered
213         ClockLog lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin");
214         // Make sure both timestamps preserve seconds
215         Assert.assertTrue("The seconds on clock timestamp should NOT be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() == 0);
216         Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0);
217 
218         // Clock out
219         clockOut();
220         // Make sure both timestamps preserve seconds
221         lastClockLog = TkServiceLocator.getClockLogService().getLastClockLog("admin");
222         Assert.assertTrue("The seconds on clock timestamp should NOT be preserved", new DateTime(lastClockLog.getClockTimestamp().getTime()).getSecondOfMinute() == 0);
223         Assert.assertTrue("The seconds on timestamp should be preserved", new DateTime(lastClockLog.getTimestamp().getTime()).getSecondOfMinute() != 0);
224 
225 
226     }
227 
228     private HtmlPage clockIn() throws Exception {
229 
230         // Clock in
231         HtmlPage page = clockAction(TkConstants.CLOCK_IN);
232 
233         // Make sure clock in button is rendered
234         HtmlUnitUtil.createTempFile(page);
235         Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Clock Out"));
236         Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Take Lunch"));
237 
238         return page;
239     }
240 
241     private HtmlPage clockOut() throws Exception {
242         DateTime dateTime = new DateTime();
243         if (dateTime.getSecondOfMinute() >= 58
244                 || dateTime.getSecondOfMinute() == 0) {
245             Thread.sleep(4000);
246         }
247         // Clock out
248         HtmlPage page = clockAction(TkConstants.CLOCK_OUT);
249 
250         // Make sure clock in button is rendered
251         HtmlUnitUtil.createTempFile(page);
252         Assert.assertTrue("The clock out button should have displayed", page.asText().contains("Clock In"));
253 
254         return page;
255     }
256 
257     /**
258      * This method is used for clocking in and out.
259      * For some reason, htmlunit couldn't click the clock action button correctly.
260      * It's probably because we bind a onClick event to the button instead of submitting the form.
261      *
262      * @param clockAction
263      * @return HtmlPage page
264      */
265     private HtmlPage clockAction(String clockAction) throws Exception {
266         DateTime dateTime = new DateTime();
267         if (dateTime.getSecondOfMinute() >= 58
268                 || dateTime.getSecondOfMinute() == 0) {
269             Thread.sleep(4000);
270         }
271         String baseUrl = TkTestConstants.Urls.CLOCK_URL;
272         String actionUrl = baseUrl + "?methodToCall=clockAction&selectedAssignment=30_30_30&currentClockAction=" + clockAction;
273         HtmlPage page = HtmlUnitUtil.gotoPageAndLogin(actionUrl);
274         Assert.assertNotNull("The login page shouldn't be null", page);
275         Thread.sleep(3000);
276         return page;
277     }
278 
279 
280 }