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