package de.asideas.crowdsource.domain.model; import de.asideas.crowdsource.domain.exception.InvalidRequestException; import de.asideas.crowdsource.domain.exception.NotAuthorizedException; import de.asideas.crowdsource.domain.exception.ResourceNotFoundException; import de.asideas.crowdsource.domain.shared.ProjectStatus; import de.asideas.crowdsource.presentation.FinancingRound; import de.asideas.crowdsource.presentation.Pledge; import de.asideas.crowdsource.presentation.project.Attachment; import de.asideas.crowdsource.presentation.project.Project; import de.asideas.crowdsource.security.Roles; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; import org.springframework.http.MediaType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; public class ProjectEntityTest { private static final int PLEDGE_GOAL = 200; final int COUNT_POST_ROUND_PLEDGES = 5; int postRoundPledgedAmount = 0; private ProjectEntity projectEntity; private UserEntity aUser; private UserEntity adminUser; private UserEntity projectCreator; @Before public void setUp() { postRoundPledgedAmount = 0; UserEntity creator = new UserEntity(); creator.setId("id"); aUser = new UserEntity("aUser@xyz.com"); aUser.setId("test_id1"); aUser.setBudget(100); adminUser = new UserEntity("adminUser@xyz.com"); adminUser.setId("test_id2"); adminUser.setBudget(200); adminUser.setRoles(Arrays.asList(Roles.ROLE_USER, Roles.ROLE_ADMIN)); projectCreator = new UserEntity("projectCreator@xyz.com"); projectCreator.setId("test_id3"); Project project = new Project(); projectEntity = new ProjectEntity(projectCreator, project, anActiveFinancingRound()); projectEntity.setPledgeGoal(PLEDGE_GOAL); } /** * For a full integration test, checking all edge cases see {@link de.asideas.crowdsource.service.ProjectServiceTest} * * @throws Exception */ @Test public void pledge() throws Exception { final List<PledgeEntity> pledgesDoneBeforw = bunchOfPledgesDone(); final Pledge pledge = new Pledge(40); projectEntity.setStatus(ProjectStatus.PUBLISHED); int userBudgetBefore = aUser.getBudget(); final PledgeEntity pledgeRes = projectEntity.pledge(pledge, aUser, pledgesDoneBeforw); assertThat(pledgeRes, is(new PledgeEntity(projectEntity, aUser, pledge, projectEntity.getFinancingRound()))); assertThat(aUser.getBudget(), is(userBudgetBefore - pledge.getAmount())); assertThat(projectEntity.pledgeGoalAchieved(), is(true)); } @Test public void pledge_reverse() throws Exception { final List<PledgeEntity> pledgesDoneBeforw = bunchOfPledgesDone(); final Pledge pledge = new Pledge(-10); projectEntity.setStatus(ProjectStatus.PUBLISHED); int userBudgetBefore = aUser.getBudget(); final PledgeEntity pledgeRes = projectEntity.pledge(pledge, aUser, pledgesDoneBeforw); assertThat(pledgeRes, is(new PledgeEntity(projectEntity, aUser, pledge, projectEntity.getFinancingRound()))); assertThat(aUser.getBudget(), is(userBudgetBefore + Math.abs(pledge.getAmount()))); } @Test public void pledge_reversePledgeThrowsInvalidRequestExWhenExceedingPledgeAmountAlreadyMade() throws Exception { final int budgetBeforePledge = aUser.getBudget(); projectEntity.setStatus(ProjectStatus.PUBLISHED); final Pledge pledge = new Pledge(-5); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(4)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.reversePledgeExceeded(), aUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledge_reversePledgeThrowsInvalidRequestExWhenAlreadyFullyPledged() throws Exception { projectEntity.setStatus(ProjectStatus.FULLY_PLEDGED); final int budgetBeforePledge = aUser.getBudget(); final Pledge pledge = new Pledge(-5); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(4)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.projectAlreadyFullyPledged(), aUser, budgetBeforePledge, ProjectStatus.FULLY_PLEDGED); } @Test public void pledge_throwsInvalidRequestExOnPledgeGoalIsExceeded() { projectEntity.setStatus(ProjectStatus.PUBLISHED); final int budgetBeforePledge = aUser.getBudget(); final Pledge pledge = new Pledge(5); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.pledgeGoalExceeded(), aUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledge_throwsInvalidRequestExOnZeroPledge() { projectEntity.setStatus(ProjectStatus.PUBLISHED); final int budgetBeforePledge = aUser.getBudget(); final Pledge pledge = new Pledge(0); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.zeroPledgeNotValid(), aUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledge_throwsInvalidRequestExOnProjectThatIsAlreadyFullyPledged() { projectEntity.setStatus(ProjectStatus.PUBLISHED); final int budgetBeforePledge = aUser.getBudget(); final Pledge pledge = new Pledge(5); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(projectEntity.getPledgeGoal())); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.projectAlreadyFullyPledged(), aUser, budgetBeforePledge, ProjectStatus.FULLY_PLEDGED); } @Test public void pledge_throwsInvalidRequestExOnProjectIsDeferred() { projectEntity.setStatus(ProjectStatus.DEFERRED); final int budgetBeforePledge = aUser.getBudget(); final Pledge pledge = new Pledge(5); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(0)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.projectNotPublished(), aUser, budgetBeforePledge, ProjectStatus.DEFERRED); } @Test public void pledge_throwsInvalidRequestExOnProjectIsNotPublished() { projectEntity.setStatus(ProjectStatus.PROPOSED); final int budgetBeforePledge = aUser.getBudget(); final Pledge pledge = new Pledge(5); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.projectNotPublished(), aUser, budgetBeforePledge, ProjectStatus.PROPOSED); } @Test public void pledge_throwsInvalidRequestExOnUserBudgetIsExceeded() { projectEntity.setStatus(ProjectStatus.PUBLISHED); final int budgetBeforePledge = aUser.getBudget(); final Pledge pledge = new Pledge(aUser.getBudget() + 10); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.userBudgetExceeded(), aUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledge_throwsInvalidRequestExOnNoFinancingRound() { projectEntity.setStatus(ProjectStatus.PUBLISHED); final int budgetBeforePledge = aUser.getBudget(); final Pledge pledge = new Pledge(4); projectEntity.setFinancingRound(null); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.noFinancingRoundCurrentlyActive(), aUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledge_throwsInvalidRequestExOnInactiveFinancingRound() { projectEntity.setStatus(ProjectStatus.PUBLISHED); final int budgetBeforePledge = aUser.getBudget(); final Pledge pledge = new Pledge(4); projectEntity.setFinancingRound(aTerminatedFinancingRound()); InvalidRequestException res = null; try { projectEntity.pledge(pledge, aUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.noFinancingRoundCurrentlyActive(), aUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledgeUsingPostroundBudget() { projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(aTerminatedFinancingRound()); final List<PledgeEntity> pledgesDoneBefore = bunchOfWithPostRoundPledgesDone(); final Pledge pledge = new Pledge(projectEntity.getPledgeGoal() - projectEntity.pledgedAmount(pledgesDoneBefore)); int userBudgetBefore = adminUser.getBudget(); final PledgeEntity pledgeRes = projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesDoneBefore, 400); assertThat(pledgeRes, is(new PledgeEntity(projectEntity, adminUser, pledge, projectEntity.getFinancingRound()))); assertThat(adminUser.getBudget(), is(userBudgetBefore)); assertThat(projectEntity.pledgeGoalAchieved(), is(true)); } @Test public void pledgeUsingPostroundBudget_reverse() { final FinancingRoundEntity round = aTerminatedFinancingRound(); projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(round); final List<PledgeEntity> pledgesInRound = bunchOfPledgesDone(); final List<PledgeEntity> postRoundPledges = bunchOfPostRoundPledges(); final List<PledgeEntity> pledgesDone = new ArrayList<>(pledgesInRound); pledgesDone.addAll(postRoundPledges); final Pledge pledge = new Pledge(-10); int userBudgetBefore = adminUser.getBudget(); final PledgeEntity pledgeRes = projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesDone, round.postRoundPledgableBudgetRemaining(postRoundPledges)); assertThat(pledgeRes, is(new PledgeEntity(projectEntity, adminUser, pledge, projectEntity.getFinancingRound()))); assertThat(adminUser.getBudget(), is(userBudgetBefore)); assertThat(projectEntity.pledgeGoalAchieved(), is(false)); postRoundPledges.add(pledgeRes); pledgeRes.setCreatedDate(new DateTime()); assertThat(round.postRoundPledgableBudgetRemaining(postRoundPledges), is(round.getPostRoundBudget() - postRoundPledgedAmount - pledge.getAmount())); } @Test public void pledgeUsingPostroundBudget_reversePledgeThrowsInvalidRequestExWhenExceedingPledgeAmountAlreadyMade() throws Exception { final FinancingRoundEntity round = aTerminatedFinancingRound(); projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(round); final List<PledgeEntity> pledgesInRound = bunchOfPledgesDone(); final List<PledgeEntity> postRoundPledges = bunchOfPostRoundPledges(); final List<PledgeEntity> pledgesDone = new ArrayList<>(pledgesInRound); pledgesDone.addAll(postRoundPledges); final Pledge pledge = new Pledge(-postRoundPledgedAmount - 1); int userBudgetBefore = adminUser.getBudget(); InvalidRequestException res = null; try { projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesDone, round.postRoundPledgableBudgetRemaining(postRoundPledges)); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.reversePledgeExceeded(), adminUser, userBudgetBefore, ProjectStatus.PUBLISHED); } @Test public void pledgeUsingPostroundBudget_reversePledgeThrowsInvalidRequestExWhenAlreadyFullyPledged() throws Exception { projectEntity.setStatus(ProjectStatus.FULLY_PLEDGED); final int budgetBeforePledge = aUser.getBudget(); projectEntity.setFinancingRound(aTerminatedFinancingRound()); final Pledge pledge = new Pledge(-5); InvalidRequestException res = null; try { projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesAlreadyDone(10), Integer.MAX_VALUE); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.projectAlreadyFullyPledged(), aUser, budgetBeforePledge, ProjectStatus.FULLY_PLEDGED); } @Test public void pledgeUsingPostroundBudget_throwsInvalidRequestExOnProjectThatIsAlreadyFullyPledged() throws Exception { projectEntity.setFinancingRound(aTerminatedFinancingRound()); projectEntity.setStatus(ProjectStatus.FULLY_PLEDGED); final int budgetBeforePledge = adminUser.getBudget(); final Pledge pledge = new Pledge(5); InvalidRequestException res = null; try { projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesAlreadyDone(projectEntity.getPledgeGoal()), Integer.MAX_VALUE); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.projectAlreadyFullyPledged(), adminUser, budgetBeforePledge, ProjectStatus.FULLY_PLEDGED); } @Test public void pledgeUsingPostroundBudget_throwsInvalidRequestExOnPledgeGoalIsExceeded() { final FinancingRoundEntity round = aTerminatedFinancingRound(); projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(round); final List<PledgeEntity> pledgesDone = bunchOfWithPostRoundPledgesDone(); final int budgetBeforePledge = adminUser.getBudget(); final Pledge pledge = new Pledge(projectEntity.getPledgeGoal() + 1); InvalidRequestException res = null; try { projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesDone, Integer.MAX_VALUE); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.pledgeGoalExceeded(), adminUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledgeUsingPostroundBudget_throwsInvalidRequestExOnZeroPledge() { final FinancingRoundEntity round = aTerminatedFinancingRound(); projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(round); final int budgetBeforePledge = adminUser.getBudget(); final Pledge pledge = new Pledge(0); InvalidRequestException res = null; try { projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4), Integer.MAX_VALUE); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.zeroPledgeNotValid(), adminUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledgeUsingPostroundBudget_throwsInvalidRequestExOnProjectIsDeferred() { final FinancingRoundEntity round = aTerminatedFinancingRound(); projectEntity.setStatus(ProjectStatus.DEFERRED); projectEntity.setFinancingRound(round); final int budgetBeforePledge = adminUser.getBudget(); final Pledge pledge = new Pledge(5); InvalidRequestException res = null; try { projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesAlreadyDone(0), 0); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.projectNotPublished(), adminUser, budgetBeforePledge, ProjectStatus.DEFERRED); } @Test public void pledgeUsingPostroundBudget_throwsInvalidRequestExOnProjectIsNotPublished() { final FinancingRoundEntity round = aTerminatedFinancingRound(); projectEntity.setFinancingRound(round); projectEntity.setStatus(ProjectStatus.PROPOSED); final int budgetBeforePledge = adminUser.getBudget(); final Pledge pledge = new Pledge(5); InvalidRequestException res = null; try { projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesAlreadyDone(1), 0); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.projectNotPublished(), adminUser, budgetBeforePledge, ProjectStatus.PROPOSED); } @Test(expected = IllegalArgumentException.class) public void pledgeUsingPostroundBudget_throwsIllegalArgumentExOnNoFinancingRound() { projectEntity.setFinancingRound(null); projectEntity.setStatus(ProjectStatus.PUBLISHED); final Pledge pledge = new Pledge(4); projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4), Integer.MAX_VALUE); } @Test(expected = IllegalArgumentException.class) public void pledgeUsingPostroundBudget_throwsIllegalArgumentExceptionIfCalledByNonAdminUser() { final FinancingRoundEntity round = aTerminatedFinancingRound(); projectEntity.setFinancingRound(round); projectEntity.setStatus(ProjectStatus.PUBLISHED); final Pledge pledge = new Pledge(4); projectEntity.pledgeUsingPostRoundBudget(pledge, aUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4), Integer.MAX_VALUE); } @Test(expected = IllegalArgumentException.class) public void pledgeUsingPostroundBudget_throwsIllegalArgumentExceptionOnNotTerminatedRound() { final FinancingRoundEntity round = anActiveFinancingRound(); projectEntity.setFinancingRound(round); projectEntity.setStatus(ProjectStatus.PUBLISHED); final Pledge pledge = new Pledge(4); projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4), Integer.MAX_VALUE); } @Test public void pledgeUsingPostroundBudget_throwsInvalidRequestExOnUserBudgetIsExceeded() { final FinancingRoundEntity round = aTerminatedFinancingRound(); projectEntity.setFinancingRound(round); projectEntity.setStatus(ProjectStatus.PUBLISHED); final int budgetBeforePledge = adminUser.getBudget(); final Pledge pledge = new Pledge(10); InvalidRequestException res = null; try { projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4), 5); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.postRoundBudgetExceeded(), adminUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledgeUsingPostroundBudget_throwsInvalidRequestExOnFinancingRoundNotPostProcessed() { final FinancingRoundEntity round = aTerminatedFinancingRound(); round.setTerminationPostProcessingDone(false); projectEntity.setFinancingRound(round); projectEntity.setStatus(ProjectStatus.PUBLISHED); final int budgetBeforePledge = adminUser.getBudget(); final Pledge pledge = new Pledge(10); InvalidRequestException res = null; try { projectEntity.pledgeUsingPostRoundBudget(pledge, adminUser, pledgesAlreadyDone(projectEntity.getPledgeGoal() - 4), Integer.MAX_VALUE); fail("InvalidRequestException expected!"); } catch (InvalidRequestException e) { res = e; } assertPledgeNotExecuted(res, InvalidRequestException.financingRoundNotPostProcessedYet(), adminUser, budgetBeforePledge, ProjectStatus.PUBLISHED); } @Test public void pledgeGoalAchieved_ReturnsFalseIfNotFullyPledged() throws Exception { assertThat(projectEntity.pledgeGoalAchieved(), is(false)); } @Test public void pledgeGoalAchieved_returnsTrueWhenFullyPledged() throws Exception { projectEntity.setStatus(ProjectStatus.FULLY_PLEDGED); assertThat(projectEntity.pledgeGoalAchieved(), is(true)); } @Test public void pledgedAmount() throws Exception { final FinancingRoundEntity activeFinancingRound = new FinancingRoundEntity(); assertThat(projectEntity.pledgedAmount(bunchOfPledgesDone()), is(160)); } @Test public void pledgedAmount_isZeroOnEmptyPledges() throws Exception { assertThat(projectEntity.pledgedAmount(new ArrayList<>()), is(0)); } @Test public void countBackers() throws Exception { final FinancingRoundEntity activeFinancingRound = new FinancingRoundEntity(); assertThat(projectEntity.countBackers(bunchOfPledgesDone()), is(2L)); } @Test public void countBackers_isZeroOnEmptyPledges() throws Exception { assertThat(projectEntity.countBackers(new ArrayList<>()), is(0L)); } @Test public void pledgedAmountOfUser() throws Exception { final FinancingRoundEntity activeFinancingRound = new FinancingRoundEntity(); assertThat(projectEntity.pledgedAmountOfUser(bunchOfPledgesDone(), aUser), is(30)); } @Test public void pledgedAmountOfUser_ReturnsZeroOnNullUser() throws Exception { final FinancingRoundEntity activeFinancingRound = new FinancingRoundEntity(); assertThat(projectEntity.pledgedAmountOfUser(bunchOfPledgesDone(), null), is(0)); } @Test public void pledgedAmountOfUser_ReturnsZeroOnEmptyPledges() throws Exception { assertThat(projectEntity.pledgedAmountOfUser(new ArrayList<>(), aUser), is(0)); } @Test public void modifyStatus() throws Exception { boolean res = projectEntity.modifyStatus(ProjectStatus.PUBLISHED); MatcherAssert.assertThat(res, Matchers.is(true)); MatcherAssert.assertThat(projectEntity.getStatus(), Matchers.is(ProjectStatus.PUBLISHED)); } @Test public void modifyStatus_settingToPublishedAlthoughFullyPledgedThrowsIvalidRequestEx() throws Exception { projectEntity.setStatus(ProjectStatus.FULLY_PLEDGED); try { projectEntity.modifyStatus(ProjectStatus.PUBLISHED); fail("Expected InvalidRequestException was not thrown"); } catch (InvalidRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.is(InvalidRequestException.projectAlreadyFullyPledged().getMessage())); } } @Test public void modifyStatus_settingToDeferredThrowsExceptionWhenFinancingRoundAssignedAndActive() throws Exception { try { projectEntity.setFinancingRound(anActiveFinancingRound()); projectEntity.modifyStatus(ProjectStatus.DEFERRED); fail("Expected InvalidRequestException was not thrown"); } catch (InvalidRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.is(InvalidRequestException.projectAlreadyInFinancingRound().getMessage())); } } @Test public void modifyStatus_settingToDeferredThrowsExceptionWhenAlreadyFullyPledged() throws Exception { projectEntity.setStatus(ProjectStatus.FULLY_PLEDGED); try { projectEntity.modifyStatus(ProjectStatus.DEFERRED); fail("Expected InvalidRequestException was not thrown"); } catch (InvalidRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.is(InvalidRequestException.projectAlreadyFullyPledged().getMessage())); } } @Test public void modifyStatus_settingToDeferredThrowsExceptionWhenRejected() throws Exception { projectEntity.setStatus(ProjectStatus.REJECTED); projectEntity.setFinancingRound(null); try { projectEntity.modifyStatus(ProjectStatus.DEFERRED); fail("Expected InvalidRequestException was not thrown"); } catch (InvalidRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.is(InvalidRequestException.setToDeferredNotPossibleOnRejected().getMessage())); } } @Test public void modifyStatus_settingToPublishedPossibleWhenDeferred() throws Exception { projectEntity.setStatus(ProjectStatus.DEFERRED); projectEntity.setFinancingRound(null); boolean res = projectEntity.modifyStatus(ProjectStatus.PUBLISHED); assertThat(res, is(true)); assertThat(projectEntity.getStatus(), is(ProjectStatus.PUBLISHED)); } @Test public void modifyStatus_settingToDeferredPossibleWhenAlreadyPublished() throws Exception { projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(null); boolean res = projectEntity.modifyStatus(ProjectStatus.DEFERRED); assertThat(res, is(true)); assertThat(projectEntity.getStatus(), is(ProjectStatus.DEFERRED)); } @Test public void modifyStatus_settingToDeferredPossibleWhenAssignedToNonActiveFinancingRound() throws Exception { projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(aTerminatedFinancingRound()); boolean res = projectEntity.modifyStatus(ProjectStatus.DEFERRED); assertThat(res, is(true)); assertThat(projectEntity.getStatus(), is(ProjectStatus.DEFERRED)); } @Test public void modifyStatus_settingToProposedPossibleWhenAlreadyPublished() throws Exception { projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(null); boolean res = projectEntity.modifyStatus(ProjectStatus.PROPOSED); assertThat(res, is(true)); assertThat(projectEntity.getStatus(), is(ProjectStatus.PROPOSED)); } @Test public void modifyStatus_settingToProposedPossibleWhenAlreadyDeferred() throws Exception { projectEntity.setStatus(ProjectStatus.DEFERRED); projectEntity.setFinancingRound(null); boolean res = projectEntity.modifyStatus(ProjectStatus.PROPOSED); assertThat(res, is(true)); assertThat(projectEntity.getStatus(), is(ProjectStatus.PROPOSED)); } @Test public void modifyStatus_settingToProposedPossibleWhenAlreadyRejected() throws Exception { projectEntity.setStatus(ProjectStatus.REJECTED); projectEntity.setFinancingRound(null); boolean res = projectEntity.modifyStatus(ProjectStatus.PROPOSED); assertThat(res, is(true)); assertThat(projectEntity.getStatus(), is(ProjectStatus.PROPOSED)); } @Test public void modifyStatus_settingToPublishedPossibleWhenAlreadyRejected() throws Exception { projectEntity.setStatus(ProjectStatus.REJECTED); projectEntity.setFinancingRound(null); boolean res = projectEntity.modifyStatus(ProjectStatus.PUBLISHED); assertThat(res, is(true)); assertThat(projectEntity.getStatus(), is(ProjectStatus.PUBLISHED)); } @Test public void modifyStatus_settingToPublishedDeferred_notPossibleWhenAlreadyPublishedInRound() throws Exception { projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(anActiveFinancingRound()); try { projectEntity.modifyStatus(ProjectStatus.PUBLISHED_DEFERRED); fail("Expected InvalidRequestException was not thrown"); } catch (InvalidRequestException e) { MatcherAssert.assertThat(e.getMessage(), Matchers.is(InvalidRequestException.projectAlreadyInFinancingRound().getMessage())); } } @Test public void modifyStatus_settingToPublishedDeferred_PossibleOnActiveRound() throws Exception { projectEntity.setStatus(ProjectStatus.PROPOSED); projectEntity.setFinancingRound(anActiveFinancingRound()); boolean res = projectEntity.modifyStatus(ProjectStatus.PUBLISHED_DEFERRED); assertThat(res, is(true)); assertThat(projectEntity.getStatus(), is(ProjectStatus.PUBLISHED_DEFERRED)); } @Test public void masterdataModificationAllowed_shouldReturnTrueHavingNoFinancingRound() throws Exception { projectEntity.setFinancingRound(null); assertThat(projectEntity.masterdataModificationAllowed(), is(true)); } @Test public void masterdataModificationAllowed_shouldReturnTrueHavingNotActiveFinancingRound() throws Exception { projectEntity.setFinancingRound(aTerminatedFinancingRound()); assertThat(projectEntity.masterdataModificationAllowed(), is(true)); } @Test public void masterdataModificationAllowed_shouldReturnFalseHavingActiveFinancingRund() throws Exception { projectEntity.setFinancingRound(anActiveFinancingRound()); projectEntity.setStatus(ProjectStatus.PUBLISHED); assertThat(projectEntity.masterdataModificationAllowed(), is(false)); } @Test public void masterdataModificationAllowed_shouldReturnFalseHavingStatusFullyPledged() throws Exception { projectEntity.setFinancingRound(aTerminatedFinancingRound()); projectEntity.setStatus(ProjectStatus.FULLY_PLEDGED); assertThat(projectEntity.masterdataModificationAllowed(), is(false)); } @Test public void masterdataModificationAllowed_shouldReturnTrueHavingStatusProposed() throws Exception { projectEntity.setFinancingRound(anActiveFinancingRound()); projectEntity.setStatus(ProjectStatus.PROPOSED); assertThat(projectEntity.masterdataModificationAllowed(), is(true)); } @Test public void masterdataModificationAllowed_shouldReturnTrueHavingStatusDeferred() throws Exception { projectEntity.setFinancingRound(anActiveFinancingRound()); projectEntity.setStatus(ProjectStatus.DEFERRED); assertThat(projectEntity.masterdataModificationAllowed(), is(true)); } @Test public void masterdataChanged_returnsTrueIfOneFieldChanges() throws Exception { Project modifiedProject; // Given prepareMasterData(projectEntity); modifiedProject = new Project(projectEntity, Collections.emptyList(), aUser); // When modifiedProject.setTitle(projectEntity.getTitle() + "_CHANGED"); // Then assertThat(projectEntity.masterdataChanged(modifiedProject), is(true)); // Given prepareMasterData(projectEntity); modifiedProject = new Project(projectEntity, Collections.emptyList(), aUser); // When modifiedProject.setDescription(null); // Then assertThat(projectEntity.masterdataChanged(modifiedProject), is(true)); // Given prepareMasterData(projectEntity); modifiedProject = new Project(projectEntity, Collections.emptyList(), aUser); // When modifiedProject.setShortDescription(projectEntity.getShortDescription() + "_CHANGED"); // Then assertThat(projectEntity.masterdataChanged(modifiedProject), is(true)); // Given prepareMasterData(projectEntity); modifiedProject = new Project(projectEntity, Collections.emptyList(), aUser); // When modifiedProject.setPledgeGoal(projectEntity.getPledgeGoal() + 25); // Then assertThat(projectEntity.masterdataChanged(modifiedProject), is(true)); } @Test public void masterdataChanged_returnsFalseOnNoChange() throws Exception { prepareMasterData(projectEntity); Project unmodifiedProject = new Project(projectEntity, Collections.emptyList(), aUser); assertThat(projectEntity.masterdataChanged(unmodifiedProject), is(false)); } @Test public void modifyMasterData_returnsTrueWhenSuccessfullyModifiedByOwner() throws Exception { projectEntity.setFinancingRound(aTerminatedFinancingRound()); Project modCmd = new Project(projectEntity, Collections.emptyList(), aUser); modCmd.setDescription("CHANGED_DESCRIPTION"); assertThat(projectEntity.modifyMasterdata(modCmd, projectCreator), is(true)); } @Test public void modifyMasterData_returnsTrueWhenSuccessfullyModifiedByAdmin() throws Exception { projectEntity.setFinancingRound(aTerminatedFinancingRound()); Project modCmd = new Project(projectEntity, Collections.emptyList(), adminUser); modCmd.setDescription("CHANGED_DESCRIPTION"); assertThat(projectEntity.modifyMasterdata(modCmd, adminUser), is(true)); } @Test public void modifyMasterData_returnsFalseWhenNothingChanged() throws Exception { projectEntity.setFinancingRound(aTerminatedFinancingRound()); Project modCmd = new Project(projectEntity, Collections.emptyList(), aUser); assertThat(projectEntity.modifyMasterdata(modCmd, projectCreator), is(false)); } @Test(expected = NotAuthorizedException.class) public void modifyMasterData_throwsNotAuthorizedExceptionOnIllegalUser() throws Exception { projectEntity.setFinancingRound(aTerminatedFinancingRound()); Project modCmd = new Project(projectEntity, Collections.emptyList(), aUser); assertThat(projectEntity.modifyMasterdata(modCmd, aUser), is(false)); } @Test public void modifyMasterData_throwsInvalidReqExWhenChangeNotAllowed() throws Exception { projectEntity.setStatus(ProjectStatus.FULLY_PLEDGED); Project modCmd = new Project(projectEntity, Collections.emptyList(), aUser); modCmd.setDescription("CHANGED_DESCR"); try { projectEntity.modifyMasterdata(modCmd, projectCreator); fail("Exception expected to be thrown"); } catch (InvalidRequestException e) { assertThat(e.getMessage(), is(InvalidRequestException.masterdataChangeNotAllowed().getMessage())); } assertThat(projectEntity.getDescription(), not(equalTo(modCmd.getDescription()))); } @Test public void onFinancingRoundTerminated_ProjectPublishedHavingStatusDeferred() throws Exception { projectEntity.setStatus(ProjectStatus.DEFERRED); projectEntity.onFinancingRoundTerminated(projectEntity.getFinancingRound()); assertThat(projectEntity.getStatus(), is(ProjectStatus.PUBLISHED)); assertThat(projectEntity.getFinancingRound(), is(nullValue())); } @Test public void onFinancingRoundTerminated_ProjectUnchangedWhenDeferredButDifferentFinancingRound() throws Exception { projectEntity.setStatus(ProjectStatus.DEFERRED); projectEntity.onFinancingRoundTerminated(aTerminatedFinancingRound()); assertThat(projectEntity.getStatus(), is(ProjectStatus.DEFERRED)); assertThat(projectEntity.getFinancingRound().getId(), is(anActiveFinancingRound().getId())); } @Test public void onFinancingRoundTerminated_ProjectPublishedHavingStatusPublishedDeferred() throws Exception{ projectEntity.setStatus(ProjectStatus.PUBLISHED_DEFERRED); projectEntity.onFinancingRoundTerminated(projectEntity.getFinancingRound()); assertThat(projectEntity.getStatus(), is(ProjectStatus.PUBLISHED)); assertThat(projectEntity.getFinancingRound(), is(nullValue())); } @Test public void pledgedAmountPostRound() throws Exception { projectEntity.setFinancingRound(aTerminatedFinancingRound()); assertThat(projectEntity.pledgedAmountPostRound(bunchOfWithPostRoundPledgesDone()), is(1 + 2 + 3 + 4 + 5)); } @Test public void pledgedAmountPostRound_returnsZeroOnNoRoundNoTerminatedRoundAndNullOrEmptyPledges() throws Exception { List<PledgeEntity> pledges = bunchOfPledgesDone(); projectEntity.setFinancingRound(null); assertThat(projectEntity.pledgedAmountPostRound(pledges), is(0)); projectEntity.setFinancingRound(anActiveFinancingRound()); assertThat(projectEntity.pledgedAmountPostRound(pledges), is(0)); projectEntity.setFinancingRound(aTerminatedFinancingRound()); assertThat(projectEntity.pledgedAmountPostRound(null), is(0)); assertThat(projectEntity.pledgedAmountPostRound(Collections.emptyList()), is(0)); } @Test public void addAttachmentAllowed_DoNothingIfAllowed() { projectEntity.setStatus(ProjectStatus.PROPOSED); projectEntity.addAttachmentAllowed(projectCreator); } @Test(expected = NotAuthorizedException.class) public void addAttachmentAllowed_ThrowsNotAuthorizeddExceptionWhenUserForbidden() { projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(anActiveFinancingRound()); projectEntity.addAttachmentAllowed(aUser); } @Test public void addAttachmentAllowed_ThrowInvalidRequestExceptionWhenMasterdataChangesForbidden() { try { projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(anActiveFinancingRound()); projectEntity.addAttachmentAllowed(adminUser); fail("Exception expected to be thrown"); } catch (InvalidRequestException e) { assertThat(e.getMessage(), is(InvalidRequestException.masterdataChangeNotAllowed().getMessage())); } } @Test public void findAttachmentByReference_ShouldReturnExistingAttachment() { final String existingFileRef = "an_Existing_File_Ref"; final AttachmentValue expAttachmentValue = anAttachmentValue(existingFileRef); projectEntity.setAttachments(Arrays.asList( anAttachmentValue("non_Matching_File_Ref"), expAttachmentValue, anAttachmentValue("another_non_Matching_File_Ref"))); assertThat(projectEntity.findAttachmentByReference(Attachment.asLookupByIdCommand(existingFileRef)), is(expAttachmentValue)); } @Test(expected = IllegalArgumentException.class) public void findAttachmentByReference_ShouldThrowIllegalArgExceptionOnIncompleteRequestObject() { projectEntity.findAttachmentByReference(Attachment.asLookupByIdCommand(null)); } @Test(expected = ResourceNotFoundException.class) public void findAttachmentByReference_ShouldThrowResourceNotFoundExceptionOnNonExistingAttachment() { projectEntity.setAttachments(Arrays.asList( anAttachmentValue("non_Matching_File_Ref"), anAttachmentValue("another_non_Matching_File_Ref"))); projectEntity.findAttachmentByReference(Attachment.asLookupByIdCommand("realyNotMatching!")); } @Test public void deleteAttachmentAllowed_DoNothingIfAllowed() { projectEntity.setStatus(ProjectStatus.PROPOSED); projectEntity.deleteAttachmentAllowed(projectCreator); } @Test(expected = NotAuthorizedException.class) public void deleteAttachmentAllowed_ThrowsNotAuthorizeddExceptionWhenUserForbidden() { projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(anActiveFinancingRound()); projectEntity.deleteAttachmentAllowed(aUser); } @Test public void deleteAttachmentAllowed_ThrowInvalidRequestExceptionWhenMasterdataChangesForbidden() { try { projectEntity.setStatus(ProjectStatus.PUBLISHED); projectEntity.setFinancingRound(anActiveFinancingRound()); projectEntity.deleteAttachmentAllowed(adminUser); fail("Exception expected to be thrown"); } catch (InvalidRequestException e) { assertThat(e.getMessage(), is(InvalidRequestException.masterdataChangeNotAllowed().getMessage())); } } @Test public void deleteAttachment_ShouldDeleteByFileReferenceOnly() throws Exception { final String fileRef2Del = "file_ref_1"; projectEntity.setStatus(ProjectStatus.PROPOSED); projectEntity.addAttachment(anAttachmentValue("file_ref_0")); projectEntity.addAttachment(anAttachmentValue(fileRef2Del)); projectEntity.deleteAttachment(new AttachmentValue(fileRef2Del, null, "", 17L, DateTime.now())); assertThat(projectEntity.getAttachments().size(), is(1)); assertThat(projectEntity.getAttachments().get(0).getFileReference(), is(not(fileRef2Del))); } private FinancingRoundEntity aTerminatedFinancingRound() { FinancingRoundEntity res = aFinancingRound(new DateTime().minusDays(1)); assertThat(res.active(), is(false)); res.setId("test_IdInActive"); res.setCreatedDate(new DateTime().minusDays(3)); res.initPostRoundBudget(bunchOfPledgesDone().stream().mapToInt(p -> p.getAmount()).sum()); res.setTerminationPostProcessingDone(true); return res; } private FinancingRoundEntity anActiveFinancingRound() { FinancingRoundEntity res = aFinancingRound(new DateTime().plusDays(1)); assertThat(res.active(), is(true)); res.setId("test_IdActive"); return res; } private List<PledgeEntity> pledgesAlreadyDone(int pledgeAmount) { if (pledgeAmount == projectEntity.getPledgeGoal()) { projectEntity.setStatus(ProjectStatus.FULLY_PLEDGED); } return Collections.singletonList(new PledgeEntity(projectEntity, aUser, new Pledge(pledgeAmount), projectEntity.getFinancingRound())); } private void assertPledgeNotExecuted(RuntimeException actualEx, RuntimeException expEx, UserEntity user, int userBudgetBeforePledge, ProjectStatus expStatus) { assertThat(actualEx.getMessage(), is(expEx.getMessage())); assertThat(user.getBudget(), is(userBudgetBeforePledge)); assertThat(projectEntity.getStatus(), is(expStatus)); } private FinancingRoundEntity aFinancingRound(DateTime endDate) { FinancingRound creationCmd = new FinancingRound(); creationCmd.setEndDate(endDate); creationCmd.setBudget(1000); FinancingRoundEntity res = FinancingRoundEntity.newFinancingRound(creationCmd, 7); res.setStartDate(new DateTime().minusDays(2)); return res; } private List<PledgeEntity> bunchOfPledgesDone() { List<PledgeEntity> res = new ArrayList<>(); res.add(new PledgeEntity(projectEntity, aUser, new Pledge(10), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, adminUser, new Pledge(60), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, projectCreator, new Pledge(180), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, aUser, new Pledge(20), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, adminUser, new Pledge(70), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, aUser, new Pledge(10), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, aUser, new Pledge(-10), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, projectCreator, new Pledge(-180), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, projectCreator, new Pledge(-10), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, projectCreator, new Pledge(110), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, projectCreator, new Pledge(+10), projectEntity.getFinancingRound())); res.add(new PledgeEntity(projectEntity, projectCreator, new Pledge(-110), projectEntity.getFinancingRound())); return res; } private List<PledgeEntity> bunchOfWithPostRoundPledgesDone() { List<PledgeEntity> res = bunchOfPledgesDone(); res.addAll(bunchOfPostRoundPledges()); return res; } private List<PledgeEntity> bunchOfPostRoundPledges() { List<PledgeEntity> res = new ArrayList<>(); PledgeEntity pledge; for (int i = 1; i < COUNT_POST_ROUND_PLEDGES + 1; i++) { pledge = new PledgeEntity(projectEntity, adminUser, new Pledge(i), projectEntity.getFinancingRound()); pledge.setCreatedDate(projectEntity.getFinancingRound().getEndDate().plusHours(2 * i)); postRoundPledgedAmount += i; res.add(pledge); } return res; } private ProjectEntity prepareMasterData(ProjectEntity projectEntity) { projectEntity.setTitle("test_Title"); projectEntity.setDescription("test_Description"); projectEntity.setShortDescription("test_shortDescription"); projectEntity.setPledgeGoal(17); return projectEntity; } private AttachmentValue anAttachmentValue(String fileReference) { return new AttachmentValue(fileReference, MediaType.TEXT_PLAIN_VALUE, "fileName_" + fileReference, 617, DateTime.now() ); } }