net.rrm.ehour.ui.timesheet.panel.TimesheetPanelTest.java Source code

Java tutorial

Introduction

Here is the source code for net.rrm.ehour.ui.timesheet.panel.TimesheetPanelTest.java

Source

/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package net.rrm.ehour.ui.timesheet.panel;

import com.google.common.collect.Lists;
import net.rrm.ehour.data.DateRange;
import net.rrm.ehour.domain.*;
import net.rrm.ehour.project.status.ProjectAssignmentStatus;
import net.rrm.ehour.timesheet.dto.WeekOverview;
import net.rrm.ehour.timesheet.service.IOverviewTimesheet;
import net.rrm.ehour.timesheet.service.IPersistTimesheet;
import net.rrm.ehour.timesheet.service.TimesheetLockService;
import net.rrm.ehour.ui.common.BaseSpringWebAppTester;
import net.rrm.ehour.ui.common.session.EhourWebSession;
import net.rrm.ehour.ui.timesheet.dto.Timesheet;
import net.rrm.ehour.ui.timesheet.model.TimesheetContainer;
import net.rrm.ehour.ui.timesheet.model.TimesheetModel;
import net.rrm.ehour.ui.timesheet.panel.dailycomments.DailyCommentPanelFactory;
import net.rrm.ehour.ui.timesheet.panel.renderer.SectionRenderFactory;
import net.rrm.ehour.ui.timesheet.panel.renderer.SectionRenderFactoryCollection;
import net.rrm.ehour.ui.timesheet.panel.renderer.TimesheetIconRenderFactoryCollection;
import net.rrm.ehour.ui.timesheet.panel.weeklycomment.WeeklyCommentPanelRenderFactory;
import net.rrm.ehour.user.service.UserService;
import org.apache.wicket.Component;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.util.tester.FormTester;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.*;

