/* * Copyright (c) 2005-2011 Grameen Foundation USA * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * See also http://www.apache.org/licenses/LICENSE-2.0.html for an * explanation of the license and how it is applied. */ package org.mifos.accounts.productdefinition.struts.actionforms; import static java.util.Arrays.asList; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; import java.util.Locale; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import junit.framework.Assert; import org.apache.commons.lang.StringUtils; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionMessage; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mifos.accounts.fees.business.FeeBO; import org.mifos.accounts.fees.business.FeeDto; import org.mifos.accounts.fees.business.FeeFormulaEntity; import org.mifos.accounts.fees.business.FeeFrequencyEntity; import org.mifos.accounts.fees.business.RateFeeBO; import org.mifos.accounts.fees.util.helpers.FeeFormula; import org.mifos.accounts.fees.util.helpers.RateAmountFlag; import org.mifos.accounts.productdefinition.util.helpers.ApplicableTo; import org.mifos.accounts.productdefinition.util.helpers.GraceType; import org.mifos.accounts.productdefinition.util.helpers.InterestType; import org.mifos.accounts.productdefinition.util.helpers.ProductDefinitionConstants; import org.mifos.application.meeting.business.MeetingBO; import org.mifos.application.meeting.business.MeetingDetailsEntity; import org.mifos.framework.exceptions.PageExpiredException; import org.mifos.framework.util.helpers.Constants; import org.mifos.framework.util.helpers.Flow; import org.mifos.framework.util.helpers.FlowManager; import org.mifos.platform.questionnaire.service.QuestionGroupDetail; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; @SuppressWarnings("unchecked") @RunWith(MockitoJUnitRunner.class) public class LoanPrdActionFormTest { @Mock private HttpServletRequest request; @Mock private HttpSession session; @Mock private FlowManager flowManager; @Mock private ActionErrors errors; @Mock RateFeeBO periodicFeeRate; @Mock FeeBO periodicFeeAmount; FeeBO nonPeriodicFeeRate = Mockito.mock(RateFeeBO.class); @Mock FeeBO oneTimeFee; @Mock FeeFormulaEntity feeFormulaEntity; private LoanPrdActionForm loanPrdActionForm; private static final String FLOW_KEY = "FlowKey"; @Before public void setUp() { loanPrdActionForm = new LoanPrdActionForm(); } @Test public void testApplicableMaster() throws Exception { loanPrdActionForm.setPrdApplicableMaster("" + ApplicableTo.CLIENTS.getValue()); Assert.assertEquals(ApplicableTo.CLIENTS, loanPrdActionForm.getPrdApplicableMasterEnum()); } @Test public void testSetFromEnum() throws Exception { loanPrdActionForm.setPrdApplicableMaster(ApplicableTo.ALLCUSTOMERS); Assert.assertEquals(ApplicableTo.ALLCUSTOMERS, loanPrdActionForm.getPrdApplicableMasterEnum()); } @Test public void shouldSetSelectedQuestionGroupsOnSession() throws PageExpiredException { when(request.getAttribute(Constants.CURRENTFLOWKEY)).thenReturn(FLOW_KEY); when(request.getSession()).thenReturn(session); when(session.getAttribute(Constants.FLOWMANAGER)).thenReturn(flowManager); Flow flow = new Flow(); when(flowManager.getFlowWithValidation(FLOW_KEY)).thenReturn(flow); List<QuestionGroupDetail> questionGroupDetails = asList(getQuestionGroupDetail(1, "QG1"), getQuestionGroupDetail(2, "QG2"), getQuestionGroupDetail(3, "QG3"), getQuestionGroupDetail(4, "QG4")); when(flowManager.getFromFlow(FLOW_KEY, ProductDefinitionConstants.SRCQGLIST)).thenReturn(questionGroupDetails); loanPrdActionForm.setLoanOfferingQGs(new String[] {"1", "4"}); loanPrdActionForm.setSelectedQuestionGroups(request); List<QuestionGroupDetail> selectedQGDetails = (List<QuestionGroupDetail>) flow.getObjectFromSession(ProductDefinitionConstants.SELECTEDQGLIST); assertThat(selectedQGDetails, is(notNullValue())); assertThat(selectedQGDetails.get(0).getId(), is(1)); assertThat(selectedQGDetails.get(0).getTitle(), is("QG1")); assertThat(selectedQGDetails.get(1).getId(), is(4)); assertThat(selectedQGDetails.get(1).getTitle(), is("QG4")); } @Test public void shouldSetSelectedQuestionGroupsOnSessionForNoQGs() throws PageExpiredException { when(request.getAttribute(Constants.CURRENTFLOWKEY)).thenReturn(FLOW_KEY); when(request.getSession()).thenReturn(session); when(session.getAttribute(Constants.FLOWMANAGER)).thenReturn(flowManager); Flow flow = new Flow(); when(flowManager.getFlowWithValidation(FLOW_KEY)).thenReturn(flow); List<QuestionGroupDetail> questionGroupDetails = asList(getQuestionGroupDetail(1, "QG1"), getQuestionGroupDetail(2, "QG2"), getQuestionGroupDetail(3, "QG3"), getQuestionGroupDetail(4, "QG4")); when(flowManager.getFromFlow(FLOW_KEY, ProductDefinitionConstants.SRCQGLIST)).thenReturn(questionGroupDetails); loanPrdActionForm.setLoanOfferingQGs(null); loanPrdActionForm.setSelectedQuestionGroups(request); List<QuestionGroupDetail> selectedQGDetails = (List<QuestionGroupDetail>) flow.getObjectFromSession(ProductDefinitionConstants.SELECTEDQGLIST); assertThat(selectedQGDetails, is(notNullValue())); assertThat(selectedQGDetails.isEmpty(), is(true)); } private QuestionGroupDetail getQuestionGroupDetail(int id, String title) { QuestionGroupDetail questionGroupDetail = new QuestionGroupDetail(); questionGroupDetail.setId(id); questionGroupDetail.setTitle(title); return questionGroupDetail; } @Test public void onlyDecliningInterestTypeShouldBeSelectedForVariableInstallmentLoanProduct() { ActionMessageMatcher actionMessageMatcher = new ActionMessageMatcher(ProductDefinitionConstants.INVALID_INTEREST_TYPE_FOR_VARIABLE_INSTALLMENT); loanPrdActionForm.setCanConfigureVariableInstallments(true); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verify(errors).add(Mockito.anyString(), Mockito.argThat(actionMessageMatcher)); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(InterestType.FLAT.getValueAsString()); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verifyZeroInteractions(errors); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(InterestType.DECLINING.getValueAsString()); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verifyZeroInteractions(errors); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(InterestType.COMPOUND.getValueAsString()); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verify(errors).add(Mockito.anyString(), Mockito.argThat(actionMessageMatcher)); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(InterestType.DECLINING_EPI.getValueAsString()); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verify(errors).add(Mockito.anyString(), Mockito.argThat(actionMessageMatcher)); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(InterestType.DECLINING_PB.getValueAsString()); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verify(errors).add(Mockito.anyString(), Mockito.argThat(actionMessageMatcher)); Mockito.reset(errors); } @Test public void shouldValidateForGracePeriodWithDIPBInterestTypeAndVariableInstallments() { ActionMessageMatcher actionMessageMatcher = new ActionMessageMatcher(ProductDefinitionConstants.INVALID_INTEREST_TYPE_FOR_GRACE_PERIODS); loanPrdActionForm.setGracePeriodType(GraceType.PRINCIPALONLYGRACE.getValueAsString()); loanPrdActionForm.setCanConfigureVariableInstallments(true); loanPrdActionForm.setInterestTypes(InterestType.FLAT.getValueAsString()); loanPrdActionForm.validateInterestTypeForGracePeriods(errors, Locale.getDefault()); Mockito.verify(errors).add(Mockito.anyString(), Mockito.argThat(actionMessageMatcher)); Mockito.reset(errors); loanPrdActionForm.setGracePeriodType(GraceType.PRINCIPALONLYGRACE.getValueAsString()); loanPrdActionForm.setCanConfigureVariableInstallments(false); loanPrdActionForm.setInterestTypes(InterestType.DECLINING_PB.getValueAsString()); loanPrdActionForm.validateInterestTypeForGracePeriods(errors, Locale.getDefault()); Mockito.verify(errors).add(Mockito.anyString(), Mockito.argThat(actionMessageMatcher)); Mockito.reset(errors); loanPrdActionForm.setGracePeriodType(GraceType.GRACEONALLREPAYMENTS.getValueAsString()); loanPrdActionForm.setCanConfigureVariableInstallments(true); loanPrdActionForm.setInterestTypes(InterestType.COMPOUND.getValueAsString()); loanPrdActionForm.validateInterestTypeForGracePeriods(errors, Locale.getDefault()); Mockito.verify(errors).add(Mockito.anyString(), Mockito.argThat(actionMessageMatcher)); Mockito.reset(errors); loanPrdActionForm.setGracePeriodType(GraceType.NONE.getValueAsString()); loanPrdActionForm.setCanConfigureVariableInstallments(false); loanPrdActionForm.setInterestTypes(InterestType.DECLINING_EPI.getValueAsString()); loanPrdActionForm.validateInterestTypeForGracePeriods(errors, Locale.getDefault()); Mockito.verifyZeroInteractions(errors); Mockito.reset(errors); } @Test public void shouldNotAllowPeriodicFeeForVariableInstallmentLoanProduct() { String PERIODIC_FEE_2 = "2"; String NON_PERIODIC_FEE = "3"; when(periodicFeeRate.isPeriodic()).thenReturn(true); when(periodicFeeRate.getFeeType()).thenReturn(RateAmountFlag.RATE); when(periodicFeeRate.getFeeId()).thenReturn(Short.valueOf(PERIODIC_FEE_2)); when(periodicFeeRate.getFeeName()).thenReturn("periodic fee2"); when(nonPeriodicFeeRate.isPeriodic()).thenReturn(false); when(nonPeriodicFeeRate.getFeeType()).thenReturn(RateAmountFlag.RATE); when(nonPeriodicFeeRate.getFeeId()).thenReturn(Short.valueOf(NON_PERIODIC_FEE)); when(nonPeriodicFeeRate.getFeeName()).thenReturn("non Periodic fee"); when(((RateFeeBO)nonPeriodicFeeRate).getFeeFormula()).thenReturn(feeFormulaEntity); when(feeFormulaEntity.getFeeFormula()).thenReturn(FeeFormula.INTEREST); List<FeeBO> allPrdFees = new ArrayList<FeeBO>(); allPrdFees.add(periodicFeeRate); allPrdFees.add(nonPeriodicFeeRate); when(request.getAttribute(Constants.CURRENTFLOWKEY)).thenReturn(FLOW_KEY); when(request.getSession()).thenReturn(session); when(session.getAttribute(Constants.FLOWMANAGER)).thenReturn(flowManager); when(session.getAttribute(ProductDefinitionConstants.LOANPRDFEE)).thenReturn(allPrdFees); Flow flow = new Flow(); try { when(flowManager.getFromFlow(Mockito.anyString(),Mockito.anyString())).thenReturn(allPrdFees); when(flowManager.getFlowWithValidation(FLOW_KEY)).thenReturn(flow); } catch (PageExpiredException e) { // TODO Auto-generated catch block e.printStackTrace(); } ActionMessageMatcher actionMessageMatcher = new ActionMessageMatcher(ProductDefinitionConstants.PERIODIC_FEE_NOT_APPLICABLE); loanPrdActionForm.setCanConfigureVariableInstallments(true); loanPrdActionForm.setPrdOfferinFees(new String[] {PERIODIC_FEE_2, NON_PERIODIC_FEE}); loanPrdActionForm.validateSelectedFeeForVariableInstallment(request, errors); Mockito.verify(errors, Mockito.times(1)).add(Mockito.anyString(), Mockito.argThat(actionMessageMatcher)); } @Test public void shouldAllowPeriodicFeeForNonVariableInstallmentLoanProduct() { String PERIODIC_FEE_2 = "2"; String NON_PERIODIC_FEE = "3"; final FeeDto feeDto = Mockito.mock(FeeDto.class); loanPrdActionForm = new LoanPrdActionForm() { @Override FeeDto getFeeDto(@SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") FeeBO fee) { return feeDto; } }; FeeFrequencyEntity feeFrequencyEntity = Mockito.mock(FeeFrequencyEntity.class); MeetingBO meetingBo = Mockito.mock(MeetingBO.class); MeetingDetailsEntity meetingDetailsEntity = Mockito.mock(MeetingDetailsEntity.class); when(periodicFeeRate.isPeriodic()).thenReturn(true); when(periodicFeeRate.getFeeType()).thenReturn(RateAmountFlag.RATE); when(periodicFeeRate.getFeeId()).thenReturn(Short.valueOf(PERIODIC_FEE_2)); when(periodicFeeRate.getFeeName()).thenReturn("periodic fee2"); when((periodicFeeRate).getFeeFormula()).thenReturn(feeFormulaEntity); when(feeFormulaEntity.getFeeFormula()).thenReturn(FeeFormula.INTEREST); when(periodicFeeRate.getFeeFrequency()).thenReturn(feeFrequencyEntity); when(nonPeriodicFeeRate.isPeriodic()).thenReturn(false); when(nonPeriodicFeeRate.getFeeType()).thenReturn(RateAmountFlag.RATE); when(nonPeriodicFeeRate.getFeeId()).thenReturn(Short.valueOf(NON_PERIODIC_FEE)); when(nonPeriodicFeeRate.getFeeName()).thenReturn("non Periodic fee"); when(((RateFeeBO)nonPeriodicFeeRate).getFeeFormula()).thenReturn(feeFormulaEntity); when(feeFormulaEntity.getFeeFormula()).thenReturn(FeeFormula.INTEREST); List<FeeBO> allPrdFees = new ArrayList<FeeBO>(); allPrdFees.add(periodicFeeRate); allPrdFees.add(nonPeriodicFeeRate); when(request.getAttribute(Constants.CURRENTFLOWKEY)).thenReturn(FLOW_KEY); when(request.getSession()).thenReturn(session); when(session.getAttribute(Constants.FLOWMANAGER)).thenReturn(flowManager); when(session.getAttribute(ProductDefinitionConstants.LOANPRDFEE)).thenReturn(allPrdFees); Flow flow = new Flow(); try { when(flowManager.getFromFlow(Mockito.anyString(),Mockito.anyString())).thenReturn(allPrdFees); when(flowManager.getFlowWithValidation(FLOW_KEY)).thenReturn(flow); } catch (PageExpiredException e) { // TODO Auto-generated catch block e.printStackTrace(); } loanPrdActionForm.setCanConfigureVariableInstallments(false); loanPrdActionForm.setPrdOfferinFees(new String[] { PERIODIC_FEE_2, NON_PERIODIC_FEE}); loanPrdActionForm.validateSelectedFeeForVariableInstallment(request, errors); Mockito.verifyZeroInteractions(errors); } @Test public void anyInterestTypeCanBeSelectedForNonVariableInstallmentProductTypes() { String FLAT = "1"; String DECLINING = "2"; String COMPOUND = "3"; String DECLINING_EPI = "4"; String DECLINING_PB = "5"; loanPrdActionForm.setCanConfigureVariableInstallments(false); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verifyZeroInteractions(errors); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(FLAT); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verifyZeroInteractions(errors); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(DECLINING); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verifyZeroInteractions(errors); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(COMPOUND); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verifyZeroInteractions(errors); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(DECLINING_EPI); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verifyZeroInteractions(errors); Mockito.reset(errors); loanPrdActionForm.setInterestTypes(DECLINING_PB); loanPrdActionForm.validateInterestTypeForVariableInstallment(errors, Locale.getDefault()); Mockito.verifyZeroInteractions(errors); Mockito.reset(errors); } @Test public void shouldAbleToRetrieveMaxAndMinValues() { Assert.assertNotNull(loanPrdActionForm.getMaxCashFlowThreshold()); Assert.assertNotNull(loanPrdActionForm.getMinCashFlowThreshold()); Assert.assertNotNull(loanPrdActionForm.getMaxIndebtednessRatio()); Assert.assertNotNull(loanPrdActionForm.getMinIndebtednessRatio()); Assert.assertNotNull(loanPrdActionForm.getMaxRepaymentCapacity()); Assert.assertNotNull(loanPrdActionForm.getMinRepaymentCapacity()); } @Test public void shouldReturnConsistentValuesForPropertiesWhichHaveBothValuesAndStringRepresentationFunctions() { String cashflowValue = "100"; loanPrdActionForm.setCashFlowThreshold(cashflowValue); Assert.assertEquals(cashflowValue, loanPrdActionForm.getCashFlowThreshold()); Assert.assertEquals(100d,loanPrdActionForm.getCashFlowThresholdValue()); String emptyValue = " "; loanPrdActionForm.setCashFlowThreshold(emptyValue); Assert.assertEquals(emptyValue, loanPrdActionForm.getCashFlowThreshold()); Assert.assertEquals(null,loanPrdActionForm.getCashFlowThresholdValue()); } private class ActionMessageMatcher extends TypeSafeMatcher<ActionMessage> { private String errorCode; public ActionMessageMatcher(String errorCode) { this.errorCode = errorCode; } @Override public boolean matchesSafely(ActionMessage actionMessage) { return actionMessage != null && StringUtils.equals(actionMessage.getKey(), errorCode); } @Override public void describeTo(Description arg0) { arg0.appendText("ActionMessage error code should be " + errorCode); } } }