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.roles.web;
017    
018    import java.util.ArrayList;
019    import java.util.HashMap;
020    import java.util.List;
021    import java.util.Map;
022    
023    import org.apache.log4j.Logger;
024    import org.joda.time.DateTime;
025    import org.joda.time.DateTimeZone;
026    import org.json.simple.JSONArray;
027    import org.json.simple.JSONObject;
028    import org.json.simple.JSONValue;
029    import org.junit.Assert;
030    import org.junit.Test;
031    import org.kuali.hr.time.util.TimeDetailTestUtils;
032    import org.kuali.hr.time.workflow.TimesheetWebTestBase;
033    import org.kuali.hr.util.HtmlUnitUtil;
034    import org.kuali.kpme.core.FunctionalTest;
035    import org.kuali.kpme.core.assignment.Assignment;
036    import org.kuali.kpme.core.calendar.entry.CalendarEntry;
037    import org.kuali.kpme.core.earncode.EarnCode;
038    import org.kuali.kpme.core.service.HrServiceLocator;
039    import org.kuali.kpme.core.util.TKUtils;
040    import org.kuali.kpme.tklm.time.detail.web.TimeDetailActionFormBase;
041    import org.kuali.kpme.tklm.time.service.TkServiceLocator;
042    import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
043    import org.kuali.rice.krad.util.GlobalVariables;
044    
045    import com.gargoylesoftware.htmlunit.WebRequest;
046    import com.gargoylesoftware.htmlunit.WebResponse;
047    import com.gargoylesoftware.htmlunit.html.DomElement;
048    import com.gargoylesoftware.htmlunit.html.HtmlForm;
049    import com.gargoylesoftware.htmlunit.html.HtmlPage;
050    
051    /**
052     * See: https://wiki.kuali.org/display/KPME/Role+Security+Grid
053     */
054    @FunctionalTest
055    public class RoleTimesheetWebIntegrationTest extends TimesheetWebTestBase {
056    
057        private static final Logger LOG = Logger.getLogger(RoleTimesheetWebIntegrationTest.class);
058    
059        // Non Time Entry users (for this test) who have some access to 'fred's'
060        // Time Sheet.
061        private List<String> VALID_NON_ENTRY_USERS = new ArrayList<String>() {{
062            //add fred too.
063            /*add("testuser6");*/ add("frank"); add("fran"); add("edna"); add("fred"); }};
064    
065        // Users with incorrect Department or Work Area for Time Sheet privilege.
066        private List<String> INVALID_NON_ENTRY_USERS = new ArrayList<String>(){{
067            add("testuser1"); add("testuser2"); add("testuser3"); add("testuser4"); }};
068    
069        private TimesheetDocument fredsDocument = null;
070        DateTime asOfDate = new DateTime(2011, 3, 1, 12, 0, 0, 0, TKUtils.getSystemDateTimeZone());
071    
072        @Override
073        /**
074         * This code is called before each test below - allows us to control how far
075         * into the routing process we are for any given level of testing.
076         */
077        public void setUp() throws Exception {
078            super.setUp();
079    
080            String userId = "fred";
081            DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone(userId));
082            
083            CalendarEntry pcd = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDates(userId, asOfDate);
084            Assert.assertNotNull("No PayCalendarDates", pcd);
085            fredsDocument = TkServiceLocator.getTimesheetService().openTimesheetDocument(userId, pcd);
086            String tdocId = fredsDocument.getDocumentId();
087    
088            // Verify the non time entry logins.
089            verifyLogins(fredsDocument);
090    
091            // Verify Fred, and Add Timeblocks
092            HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
093            Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
094    
095            HtmlForm form = page.getFormByName("TimeDetailActionForm");
096            Assert.assertNotNull(form);
097            List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments(userId, JAN_AS_OF_DATE.toLocalDate());
098            Assignment assignment = assignments.get(0);
099    
100            List<EarnCode> earnCodes = TkServiceLocator.getTimesheetService().getEarnCodesForTime(assignment, JAN_AS_OF_DATE.toLocalDate());
101            EarnCode earnCode = earnCodes.get(0);
102            Assert.assertEquals("There should be no existing time blocks.", 0, fredsDocument.getTimeBlocks().size());
103    
104            // 2. Set Timeblock Start and End time
105            // 3/02/2011 - 8:00a to 6:00pm
106            // OVT - 0 Hrs Expected
107            final DateTime start = new DateTime(2011, 3, 2, 8, 0, 0, 0, dateTimeZone);
108            final DateTime end = new DateTime(2011, 3, 2, 13, 0, 0, 0, dateTimeZone);
109    
110            TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(fredsDocument, assignment, earnCode, start, end, null, false, null, true);
111            List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf);
112    
113            Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size());
114            page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), getTimesheetDocumentUrl(tdocId), tdaf);
115            Assert.assertNotNull(page);
116            page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
117    
118            String pageAsText = page.asText();
119            DomElement element = page.getElementById("timeBlockString");
120            Assert.assertNotNull(element);
121            String elementAsText = element.asText();
122            String dataText = page.getElementById("timeBlockString").getFirstChild().getNodeValue();
123            JSONArray jsonData = (JSONArray) JSONValue.parse(dataText);
124            final JSONObject jsonDataObject = (JSONObject) jsonData.get(0);
125            Assert.assertTrue("TimeBlock Data Missing.", checkJSONValues(new JSONObject() {{ put("outer", jsonDataObject); }},
126                    new ArrayList<Map<String, Object>>() {{
127                        add(new HashMap<String, Object>() {{
128                            put("earnCode", "RGN");
129                            put("hours", "5.0");
130                            put("amount", null);
131                        }});
132                    }},
133                    new HashMap<String, Object>() {{
134                        put("earnCode", "RGN");
135                        start.toString();
136                        put("startNoTz", start.toString("yyyy-MM-dd'T'HH:mm:ss"));
137                        put("endNoTz", end.toString("yyyy-MM-dd'T'HH:mm:ss"));
138                        put("title", "SDR1 Work Area");
139                        put("assignment", "30_30_30");
140                    }}
141            ));
142    
143            // Set freds timesheet to have updated info.
144            fredsDocument = TkServiceLocator.getTimesheetService().openTimesheetDocument(userId, pcd);
145        }
146    
147        /*
148         * Tests while Timesheet is in INITIATED state.
149         */
150    
151        @Test
152        public void testInitiatedTimesheetIsVisibleByAll() throws Exception {
153            // test valid users
154            for (String uid : VALID_NON_ENTRY_USERS) {
155                LOG.info("Testing visibility for " + uid);
156                HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), uid, fredsDocument.getDocumentId(), true);
157                Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
158            }
159        }
160    
161        @Test
162        public void testInitiatedTimesheetIsNotVisible() throws Exception {
163            for (String uid : INVALID_NON_ENTRY_USERS) {
164                LOG.info("Testing visibility for " + uid);
165                HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), uid, fredsDocument.getDocumentId(), false);
166                //HtmlUnitUtil.createTempFile(page, "badlogin");
167                Assert.assertTrue("Should not have access", page.asText().contains("You are not authorized to access this portion of the application."));
168            }
169        }
170    
171        public void testInitiatedTimesheetEditable(String userId) throws Exception {
172            // admin, add one timeblock
173            String tdocId = fredsDocument.getDocumentId();
174            HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
175            LOG.debug(page.asText());
176            //HtmlUnitUtil.createTempFile(page, "loggedin");
177            Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
178    
179            HtmlForm form = page.getFormByName("TimeDetailActionForm");
180            Assert.assertNotNull(form);
181            List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments("fred", JAN_AS_OF_DATE.toLocalDate());
182            Assignment assignment = assignments.get(0);
183    
184            List<EarnCode> earnCodes = TkServiceLocator.getTimesheetService().getEarnCodesForTime(assignment, JAN_AS_OF_DATE.toLocalDate());
185            EarnCode earnCode = earnCodes.get(0);
186    
187            Assert.assertEquals("There should be one existing time block.", 1, fredsDocument.getTimeBlocks().size());
188    
189            DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone(userId));
190            final DateTime start = new DateTime(2011, 3, 2, 13, 0, 0, 0, dateTimeZone);
191            final DateTime end = new DateTime(2011, 3, 2, 18, 0, 0, 0, dateTimeZone);
192            TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(fredsDocument, assignment, earnCode, start, end, null, false, null, true);
193    
194            List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf);
195            Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size());
196            String targetedTimesheetUrl = getTargetedTimesheetDocumentUrl(tdocId,"fred");
197            page = getWebClient().getPage(targetedTimesheetUrl);
198            Assert.assertNotNull(page);
199            String submitDetailsUrl = BASE_DETAIL_URL + tdocId;
200            //The following page does not contain timeBlockString data after KPME-2959.
201            page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), submitDetailsUrl, tdaf);
202            Assert.assertNotNull(page);
203            //This extra page get was needed for KPME-2959.
204            page = getWebClient().getPage(targetedTimesheetUrl);
205            HtmlUnitUtil.createTempFile(page, "initiatetest");
206            String dataText = page.getElementById("timeBlockString").getFirstChild().getNodeValue();
207            JSONArray jsonData = (JSONArray) JSONValue.parse(dataText);
208            final JSONObject jsonDataObject = (JSONObject) jsonData.get(1);
209            Assert.assertTrue("TimeBlock Data Missing.", checkJSONValues(new JSONObject() {{ put("outer", jsonDataObject); }},
210                    new ArrayList<Map<String, Object>>() {{
211                        add(new HashMap<String, Object>() {{
212                            put("earnCode", "RGN");
213                            put("hours", "5.0");
214                            put("amount", null);
215                        }});
216                    }},
217                    new HashMap<String, Object>() {{
218                        put("earnCode", "RGN");
219                        put("startNoTz", start.toString("yyyy-MM-dd'T'HH:mm:ss"));
220                        put("endNoTz", end.toString("yyyy-MM-dd'T'HH:mm:ss"));
221                        put("title", "SDR1 Work Area");
222                        put("assignment", "30_30_30");
223                    }}
224            ));
225        }
226    
227        public void testInitiatedTimesheetNotEditable(String userId) throws Exception {
228            // admin, add one timeblock
229            String tdocId = fredsDocument.getDocumentId();
230            HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
231            //HtmlUnitUtil.createTempFile(page, "loggedin");
232            Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
233    
234            HtmlForm form = page.getFormByName("TimeDetailActionForm");
235            Assert.assertNotNull(form);
236            List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments("fred", JAN_AS_OF_DATE.toLocalDate());
237            Assignment assignment = assignments.get(0);
238    
239            List<EarnCode> earnCodes = TkServiceLocator.getTimesheetService().getEarnCodesForTime(assignment, JAN_AS_OF_DATE.toLocalDate());
240            EarnCode earnCode = earnCodes.get(0);
241    
242            Assert.assertEquals("There should be one existing time block.", 1, fredsDocument.getTimeBlocks().size());
243    
244            DateTimeZone dateTimeZone = DateTimeZone.forID(HrServiceLocator.getTimezoneService().getUserTimezone(userId));
245            DateTime start = new DateTime(2011, 3, 4, 8, 0, 0, 0, dateTimeZone);
246            DateTime end = new DateTime(2011, 3, 4, 13, 0, 0, 0, dateTimeZone);
247            TimeDetailActionFormBase tdaf = TimeDetailTestUtils.buildDetailActionForm(fredsDocument, assignment, earnCode, start, end, null, false, null, true);
248            List<String> errors = TimeDetailTestUtils.setTimeBlockFormDetails(form, tdaf);
249            Assert.assertEquals("There should be no errors in this time detail submission", 0, errors.size());
250            page = TimeDetailTestUtils.submitTimeDetails(getWebClient(), userId, getTimesheetDocumentUrl(tdocId), tdaf);
251            Assert.assertNotNull(page);
252            HtmlUnitUtil.createTempFile(page, "aftertdadd");
253            Assert.assertTrue("Should not have access", page.asText().contains("You are not authorized to access this portion of the application."));
254        }
255    
256        @Test
257        public void testInitiatedTimesheetIsEditableByAdmin() throws Exception {
258            testInitiatedTimesheetEditable("admin");
259        }
260    
261        @Test
262        public void testInitiatedTimesheetIsEditableByApprover() throws Exception {
263            testInitiatedTimesheetEditable("fran");
264        }
265    
266        @Test
267        public void testInitiatedTimesheetIsEditableByReviewer() throws Exception {
268            testInitiatedTimesheetEditable("frank");
269        }
270    
271        @Test
272        public void testInitiatedTimesheetIs_NOT_EditableByViewOnly() throws Exception {
273            testInitiatedTimesheetNotEditable("edna");
274        }
275    
276        @Test
277        public void testInitiatedTimesheetIs_NOT_EditableByDeptAdmin() throws Exception {
278            testInitiatedTimesheetNotEditable("testuser6");
279        }
280    
281    
282        @Test
283        public void testInitiatedTimesheetSubmitUser() throws Exception {
284            // User,
285            // Check for submit button.
286            // Click Button
287        }
288    
289        @Test
290        public void testInitiatedTimesheetSubmitAdmin() throws Exception {
291            // Admin
292            // Check for submit button.
293            // Click Button
294        }
295    
296        @Test
297        public void testInitiatedTimesheetSubmitApprover() throws Exception {
298            // Approver
299            // Check for submit button.
300            // Click Button
301        }
302    
303    
304        @Test
305        public void testInitiatedTimesheetIs_NOT_SubmittableByUsers() throws Exception {
306            // DeptAdmin, View Only, Reviewer
307            // Check that submit button is not present.
308        }
309    
310        /*
311         * Test for ENROUTE state.
312         */
313    
314        @Test
315        public void testEnrouteTimesheetIsVisibleByAll() throws Exception {
316            // test valid users
317        }
318    
319        @Test
320        public void testEnrouteTimesheetIsNotVisible() throws Exception {
321            // make sure invalid users do not have access
322        }
323    
324        @Test
325        public void testEnrouteTimesheetIsEditableByAdmin() throws Exception {
326            // admin, add one timeblock
327        }
328    
329        @Test
330        public void testEnrouteTimesheetIsEditableByApprover() throws Exception {
331            // approver, add one timeblock
332        }
333    
334        @Test
335        public void testEnrouteTimesheetIsEditableByReviewer() throws Exception {
336            // reviewer add one timeblock.
337        }
338    
339        @Test
340        public void testEnrouteTimesheetIs_NOT_EditableByViewOnly() throws Exception {
341        }
342    
343        @Test
344        public void testEnrouteTimesheetIs_NOT_EditableByDeptAdmin() throws Exception {
345        }
346    
347    
348        @Test
349        public void testEnrouteTimesheet_NOT_Approvable() throws Exception {
350            // User, Reviewer, View Only, Dept Admin
351            // Check for approve button
352        }
353    
354        @Test
355        public void testEnrouteTimesheetApproveAdmin() throws Exception {
356            // Admin
357            // Check for approve button.
358            // Click Button
359        }
360    
361        @Test
362        public void testEnrouteTimesheetApproveApprover() throws Exception {
363            // Approver
364            // Check for approve button.
365            // Click Button
366        }
367    
368        @Test
369        public void testEnrouteTimesheetIs_NOT_SubmittableByUsers() throws Exception {
370            // DeptAdmin, View Only, Reviewer
371            // Check that submit button is not present.
372        }
373    
374    
375        /*
376         * Final State
377         */
378    
379        @Test
380        public void testFinalTimesheetIsVisibleByAll() throws Exception {
381            // test valid users
382        }
383    
384        @Test
385        public void testFinalTimesheetIsNotVisible() throws Exception {
386            // make sure invalid users do not have access
387        }
388    
389        @Test
390        public void testFinalTimesheetIsNotEditable() throws Exception {
391            // by everyone but admin
392        }
393    
394        @Test
395        public void testFinalTimesheetIsAdminEditable() throws Exception {
396            // admin, add timeblock.
397        }
398    
399        /**
400         * Verifies that each admin/approver/reviewer login is active for this test.
401         */
402        private void verifyLogins(TimesheetDocument tdoc) throws Exception {
403            for (String userId : VALID_NON_ENTRY_USERS) {
404                String tdocId = tdoc.getDocumentId();
405                HtmlPage page = loginAndGetTimeDetailsHtmlPage(getWebClient(), userId, tdocId, true);
406                Assert.assertTrue("Calendar not loaded.", page.asText().contains("March 2011"));
407            }
408        }
409    
410    }