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 java.util.Arrays;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.joda.time.LocalDate;
import org.junit.Before;
import org.junit.Test;
import br.com.caelum.calopsita.controller.IterationsController;
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.Iteration;
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.IterationRepository;
import br.com.caelum.calopsita.repository.ProjectRepository;
import br.com.caelum.calopsita.repository.UserRepository;
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 IterationTest {
private Mockery mockery;
private IterationsController logic;
private IterationRepository iterationRepository;
private CardRepository cardRepository;
private Project project;
private ProjectRepository projectRepository;
private User currentUser;
private UserRepository userRepository;
@Before
public void setUp() throws Exception {
mockery = new Mockery();
iterationRepository = mockery.mock(IterationRepository.class);
cardRepository = mockery.mock(CardRepository.class);
projectRepository = mockery.mock(ProjectRepository.class);
userRepository = mockery.mock(UserRepository.class);
currentUser = new User(userRepository);
currentUser.setLogin("me");
project = new Project(projectRepository);
SessionUser sessionUser = new SessionUser(new MockHttpSession());
sessionUser.setUser(currentUser);
logic = new IterationsController(new MockResult(), new MockValidator(), sessionUser);
}
@Test
public void savingAnIteration() throws Exception {
Iteration iteration = givenAnIteration();
shouldSaveOnTheRepositoryTheIteration(iteration);
whenISaveTheIteration(iteration);
mockery.assertIsSatisfied();
}
@Test
public void addingACardInAnIteration() throws Exception {
Iteration iteration = givenAnIteration();
Card card = givenACard();
shouldUpdateTheCard(card);
whenIAddTheCardToIteration(card, iteration);
assertThat(card.getIteration(), is(iteration));
mockery.assertIsSatisfied();
}
@Test
public void removingACardOfAnIteration() throws Exception {
Iteration iteration = givenAnIteration();
Card card = givenACard();
Card loaded = givenLoadedCardContainsIteration(card, iteration);
whenIRemoveTheCardOfIteration(card, iteration);
assertThat(loaded.getIteration(), is(nullValue()));
mockery.assertIsSatisfied();
}
@Test(expected=ValidationException.class)
public void removeAnIterationFromOtherProject() throws Exception {
Iteration iteration = givenAnIteration();
givenTheProjectIsOwnedBy(anyUser());
Iteration returned = givenTheIterationIsInThisProject(iteration);
shouldNotRemoveTheIterationFromRepository(returned);
whenIRemove(iteration);
mockery.assertIsSatisfied();
}
@Test
public void removeAnIterationFromMyProject() throws Exception {
Iteration iteration = givenAnIteration();
givenTheProjectIsOwnedBy(currentUser);
Card card = givenACard();
Iteration returnedIteration = givenTheIterationIsInThisProject(iteration);
givenTheIterationHasThisCard(card, returnedIteration);
shouldRemoveTheIterationFromRepository(returnedIteration);
whenIRemove(iteration);
assertThat(card.getIteration(), is(nullValue()));
mockery.assertIsSatisfied();
}
@Test(expected=ValidationException.class)
public void validatingDateOnSave() throws Exception {
Iteration iteration = givenAnIteration();
iteration.setStartDate(new LocalDate(2005,10,1));
iteration.setEndDate(new LocalDate(2005,8,1));
whenISaveTheIteration(iteration);
//should throw exception
}
@Test
public void startingAnIteration() throws Exception {
Iteration iteration = givenAnIteration();
Iteration loaded = givenTheIterationHaveNoStartDate(iteration);
whenIStartTheIteration(iteration);
assertThat(loaded.getStartDate(), is(today()));
mockery.assertIsSatisfied();
}
@Test(expected=IllegalArgumentException.class)
public void startingAnIterationAlreadyStarted() throws Exception {
Iteration iteration = givenAnIteration();
givenTheIterationAlreadyStarted(iteration);
whenIStartTheIteration(iteration);
}
@Test
public void endingAnIteration() throws Exception {
Iteration iteration = givenAnIteration();
Iteration loaded = givenTheIterationStartedYesterday(iteration);
whenIEndTheIteration(iteration);
assertThat(loaded.getEndDate(), is(today()));
mockery.assertIsSatisfied();
}
@Test(expected=IllegalArgumentException.class)
public void endingAnIterationAlreadyStarted() throws Exception {
Iteration iteration = givenAnIteration();
givenTheIterationNotStarted(iteration);
whenIEndTheIteration(iteration);
}
private Iteration givenTheIterationNotStarted(final Iteration iteration) {
final Iteration result = new Iteration(iterationRepository);
mockery.checking(new Expectations() {
{
one(iterationRepository).load(iteration);
will(returnValue(result));
}
});
return result;
}
@Test
public void editingAnIteration() throws Exception {
Iteration iteration = givenAnIteration();
Iteration loaded = shouldLoadFromRepository(iteration);
iteration.setGoal("Altered goal");
iteration.setStartDate(today());
iteration.setEndDate(tomorrow());
logic.update(iteration);
assertThat(loaded.getGoal(), is("Altered goal"));
assertThat(loaded.getStartDate(), is(today()));
assertThat(loaded.getEndDate(), is(tomorrow()));
mockery.assertIsSatisfied();
}
@Test
public void editingIterationShouldLoadItsFields() throws Exception {
Iteration iteration = givenAnIteration();
shouldLoadIteration(iteration);
logic.edit(iteration);
mockery.assertIsSatisfied();
}
@Test
public void formShouldIncludeLoadedProject() throws Exception {
Project project = givenAProject();
shouldLoadProject(project);
logic.form(project);
mockery.assertIsSatisfied();
}
@Test
public void currentShouldLoadCurrentIteration() throws Exception {
Project project = givenAProject();
shouldLoadCurrentIteration(project);
logic.current(project);
mockery.assertIsSatisfied();
}
@Test
public void shouldListIterationsOfAProject() throws Exception {
Project project = givenAProject();
shouldListIterations(project);
logic.list(project);
mockery.assertIsSatisfied();
}
@Test
public void showingIterationsShouldListBacklogCards() throws Exception {
Iteration iteration = givenAnIteration();
iteration.setProject(project);
shouldListBacklogCards(iteration);
logic.show(iteration);
mockery.assertIsSatisfied();
}
private void shouldListBacklogCards(final Iteration iteration) {
mockery.checking(new Expectations() {
{
one(projectRepository).planningCardsWithoutIteration(iteration.getProject());
ignoring(anything());
}
});
}
private void shouldListIterations(final Project project2) {
mockery.checking(new Expectations() {
{
one(projectRepository).listIterationsFrom(project2);
ignoring(anything());
}
});
}
private void shouldLoadCurrentIteration(final Project project2) {
mockery.checking(new Expectations() {
{
one(projectRepository).getCurrentIterationFromProject(project2);
ignoring(anything());
}
});
}
private void shouldLoadProject(final Project project2) {
mockery.checking(new Expectations() {
{
one(projectRepository).load(project2);
}
});
}
private Project givenAProject() {
return new Project(projectRepository);
}
private void shouldLoadIteration(final Iteration iteration) {
mockery.checking(new Expectations() {
{
one(iterationRepository).load(iteration);
ignoring(anything());
}
});
}
private LocalDate tomorrow() {
return new LocalDate().plusDays(1);
}
private LocalDate today() {
return new LocalDate();
}
private Iteration shouldLoadFromRepository(final Iteration iteration) {
final Iteration result = new Iteration(iterationRepository);
mockery.checking(new Expectations() {
{
one(iterationRepository).load(iteration);
will(returnValue(result));
}
});
return result;
}
private Iteration givenTheIterationAlreadyStarted(final Iteration iteration) {
final Iteration result = new Iteration(iterationRepository);
result.setStartDate(today().minusDays(1));
mockery.checking(new Expectations() {
{
one(iterationRepository).load(iteration);
will(returnValue(result));
}
});
return result;
}
private void whenIStartTheIteration(Iteration iteration) {
logic.start(iteration);
}
private void whenIEndTheIteration(Iteration iteration) {
logic.end(iteration);
}
private Iteration givenTheIterationHaveNoStartDate(final Iteration iteration) {
final Iteration result = new Iteration(iterationRepository);
mockery.checking(new Expectations() {
{
one(iterationRepository).load(iteration);
will(returnValue(result));
}
});
return result;
}
private Iteration givenTheIterationStartedYesterday(final Iteration iteration) {
final Iteration result = new Iteration(iterationRepository);
result.setStartDate(today().minusDays(1));
mockery.checking(new Expectations() {
{
one(iterationRepository).load(iteration);
will(returnValue(result));
}
});
return result;
}
private void givenTheIterationHasThisCard(final Card card, final Iteration returnedIteration) {
returnedIteration.addCard(card);
card.setIteration(returnedIteration);
mockery.checking(new Expectations() {
{
one(iterationRepository).listCards(returnedIteration);
will(returnValue(Arrays.asList(card)));
}
});
}
private void givenTheProjectIsOwnedBy(User user) {
project.setOwner(user);
}
private void shouldNotRemoveTheIterationFromRepository(final Iteration returned) {
mockery.checking(new Expectations() {
{
never(iterationRepository).remove(returned);
}
});
}
private User anyUser() {
User user = new User(userRepository);
user.setName("any name");
return user;
}
private void whenIRemove(Iteration iteration) {
logic.delete(iteration);
}
private void shouldRemoveTheIterationFromRepository(final Iteration returned) {
mockery.checking(new Expectations() {
{
one(iterationRepository).remove(returned);
allowing(iterationRepository).listCards(returned);
}
});
}
private Iteration givenTheIterationIsInThisProject(final Iteration iteration) {
final Iteration returned = new Iteration(iterationRepository);
returned.setProject(this.project);
mockery.checking(new Expectations() {
{
one(iterationRepository).load(iteration);
will(returnValue(returned));
}
});
return returned;
}
private void whenIRemoveTheCardOfIteration(Card card, Iteration iteration) {
logic.removeCards(iteration, Arrays.asList(card));
}
private Card givenLoadedCardContainsIteration(final Card card, final Iteration iteration) {
final Card loaded = new Card(cardRepository);
mockery.checking(new Expectations() {
{
loaded.setIteration(iteration);
one(cardRepository).load(card);
will(returnValue(loaded));
one(cardRepository).update(loaded);
allowing(iterationRepository).listCards(with(any(Iteration.class)));
allowing(projectRepository).planningCardsWithoutIteration(with(any(Project.class)));
allowing(iterationRepository).load(iteration);
will(returnValue(iteration));
ignoring(anything());
}
});
return loaded;
}
private void shouldUpdateTheCard(final Card card) {
mockery.checking(new Expectations() {
{
one(cardRepository).update(card);
one(cardRepository).load(card);
will(returnValue(card));
allowing(iterationRepository).listCards(with(any(Iteration.class)));
allowing(projectRepository).planningCardsWithoutIteration(with(any(Project.class)));
allowing(iterationRepository).load(with(any(Iteration.class)));
will(returnValue(new Iteration(iterationRepository)));
ignoring(anything());
}
});
}
private void whenIAddTheCardToIteration(Card card, Iteration iteration) {
logic.updateCards(iteration, Arrays.asList(card));
}
private Card givenACard() {
return new Card(cardRepository);
}
private void shouldSaveOnTheRepositoryTheIteration(final Iteration iteration) {
mockery.checking(new Expectations() {
{
one(iterationRepository).add(iteration);
}
});
}
private void whenISaveTheIteration(Iteration iteration) {
logic.save(iteration);
}
private Iteration givenAnIteration() {
Iteration iteration = new Iteration(iterationRepository);
iteration.setProject(project);
return iteration;
}
}