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 */
016package org.kuali.hr.time.roles.web;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.log4j.Logger;
024import org.joda.time.DateTime;
025import org.joda.time.DateTimeZone;
026import org.json.simple.JSONArray;
027import org.json.simple.JSONObject;
028import org.json.simple.JSONValue;
029import org.junit.Assert;
030import org.junit.Ignore;
031import org.junit.Test;
032import org.kuali.hr.time.util.TimeDetailTestUtils;
033import org.kuali.hr.time.workflow.TimesheetWebTestBase;
034import org.kuali.hr.util.HtmlUnitUtil;
035import org.kuali.kpme.core.FunctionalTest;
036import org.kuali.kpme.core.assignment.Assignment;
037import org.kuali.kpme.core.calendar.entry.CalendarEntry;
038import org.kuali.kpme.core.earncode.EarnCode;
039import org.kuali.kpme.core.service.HrServiceLocator;
040import org.kuali.kpme.core.util.TKUtils;
041import org.kuali.kpme.tklm.time.detail.web.TimeDetailActionFormBase;
042import org.kuali.kpme.tklm.time.service.TkServiceLocator;
043import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
044import org.kuali.rice.krad.util.GlobalVariables;
045
046import com.gargoylesoftware.htmlunit.WebRequest;
047import com.gargoylesoftware.htmlunit.WebResponse;
048import com.gargoylesoftware.htmlunit.html.DomElement;
049import com.gargoylesoftware.htmlunit.html.HtmlForm;
050import com.gargoylesoftware.htmlunit.html.HtmlPage;
051
052/**
053 * See: https://wiki.kuali.org/display/KPME/Role+Security+Grid
054 */
055@FunctionalTest
056public 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}