From cd933c47243a0b7c99116070c39d7cd24d207fb3 Mon Sep 17 00:00:00 2001 From: Adriel Felix Date: Mon, 29 Apr 2024 14:19:15 -0300 Subject: [PATCH 1/6] change task id type>: Long -> UUID --- .../challenge/modules/task/dtos/TaskProgressDTO.java | 4 +++- source/backend/challenge/modules/task/models/Task.java | 6 ++---- .../challenge/modules/task/services/DeleteTaskService.java | 3 ++- .../challenge/modules/task/services/IDeleteTaskService.java | 4 +++- .../modules/task/services/IRetrieveTaskByIdService.java | 4 +++- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/source/backend/challenge/modules/task/dtos/TaskProgressDTO.java b/source/backend/challenge/modules/task/dtos/TaskProgressDTO.java index ee6277f..2683e42 100644 --- a/source/backend/challenge/modules/task/dtos/TaskProgressDTO.java +++ b/source/backend/challenge/modules/task/dtos/TaskProgressDTO.java @@ -5,13 +5,15 @@ import lombok.Setter; import lombok.experimental.Accessors; +import java.util.UUID; + @Getter @Setter @Accessors(chain = true) @NoArgsConstructor(staticName = "create") public class TaskProgressDTO { - private Long id; + private UUID id; private int progress; } diff --git a/source/backend/challenge/modules/task/models/Task.java b/source/backend/challenge/modules/task/models/Task.java index 123f10c..4a039b4 100644 --- a/source/backend/challenge/modules/task/models/Task.java +++ b/source/backend/challenge/modules/task/models/Task.java @@ -2,18 +2,16 @@ import backend.challenge.modules.task.enums.TaskStatus; import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.RequiredArgsConstructor; import lombok.Setter; -import lombok.experimental.Accessors; import java.util.Date; +import java.util.UUID; @Getter @Setter public class Task { - private Long id; + private UUID id; private String title; private String description; private int progress; diff --git a/source/backend/challenge/modules/task/services/DeleteTaskService.java b/source/backend/challenge/modules/task/services/DeleteTaskService.java index c957d70..0316c75 100644 --- a/source/backend/challenge/modules/task/services/DeleteTaskService.java +++ b/source/backend/challenge/modules/task/services/DeleteTaskService.java @@ -4,6 +4,7 @@ import javax.inject.Inject; import javax.inject.Singleton; +import java.util.UUID; @Singleton public class DeleteTaskService implements IDeleteTaskService { @@ -16,7 +17,7 @@ public DeleteTaskService(final ITaskRepository taskRepository) { } @Override - public void execute(Long taskId) { + public void execute(UUID taskId) { // TODO: Criar serviço responsável por deletar a tarefa } diff --git a/source/backend/challenge/modules/task/services/IDeleteTaskService.java b/source/backend/challenge/modules/task/services/IDeleteTaskService.java index 6b031ac..f83d9ce 100644 --- a/source/backend/challenge/modules/task/services/IDeleteTaskService.java +++ b/source/backend/challenge/modules/task/services/IDeleteTaskService.java @@ -1,8 +1,10 @@ package backend.challenge.modules.task.services; +import java.util.UUID; + public interface IDeleteTaskService { - void execute(Long taskId); + void execute(UUID taskId); } diff --git a/source/backend/challenge/modules/task/services/IRetrieveTaskByIdService.java b/source/backend/challenge/modules/task/services/IRetrieveTaskByIdService.java index 192e28c..ee5461d 100644 --- a/source/backend/challenge/modules/task/services/IRetrieveTaskByIdService.java +++ b/source/backend/challenge/modules/task/services/IRetrieveTaskByIdService.java @@ -2,8 +2,10 @@ import backend.challenge.modules.task.models.Task; +import java.util.UUID; + public interface IRetrieveTaskByIdService { - Task execute(Long taskId); + Task execute(UUID taskId); } From d97514dfbed0927dabe509955e0a4c347693f748 Mon Sep 17 00:00:00 2001 From: Adriel Felix Date: Mon, 29 Apr 2024 14:19:37 -0300 Subject: [PATCH 2/6] task not found exception --- .../modules/task/exception/TaskNotFoundException.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 source/backend/challenge/modules/task/exception/TaskNotFoundException.java diff --git a/source/backend/challenge/modules/task/exception/TaskNotFoundException.java b/source/backend/challenge/modules/task/exception/TaskNotFoundException.java new file mode 100644 index 0000000..c5cb154 --- /dev/null +++ b/source/backend/challenge/modules/task/exception/TaskNotFoundException.java @@ -0,0 +1,11 @@ +package backend.challenge.modules.task.exception; + +import java.util.UUID; + +public class TaskNotFoundException extends RuntimeException { + + public TaskNotFoundException(UUID taskId){ + super("Task with id {"+taskId+"} was not found!"); + } + +} From a903293f8e2f8a3b068e2a69c13ab9e6bef289aa Mon Sep 17 00:00:00 2001 From: Adriel Felix Date: Mon, 29 Apr 2024 17:38:35 -0300 Subject: [PATCH 3/6] TaskRepository impl and TaskNotFoundException --- .../task/exception/TaskNotFoundException.java | 2 +- .../challenge/modules/task/models/Task.java | 13 ++++- .../task/repositories/ITaskRepository.java | 5 +- .../task/repositories/TaskRepository.java | 47 ++++++++++++------- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/source/backend/challenge/modules/task/exception/TaskNotFoundException.java b/source/backend/challenge/modules/task/exception/TaskNotFoundException.java index c5cb154..dc3dbba 100644 --- a/source/backend/challenge/modules/task/exception/TaskNotFoundException.java +++ b/source/backend/challenge/modules/task/exception/TaskNotFoundException.java @@ -5,7 +5,7 @@ public class TaskNotFoundException extends RuntimeException { public TaskNotFoundException(UUID taskId){ - super("Task with id {"+taskId+"} was not found!"); + super("Task with id {"+taskId.toString()+"} was not found!"); } } diff --git a/source/backend/challenge/modules/task/models/Task.java b/source/backend/challenge/modules/task/models/Task.java index 4a039b4..b3e0f16 100644 --- a/source/backend/challenge/modules/task/models/Task.java +++ b/source/backend/challenge/modules/task/models/Task.java @@ -3,12 +3,16 @@ import backend.challenge.modules.task.enums.TaskStatus; import lombok.Getter; import lombok.Setter; +import lombok.experimental.Accessors; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.Date; import java.util.UUID; @Getter @Setter +@Accessors(chain = true) public class Task { private UUID id; @@ -16,6 +20,13 @@ public class Task { private String description; private int progress; private TaskStatus status; - private Date createdAt; + private LocalDateTime createdAt; + public void updateFrom(Task task) { + this.title = task.getTitle(); + this.description = task.getDescription(); + this.progress = task.getProgress(); + this.status = task.getStatus(); + this.createdAt = task.getCreatedAt(); + } } diff --git a/source/backend/challenge/modules/task/repositories/ITaskRepository.java b/source/backend/challenge/modules/task/repositories/ITaskRepository.java index 527450a..f438bf6 100644 --- a/source/backend/challenge/modules/task/repositories/ITaskRepository.java +++ b/source/backend/challenge/modules/task/repositories/ITaskRepository.java @@ -4,13 +4,14 @@ import backend.challenge.modules.task.models.Task; import java.util.List; +import java.util.UUID; public interface ITaskRepository { - Task index(Long taskId); + Task index(UUID taskId); List show(); Task create(TaskDTO taskDTO); Task update(Task task); - void delete(Long taskId); + void delete(UUID taskId); } diff --git a/source/backend/challenge/modules/task/repositories/TaskRepository.java b/source/backend/challenge/modules/task/repositories/TaskRepository.java index c47c8fd..7fbf278 100644 --- a/source/backend/challenge/modules/task/repositories/TaskRepository.java +++ b/source/backend/challenge/modules/task/repositories/TaskRepository.java @@ -1,46 +1,59 @@ package backend.challenge.modules.task.repositories; import backend.challenge.modules.task.dtos.TaskDTO; +import backend.challenge.modules.task.enums.TaskStatus; +import backend.challenge.modules.task.exception.TaskNotFoundException; import backend.challenge.modules.task.models.Task; import javax.inject.Singleton; -import java.util.List; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; @Singleton public class TaskRepository implements ITaskRepository { - @Override - public Task index(final Long taskId) { - // TODO: Criar método responsável por retornar tarefa por id + private final List inMemoryTaskDb = new ArrayList<>(); - return null; + @Override + public Task index(final UUID taskId) { + for(Task task : inMemoryTaskDb) { + if(taskId.equals(task.getId())){ + return task; + } + } + throw new TaskNotFoundException(taskId); } @Override public List show() { - // TODO: Criar método responsável por retornar todas as tarefas - - return null; + return this.inMemoryTaskDb; } @Override public Task create(final TaskDTO taskDTO) { - // TODO: Criar método responsável por criar uma tarefa - - return null; + var taskToCreate = new Task() + .setId(UUID.randomUUID()) + .setTitle(taskDTO.getTitle()) + .setDescription(taskDTO.getDescription()) + .setStatus(TaskStatus.PROGRESS) + .setProgress(0) + .setCreatedAt(LocalDateTime.now()); + inMemoryTaskDb.add(taskToCreate); + return taskToCreate; } @Override public Task update(final Task task) { - // TODO: Criar método responsável por atualizar uma tarefa - - return null; + var foundTask = index(task.getId()); + foundTask.updateFrom(task); + return foundTask; } @Override - public void delete(final Long taskId) { - // TODO: Criar método responsável por deletar tarefa por id - + public void delete(final UUID taskId) { + var foundTask = index(taskId); + inMemoryTaskDb.remove(foundTask); } } From 534cb6183a144f84cf6e6be99330590b8513fb64 Mon Sep 17 00:00:00 2001 From: Adriel Felix Date: Mon, 29 Apr 2024 20:02:38 -0300 Subject: [PATCH 4/6] task services impl --- .../{ => impl}/CreateTaskService.java | 7 +++-- .../{ => impl}/DeleteTaskService.java | 5 ++-- .../{ => impl}/RetrieveAllTasksService.java | 7 +++-- .../impl/RetrieveTaskByIdService.java | 24 +++++++++++++++++ .../impl/UpdateTaskProgressService.java | 26 +++++++++++++++++++ .../task/services/impl/UpdateTaskService.java | 23 ++++++++++++++++ .../task/services/CreateTaskServiceTest.java | 2 +- .../task/services/DeleteTaskServiceTest.java | 2 +- .../services/RetrieveAllTasksServiceTest.java | 2 +- 9 files changed, 85 insertions(+), 13 deletions(-) rename source/backend/challenge/modules/task/services/{ => impl}/CreateTaskService.java (76%) rename source/backend/challenge/modules/task/services/{ => impl}/DeleteTaskService.java (74%) rename source/backend/challenge/modules/task/services/{ => impl}/RetrieveAllTasksService.java (76%) create mode 100644 source/backend/challenge/modules/task/services/impl/RetrieveTaskByIdService.java create mode 100644 source/backend/challenge/modules/task/services/impl/UpdateTaskProgressService.java create mode 100644 source/backend/challenge/modules/task/services/impl/UpdateTaskService.java diff --git a/source/backend/challenge/modules/task/services/CreateTaskService.java b/source/backend/challenge/modules/task/services/impl/CreateTaskService.java similarity index 76% rename from source/backend/challenge/modules/task/services/CreateTaskService.java rename to source/backend/challenge/modules/task/services/impl/CreateTaskService.java index 46b144b..4883f38 100644 --- a/source/backend/challenge/modules/task/services/CreateTaskService.java +++ b/source/backend/challenge/modules/task/services/impl/CreateTaskService.java @@ -1,8 +1,9 @@ -package backend.challenge.modules.task.services; +package backend.challenge.modules.task.services.impl; import backend.challenge.modules.task.dtos.TaskDTO; import backend.challenge.modules.task.models.Task; import backend.challenge.modules.task.repositories.ITaskRepository; +import backend.challenge.modules.task.services.ICreateTaskService; import javax.inject.Inject; import javax.inject.Singleton; @@ -19,9 +20,7 @@ public CreateTaskService(final ITaskRepository taskRepository) { @Override public Task execute(TaskDTO taskDTO) { - // TODO: Criar serviço responsável por criar uma tarefa - - return null; + return taskRepository.create(taskDTO); } } diff --git a/source/backend/challenge/modules/task/services/DeleteTaskService.java b/source/backend/challenge/modules/task/services/impl/DeleteTaskService.java similarity index 74% rename from source/backend/challenge/modules/task/services/DeleteTaskService.java rename to source/backend/challenge/modules/task/services/impl/DeleteTaskService.java index 0316c75..88bcabb 100644 --- a/source/backend/challenge/modules/task/services/DeleteTaskService.java +++ b/source/backend/challenge/modules/task/services/impl/DeleteTaskService.java @@ -1,6 +1,7 @@ -package backend.challenge.modules.task.services; +package backend.challenge.modules.task.services.impl; import backend.challenge.modules.task.repositories.ITaskRepository; +import backend.challenge.modules.task.services.IDeleteTaskService; import javax.inject.Inject; import javax.inject.Singleton; @@ -18,7 +19,7 @@ public DeleteTaskService(final ITaskRepository taskRepository) { @Override public void execute(UUID taskId) { - // TODO: Criar serviço responsável por deletar a tarefa + taskRepository.delete(taskId); } } diff --git a/source/backend/challenge/modules/task/services/RetrieveAllTasksService.java b/source/backend/challenge/modules/task/services/impl/RetrieveAllTasksService.java similarity index 76% rename from source/backend/challenge/modules/task/services/RetrieveAllTasksService.java rename to source/backend/challenge/modules/task/services/impl/RetrieveAllTasksService.java index 52a4149..cb25e18 100644 --- a/source/backend/challenge/modules/task/services/RetrieveAllTasksService.java +++ b/source/backend/challenge/modules/task/services/impl/RetrieveAllTasksService.java @@ -1,7 +1,8 @@ -package backend.challenge.modules.task.services; +package backend.challenge.modules.task.services.impl; import backend.challenge.modules.task.models.Task; import backend.challenge.modules.task.repositories.ITaskRepository; +import backend.challenge.modules.task.services.IRetrieveAllTasksService; import javax.inject.Inject; import javax.inject.Singleton; @@ -19,9 +20,7 @@ public RetrieveAllTasksService(final ITaskRepository taskRepository) { @Override public List execute() { - // TODO: Criar serviço responsável por recuperar todas as tarefas - - return null; + return taskRepository.show(); } } diff --git a/source/backend/challenge/modules/task/services/impl/RetrieveTaskByIdService.java b/source/backend/challenge/modules/task/services/impl/RetrieveTaskByIdService.java new file mode 100644 index 0000000..db01f8d --- /dev/null +++ b/source/backend/challenge/modules/task/services/impl/RetrieveTaskByIdService.java @@ -0,0 +1,24 @@ +package backend.challenge.modules.task.services.impl; + +import backend.challenge.modules.task.models.Task; +import backend.challenge.modules.task.repositories.ITaskRepository; +import backend.challenge.modules.task.services.IRetrieveTaskByIdService; + +import javax.inject.Singleton; +import java.util.UUID; + +@Singleton +public class RetrieveTaskByIdService implements IRetrieveTaskByIdService { + + private final ITaskRepository taskRepository; + + public RetrieveTaskByIdService(ITaskRepository taskRepository) { + this.taskRepository = taskRepository; + } + + @Override + public Task execute(UUID taskId) { + return taskRepository.index(taskId); + } + +} diff --git a/source/backend/challenge/modules/task/services/impl/UpdateTaskProgressService.java b/source/backend/challenge/modules/task/services/impl/UpdateTaskProgressService.java new file mode 100644 index 0000000..7a07f5f --- /dev/null +++ b/source/backend/challenge/modules/task/services/impl/UpdateTaskProgressService.java @@ -0,0 +1,26 @@ +package backend.challenge.modules.task.services.impl; + +import backend.challenge.modules.task.dtos.TaskProgressDTO; +import backend.challenge.modules.task.models.Task; +import backend.challenge.modules.task.repositories.ITaskRepository; +import backend.challenge.modules.task.services.IUpdateTaskProgressService; + +import javax.inject.Singleton; + +@Singleton +public class UpdateTaskProgressService implements IUpdateTaskProgressService { + + private final ITaskRepository taskRepository; + + public UpdateTaskProgressService(ITaskRepository taskRepository) { + this.taskRepository = taskRepository; + } + + @Override + public Task execute(TaskProgressDTO taskProgressDTO) { + var foundTask = taskRepository.index(taskProgressDTO.getId()); + foundTask.setProgress(taskProgressDTO.getProgress()); + return foundTask; + } + +} diff --git a/source/backend/challenge/modules/task/services/impl/UpdateTaskService.java b/source/backend/challenge/modules/task/services/impl/UpdateTaskService.java new file mode 100644 index 0000000..c605dd6 --- /dev/null +++ b/source/backend/challenge/modules/task/services/impl/UpdateTaskService.java @@ -0,0 +1,23 @@ +package backend.challenge.modules.task.services.impl; + +import backend.challenge.modules.task.models.Task; +import backend.challenge.modules.task.repositories.ITaskRepository; +import backend.challenge.modules.task.services.IUpdateTaskService; + +import javax.inject.Singleton; + +@Singleton +public class UpdateTaskService implements IUpdateTaskService { + + private final ITaskRepository taskRepository; + + public UpdateTaskService(ITaskRepository taskRepository) { + this.taskRepository = taskRepository; + } + + @Override + public Task execute(Task task) { + return taskRepository.update(task); + } + +} diff --git a/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java b/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java index 684dc44..253395e 100644 --- a/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java +++ b/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java @@ -2,9 +2,9 @@ import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; +import backend.challenge.modules.task.services.impl.CreateTaskService; import kikaha.core.test.KikahaRunner; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java b/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java index 93497a5..e297668 100644 --- a/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java +++ b/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java @@ -2,9 +2,9 @@ import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; +import backend.challenge.modules.task.services.impl.DeleteTaskService; import kikaha.core.test.KikahaRunner; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java b/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java index 68f0012..fd77f76 100644 --- a/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java +++ b/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java @@ -2,9 +2,9 @@ import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; +import backend.challenge.modules.task.services.impl.RetrieveAllTasksService; import kikaha.core.test.KikahaRunner; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; From 76a245fad777c4bb168b59b0832c7399cd129fb4 Mon Sep 17 00:00:00 2001 From: Adriel Felix Date: Tue, 30 Apr 2024 03:35:31 -0300 Subject: [PATCH 5/6] task and task progress controllers --- pom.xml | 3 +- .../task/converter/ITaskConverter.java | 19 ++++ .../modules/task/converter/TaskConverter.java | 56 +++++++++++ .../InvalidTaskProgressException.java | 11 +++ .../http/api/request/CreateTaskRequest.java | 13 +++ .../request/UpdateTaskProgressRequest.java | 12 +++ .../http/api/request/UpdateTaskRequest.java | 13 +++ .../infra/http/api/response/TaskResponse.java | 22 +++++ .../http/controllers/TaskController.java | 93 +++++++++++++------ .../controllers/TaskProgressController.java | 38 +++++--- .../task/infra/http/error/ErrorResponse.java | 22 +++++ .../infra/http/views/TaskProgressView.java | 12 --- .../task/infra/http/views/TaskView.java | 16 ---- .../challenge/modules/task/models/Task.java | 13 ++- .../task/repositories/ITaskRepository.java | 2 +- .../task/repositories/TaskRepository.java | 19 ++-- .../task/services/IUpdateTaskService.java | 5 +- .../impl/RetrieveTaskByIdService.java | 2 + .../impl/UpdateTaskProgressService.java | 9 +- .../task/services/impl/UpdateTaskService.java | 8 +- tests/{ => backend/challenge}/Runner.java | 0 .../task/services/CreateTaskServiceTest.java | 9 +- .../task/services/DeleteTaskServiceTest.java | 8 +- .../services/RetrieveAllTasksServiceTest.java | 9 +- 24 files changed, 327 insertions(+), 87 deletions(-) create mode 100644 source/backend/challenge/modules/task/converter/ITaskConverter.java create mode 100644 source/backend/challenge/modules/task/converter/TaskConverter.java create mode 100644 source/backend/challenge/modules/task/exception/InvalidTaskProgressException.java create mode 100644 source/backend/challenge/modules/task/infra/http/api/request/CreateTaskRequest.java create mode 100644 source/backend/challenge/modules/task/infra/http/api/request/UpdateTaskProgressRequest.java create mode 100644 source/backend/challenge/modules/task/infra/http/api/request/UpdateTaskRequest.java create mode 100644 source/backend/challenge/modules/task/infra/http/api/response/TaskResponse.java create mode 100644 source/backend/challenge/modules/task/infra/http/error/ErrorResponse.java delete mode 100644 source/backend/challenge/modules/task/infra/http/views/TaskProgressView.java delete mode 100644 source/backend/challenge/modules/task/infra/http/views/TaskView.java rename tests/{ => backend/challenge}/Runner.java (100%) diff --git a/pom.xml b/pom.xml index 53ab393..292f520 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ 2.1.8.Final 1.2.3 4.13.1 + 1.3.2 source @@ -76,7 +77,7 @@ javax.annotation javax.annotation-api - 1.3.2 + ${version.javax.annotation} diff --git a/source/backend/challenge/modules/task/converter/ITaskConverter.java b/source/backend/challenge/modules/task/converter/ITaskConverter.java new file mode 100644 index 0000000..b7b5f62 --- /dev/null +++ b/source/backend/challenge/modules/task/converter/ITaskConverter.java @@ -0,0 +1,19 @@ +package backend.challenge.modules.task.converter; + +import backend.challenge.modules.task.dtos.TaskDTO; +import backend.challenge.modules.task.dtos.TaskProgressDTO; +import backend.challenge.modules.task.infra.http.api.request.CreateTaskRequest; +import backend.challenge.modules.task.infra.http.api.request.UpdateTaskProgressRequest; +import backend.challenge.modules.task.infra.http.api.request.UpdateTaskRequest; +import backend.challenge.modules.task.infra.http.api.response.TaskResponse; +import backend.challenge.modules.task.models.Task; + +import java.util.UUID; + +public interface ITaskConverter { + TaskDTO createTaskRequestToTaskDto(CreateTaskRequest createTaskRequest); + TaskDTO updateTaskRequestToTaskDto(UpdateTaskRequest updateTaskRequest); + Task taskDtoToTask(TaskDTO taskDTO); + TaskProgressDTO updateTaskProgressRequestToTaskProgressDto(UUID taskId, UpdateTaskProgressRequest updateTaskProgressRequest); + TaskResponse taskToTaskResponse(Task task); +} diff --git a/source/backend/challenge/modules/task/converter/TaskConverter.java b/source/backend/challenge/modules/task/converter/TaskConverter.java new file mode 100644 index 0000000..3cbc8c9 --- /dev/null +++ b/source/backend/challenge/modules/task/converter/TaskConverter.java @@ -0,0 +1,56 @@ +package backend.challenge.modules.task.converter; + +import backend.challenge.modules.task.dtos.TaskDTO; +import backend.challenge.modules.task.dtos.TaskProgressDTO; +import backend.challenge.modules.task.infra.http.api.request.CreateTaskRequest; +import backend.challenge.modules.task.infra.http.api.request.UpdateTaskProgressRequest; +import backend.challenge.modules.task.infra.http.api.request.UpdateTaskRequest; +import backend.challenge.modules.task.infra.http.api.response.TaskResponse; +import backend.challenge.modules.task.models.Task; + +import javax.inject.Singleton; +import java.util.UUID; + +@Singleton +public class TaskConverter implements ITaskConverter { + + @Override + public TaskDTO createTaskRequestToTaskDto(CreateTaskRequest createTaskRequest) { + return TaskDTO.create() + .setTitle(createTaskRequest.getTitle()) + .setDescription(createTaskRequest.getDescription()); + } + + @Override + public TaskDTO updateTaskRequestToTaskDto(UpdateTaskRequest updateTaskRequest) { + return TaskDTO.create() + .setTitle(updateTaskRequest.getTitle()) + .setDescription(updateTaskRequest.getDescription()); + } + + @Override + public Task taskDtoToTask(TaskDTO taskDTO) { + return new Task() + .setTitle(taskDTO.getTitle()) + .setDescription(taskDTO.getDescription()); + } + + @Override + public TaskProgressDTO updateTaskProgressRequestToTaskProgressDto(UUID taskId, UpdateTaskProgressRequest updateTaskProgressRequest) { + return TaskProgressDTO.create() + .setId(taskId) + .setProgress(updateTaskProgressRequest.getProgress()); + } + + @Override + public TaskResponse taskToTaskResponse(Task task) { + return new TaskResponse() + .setId(task.getId()) + .setTitle(task.getTitle()) + .setDescription(task.getDescription()) + .setStatus(task.getStatus()) + .setProgress(task.getProgress()) + .setCreatedAt(task.getCreatedAt().toString()); + } + +} diff --git a/source/backend/challenge/modules/task/exception/InvalidTaskProgressException.java b/source/backend/challenge/modules/task/exception/InvalidTaskProgressException.java new file mode 100644 index 0000000..729a3b2 --- /dev/null +++ b/source/backend/challenge/modules/task/exception/InvalidTaskProgressException.java @@ -0,0 +1,11 @@ +package backend.challenge.modules.task.exception; + +import java.util.UUID; + +public class InvalidTaskProgressException extends RuntimeException { + + public InvalidTaskProgressException(){ + super("The task progress value must not be less than 0 or greater than 100!"); + } + +} diff --git a/source/backend/challenge/modules/task/infra/http/api/request/CreateTaskRequest.java b/source/backend/challenge/modules/task/infra/http/api/request/CreateTaskRequest.java new file mode 100644 index 0000000..9d89cbb --- /dev/null +++ b/source/backend/challenge/modules/task/infra/http/api/request/CreateTaskRequest.java @@ -0,0 +1,13 @@ +package backend.challenge.modules.task.infra.http.api.request; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CreateTaskRequest { + + private String title; + private String description; + +} diff --git a/source/backend/challenge/modules/task/infra/http/api/request/UpdateTaskProgressRequest.java b/source/backend/challenge/modules/task/infra/http/api/request/UpdateTaskProgressRequest.java new file mode 100644 index 0000000..ce086ad --- /dev/null +++ b/source/backend/challenge/modules/task/infra/http/api/request/UpdateTaskProgressRequest.java @@ -0,0 +1,12 @@ +package backend.challenge.modules.task.infra.http.api.request; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UpdateTaskProgressRequest { + + private int progress; + +} diff --git a/source/backend/challenge/modules/task/infra/http/api/request/UpdateTaskRequest.java b/source/backend/challenge/modules/task/infra/http/api/request/UpdateTaskRequest.java new file mode 100644 index 0000000..ae3f8f1 --- /dev/null +++ b/source/backend/challenge/modules/task/infra/http/api/request/UpdateTaskRequest.java @@ -0,0 +1,13 @@ +package backend.challenge.modules.task.infra.http.api.request; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class UpdateTaskRequest { + + private String title; + private String description; + +} diff --git a/source/backend/challenge/modules/task/infra/http/api/response/TaskResponse.java b/source/backend/challenge/modules/task/infra/http/api/response/TaskResponse.java new file mode 100644 index 0000000..a686deb --- /dev/null +++ b/source/backend/challenge/modules/task/infra/http/api/response/TaskResponse.java @@ -0,0 +1,22 @@ +package backend.challenge.modules.task.infra.http.api.response; + +import backend.challenge.modules.task.enums.TaskStatus; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.util.UUID; + +@Getter +@Setter +@Accessors(chain = true) +public class TaskResponse { + + private UUID id; + private String title; + private String description; + private int progress; + private TaskStatus status; + private String createdAt; + +} diff --git a/source/backend/challenge/modules/task/infra/http/controllers/TaskController.java b/source/backend/challenge/modules/task/infra/http/controllers/TaskController.java index 6a06a52..dbb7b8a 100644 --- a/source/backend/challenge/modules/task/infra/http/controllers/TaskController.java +++ b/source/backend/challenge/modules/task/infra/http/controllers/TaskController.java @@ -1,12 +1,20 @@ package backend.challenge.modules.task.infra.http.controllers; -import backend.challenge.modules.task.infra.http.views.TaskView; +import backend.challenge.modules.task.converter.ITaskConverter; +import backend.challenge.modules.task.exception.TaskNotFoundException; +import backend.challenge.modules.task.infra.http.api.request.CreateTaskRequest; +import backend.challenge.modules.task.infra.http.api.request.UpdateTaskRequest; +import backend.challenge.modules.task.infra.http.error.ErrorResponse; import backend.challenge.modules.task.models.Task; import backend.challenge.modules.task.services.*; import kikaha.urouting.api.*; import javax.inject.Inject; import javax.inject.Singleton; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.UUID; +import java.util.stream.Collectors; @Singleton @Path("tasks") @@ -18,58 +26,87 @@ public class TaskController { private final IRetrieveTaskByIdService retrieveTaskByIdService; private final IUpdateTaskService updateTaskService; + private final ITaskConverter taskConverter; + @Inject public TaskController( - final ICreateTaskService createTaskService, - final IDeleteTaskService deleteTaskService, - final IRetrieveAllTasksService retrieveAllTasksService - ) { + final ICreateTaskService createTaskService, + final IDeleteTaskService deleteTaskService, + final IRetrieveAllTasksService retrieveAllTasksService, + final IRetrieveTaskByIdService retrieveTaskByIdService, + final IUpdateTaskService updateTaskService, + final ITaskConverter taskConverter + ) { this.createTaskService = createTaskService; this.deleteTaskService = deleteTaskService; this.retrieveAllTasksService = retrieveAllTasksService; - this.retrieveTaskByIdService = null; - this.updateTaskService = null; + this.retrieveTaskByIdService = retrieveTaskByIdService; + this.updateTaskService = updateTaskService; + this.taskConverter = taskConverter; } @GET public Response show() { - // TODO: Rota que lista todas as tarefas - - return DefaultResponse.ok().entity("Hello world"); + var tasksList = retrieveAllTasksService.execute(); + var tasksResponse = tasksList.stream().map(taskConverter::taskToTaskResponse).collect(Collectors.toList()); + return DefaultResponse.ok().entity(tasksResponse); } @GET @Path("single/{taskId}") - public Response index(@PathParam("taskId") Long taskId) { - // TODO: A rota deve retornar somente a tarefa a qual o id corresponder + public Response index(@PathParam("taskId") String taskId) { + try { + var foundTask = retrieveTaskByIdService.execute(UUID.fromString(taskId)); + return DefaultResponse.ok().entity(taskConverter.taskToTaskResponse(foundTask)); + } catch (TaskNotFoundException e) { + var errorResponse = ErrorResponse.create() + .setError("Not Found") + .setStatus(404) + .setMessage(e.getMessage()) + .setTimestamp(Instant.now().truncatedTo(ChronoUnit.SECONDS).toString()); + return DefaultResponse.notFound().entity(errorResponse); + } - return DefaultResponse.ok().entity("Hello world"); } @POST - public Response create(TaskView task) { - // TODO: A rota deve receber title e description, sendo o `title` o título da tarefa e `description` uma descrição da tarefa. - - return DefaultResponse.ok().entity("Hello world"); + public Response create(CreateTaskRequest task) { + var taskDto = taskConverter.createTaskRequestToTaskDto(task); + var createdTask = createTaskService.execute(taskDto); + return DefaultResponse.created("tasks/single/"+createdTask.getId()).entity(taskConverter.taskToTaskResponse(createdTask)); } @PUT @Path("single/{taskId}") - public Response update(@PathParam("taskId") Long taskId, Task task) { - /* - TODO: A rota deve alterar apenas o title e description da tarefa - que possua o id igual ao id correspondente nos parâmetros da rota. - */ - - return DefaultResponse.ok().entity("Hello world"); + public Response update(@PathParam("taskId") String taskId, UpdateTaskRequest task) { + try { + var taskDto = taskConverter.updateTaskRequestToTaskDto(task); + var updatedTask = updateTaskService.execute(UUID.fromString(taskId), taskDto); + return DefaultResponse.ok().entity(taskConverter.taskToTaskResponse(updatedTask)); + } catch (TaskNotFoundException e) { + var errorResponse = ErrorResponse.create() + .setError("Not Found") + .setStatus(404) + .setMessage(e.getMessage()) + .setTimestamp(Instant.now().truncatedTo(ChronoUnit.SECONDS).toString()); + return DefaultResponse.notFound().entity(errorResponse); + } } @DELETE @Path("single/{taskId}") - public Response delete(@PathParam("taskId") Long taskId) { - // TODO: A rota deve deletar a tarefa com o id correspondente nos parâmetros da rota - - return DefaultResponse.ok().entity("Hello world"); + public Response delete(@PathParam("taskId") String taskId) { + try { + deleteTaskService.execute(UUID.fromString(taskId)); + return DefaultResponse.noContent(); + } catch (TaskNotFoundException e) { + var errorResponse = ErrorResponse.create() + .setError("Not Found") + .setStatus(404) + .setMessage(e.getMessage()) + .setTimestamp(Instant.now().truncatedTo(ChronoUnit.SECONDS).toString()); + return DefaultResponse.notFound().entity(errorResponse); + } } } diff --git a/source/backend/challenge/modules/task/infra/http/controllers/TaskProgressController.java b/source/backend/challenge/modules/task/infra/http/controllers/TaskProgressController.java index 4a25520..479a368 100644 --- a/source/backend/challenge/modules/task/infra/http/controllers/TaskProgressController.java +++ b/source/backend/challenge/modules/task/infra/http/controllers/TaskProgressController.java @@ -1,12 +1,17 @@ package backend.challenge.modules.task.infra.http.controllers; -import backend.challenge.modules.task.infra.http.views.TaskProgressView; -import backend.challenge.modules.task.models.Task; +import backend.challenge.modules.task.converter.ITaskConverter; +import backend.challenge.modules.task.exception.InvalidTaskProgressException; +import backend.challenge.modules.task.infra.http.api.request.UpdateTaskProgressRequest; +import backend.challenge.modules.task.infra.http.error.ErrorResponse; import backend.challenge.modules.task.services.*; import kikaha.urouting.api.*; import javax.inject.Inject; import javax.inject.Singleton; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.UUID; @Singleton @Path("tasks/progress") @@ -14,22 +19,29 @@ public class TaskProgressController { private final IUpdateTaskProgressService updateTaskProgressService; + private final ITaskConverter taskConverter; + @Inject - public TaskProgressController(final IUpdateTaskProgressService updateTaskProgressService) { + public TaskProgressController(final IUpdateTaskProgressService updateTaskProgressService, ITaskConverter taskConverter) { this.updateTaskProgressService = updateTaskProgressService; - } + this.taskConverter = taskConverter; + } @PUT @Path("single/{taskId}") - public Response updateProgress(@PathParam("taskId") Long taskId, TaskProgressView taskProgressView) { - /* - TODO: A rota deve alterar apenas o progresso da tarefa que possua o id igual ao id correspondente - nos parâmetros da rota. - O `progress` pode ter o valor máximo de 100, e quando ele atingi o máximo, - o `status` deve ser alterado para `COMPLETE` - */ - - return DefaultResponse.ok().entity("Hello world"); + public Response updateProgress(@PathParam("taskId") String taskId, UpdateTaskProgressRequest updateTaskProgressRequest) { + try { + var taskProgressDto = taskConverter.updateTaskProgressRequestToTaskProgressDto(UUID.fromString(taskId), updateTaskProgressRequest); + var updatedTask = updateTaskProgressService.execute(taskProgressDto); + return DefaultResponse.ok().entity(taskConverter.taskToTaskResponse(updatedTask)); + } catch (InvalidTaskProgressException e) { + var errorResponse = ErrorResponse.create() + .setError("Bad Request") + .setStatus(400) + .setMessage(e.getMessage()) + .setTimestamp(Instant.now().truncatedTo(ChronoUnit.SECONDS).toString()); + return DefaultResponse.badRequest().entity(errorResponse); + } } } diff --git a/source/backend/challenge/modules/task/infra/http/error/ErrorResponse.java b/source/backend/challenge/modules/task/infra/http/error/ErrorResponse.java new file mode 100644 index 0000000..1c6a736 --- /dev/null +++ b/source/backend/challenge/modules/task/infra/http/error/ErrorResponse.java @@ -0,0 +1,22 @@ +package backend.challenge.modules.task.infra.http.error; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +@Getter +@Setter +@Accessors(chain = true) +@NoArgsConstructor(staticName = "create") +public class ErrorResponse { + + private int status; + private String error; + private String message; + private String timestamp; + +} diff --git a/source/backend/challenge/modules/task/infra/http/views/TaskProgressView.java b/source/backend/challenge/modules/task/infra/http/views/TaskProgressView.java deleted file mode 100644 index 3375195..0000000 --- a/source/backend/challenge/modules/task/infra/http/views/TaskProgressView.java +++ /dev/null @@ -1,12 +0,0 @@ -package backend.challenge.modules.task.infra.http.views; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class TaskProgressView { - - private int progress; - -} diff --git a/source/backend/challenge/modules/task/infra/http/views/TaskView.java b/source/backend/challenge/modules/task/infra/http/views/TaskView.java deleted file mode 100644 index 8b0d67e..0000000 --- a/source/backend/challenge/modules/task/infra/http/views/TaskView.java +++ /dev/null @@ -1,16 +0,0 @@ -package backend.challenge.modules.task.infra.http.views; - -import backend.challenge.modules.task.enums.TaskStatus; -import lombok.Getter; -import lombok.Setter; - -import java.util.Date; - -@Getter -@Setter -public class TaskView { - - private String title; - private String description; - -} diff --git a/source/backend/challenge/modules/task/models/Task.java b/source/backend/challenge/modules/task/models/Task.java index b3e0f16..2e7a064 100644 --- a/source/backend/challenge/modules/task/models/Task.java +++ b/source/backend/challenge/modules/task/models/Task.java @@ -1,12 +1,15 @@ package backend.challenge.modules.task.models; import backend.challenge.modules.task.enums.TaskStatus; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonValue; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.UUID; @@ -22,11 +25,15 @@ public class Task { private TaskStatus status; private LocalDateTime createdAt; + public Task() { + this.progress = 0; + this.status = TaskStatus.PROGRESS; + this.createdAt = LocalDateTime.now(); + } + public void updateFrom(Task task) { this.title = task.getTitle(); this.description = task.getDescription(); - this.progress = task.getProgress(); - this.status = task.getStatus(); - this.createdAt = task.getCreatedAt(); } + } diff --git a/source/backend/challenge/modules/task/repositories/ITaskRepository.java b/source/backend/challenge/modules/task/repositories/ITaskRepository.java index f438bf6..14eda5e 100644 --- a/source/backend/challenge/modules/task/repositories/ITaskRepository.java +++ b/source/backend/challenge/modules/task/repositories/ITaskRepository.java @@ -11,7 +11,7 @@ public interface ITaskRepository { Task index(UUID taskId); List show(); Task create(TaskDTO taskDTO); - Task update(Task task); + Task update(UUID taskId, TaskDTO taskDto); void delete(UUID taskId); } diff --git a/source/backend/challenge/modules/task/repositories/TaskRepository.java b/source/backend/challenge/modules/task/repositories/TaskRepository.java index 7fbf278..61fae99 100644 --- a/source/backend/challenge/modules/task/repositories/TaskRepository.java +++ b/source/backend/challenge/modules/task/repositories/TaskRepository.java @@ -1,10 +1,12 @@ package backend.challenge.modules.task.repositories; +import backend.challenge.modules.task.converter.ITaskConverter; import backend.challenge.modules.task.dtos.TaskDTO; import backend.challenge.modules.task.enums.TaskStatus; import backend.challenge.modules.task.exception.TaskNotFoundException; import backend.challenge.modules.task.models.Task; +import javax.inject.Inject; import javax.inject.Singleton; import java.time.LocalDateTime; import java.util.*; @@ -15,6 +17,13 @@ public class TaskRepository implements ITaskRepository { private final List inMemoryTaskDb = new ArrayList<>(); + private final ITaskConverter taskConverter; + + @Inject + public TaskRepository(ITaskConverter taskConverter) { + this.taskConverter = taskConverter; + } + @Override public Task index(final UUID taskId) { for(Task task : inMemoryTaskDb) { @@ -35,17 +44,15 @@ public Task create(final TaskDTO taskDTO) { var taskToCreate = new Task() .setId(UUID.randomUUID()) .setTitle(taskDTO.getTitle()) - .setDescription(taskDTO.getDescription()) - .setStatus(TaskStatus.PROGRESS) - .setProgress(0) - .setCreatedAt(LocalDateTime.now()); + .setDescription(taskDTO.getDescription()); inMemoryTaskDb.add(taskToCreate); return taskToCreate; } @Override - public Task update(final Task task) { - var foundTask = index(task.getId()); + public Task update(final UUID taskId, final TaskDTO taskDTO) { + var foundTask = index(taskId); + var task = taskConverter.taskDtoToTask(taskDTO); foundTask.updateFrom(task); return foundTask; } diff --git a/source/backend/challenge/modules/task/services/IUpdateTaskService.java b/source/backend/challenge/modules/task/services/IUpdateTaskService.java index 3da8340..ee08d9b 100644 --- a/source/backend/challenge/modules/task/services/IUpdateTaskService.java +++ b/source/backend/challenge/modules/task/services/IUpdateTaskService.java @@ -1,9 +1,12 @@ package backend.challenge.modules.task.services; +import backend.challenge.modules.task.dtos.TaskDTO; import backend.challenge.modules.task.models.Task; +import java.util.UUID; + public interface IUpdateTaskService { - Task execute(Task task); + Task execute(UUID taskId, TaskDTO taskDto); } diff --git a/source/backend/challenge/modules/task/services/impl/RetrieveTaskByIdService.java b/source/backend/challenge/modules/task/services/impl/RetrieveTaskByIdService.java index db01f8d..740c896 100644 --- a/source/backend/challenge/modules/task/services/impl/RetrieveTaskByIdService.java +++ b/source/backend/challenge/modules/task/services/impl/RetrieveTaskByIdService.java @@ -4,6 +4,7 @@ import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.services.IRetrieveTaskByIdService; +import javax.inject.Inject; import javax.inject.Singleton; import java.util.UUID; @@ -12,6 +13,7 @@ public class RetrieveTaskByIdService implements IRetrieveTaskByIdService { private final ITaskRepository taskRepository; + @Inject public RetrieveTaskByIdService(ITaskRepository taskRepository) { this.taskRepository = taskRepository; } diff --git a/source/backend/challenge/modules/task/services/impl/UpdateTaskProgressService.java b/source/backend/challenge/modules/task/services/impl/UpdateTaskProgressService.java index 7a07f5f..0aa295e 100644 --- a/source/backend/challenge/modules/task/services/impl/UpdateTaskProgressService.java +++ b/source/backend/challenge/modules/task/services/impl/UpdateTaskProgressService.java @@ -1,10 +1,13 @@ package backend.challenge.modules.task.services.impl; import backend.challenge.modules.task.dtos.TaskProgressDTO; +import backend.challenge.modules.task.enums.TaskStatus; +import backend.challenge.modules.task.exception.InvalidTaskProgressException; import backend.challenge.modules.task.models.Task; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.services.IUpdateTaskProgressService; +import javax.inject.Inject; import javax.inject.Singleton; @Singleton @@ -12,14 +15,18 @@ public class UpdateTaskProgressService implements IUpdateTaskProgressService { private final ITaskRepository taskRepository; + @Inject public UpdateTaskProgressService(ITaskRepository taskRepository) { this.taskRepository = taskRepository; } @Override public Task execute(TaskProgressDTO taskProgressDTO) { + var progress = taskProgressDTO.getProgress(); + if(progress < 0 || progress > 100) { throw new InvalidTaskProgressException(); } var foundTask = taskRepository.index(taskProgressDTO.getId()); - foundTask.setProgress(taskProgressDTO.getProgress()); + foundTask.setProgress(progress); + if(progress == 100) { foundTask.setStatus(TaskStatus.COMPLETE); } return foundTask; } diff --git a/source/backend/challenge/modules/task/services/impl/UpdateTaskService.java b/source/backend/challenge/modules/task/services/impl/UpdateTaskService.java index c605dd6..c7d11e9 100644 --- a/source/backend/challenge/modules/task/services/impl/UpdateTaskService.java +++ b/source/backend/challenge/modules/task/services/impl/UpdateTaskService.java @@ -1,23 +1,27 @@ package backend.challenge.modules.task.services.impl; +import backend.challenge.modules.task.dtos.TaskDTO; import backend.challenge.modules.task.models.Task; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.services.IUpdateTaskService; +import javax.inject.Inject; import javax.inject.Singleton; +import java.util.UUID; @Singleton public class UpdateTaskService implements IUpdateTaskService { private final ITaskRepository taskRepository; + @Inject public UpdateTaskService(ITaskRepository taskRepository) { this.taskRepository = taskRepository; } @Override - public Task execute(Task task) { - return taskRepository.update(task); + public Task execute(UUID taskId, TaskDTO taskDto) { + return taskRepository.update(taskId, taskDto); } } diff --git a/tests/Runner.java b/tests/backend/challenge/Runner.java similarity index 100% rename from tests/Runner.java rename to tests/backend/challenge/Runner.java diff --git a/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java b/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java index 253395e..63d3a36 100644 --- a/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java +++ b/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java @@ -1,5 +1,6 @@ package backend.challenge.modules.task.services; +import backend.challenge.modules.task.converter.ITaskConverter; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; import backend.challenge.modules.task.services.impl.CreateTaskService; @@ -13,9 +14,15 @@ public class CreateTaskServiceTest { private ICreateTaskService createTaskService; + private final ITaskConverter taskConverter; + + public CreateTaskServiceTest(ITaskConverter taskConverter) { + this.taskConverter = taskConverter; + } + @Before public void init() { - final ITaskRepository taskRepository = new TaskRepository(); + final ITaskRepository taskRepository = new TaskRepository(taskConverter); createTaskService = new CreateTaskService(taskRepository); } diff --git a/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java b/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java index e297668..4aa37c5 100644 --- a/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java +++ b/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java @@ -1,5 +1,6 @@ package backend.challenge.modules.task.services; +import backend.challenge.modules.task.converter.ITaskConverter; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; import backend.challenge.modules.task.services.impl.DeleteTaskService; @@ -12,10 +13,15 @@ public class DeleteTaskServiceTest { private IDeleteTaskService deleteTaskService; + private final ITaskConverter taskConverter; + + public DeleteTaskServiceTest(ITaskConverter taskConverter) { + this.taskConverter = taskConverter; + } @Before public void init() { - final ITaskRepository taskRepository = new TaskRepository(); + final ITaskRepository taskRepository = new TaskRepository(taskConverter); deleteTaskService = new DeleteTaskService(taskRepository); } diff --git a/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java b/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java index fd77f76..88a8668 100644 --- a/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java +++ b/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java @@ -1,5 +1,6 @@ package backend.challenge.modules.task.services; +import backend.challenge.modules.task.converter.ITaskConverter; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; import backend.challenge.modules.task.services.impl.RetrieveAllTasksService; @@ -13,9 +14,15 @@ public class RetrieveAllTasksServiceTest { private IRetrieveAllTasksService retrieveAllTasksService; + private final ITaskConverter taskConverter; + + public RetrieveAllTasksServiceTest(ITaskConverter taskConverter) { + this.taskConverter = taskConverter; + } + @Before public void init() { - final ITaskRepository taskRepository = new TaskRepository(); + final ITaskRepository taskRepository = new TaskRepository(taskConverter); retrieveAllTasksService = new RetrieveAllTasksService(taskRepository); } From 3ba884c9a231d5892cd93a7c5890ea6f2db97b97 Mon Sep 17 00:00:00 2001 From: Adriel Felix Date: Tue, 30 Apr 2024 14:46:47 -0300 Subject: [PATCH 6/6] unit tests for task services --- .../task/services/CreateTaskServiceTest.java | 31 +++++-- .../task/services/DeleteTaskServiceTest.java | 23 +++-- .../services/RetrieveAllTasksServiceTest.java | 36 +++++--- .../services/RetrieveTaskByIdServiceTest.java | 32 ++++++- .../UpdateTaskProgressServiceTest.java | 89 +++++++++++++++++-- .../task/services/UpdateTaskServiceTest.java | 56 +++++++++--- 6 files changed, 223 insertions(+), 44 deletions(-) diff --git a/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java b/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java index 63d3a36..2144bfd 100644 --- a/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java +++ b/tests/backend/challenge/modules/task/services/CreateTaskServiceTest.java @@ -1,27 +1,26 @@ package backend.challenge.modules.task.services; import backend.challenge.modules.task.converter.ITaskConverter; +import backend.challenge.modules.task.converter.TaskConverter; +import backend.challenge.modules.task.dtos.TaskDTO; +import backend.challenge.modules.task.enums.TaskStatus; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; import backend.challenge.modules.task.services.impl.CreateTaskService; import kikaha.core.test.KikahaRunner; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -@RunWith( KikahaRunner.class ) +@RunWith(KikahaRunner.class) public class CreateTaskServiceTest { private ICreateTaskService createTaskService; - private final ITaskConverter taskConverter; - - public CreateTaskServiceTest(ITaskConverter taskConverter) { - this.taskConverter = taskConverter; - } - @Before public void init() { + final ITaskConverter taskConverter = new TaskConverter(); final ITaskRepository taskRepository = new TaskRepository(taskConverter); createTaskService = new CreateTaskService(taskRepository); @@ -29,8 +28,22 @@ public void init() { @Test public void shouldBeAbleToCreateANewTask() { - // TODO: Para que esse teste passe, sua aplicação deve permitir que - // uma tarefa seja criado, e retorne um json com a tarefa criada. + //given + final var taskTitle = "Task test"; + final var taskDescription = "Test description"; + var taskDto = TaskDTO.create() + .setTitle(taskTitle) + .setDescription(taskDescription); + //when + var savedTask = createTaskService.execute(taskDto); + //then + Assert.assertNotNull(savedTask); + Assert.assertNotNull(savedTask.getId()); + Assert.assertEquals(savedTask.getTitle(), taskTitle); + Assert.assertEquals(savedTask.getDescription(), taskDescription); + Assert.assertEquals(savedTask.getProgress(), 0); + Assert.assertEquals(savedTask.getStatus(), TaskStatus.PROGRESS); + Assert.assertNotNull(savedTask.getCreatedAt()); } diff --git a/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java b/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java index 4aa37c5..77fbefc 100644 --- a/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java +++ b/tests/backend/challenge/modules/task/services/DeleteTaskServiceTest.java @@ -1,10 +1,14 @@ package backend.challenge.modules.task.services; import backend.challenge.modules.task.converter.ITaskConverter; +import backend.challenge.modules.task.converter.TaskConverter; +import backend.challenge.modules.task.dtos.TaskDTO; +import backend.challenge.modules.task.exception.TaskNotFoundException; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; import backend.challenge.modules.task.services.impl.DeleteTaskService; import kikaha.core.test.KikahaRunner; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -13,22 +17,29 @@ public class DeleteTaskServiceTest { private IDeleteTaskService deleteTaskService; - private final ITaskConverter taskConverter; - public DeleteTaskServiceTest(ITaskConverter taskConverter) { - this.taskConverter = taskConverter; - } + private ITaskRepository taskRepository; @Before public void init() { - final ITaskRepository taskRepository = new TaskRepository(taskConverter); + final ITaskConverter taskConverter = new TaskConverter(); + taskRepository = new TaskRepository(taskConverter); deleteTaskService = new DeleteTaskService(taskRepository); } @Test public void shouldBeAbleToDeleteTaskById() { - // TODO: Para que esse teste passe, sua aplicação deve permitir que tarefas sejam deletadas por id. + //given + var taskDto = TaskDTO.create() + .setTitle("Task test") + .setDescription("Test description"); + var createdTask = taskRepository.create(taskDto); + var taskId = createdTask.getId(); + //when + deleteTaskService.execute(taskId); + //then + Assert.assertThrows(TaskNotFoundException.class, () -> taskRepository.index(taskId)); } diff --git a/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java b/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java index 88a8668..86cf700 100644 --- a/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java +++ b/tests/backend/challenge/modules/task/services/RetrieveAllTasksServiceTest.java @@ -1,38 +1,54 @@ package backend.challenge.modules.task.services; import backend.challenge.modules.task.converter.ITaskConverter; +import backend.challenge.modules.task.converter.TaskConverter; +import backend.challenge.modules.task.dtos.TaskDTO; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; import backend.challenge.modules.task.services.impl.RetrieveAllTasksService; import kikaha.core.test.KikahaRunner; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.List; + @RunWith( KikahaRunner.class ) public class RetrieveAllTasksServiceTest { private IRetrieveAllTasksService retrieveAllTasksService; - private final ITaskConverter taskConverter; - - public RetrieveAllTasksServiceTest(ITaskConverter taskConverter) { - this.taskConverter = taskConverter; - } + private ITaskRepository taskRepository; @Before public void init() { - final ITaskRepository taskRepository = new TaskRepository(taskConverter); + final ITaskConverter taskConverter = new TaskConverter(); + taskRepository = new TaskRepository(taskConverter); retrieveAllTasksService = new RetrieveAllTasksService(taskRepository); } @Test public void shouldBeAbleToListTheTasks() { - /* - TODO: Para que esse teste passe, sua aplicação deve permitir que seja - retornado um array com todas as tarefas que foram criadas até o momento. - */ + //given + int numOfRecords = 5; + populateInMemoryDb(numOfRecords); + //when + var tasksList = retrieveAllTasksService.execute(); + //then + Assert.assertNotNull(tasksList); + Assert.assertEquals(tasksList.size(), numOfRecords); + } + + private void populateInMemoryDb(int numOfRecords) { + for (int i = 0; i < numOfRecords; i++) { + taskRepository.create( + TaskDTO.create() + .setTitle("Task test "+i) + .setDescription("Test description "+i) + ); + } } } \ No newline at end of file diff --git a/tests/backend/challenge/modules/task/services/RetrieveTaskByIdServiceTest.java b/tests/backend/challenge/modules/task/services/RetrieveTaskByIdServiceTest.java index eb96b15..32a6655 100644 --- a/tests/backend/challenge/modules/task/services/RetrieveTaskByIdServiceTest.java +++ b/tests/backend/challenge/modules/task/services/RetrieveTaskByIdServiceTest.java @@ -1,24 +1,48 @@ package backend.challenge.modules.task.services; +import backend.challenge.modules.task.converter.ITaskConverter; +import backend.challenge.modules.task.converter.TaskConverter; +import backend.challenge.modules.task.dtos.TaskDTO; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; +import backend.challenge.modules.task.services.impl.RetrieveTaskByIdService; import kikaha.core.test.KikahaRunner; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.List; + @RunWith( KikahaRunner.class ) public class RetrieveTaskByIdServiceTest { private IRetrieveTaskByIdService retrieveTaskByIdService; + private ITaskRepository taskRepository; + + @Before + public void init() { + final ITaskConverter taskConverter = new TaskConverter(); + taskRepository = new TaskRepository(taskConverter); + + retrieveTaskByIdService = new RetrieveTaskByIdService(taskRepository); + } + @Test public void shouldBeAbleToListTheTaskById() { - /* - TODO: Para que esse teste passe, sua aplicação deve permitir que seja - retornado uma tarefa com o mesmo id informado. - */ + //given + var taskDto = TaskDTO.create() + .setTitle("Task test") + .setDescription("Test description"); + var createdTask = taskRepository.create(taskDto); + var taskId = createdTask.getId(); + //when + var foundTask = retrieveTaskByIdService.execute(taskId); + //then + Assert.assertNotNull(foundTask); + Assert.assertEquals(foundTask.getId(), taskId); } } diff --git a/tests/backend/challenge/modules/task/services/UpdateTaskProgressServiceTest.java b/tests/backend/challenge/modules/task/services/UpdateTaskProgressServiceTest.java index e6b0bf6..574499e 100644 --- a/tests/backend/challenge/modules/task/services/UpdateTaskProgressServiceTest.java +++ b/tests/backend/challenge/modules/task/services/UpdateTaskProgressServiceTest.java @@ -1,19 +1,51 @@ package backend.challenge.modules.task.services; +import backend.challenge.modules.task.converter.ITaskConverter; +import backend.challenge.modules.task.converter.TaskConverter; +import backend.challenge.modules.task.dtos.TaskDTO; +import backend.challenge.modules.task.dtos.TaskProgressDTO; +import backend.challenge.modules.task.enums.TaskStatus; +import backend.challenge.modules.task.exception.InvalidTaskProgressException; +import backend.challenge.modules.task.repositories.ITaskRepository; +import backend.challenge.modules.task.repositories.TaskRepository; +import backend.challenge.modules.task.services.impl.UpdateTaskProgressService; import kikaha.core.test.KikahaRunner; +import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -@RunWith( KikahaRunner.class ) +@RunWith(KikahaRunner.class) public class UpdateTaskProgressServiceTest { + private IUpdateTaskProgressService updateTaskProgressService; + + private ITaskRepository taskRepository; + + @Before + public void init() { + final ITaskConverter taskConverter = new TaskConverter(); + taskRepository = new TaskRepository(taskConverter); + + updateTaskProgressService = new UpdateTaskProgressService(taskRepository); + } + @Test public void shouldBeAbleToUpdateTaskProgress() { - /* - TODO: Para que esse teste passe, sua aplicação deve permitir que sejam - alterados apenas o campo `progress`. - */ + //given + var taskDto = TaskDTO.create() + .setTitle("Task test") + .setDescription("Test description"); + var createdTask = taskRepository.create(taskDto); + var taskId = createdTask.getId(); + var taskProgressDto = TaskProgressDTO.create() + .setId(taskId) + .setProgress(100); + //when + var updatedTask = updateTaskProgressService.execute(taskProgressDto); + //then + Assert.assertEquals(updatedTask.getProgress(), 100); } @Test @@ -22,6 +54,53 @@ public void shouldBeAbleToUpdateOnlyTaskStatusWhenProgressEqualsOneHundred() { TODO: Para que esse teste passe, sua aplicação deve permitir que sejam alterado apenas o campo `status`, quando o progresso for igual a 100. */ + //given + var taskDto = TaskDTO.create() + .setTitle("Task test") + .setDescription("Test description"); + var createdTask = taskRepository.create(taskDto); + var taskId = createdTask.getId(); + var taskProgressDto = TaskProgressDTO.create() + .setId(taskId) + .setProgress(100); + //when + var updatedTask = updateTaskProgressService.execute(taskProgressDto); + //then + Assert.assertEquals(updatedTask.getProgress(), 100); + Assert.assertEquals(updatedTask.getStatus(), TaskStatus.COMPLETE); + } + + @Test + public void shouldGetExceptionWhenProgressGreaterThanOneHundred() { + //given + var taskDto = TaskDTO.create() + .setTitle("Task test") + .setDescription("Test description"); + var createdTask = taskRepository.create(taskDto); + var taskId = createdTask.getId(); + var taskProgressDto = TaskProgressDTO.create() + .setId(taskId) + .setProgress(101); + //when + //then + Assert.assertThrows(InvalidTaskProgressException.class, () -> updateTaskProgressService.execute(taskProgressDto)); + } + + + @Test + public void shouldGetExceptionWhenProgressLessThanZero() { + //given + var taskDto = TaskDTO.create() + .setTitle("Task test") + .setDescription("Test description"); + var createdTask = taskRepository.create(taskDto); + var taskId = createdTask.getId(); + var taskProgressDto = TaskProgressDTO.create() + .setId(taskId) + .setProgress(-1); + //when + //then + Assert.assertThrows(InvalidTaskProgressException.class, () -> updateTaskProgressService.execute(taskProgressDto)); } } diff --git a/tests/backend/challenge/modules/task/services/UpdateTaskServiceTest.java b/tests/backend/challenge/modules/task/services/UpdateTaskServiceTest.java index 53a4082..b220cfe 100644 --- a/tests/backend/challenge/modules/task/services/UpdateTaskServiceTest.java +++ b/tests/backend/challenge/modules/task/services/UpdateTaskServiceTest.java @@ -1,32 +1,66 @@ package backend.challenge.modules.task.services; +import backend.challenge.modules.task.converter.ITaskConverter; +import backend.challenge.modules.task.converter.TaskConverter; +import backend.challenge.modules.task.dtos.TaskDTO; +import backend.challenge.modules.task.exception.TaskNotFoundException; import backend.challenge.modules.task.repositories.ITaskRepository; import backend.challenge.modules.task.repositories.TaskRepository; +import backend.challenge.modules.task.services.impl.UpdateTaskService; import kikaha.core.test.KikahaRunner; +import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; -@RunWith( KikahaRunner.class ) +import java.util.UUID; + +@RunWith(KikahaRunner.class) public class UpdateTaskServiceTest { private IUpdateTaskService updateTaskService; + private ITaskRepository taskRepository; + + @Before + public void init() { + final ITaskConverter taskConverter = new TaskConverter(); + taskRepository = new TaskRepository(taskConverter); + + updateTaskService = new UpdateTaskService(taskRepository); + } + @Test public void shouldBeAbleToUpdateTask() { - /* - TODO: Para que esse teste passe, sua aplicação deve permitir que sejam - alterados apenas os campos `title` e `observation`. - */ + //given + var taskToCreate = TaskDTO.create() + .setTitle("Task test") + .setDescription("Test description"); + var createdTask = taskRepository.create(taskToCreate); + var taskId = createdTask.getId(); + var titleUpdate = "Task UPDATE"; + var descriptionUpdate = "Description UPDATE"; + var taskDto = TaskDTO.create() + .setTitle(titleUpdate) + .setDescription(descriptionUpdate); + //when + var updatedTask = updateTaskService.execute(taskId, taskDto); + //then + Assert.assertNotNull(updatedTask); + Assert.assertEquals(updatedTask.getTitle(), titleUpdate); + Assert.assertEquals(updatedTask.getDescription(), descriptionUpdate); } @Test public void shouldNotBeAbleToUpdateATaskThatDoesNotExist() { - /* - TODO: Para que esse teste passe, você deve validar na sua rota de update se - o id da tarefa enviada pela url existe ou não. Caso não exista, retornar um erro com status 400. - */ + //given + var taskId = UUID.fromString("f242ac84-2431-4c99-97fa-9bb02c19015f"); + var taskDto = TaskDTO.create() + .setTitle("Task update attempt") + .setDescription("Test description update attempt"); + //when + //then + Assert.assertThrows(TaskNotFoundException.class, () -> updateTaskService.execute(taskId, taskDto)); } @Test @@ -36,6 +70,8 @@ public void shouldNotBeAbleToUpdateTaskStatusManually() { altere diretamente o `status` dessa tarefa, mantendo o mesmo status que a tarefa já possuía antes da atualização. Isso porque o único lugar que deve atualizar essa informação é a rota responsável por alterar o progresso da tarefa. + ---> TESTE NÃO É NECESSÁRIO DEVIDO AO FLUXO DESENVOLVIDO PARA UPDATE, + ONDE O TASK DTO RECEBIDO PELO SERVICE NÃO POSSUI O ATRIBUTO TaskStatus, DESSA FORMA A ATUALIZAÇÃO DESSE CAMPO NÃO OCORRE. <--- */ }