import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class TimesheetPanelTest extends BaseSpringWebAppTester {
    private static final String TIMESHEET_PATH = "panel:timesheetFrame:timesheetFrame_body:timesheetForm";
    private static final String DAY1_PATH = "blueFrame:blueFrame_body:customers:0:rows:0:days:0";
    private static final String DAY1_FULL_PATH = TIMESHEET_PATH + ":" + DAY1_PATH;
    private static final User USER = new User(1);
    private static final String DAY_INPUT = ":day:day";

    @Mock
    private IPersistTimesheet persistTimesheet;

    @Mock
    private IOverviewTimesheet overviewTimesheet;

    @Mock
    private UserService userService;

    @Mock
    private TimesheetLockService lockService;

    private DateTime jodaNow = DateTime.now().withTimeAtStartOfDay();
    private Date dateNow = jodaNow.toDate();
    private GregorianCalendar calNow = jodaNow.toGregorianCalendar();
    private Date tomorrow = jodaNow.plusDays(1).toDate();
    private final ArrayList<Date> tomorrowAsList = Lists.newArrayList(tomorrow);

    @Before
    public void setup() {
        getConfig().setCompleteDayHours(8l);
        EhourWebSession.getSession().reloadConfig();

        getMockContext().putBean(persistTimesheet);
        getMockContext().putBean(overviewTimesheet);
        getMockContext().putBean("userService", userService);
        getMockContext().putBean(lockService);

        getMockContext().putBean(new TimesheetModel());
        TimesheetIconRenderFactoryCollection iconRenderFactoryCollection = new TimesheetIconRenderFactoryCollection(
                Lists.newArrayList(new DailyCommentPanelFactory()));
        getMockContext().putBean(iconRenderFactoryCollection);

        SectionRenderFactoryCollection sectionRenderFactoryCollection = new SectionRenderFactoryCollection(
                Lists.<SectionRenderFactory>newArrayList(new WeeklyCommentPanelRenderFactory()));
        getMockContext().putBean(sectionRenderFactoryCollection);
    }

    @Test
    public void addDayComment() {
        startAndReplayWithDefaultWeekOverview();

        final String comment = "commentaar";

        ModalWindow window = openCommentWindow(DAY1_FULL_PATH);
        assertTrue(window.isShown());

        FormTester timesheetFormTester = tester.newFormTester(TIMESHEET_PATH);
        timesheetFormTester.setValue(DAY1_PATH + ":options:1:dayWin:content:comment", comment);

        tester.executeAjaxEvent(DAY1_FULL_PATH + ":options:1:dayWin:content:comment", "onchange");
        tester.executeAjaxEvent(DAY1_FULL_PATH + ":options:1:dayWin:content:submit", "onclick");

        Timesheet timesheet = ((TimesheetContainer) tester.getComponentFromLastRenderedPage("panel")
                .getDefaultModelObject()).getTimesheet();
        assertEquals(comment, timesheet.getTimesheetEntries().get(0).getComment());

        tester.assertNoErrorMessage();
    }

    private ModalWindow openCommentWindow(String path) {
        ModalWindow window = (ModalWindow) tester.getComponentFromLastRenderedPage(path + ":options:1:dayWin");
        tester.executeAjaxEvent(path + ":options:1:commentLink", "onclick");
        return window;
    }

    @Test
    public void addDayCommentCancelled() {
        startAndReplayWithDefaultWeekOverview();

        final String comment = "commentaar";

        clickDay1();

        FormTester formTester = tester.newFormTester(TIMESHEET_PATH);
        formTester.setValue(DAY1_PATH + ":options:1:dayWin:content:comment", comment);

        tester.executeAjaxEvent(DAY1_FULL_PATH + ":options:1:dayWin:content:comment", "onchange");
        tester.executeAjaxEvent(DAY1_FULL_PATH + ":options:1:dayWin:content:cancel", "onclick");

        Timesheet timesheet = ((TimesheetContainer) tester.getComponentFromLastRenderedPage("panel")
                .getDefaultModelObject()).getTimesheet();
        assertNull(timesheet.getTimesheetEntries().get(0).getComment());

        tester.assertNoErrorMessage();
    }

    private void clickDay1() {
        tester.executeAjaxEvent(DAY1_FULL_PATH + ":options:1:commentLink", "onclick");
    }

    @Test
    public void shouldBookAllHours() {
        startAndReplayWithDefaultWeekOverview();

        tester.executeAjaxEvent(TIMESHEET_PATH + ":blueFrame:blueFrame_body:customers:0:rows:0:bookWholeWeek",
                "onclick");
        tester.assertNoErrorMessage();

        Label grandTotalLabel = (Label) tester
                .getComponentFromLastRenderedPage(TIMESHEET_PATH + ":blueFrame:blueFrame_body:grandTotal");
        assertEquals(40f, (Float) grandTotalLabel.getDefaultModelObject(), 0.01f);

        tester.assertNoErrorMessage();
    }

    @Test
    public void updateCounts() {
        startAndReplayWithDefaultWeekOverview();

        FormTester formTester = tester.newFormTester(TIMESHEET_PATH);

        formTester.setValue(DAY1_PATH + DAY_INPUT, "12");
        tester.executeAjaxEvent(DAY1_FULL_PATH + DAY_INPUT, "onblur");
        tester.assertNoErrorMessage();

        Label grandTotalLabel = (Label) tester
                .getComponentFromLastRenderedPage(TIMESHEET_PATH + ":blueFrame:blueFrame_body:grandTotal");
        assertEquals(12f, (Float) grandTotalLabel.getDefaultModelObject(), 0.01f);
    }

    @Test
    public void moveToNextWeek() {
        startAndReplayWithDefaultWeekOverview();

        tester.executeAjaxEvent("panel:timesheetFrame:title:nextWeek", "onclick");

        Calendar cal = getWebApp().getSession().getNavCalendar();

        Calendar now = GregorianCalendar.getInstance();
        now.add(Calendar.DAY_OF_YEAR, 1);

        assertTrue(now.getTime().before(cal.getTime()));
    }

    @Test
    public void shouldNotResendUnmodifiedEntries() {
        startAndReplayWithDefaultWeekOverview();

        FormTester formTester = tester.newFormTester(TIMESHEET_PATH);

        formTester.setValue(DAY1_PATH + DAY_INPUT, "12");
        tester.executeAjaxEvent(DAY1_FULL_PATH + DAY_INPUT, "onblur");
        tester.assertNoErrorMessage();
        tester.assertContains(DAY1_PATH + DAY_INPUT);

        //changing another field should not resend the unmodified day1
        formTester.setValue("blueFrame:blueFrame_body:customers:0:rows:0:days:1:day:day", "8");
        tester.executeAjaxEvent(TIMESHEET_PATH + ":blueFrame:blueFrame_body:customers:0:rows:0:days:1:day:day",
                "onblur");
        tester.assertNoErrorMessage();
        tester.assertContains("blueFrame:blueFrame_body:customers:0:rows:0:days:1:day:day");
    }

    @Test
    public void shouldResetErrorState() {
        startAndReplayWithDefaultWeekOverview();

        FormTester formTester = tester.newFormTester(TIMESHEET_PATH);

        formTester.setValue(DAY1_PATH + DAY_INPUT, "12");
        tester.executeAjaxEvent(DAY1_FULL_PATH + DAY_INPUT, "onblur");
        tester.assertNoErrorMessage();
        tester.assertContains(DAY1_PATH + DAY_INPUT);
        tester.assertContainsNot("color: #ff0000");

        formTester.setValue(DAY1_PATH + DAY_INPUT, "ff");
        tester.executeAjaxEvent(DAY1_FULL_PATH + DAY_INPUT, "onblur");
        tester.assertContains(DAY1_PATH + DAY_INPUT);
        tester.assertContains("color: #ff0000");
        tester.assertErrorMessages("day.IConverter.Float");

        formTester.setValue(DAY1_PATH + DAY_INPUT, "1");
        tester.executeAjaxEvent(DAY1_FULL_PATH + DAY_INPUT, "onblur");
        tester.assertContains(DAY1_PATH + DAY_INPUT);
        tester.assertContainsNot("color: #ff0000");
    }

    @SuppressWarnings("unchecked")
    @Test
    public void shouldSubmitSuccessful() {
        when(persistTimesheet.persistTimesheetWeek(any(Collection.class), any(TimesheetComment.class),
                any(DateRange.class), any(User.class))).thenReturn(new ArrayList<ProjectAssignmentStatus>());

        startAndReplayWithDefaultWeekOverview();

        tester.executeAjaxEvent(TIMESHEET_PATH + ":submitButton", "onclick");

        tester.assertNoErrorMessage();
    }

    @Test
    public void shouldDisableInputForLockedDays() {
        startWithLockedDays(Arrays.asList(tomorrow));

        tester.assertComponent(TIMESHEET_PATH + ":blueFrame:blueFrame_body:customers:0:rows:0:days:1:day:day",
                Label.class);
        tester.assertComponent(TIMESHEET_PATH + ":blueFrame:blueFrame_body:customers:0:rows:0:days:2:day:day",
                TimesheetTextField.class);

        tester.assertNoErrorMessage();
    }

    @Test
    public void shouldDisableDailyCommentInputForLockedDaysWithExistingComment() {
        // given
        List<Date> lockedDays = tomorrowAsList;
        startWithLockedDays(lockedDays);

        DateRange nextWeekRange = new DateRange(dateNow, jodaNow.plusWeeks(1).toDate());

        TimesheetEntry timesheetEntry = TimesheetEntryObjectMother.createTimesheetEntry(1, tomorrow, 5);
        timesheetEntry.setComment("Comment");

        List<TimesheetEntry> entries = Arrays.asList(timesheetEntry);
        List<ProjectAssignment> assignments = Arrays
                .asList(ProjectAssignmentObjectMother.createProjectAssignment(1));

        WeekOverview overview = new WeekOverview(entries, null, assignments, nextWeekRange, USER, lockedDays);

        whenDefaultWeekOverview(overview);

        // when
        tester.startComponentInPage(new TimesheetPanel("panel", USER, new GregorianCalendar()));

        // then
        openCommentWindow(TIMESHEET_PATH + ":blueFrame:blueFrame_body:customers:0:rows:0:days:1");

        tester.assertComponent(
                TIMESHEET_PATH
                        + ":blueFrame:blueFrame_body:customers:0:rows:0:days:1:options:1:dayWin:content:comment",
                Label.class);

        tester.assertNoErrorMessage();
        tester.assertNoInfoMessage();
    }

    @Test
    public void shouldHideCommentInputLinkForLockedDaysWithoutComment() {
        startWithLockedDays(tomorrowAsList);

        Component commentLink = tester.getComponentFromLastRenderedPage(
                TIMESHEET_PATH + ":blueFrame:blueFrame_body:customers:0:rows:0:days:1:options:1:commentLink");
        assertNull(commentLink); // null = not visible...

        tester.assertNoErrorMessage();
    }

    @Test
    public void shouldAddLockedIconInDayForLockedDay() {
        startWithLockedDays(tomorrowAsList);

        String path = TIMESHEET_PATH + ":blueFrame:blueFrame_body:day2Label:lock:lockedContainer";
        tester.assertVisible(path);

        tester.assertNoErrorMessage();
    }

    @Test
    public void shouldHideBookWholeWeekIconWhenDisabledInConfig() {
        webApp.setEnableBookWholeWeek(false);

        startAndReplayWithDefaultWeekOverview();

        Component book = tester.getComponentFromLastRenderedPage(
                TIMESHEET_PATH + ":blueFrame:blueFrame_body:customers:0:rows:0:bookWholeWeek");
        // not visible = null
        assertNull(book);
    }

    @Test
    public void shouldHideBookWholeWeekIconWhenADayIsLocked() {
        startWithLockedDays(tomorrowAsList);

        Component book = tester.getComponentFromLastRenderedPage(
                TIMESHEET_PATH + ":blueFrame:blueFrame_body:customers:0:rows:0:bookWholeWeek");
        // not visible = null
        assertNull(book);
    }

    @Test
    public void shouldHideStoreButtonsWhenWholeWeekIsLocked() {
        List<Date> dates = Lists.newArrayList();

        for (int i = 0; i < 8; i++) {
            dates.add(jodaNow.plusDays(i).toDate());
        }

        startWithLockedDays(dates);

        assertNull(tester.getComponentFromLastRenderedPage(TIMESHEET_PATH + ":submitButton"));
        assertNull(tester
                .getComponentFromLastRenderedPage(TIMESHEET_PATH + ":blueFrame:blueFrame_body:submitButtonTop"));
    }

    private void startAndReplayWithDefaultWeekOverview() {
        startWithLockedDays(Lists.<Date>newArrayList());
    }

    private void startWithLockedDays(List<Date> lockedDays) {
        whenDefaultWeekOverview(withDefaultWeekOverview(lockedDays));

        tester.startComponentInPage(new TimesheetPanel("panel", USER, calNow));
    }

    private void whenDefaultWeekOverview(WeekOverview overview) {
        when(overviewTimesheet.getWeekOverview(any(User.class), any(Calendar.class))).thenReturn(overview);
    }

    private WeekOverview withDefaultWeekOverview(List<Date> lockedDates) {
        DateRange nextWeekRange = new DateRange(dateNow, jodaNow.plusWeeks(1).toDate());

        List<TimesheetEntry> entries = Arrays
                .asList(TimesheetEntryObjectMother.createTimesheetEntry(1, dateNow, 5));
        List<ProjectAssignment> assignments = Arrays
                .asList(ProjectAssignmentObjectMother.createProjectAssignment(1));

        return new WeekOverview(entries, null, assignments, nextWeekRange, USER, lockedDates);
    }
}