package br.com.caelum.calopsita.persistence.dao; import static br.com.caelum.calopsita.CustomMatchers.hasItemsInThisOrder; import static br.com.caelum.calopsita.CustomMatchers.hasSameId; import static br.com.caelum.calopsita.CustomMatchers.isEmpty; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; import java.text.ParseException; import java.util.Arrays; import java.util.List; import org.hibernate.Session; import org.jmock.Expectations; import org.jmock.Sequence; import org.joda.time.LocalDate; import org.junit.Before; import org.junit.Test; import br.com.caelum.calopsita.model.Card; import br.com.caelum.calopsita.model.Iteration; import br.com.caelum.calopsita.model.Project; import br.com.caelum.calopsita.model.User; import br.com.caelum.calopsita.model.Card.Status; import br.com.caelum.calopsita.plugins.PluginResultTransformer; import br.com.caelum.calopsita.plugins.Transformer; import br.com.caelum.calopsita.plugins.planning.PlanningCard; import br.com.caelum.calopsita.plugins.prioritization.OrderByPriorityTransformer; import br.com.caelum.calopsita.plugins.prioritization.PrioritizableCard; import br.com.caelum.calopsita.repository.ProjectRepository; public class ProjectDaoTest extends AbstractDaoTest { private ProjectRepository dao; private IterationDao iterationDao; private CardDao cardDao; private UserDao userDao; private Session mockSession; @Override @Before public void setUp() throws Exception { super.setUp(); List<Transformer> transformers = Arrays.<Transformer>asList(new OrderByPriorityTransformer()); PluginResultTransformer transformer = new PluginResultTransformer(session, transformers); dao = new ProjectDao(session, transformer); iterationDao = new IterationDao(session, transformer); cardDao = new CardDao(session,transformer); userDao = new UserDao(session); } @Test public void gettingCurrentIterationWithNoDates() throws Exception { Iteration iteration = givenAnIteration(null, null); Iteration current = dao.getCurrentIterationFromProject(iteration.getProject()); assertThat(current, not(is(iteration))); } @Test public void gettingCurrentIterationAlreadyStartedButNotFinished() throws Exception { Iteration iteration = givenAnIteration(withStartDate(yesterday()), withEndDate(tomorrow())); Iteration current = dao.getCurrentIterationFromProject(iteration.getProject()); assertThat(current, is(iteration)); } @Test public void gettingCurrentIterationAlreadyStartedAndFinished() throws Exception { Iteration iteration = givenAnIteration(withStartDate(yesterday()), withEndDate(yesterday())); Iteration current = dao.getCurrentIterationFromProject(iteration.getProject()); assertThat(current, not(is(iteration))); } @Test public void gettingCurrentIterationAlreadyStartedWithNoEndDate() throws Exception { Iteration iteration = givenAnIteration(withStartDate(yesterday())); Iteration current = dao.getCurrentIterationFromProject(iteration.getProject()); assertThat(current, is(iteration)); } @Test public void gettingCurrentIterationNotStartedYet() throws Exception { Iteration iteration = givenAnIteration(withStartDate(tomorrow())); Iteration current = dao.getCurrentIterationFromProject(iteration.getProject()); assertThat(current, not(is(iteration))); } @Test public void orderedListings() throws Exception { Project project = givenAProject(); Card card3 = givenAPlanningCard(project, withPriority(3)); Card card1 = givenAPlanningCard(project, withPriority(1)); assertThat(dao.planningCardsWithoutIteration(project), hasItemsInThisOrder(card1, card3)); } @Test public void cardsWithoutIteration() throws Exception { Iteration iteration = givenAnIteration(); Card card = givenAPlanningCard(iteration.getProject()); Card cardOfIteration = givenAPrioritizableCardOfTheIteration(iteration); Card cardOfOtherProject = givenAPlanningCard(givenAProject()); Card notAPlanningCard = givenACard(givenAProject()); List<Card> list = dao.planningCardsWithoutIteration(iteration.getProject()); assertThat(list, hasItem(card)); assertThat(list, not(hasItem(cardOfIteration))); assertThat(list, not(hasItem(cardOfOtherProject))); assertThat(list, not(hasItem(notAPlanningCard))); } @Test public void refreshingAProject() throws Exception { Project project = givenAProject(); session.evict(project); Project project2 = new Project(dao); project2.setId(project.getId()); project2.refresh(); assertThat(project2.getName(), is(project.getName())); } @Test public void onlyListCardsFromTheGivenProject() throws Exception { Project project = givenAProject(); Card cardFromOtherProject = givenACard(); Card cardFromThisProject = givenACardOfProject(project); List<Card> list = dao.listRootCardsFrom(project); assertThat(list, not(hasItem(hasSameId(cardFromOtherProject)))); assertThat(list, hasItem(hasSameId(cardFromThisProject))); } @Test public void doNotListSubCardsWhenListingCards() throws Exception { Project project = givenAProject(); Card parent = givenACardOfProject(project); Card subcard = givenASubcardOf(parent); List<Card> list = dao.listRootCardsFrom(project); assertThat(list, not(hasItem(hasSameId(subcard)))); assertThat(list, hasItem(hasSameId(parent))); } @Test public void onlyListToDoCardsFromTheGivenProject() throws Exception { Project project = givenAProject(); Card cardFromOtherProject = givenACard(); Card cardFromThisProject = givenACardOfProject(project); Card donecardFromThisProject = givenACardOfProject(project); donecardFromThisProject.setStatus(Status.DONE); List<Card> list = dao.listTodoCardsFrom(project); assertThat(list, not(hasItems(hasSameId(cardFromOtherProject), hasSameId(donecardFromThisProject)))); assertThat(list, hasItem(hasSameId(cardFromThisProject))); } @Test public void doNotListSubCardsWhenListingTodoCards() throws Exception { Project project = givenAProject(); Card parent = givenACardOfProject(project); Card subcard = givenASubcardOf(parent); List<Card> list = dao.listTodoCardsFrom(project); assertThat(list, not(hasItem(hasSameId(subcard)))); assertThat(list, hasItem(hasSameId(parent))); } @Test public void onlyListIterationsFromTheGivenProject() throws Exception { Project project = givenAProject(); Iteration iterationFromOtherProject = givenAnIteration(); Iteration iterationFromThisProject = givenAnIterationOfProject(project); List<Iteration> list = dao.listIterationsFrom(project); assertThat(list, not(hasItem(hasSameId(iterationFromOtherProject)))); assertThat(list, hasItem(hasSameId(iterationFromThisProject))); } @Test public void removeAProjectAlsoRemoveRelatedCardsAndIterations() throws Exception { Project project = givenAProject(); givenAnIterationOfProject(project); givenACardOfProject(project); dao.remove(project); assertThat(dao.listIterationsFrom(project), isEmpty()); assertThat(dao.listRootCardsFrom(project), isEmpty()); } @Test public void aProjectNotOwnedByAUserIsAnInconsistentValue() throws Exception { Project project = givenAProject(); User user = givenAUser(); assertThat(dao.hasInconsistentValues(new Object[] {project}, user), is(true)); } @Test public void aProjectNotOwnedByAUserIsAConsistentValue() throws Exception { User user = givenAUser(); Project project1 = givenAProjectOwnedBy(user); Project project2 = givenAProjectWithColaborator(user); assertThat(dao.hasInconsistentValues(new Object[] {project1, project2}, user), is(false)); } @Test public void checkingForInconsistentValuesInIterations() throws Exception { User user = givenAUser(); Iteration unrelatedProject = givenAnIterationOfProject(givenAProject()); assertThat(dao.hasInconsistentValues(new Object[] {unrelatedProject}, user), is(true)); Iteration projectOwned = givenAnIterationOfProject(givenAProjectOwnedBy(user)); Iteration projectWithColaborator = givenAnIterationOfProject(givenAProjectWithColaborator(user)); assertThat(dao.hasInconsistentValues(new Object[] {projectOwned, projectWithColaborator}, user), is(false)); } @Test public void iterationWithWrongProjectId() throws Exception { User user = givenAUser(); Iteration iteration = givenAnIterationOfProject(givenAProjectOwnedBy(user)); session.evict(iteration); iteration.setProject(givenAProjectOwnedBy(user)); assertThat(dao.hasInconsistentValues(new Object[] {iteration}, user), is(true)); } @Test public void cardWithWrongProjectId() throws Exception { User user = givenAUser(); Card card = givenACardOfProject(givenAProjectOwnedBy(user)); session.evict(card); card.setProject(givenAProjectOwnedBy(user)); assertThat(dao.hasInconsistentValues(new Object[] {card}, user), is(true)); } @Test public void cardWithoutIdWithAProjectIdIsConsistent() throws Exception { User user = givenAUser(); Card card = givenACardOfProject(givenAProjectOwnedBy(user)); session.evict(card); card.setId(null); assertThat(dao.hasInconsistentValues(new Object[] {card}, user), is(false)); } @Test(expected=IllegalArgumentException.class) public void iterationWithoutProjectIdThrowsException() throws Exception { Iteration projectWithoutId = new Iteration(iterationDao); projectWithoutId.setProject(new Project(dao)); dao.hasInconsistentValues(new Object[] {projectWithoutId}, givenAUser()); } @Test(expected=IllegalArgumentException.class) public void iterationWithoutProjectThrowsException() throws Exception { Iteration outOfProject = new Iteration(iterationDao); dao.hasInconsistentValues(new Object[] {outOfProject}, givenAUser()); } @Test public void findUnrelatedUsers() throws Exception { Project project = givenAProject(); User owner = givenAnUserOwnerOf(project); User colaborator = givenAnUserColaboratorOf(project); User user = givenAnUnrelatedUser("pedro"); List<User> users = dao.listUnrelatedUsers(project); assertThat(users, hasItem(user)); assertThat(users, not(hasItem(owner))); assertThat(users, not(hasItem(colaborator))); } @Test public void findUnreleatedUsersWhenThereIsNoColaborator() throws Exception { Project project = givenAProject(); User owner = givenAnUserOwnerOf(project); User user = givenAnUnrelatedUser("pedro"); List<User> users = dao.listUnrelatedUsers(project); assertThat(users, hasItem(user)); assertThat(users, not(hasItem(owner))); } @Test public void shouldShowOnlyLastFiveAddedCards() throws Exception { Project project = givenAProject(); Card first = givenACard(project); Card second = givenACard(project); Card third = givenACard(project); Card forth = givenACard(project); Card fifth = givenACard(project); Card sixth = givenACard(project); List<Card> list = dao.listLastAddedCards(project); assertThat(list.size(), is(5)); assertThat(list, not(hasItem(first))); assertThat(list, hasItems(second, third, forth, fifth, sixth)); } @Test public void testDelegation() throws Exception { ProjectRepository mockedDao = givenAMockedDao(); shouldExecuteCrudInSequence(); mockedDao.add(new Project()); mockedDao.load(new Project()); mockedDao.update(new Project()); mockery.assertIsSatisfied(); } @Test public void cardsWithoutIterationDontIncludeCardsFromOtherProject() throws Exception { Project project = givenAProject(); Card cardFromProject = givenAPlanningCard(project); Card cardFromOtherProject = givenAPlanningCard(givenAProject()); List<Card> cards = dao.planningCardsWithoutIteration(project); assertThat(cards, hasItem(cardFromProject)); assertThat(cards, not(hasItem(cardFromOtherProject))); mockery.assertIsSatisfied(); } @Test public void cardsWithoutIterationDontIncludeCardsInAnIteration() throws Exception { Project project = givenAProject(); Iteration iteration = givenAnIteration(project); Card cardFromOtherIteration = givenAPlanningCard(project); Card cardWithoutIteration = givenAPlanningCardOfIteration(iteration); List<Card> cards = dao.planningCardsWithoutIteration(project); assertThat(cards, hasItem(cardFromOtherIteration)); assertThat(cards, not(hasItem(cardWithoutIteration))); mockery.assertIsSatisfied(); } @Test public void cardsWithoutIterationIncludeTodoCardsOfAnPastIteration() throws Exception { Project project = givenAProject(); Iteration pastIteration = givenAnIteration(yesterday(), yesterday(), project); Iteration futureIteration = givenAnIteration(tomorrow(), tomorrow(), project); Card donePastCard = givenAPlanningCardOfIteration(pastIteration); donePastCard.setStatus(Status.DONE); Card todoPastCard = givenAPlanningCardOfIteration(pastIteration); todoPastCard.setStatus(Status.TODO); Card doneFutureCard = givenAPlanningCardOfIteration(futureIteration); doneFutureCard.setStatus(Status.DONE); Card todoFutureCard = givenAPlanningCardOfIteration(futureIteration); todoFutureCard.setStatus(Status.TODO); List<Card> cards = dao.planningCardsWithoutIteration(project); assertThat(cards, not(hasItem(doneFutureCard))); assertThat(cards, not(hasItem(todoFutureCard))); assertThat(cards, not(hasItem(donePastCard))); assertThat(cards, hasItem(todoPastCard)); mockery.assertIsSatisfied(); } private Iteration givenAnIteration(LocalDate startDate, LocalDate endDate, Project project) { Iteration iteration = givenAnIteration(startDate, endDate); iteration.setProject(project); session.flush(); return iteration; } private Iteration givenAnIteration(Project project) throws ParseException { Iteration iteration = givenAnIteration(); iteration.setProject(project); return iteration; } private Card givenAPlanningCardOfIteration(Iteration iteration) { Card card = givenAPlanningCard(iteration.getProject()); card.setIteration(iteration); return card; } private ProjectRepository givenAMockedDao() { mockSession = mockery.mock(Session.class); return new ProjectDao(mockSession, null); } private void shouldExecuteCrudInSequence() { final Sequence crud = mockery.sequence("crud"); mockery.checking(new Expectations() { { one(mockSession).save(with(any(Project.class))); inSequence(crud); one(mockSession).load(Project.class, null); will(returnValue(new Project())); inSequence(crud); one(mockSession).update(with(any(Project.class))); inSequence(crud); } }); } private User givenAnUserColaboratorOf(Project project) { User user = givenAnUnrelatedUser("caue"); project.setColaborators(Arrays.asList(user)); this.session.flush(); return user; } private User givenAnUserOwnerOf(Project project) { User user = givenAnUnrelatedUser("lucas"); project.setOwner(user); this.session.flush(); return user; } private Iteration givenAnIteration(LocalDate startDate, LocalDate endDate) { Iteration iteration = new Iteration(iterationDao); iteration.setGoal("An iteration"); iteration.setProject(givenAProject()); iteration.setStartDate(startDate); iteration.setEndDate(endDate); session.save(iteration); session.flush(); return iteration; } private User givenAnUnrelatedUser(String name) { User user = new User(userDao); user.setName(name); user.setEmail(name + "@caelum.com.br"); user.setLogin(name); user.setPassword(name); this.session.save(user); this.session.flush(); return user; } private Iteration givenAnIteration(LocalDate startDate) { Iteration iteration = new Iteration(iterationDao); iteration.setGoal("An iteration"); iteration.setProject(givenAProject()); iteration.setStartDate(startDate); session.save(iteration); session.flush(); return iteration; } private Iteration givenAnIterationOfProject(Project project) throws ParseException { Iteration iteration = givenAnIteration(); iteration.setProject(project); session.update(iteration); session.flush(); return iteration; } private Iteration givenAnIteration() throws ParseException { Iteration iteration = new Iteration(iterationDao); iteration.setGoal("Be ready"); iteration.setStartDate(yesterday()); iteration.setEndDate(tomorrow()); iteration.setProject(givenAProject()); session.save(iteration); session.flush(); return iteration; } private Card givenAPlanningCard(Project project, int priority) { Card card = givenAPlanningCard(project); PrioritizableCard pCard = new PrioritizableCard(); pCard.setCard(card); pCard.setPriority(priority); session.save(pCard); session.flush(); return card; } private int withPriority(int i) { return i; } private Card givenACardOfProject(Project project) { Card card = givenACard(); card.setProject(project); session.update(card); session.flush(); return card; } private Card givenASubcardOf(Card card) { Card subcard = givenACardOfProject(card.getProject()); subcard.setParent(card); session.update(subcard); session.flush(); return subcard; } private Card givenACard() { Card card = new Card(cardDao); card.setName("Snow White"); card.setDescription("She hangs out with the dwarves"); session.save(card); session.flush(); return card; } private LocalDate withEndDate(LocalDate date) { return date; } private LocalDate tomorrow() { return new LocalDate().plusDays(1); } private LocalDate withStartDate(LocalDate date) { return date; } private LocalDate yesterday() { return new LocalDate().minusDays(1); } private Card givenAPrioritizableCardOfTheIteration(Iteration iteration) { Card card = givenAPlanningCard(iteration.getProject()); card.setIteration(iteration); session.update(card); session.flush(); return card; } private Card givenAPlanningCard(Project project) { Card card = givenACard(project); session.save(PlanningCard.of(card)); session.flush(); return card; } private Card givenACard(Project project) { Card card = givenACard(); card.setProject(project); session.flush(); return card; } private Project givenAProjectWithColaborator(User user) { Project project = givenAProject(); project.getColaborators().add(user); session.update(project); session.flush(); return project; } private Project givenAProjectOwnedBy(User user) { Project project = givenAProject(); project.setOwner(user); session.update(project); session.flush(); return project; } private Project givenAProject() { Project project = new Project(dao); project.setName("Tuba"); session.save(project); session.flush(); return project; } private User givenAUser() { User user = new User(userDao); user.setLogin("test"); user.setPassword("test"); user.setName("User test"); user.setEmail("test@caelum.com.br"); session.save(user); session.flush(); return user; } }