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