package br.com.caelum.calopsita.logic; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.jmock.Expectations; import org.jmock.Mockery; import org.junit.Before; import org.junit.Test; import br.com.caelum.calopsita.controller.CardsController; import br.com.caelum.calopsita.infra.vraptor.SessionUser; import br.com.caelum.calopsita.mocks.MockHttpSession; import br.com.caelum.calopsita.model.Card; import br.com.caelum.calopsita.model.Gadgets; import br.com.caelum.calopsita.model.Project; import br.com.caelum.calopsita.model.User; import br.com.caelum.calopsita.repository.CardRepository; import br.com.caelum.calopsita.repository.ProjectRepository; import br.com.caelum.vraptor.util.test.MockResult; import br.com.caelum.vraptor.util.test.MockValidator; import br.com.caelum.vraptor.validator.ValidationException; public class CardTest { private Mockery mockery; private CardsController logic; private CardRepository repository; private Card currentCard; private ProjectRepository projectRepository; private Project project; private User currentUser; private MockValidator validator; @Before public void setUp() throws Exception { mockery = new Mockery(); repository = mockery.mock(CardRepository.class); SessionUser sessionUser = new SessionUser(new MockHttpSession()); currentUser = new User(); currentUser.setLogin("me"); sessionUser.setUser(currentUser); projectRepository = mockery.mock(ProjectRepository.class); project = new Project(projectRepository); validator = new MockValidator(); logic = new CardsController(new MockResult(), validator, sessionUser); } @Test public void savingACard() throws Exception { Project project = givenAProject(); Card card = givenACard(); shouldSaveOnTheRepositoryTheCard(card); whenISaveTheCard(card, onThe(project)); assertThat(card.getProject(), is(project)); assertThat(card.getCreator(), is(currentUser)); mockery.assertIsSatisfied(); } @Test public void editingACardsDescription() throws Exception { Card card = givenACard(); givenTheCard(card).withName("Huck Finn") .withDescription("He is Tom Sawyer's best mate."); Card loadedCard = shouldLoadTheCard(card); shouldUpdateOnTheRepositoryTheCard(loadedCard); whenIEditTheCard(card, changingNameTo("Huckleberry Finn"), changingDescriptionTo("He has a drunk father.")); assertThat(loadedCard.getName(), is("Huckleberry Finn")); assertThat(loadedCard.getDescription(), is("He has a drunk father.")); mockery.assertIsSatisfied(); } @Test public void removeACardFromMyProject() throws Exception { Card card = givenACard(); givenTheProjectIsOwnedBy(currentUser); Card returned = givenTheCardIsInThisProject(card); shouldRemoveTheCardFromRepository(returned); whenIRemove(card); mockery.assertIsSatisfied(); } @Test public void removeACardFromOtherProjectThanMine() throws Exception { Card card = givenACard(); givenTheProjectIsOwnedBy(anyUser()); Card returned = givenTheCardIsInThisProject(card); shouldNotRemoveTheCardFromRepository(returned); try { whenIRemove(card); fail("Expected ValidationException"); } catch (ValidationException e) { mockery.assertIsSatisfied(); } } @Test public void removeACardAndSubcards() throws Exception { Card card = givenACard(); givenTheProjectIsOwnedBy(currentUser); Card subcard = givenACard(); subcard.setParent(card); Card returned = givenTheCardIsInThisProject(card); givenTheCardHasSubCard(returned, subcard); shouldRemoveTheCardFromRepository(returned); shouldRemoveTheCardFromRepository(subcard); logic.delete(card, true); mockery.assertIsSatisfied(); } private void givenTheCardHasSubCard(final Card returned, final Card subcard) { mockery.checking(new Expectations() { { one(repository).listSubcards(returned); will(returnValue(Arrays.asList(subcard))); } }); } @Test public void removeACardButNotSubcards() throws Exception { Card card = givenACard(); givenTheProjectIsOwnedBy(currentUser); Card subCard = givenACard(); subCard.setParent(card); Card returned = givenTheCardIsInThisProject(card); givenTheCardHasSubCard(returned, subCard); shouldRemoveTheCardFromRepository(returned); shouldUpdateTheCardFromRepository(subCard); logic.delete(card, false); assertThat(subCard.getParent(), is(nullValue())); mockery.assertIsSatisfied(); } @Test public void savingACardWithGadgets() throws Exception { Project project = givenAProject(); Card card = givenACard(); Gadgets prioritization = Gadgets.PRIORITIZATION; shouldSaveOnTheRepositoryTheCard(card); shouldSaveAGadgetOfType(prioritization); whenISaveTheCard(card, onThe(project), withGadgets(prioritization)); assertThat(card.getProject(), is(project)); mockery.assertIsSatisfied(); } @Test public void listingCardsShouldIncludeOnlyTodoCards() throws Exception { shouldIncludeTodoCards(); logic.list(project); mockery.assertIsSatisfied(); } @Test public void listingAllCardsShouldIncludeAllCards() throws Exception { shouldIncludeAllCards(); logic.all(project); mockery.assertIsSatisfied(); } @Test public void formShouldIncludeAllCardTypes() throws Exception { shouldIncludeAllCardTypes(); logic.form(project); mockery.assertIsSatisfied(); } @Test public void subcardFormShouldIncludeAllCardTypes() throws Exception { Card card = givenACard(); card.setProject(project); shouldIncludeAllCardTypes(); logic.subcardForm(card); mockery.assertIsSatisfied(); } @Test public void editFormShouldIncludeAllCardTypes() throws Exception { Card card = givenACard(); card.setProject(project); shouldIncludeAllCardTypes(); logic.edit(card); mockery.assertIsSatisfied(); } @Test public void listingSubcardsShouldIncludeSubcardsList() throws Exception { Card card = givenACard(); shouldIncludeSubcardsList(card); logic.listSubcards(card); mockery.assertIsSatisfied(); } private void shouldIncludeSubcardsList(final Card card) { mockery.checking(new Expectations() { { one(repository).listSubcards(card); ignoring(anything()); } }); } private void shouldIncludeAllCardTypes() { mockery.checking(new Expectations() { { one(projectRepository).listCardTypesFrom(project); ignoring(anything()); } }); } private void shouldIncludeAllCards() { mockery.checking(new Expectations() { { one(projectRepository).listRootCardsFrom(project); ignoring(anything()); } }); } private void whenISaveTheCard(Card card, Project project, List<Gadgets> gadgets) { card.setProject(project); logic.save(card, gadgets); } private List<Gadgets> withGadgets(Gadgets... gadgets) { return Arrays.asList(gadgets); } private void shouldSaveAGadgetOfType(final Gadgets prioritization) { mockery.checking(new Expectations() { { one(repository).add(with(any(prioritization.gadgetClass()))); } }); } private void shouldIncludeTodoCards() { mockery.checking(new Expectations() { { one(projectRepository).listTodoCardsFrom(project); ignoring(anything()); } }); } private Card givenTheCardIsInThisProject(final Card card) { mockery.checking(new Expectations() { { one(repository).load(card); will(returnValue(card)); one(projectRepository).load(project); will(returnValue(project)); } }); return card; } private void givenTheProjectIsOwnedBy(User user) { project.setOwner(user); } private void shouldUpdateTheCardFromRepository(final Card subcard) { mockery.checking(new Expectations() { { one(repository).update(subcard); } }); } private void shouldNotRemoveTheCardFromRepository(final Card returned) { mockery.checking(new Expectations() { { never(repository).remove(returned); } }); } private User anyUser() { User user = new User(); user.setLogin("any"); return user; } private void shouldRemoveTheCardFromRepository(final Card returned) { mockery.checking(new Expectations() { { one(repository).remove(returned); allowing(projectRepository).listTodoCardsFrom(project); allowing(repository).listSubcards(returned); } }); } private void whenIRemove(Card card) { logic.delete(card, false); } private CardTest givenTheCard(Card card) { currentCard = card; return this; } private CardTest withName(String cardName) { currentCard.setName(cardName); return this; } private CardTest withDescription(String cardDescription) { currentCard.setDescription(cardDescription); return this; } private Card shouldLoadTheCard(final Card card) { final Card newcard = new Card(repository); mockery.checking(new Expectations() { { allowing(projectRepository); one(repository).load(card); will(returnValue(newcard)); } }); return newcard; } private void shouldUpdateOnTheRepositoryTheCard(final Card card) { mockery.checking(new Expectations() { { allowing(projectRepository); one(repository).update(card); one(repository).updateGadgets(with(any(Card.class)), with(any(List.class))); } }); } private String changingNameTo(String cardName) { return cardName; } private String changingDescriptionTo(String newDescription) { return newDescription; } private void whenIEditTheCard(Card card, String newName, String newDescription) { card.setName(newName); card.setDescription(newDescription); logic.update(card, new ArrayList<Gadgets>()); } private void shouldSaveOnTheRepositoryTheCard(final Card card) { mockery.checking(new Expectations() { { allowing(projectRepository); one(repository).add(card); } }); } private Project onThe(Project project) { return project; } private void whenISaveTheCard(Card card, Project project) { card.setProject(project); logic.save(card, new ArrayList<Gadgets>()); } private Project givenAProject() { Project project2 = new Project(projectRepository); return project2; } private Card givenACard() { Card card = new Card(repository); card.setProject(project); return card; } }