package br.com.caelum.calopsita.logic;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.util.Collections;
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.ProjectsController;
import br.com.caelum.calopsita.infra.vraptor.SessionUser;
import br.com.caelum.calopsita.mocks.MockHttpSession;
import br.com.caelum.calopsita.model.Project;
import br.com.caelum.calopsita.model.User;
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 ProjectTest {
private Mockery mockery;
private ProjectsController logic;
private ProjectRepository repository;
private User currentUser;
private UserRepository userRepository;
@Before
public void setUp() throws Exception {
mockery = new Mockery();
repository = mockery.mock(ProjectRepository.class);
userRepository = mockery.mock(UserRepository.class);
currentUser = currentUser();
SessionUser sessionUser = new SessionUser(new MockHttpSession());
sessionUser.setUser(currentUser);
logic = new ProjectsController(new MockValidator(), new MockResult(), sessionUser);
}
@Test
public void listingAProject() throws Exception {
Project project = givenThatOnlyExistsOneProjectForCurrentUser();
List<Project> projects = whenIListProjects();
thenTheLogicShouldExposeOnlyTheProject(projects, project);
mockery.assertIsSatisfied();
}
@Test
public void saveAProject() throws Exception {
Project project = givenAProject();
shouldSaveTheProjectOnTheRepository(project);
whenISaveTheProject(project);
assertThat(project.getOwner(), is(currentUser));
mockery.assertIsSatisfied();
}
@Test
public void addingColaboratorsToAProject() throws Exception {
Project project = givenAProject();
User user = givenAUser();
shouldReloadAndUpdateTheProject(project);
whenIAddTheUserToTheProject(user, project);
thenTheProjectWillContainTheUserAsColaborator(project, user);
mockery.assertIsSatisfied();
}
@Test
public void removingAProjectOwnedByMe() throws Exception {
Project project = givenAProject();
Project loaded = givenProjectIsOwnedBy(project, currentUser);
shouldRemoveFromRepository(loaded);
whenIRemoveTheProject(project);
mockery.assertIsSatisfied();
}
@Test(expected=ValidationException.class)
public void removingAProjectOwnedByOthers() throws Exception {
Project project = givenAProject();
Project loaded = givenProjectIsOwnedBy(project, givenAUser());
shouldNotRemoveFromRepository(loaded);
whenIRemoveTheProject(project);
mockery.assertIsSatisfied();
}
@Test
public void editingAProjectOwnedByMe() throws Exception {
Project project = givenAProject();
project.setDescription("New description");
Project loaded = givenProjectIsOwnedBy(project, currentUser);
whenIEditTheProject(project);
assertThat(loaded.getDescription(), is("New description"));
mockery.assertIsSatisfied();
}
@Test(expected=ValidationException.class)
public void editingAProjectOwnedByOthers() throws Exception {
Project project = givenAProject();
project.setDescription("Anything");
Project loaded = givenProjectIsOwnedBy(project, givenAUser());
whenIEditTheProject(project);
assertThat(loaded.getDescription(), is(not("Anything")));
mockery.assertIsSatisfied();
}
private void whenIEditTheProject(Project project) {
logic.update(project);
}
private void shouldNotRemoveFromRepository(final Project project) {
mockery.checking(new Expectations() {
{
never(repository).remove(project);
}
});
}
private Project givenProjectIsOwnedBy(final Project project, final User user) {
final Project result = new Project(repository);
result.setOwner(user);
mockery.checking(new Expectations() {
{
one(repository).load(project);
will(returnValue(result));
}
});
return result;
}
private void shouldRemoveFromRepository(final Project project) {
mockery.checking(new Expectations() {
{
one(repository).remove(project);
}
});
}
private void whenIRemoveTheProject(Project project) {
logic.delete(project);
}
private void shouldReloadAndUpdateTheProject(final Project project) {
mockery.checking(new Expectations() {
{
one(repository).load(project);
will(returnValue(project));
}
});
}
private void thenTheProjectWillContainTheUserAsColaborator(Project project, User user) {
assertThat(project.getColaborators(), hasItem(user));
}
private void whenIAddTheUserToTheProject(User user, Project project) {
logic.addColaborator(project, user);
}
private User givenAUser() {
return new User(userRepository);
}
private void whenISaveTheProject(Project project) {
logic.save(project);
}
private void shouldSaveTheProjectOnTheRepository(final Project project) {
mockery.checking(new Expectations() {
{
one(repository).add(project);
}
});
}
private Project givenAProject() {
Project project = new Project(repository);
project.setName("A project");
return project;
}
private void thenTheLogicShouldExposeOnlyTheProject(List<Project> projects, Project project) {
assertThat(projects, is(notNullValue()));
assertThat(projects.size(), is(1));
assertThat(projects, hasItem(project));
}
private List<Project> whenIListProjects() {
return logic.list();
}
private Project givenThatOnlyExistsOneProjectForCurrentUser() {
final Project project = new Project(repository);
mockery.checking(new Expectations() {
{
one(userRepository).listAllFrom(currentUser);
will(returnValue(Collections.singletonList(project)));
}
});
return project;
}
private User currentUser() {
final User user = new User(userRepository);
String login = "caue";
user.setLogin(login);
user.setEmail(login + "@caelum.com.br");
user.setName(login);
user.setPassword(login);
return user;
}
}