diff --git a/pom.xml b/pom.xml
index 2029fbc..e98e19c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,6 +66,12 @@
h2
test
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.14
+ compile
+
diff --git a/src/main/java/com/jonassavas/spring_task_api/controllers/TaskController.java b/src/main/java/com/jonassavas/spring_task_api/controllers/TaskController.java
index 30f41ae..c99f260 100644
--- a/src/main/java/com/jonassavas/spring_task_api/controllers/TaskController.java
+++ b/src/main/java/com/jonassavas/spring_task_api/controllers/TaskController.java
@@ -1,16 +1,18 @@
package com.jonassavas.spring_task_api.controllers;
-import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+import com.jonassavas.spring_task_api.domain.dto.TaskRequestDto;
import com.jonassavas.spring_task_api.domain.dto.TaskDto;
import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
import com.jonassavas.spring_task_api.mappers.Mapper;
+import com.jonassavas.spring_task_api.services.TaskGroupService;
import com.jonassavas.spring_task_api.services.TaskService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -21,12 +23,19 @@
public class TaskController {
private Mapper taskMapper;
+ private Mapper taskRequestMapper;
private TaskService taskService;
+ private TaskGroupService taskGroupService;
- public TaskController(Mapper taskMapper, TaskService taskService){
+ public TaskController(Mapper taskMapper,
+ TaskService taskService,
+ TaskGroupService taskGroupService,
+ Mapper taskRequestMapper){
this.taskMapper = taskMapper;
this.taskService = taskService;
+ this.taskGroupService = taskGroupService;
+ this.taskRequestMapper = taskRequestMapper;
}
@@ -34,6 +43,11 @@ public TaskController(Mapper taskMapper, TaskService taskSe
public ResponseEntity createTask(
@PathVariable Long groupId,
@RequestBody TaskDto dto) {
+
+ // Can't create a task without a valid task group
+ if(!taskGroupService.isExist(groupId)){
+ return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+ }
TaskEntity taskEntity = taskMapper.mapFrom(dto);
TaskEntity savedTask = taskService.createTask(groupId, taskEntity);
@@ -43,8 +57,14 @@ public ResponseEntity createTask(
@DeleteMapping(path = "/tasks/{id}")
public ResponseEntity deleteTask(@PathVariable("id") Long id){
- taskService.deleteTask(id);
+ taskService.delete(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
+ @PatchMapping(path = "/tasks/{id}")
+ public ResponseEntity update(@PathVariable Long id, @RequestBody TaskRequestDto dto){
+ TaskEntity updated = taskService.update(id, dto);
+
+ return new ResponseEntity<>(taskRequestMapper.mapTo(updated), HttpStatus.OK);
+ }
}
diff --git a/src/main/java/com/jonassavas/spring_task_api/controllers/TaskGroupController.java b/src/main/java/com/jonassavas/spring_task_api/controllers/TaskGroupController.java
index 4a8b8b9..9c1a9d6 100644
--- a/src/main/java/com/jonassavas/spring_task_api/controllers/TaskGroupController.java
+++ b/src/main/java/com/jonassavas/spring_task_api/controllers/TaskGroupController.java
@@ -2,9 +2,10 @@
import org.springframework.web.bind.annotation.RestController;
-import com.jonassavas.spring_task_api.domain.dto.CreateTaskGroupDto;
+import com.jonassavas.spring_task_api.domain.dto.TaskGroupRequestDto;
import com.jonassavas.spring_task_api.domain.dto.TaskDto;
import com.jonassavas.spring_task_api.domain.dto.TaskGroupDto;
+import com.jonassavas.spring_task_api.domain.dto.TaskGroupWithTasksDto;
import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
import com.jonassavas.spring_task_api.domain.entities.TaskGroupEntity;
import com.jonassavas.spring_task_api.mappers.Mapper;
@@ -16,38 +17,88 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
@RestController
public class TaskGroupController {
private TaskGroupService taskGroupService;
- private Mapper createTaskGroupMapper;
+ private Mapper taskGroupRequestMapper;
+ private Mapper taskGroupWithTasksMapper;
private Mapper taskGroupMapper;
public TaskGroupController(TaskGroupService taskGroupService,
- Mapper createTaskGroupMapper,
- Mapper taskGroupMapper){
+ Mapper taskGroupRequestMapper,
+ Mapper taskGroupMapper,
+ Mapper taskGroupWithTasksMapper){
this.taskGroupService = taskGroupService;
- this.createTaskGroupMapper = createTaskGroupMapper;
+ this.taskGroupRequestMapper = taskGroupRequestMapper;
this.taskGroupMapper = taskGroupMapper;
+ this.taskGroupWithTasksMapper = taskGroupWithTasksMapper;
}
@PostMapping(path = "/taskgroups")
- public ResponseEntity createTaskGroup(@RequestBody CreateTaskGroupDto taskGroup) {
- TaskGroupEntity taskGroupEntity = createTaskGroupMapper.mapFrom(taskGroup);
+ public ResponseEntity createTaskGroup(@RequestBody TaskGroupRequestDto taskGroup) {
+ TaskGroupEntity taskGroupEntity = taskGroupRequestMapper.mapFrom(taskGroup);
TaskGroupEntity savedTaskGroupEntity = taskGroupService.save(taskGroupEntity);
- return new ResponseEntity<>(createTaskGroupMapper.mapTo(savedTaskGroupEntity), HttpStatus.CREATED);
+ return new ResponseEntity<>(taskGroupRequestMapper.mapTo(savedTaskGroupEntity), HttpStatus.CREATED);
}
- @GetMapping(path = "/taskgroups")
+ @GetMapping("/taskgroups")
public List listTaskGroups() {
- List taskGroups = taskGroupService.findAll();
- return taskGroups.stream().map(taskGroupMapper::mapTo).collect(Collectors.toList());
+ return taskGroupService.findAll()
+ .stream()
+ .map(taskGroupMapper::mapTo)
+ .toList();
+ }
+
+ // @GetMapping("/taskgroups/{id}/tasks")
+ // public List listTasksForGroup(@PathVariable Long id) {
+ // return taskService.findByGroupId(id)
+ // .stream()
+ // .map(taskMapper::mapTo)
+ // .toList();
+ // }
+
+ @GetMapping("/taskgroups/with-tasks")
+ public List listTaskGroupsWithTasks() {
+ return taskGroupService.findAllWithTasks()
+ .stream()
+ .map(taskGroupWithTasksMapper::mapTo)
+ .toList();
+ }
+
+
+
+ // @GetMapping(path = "/taskgroups")
+ // public List listTaskGroups() {
+ // List taskGroups = taskGroupService.findAll();
+ // return taskGroups.stream().map(taskGroupMapper::mapTo).collect(Collectors.toList());
+ // }
+
+ @DeleteMapping(path = "/taskgroups/{id}")
+ public ResponseEntity deleteTaskGroup(@PathVariable("id") Long id){
+ taskGroupService.delete(id);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @DeleteMapping(path = "/taskgroups/{groupId}/tasks")
+ public ResponseEntity deleteAllTasks(@PathVariable("groupId") Long groupId){
+ taskGroupService.deleteAllTasks(groupId);
+ return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+ }
+
+ @PatchMapping(path = "/taskgroups/{id}")
+ public ResponseEntity updateTaskGroup(@PathVariable Long id, @RequestBody TaskGroupRequestDto dto){
+ TaskGroupEntity updated = taskGroupService.update(id, dto);
+ return new ResponseEntity<>(taskGroupRequestMapper.mapTo(updated), HttpStatus.OK);
}
}
diff --git a/src/main/java/com/jonassavas/spring_task_api/domain/dto/CreateTaskDto.java b/src/main/java/com/jonassavas/spring_task_api/domain/dto/CreateTaskDto.java
deleted file mode 100644
index 5afceb3..0000000
--- a/src/main/java/com/jonassavas/spring_task_api/domain/dto/CreateTaskDto.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.jonassavas.spring_task_api.domain.dto;
-
-public class CreateTaskDto {
-
-}
diff --git a/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupDto.java b/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupDto.java
index b38fc8f..abf3a31 100644
--- a/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupDto.java
+++ b/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupDto.java
@@ -1,9 +1,5 @@
package com.jonassavas.spring_task_api.domain.dto;
-import java.util.List;
-
-import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
-
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -18,5 +14,4 @@ public class TaskGroupDto {
private String taskGroupName;
- private List tasks;
}
diff --git a/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupRequestDto.java b/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupRequestDto.java
new file mode 100644
index 0000000..79fd946
--- /dev/null
+++ b/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupRequestDto.java
@@ -0,0 +1,25 @@
+package com.jonassavas.spring_task_api.domain.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+
+/*
+ USED FOR:
+ - CREATE
+ - UPDATE
+
+ This class serves as the DTO for incoming and outgoing requests.
+ This means that when the user wants to create/change any parameter
+ of their TaskGroup they do it via this DTO.
+*/
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class TaskGroupRequestDto {
+ private String taskGroupName;
+}
diff --git a/src/main/java/com/jonassavas/spring_task_api/domain/dto/CreateTaskGroupDto.java b/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupWithTasksDto.java
similarity index 62%
rename from src/main/java/com/jonassavas/spring_task_api/domain/dto/CreateTaskGroupDto.java
rename to src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupWithTasksDto.java
index 81962ce..6d0d3a0 100644
--- a/src/main/java/com/jonassavas/spring_task_api/domain/dto/CreateTaskGroupDto.java
+++ b/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskGroupWithTasksDto.java
@@ -1,5 +1,9 @@
package com.jonassavas.spring_task_api.domain.dto;
+import java.util.List;
+
+import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
+
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -9,10 +13,10 @@
@AllArgsConstructor
@NoArgsConstructor
@Builder
-public class CreateTaskGroupDto {
+public class TaskGroupWithTasksDto {
private Long id;
private String taskGroupName;
- //private List tasks; //We don't allow tasks on create
-}
+ private List tasks;
+}
\ No newline at end of file
diff --git a/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskRequestDto.java b/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskRequestDto.java
new file mode 100644
index 0000000..9c9db7a
--- /dev/null
+++ b/src/main/java/com/jonassavas/spring_task_api/domain/dto/TaskRequestDto.java
@@ -0,0 +1,15 @@
+package com.jonassavas.spring_task_api.domain.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class TaskRequestDto {
+ private Long taskGroupId;
+ private String taskName;
+}
\ No newline at end of file
diff --git a/src/main/java/com/jonassavas/spring_task_api/mappers/impl/CreateTaskGroupMapper.java b/src/main/java/com/jonassavas/spring_task_api/mappers/impl/TaskGroupRequestMapper.java
similarity index 52%
rename from src/main/java/com/jonassavas/spring_task_api/mappers/impl/CreateTaskGroupMapper.java
rename to src/main/java/com/jonassavas/spring_task_api/mappers/impl/TaskGroupRequestMapper.java
index 8b50cb8..890ce01 100644
--- a/src/main/java/com/jonassavas/spring_task_api/mappers/impl/CreateTaskGroupMapper.java
+++ b/src/main/java/com/jonassavas/spring_task_api/mappers/impl/TaskGroupRequestMapper.java
@@ -4,25 +4,25 @@
import org.springframework.stereotype.Component;
-import com.jonassavas.spring_task_api.domain.dto.CreateTaskGroupDto;
+import com.jonassavas.spring_task_api.domain.dto.TaskGroupRequestDto;
import com.jonassavas.spring_task_api.domain.entities.TaskGroupEntity;
import com.jonassavas.spring_task_api.mappers.Mapper;
@Component
-public class CreateTaskGroupMapper implements Mapper{
+public class TaskGroupRequestMapper implements Mapper{
private ModelMapper modelMapper;
- public CreateTaskGroupMapper(ModelMapper modelMapper){
+ public TaskGroupRequestMapper(ModelMapper modelMapper){
this.modelMapper = modelMapper;
}
@Override
- public CreateTaskGroupDto mapTo(TaskGroupEntity taskGroupEntity){
- return modelMapper.map(taskGroupEntity, CreateTaskGroupDto.class);
+ public TaskGroupRequestDto mapTo(TaskGroupEntity taskGroupEntity){
+ return modelMapper.map(taskGroupEntity, TaskGroupRequestDto.class);
}
@Override
- public TaskGroupEntity mapFrom(CreateTaskGroupDto taskGroupDto){
+ public TaskGroupEntity mapFrom(TaskGroupRequestDto taskGroupDto){
return modelMapper.map(taskGroupDto, TaskGroupEntity.class);
}
}
diff --git a/src/main/java/com/jonassavas/spring_task_api/mappers/impl/TaskGroupWithTasksMapper.java b/src/main/java/com/jonassavas/spring_task_api/mappers/impl/TaskGroupWithTasksMapper.java
new file mode 100644
index 0000000..a1d13c5
--- /dev/null
+++ b/src/main/java/com/jonassavas/spring_task_api/mappers/impl/TaskGroupWithTasksMapper.java
@@ -0,0 +1,28 @@
+package com.jonassavas.spring_task_api.mappers.impl;
+
+import org.modelmapper.ModelMapper;
+import org.springframework.stereotype.Component;
+
+
+import com.jonassavas.spring_task_api.domain.dto.TaskGroupWithTasksDto;
+import com.jonassavas.spring_task_api.domain.entities.TaskGroupEntity;
+import com.jonassavas.spring_task_api.mappers.Mapper;
+
+@Component
+public class TaskGroupWithTasksMapper implements Mapper{
+ private ModelMapper modelMapper;
+
+ public TaskGroupWithTasksMapper(ModelMapper modelMapper){
+ this.modelMapper = modelMapper;
+ }
+
+ @Override
+ public TaskGroupWithTasksDto mapTo(TaskGroupEntity taskGroupEntity){
+ return modelMapper.map(taskGroupEntity, TaskGroupWithTasksDto.class);
+ }
+
+ @Override
+ public TaskGroupEntity mapFrom(TaskGroupWithTasksDto taskGroupDto){
+ return modelMapper.map(taskGroupDto, TaskGroupEntity.class);
+ }
+}
diff --git a/src/main/java/com/jonassavas/spring_task_api/mappers/impl/TaskRequestMapper.java b/src/main/java/com/jonassavas/spring_task_api/mappers/impl/TaskRequestMapper.java
new file mode 100644
index 0000000..3918c87
--- /dev/null
+++ b/src/main/java/com/jonassavas/spring_task_api/mappers/impl/TaskRequestMapper.java
@@ -0,0 +1,36 @@
+package com.jonassavas.spring_task_api.mappers.impl;
+
+import org.modelmapper.ModelMapper;
+import org.springframework.stereotype.Component;
+
+import com.jonassavas.spring_task_api.domain.dto.TaskRequestDto;
+import com.jonassavas.spring_task_api.domain.dto.TaskDto;
+import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
+import com.jonassavas.spring_task_api.mappers.Mapper;
+
+@Component
+public class TaskRequestMapper implements Mapper {
+
+ private ModelMapper modelMapper;
+
+ public TaskRequestMapper(ModelMapper modelMapper) {
+ this.modelMapper = modelMapper;
+
+ // Skip taskGroup when mapping DTO -> Entity
+ this.modelMapper.typeMap(TaskRequestDto.class, TaskEntity.class)
+ .addMappings(mapper -> mapper.skip(TaskEntity::setTaskGroup));
+ }
+
+ @Override
+ public TaskRequestDto mapTo(TaskEntity taskEntity) {
+ TaskRequestDto dto = modelMapper.map(taskEntity, TaskRequestDto.class);
+ //dto.setTaskGroupId(taskEntity.getTaskGroup().getId());
+ return dto;
+ }
+
+ @Override
+ public TaskEntity mapFrom(TaskRequestDto createTaskDto) {
+ return modelMapper.map(createTaskDto, TaskEntity.class);
+ }
+}
+
diff --git a/src/main/java/com/jonassavas/spring_task_api/repositories/TaskGroupRepository.java b/src/main/java/com/jonassavas/spring_task_api/repositories/TaskGroupRepository.java
index 5f39eec..de1d7ba 100644
--- a/src/main/java/com/jonassavas/spring_task_api/repositories/TaskGroupRepository.java
+++ b/src/main/java/com/jonassavas/spring_task_api/repositories/TaskGroupRepository.java
@@ -1,5 +1,10 @@
package com.jonassavas.spring_task_api.repositories;
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@@ -10,6 +15,18 @@
which is used to indicate that the class provides the mechanism for storage,
retrieval, update, delete, and search operation on objects.*/
@Repository
-public interface TaskGroupRepository extends CrudRepository{
+public interface TaskGroupRepository extends JpaRepository{
+ @Query("""
+ SELECT tg FROM TaskGroupEntity tg
+ LEFT JOIN FETCH tg.tasks
+ """)
+ List findAllWithTasks();
+
+ @Query("""
+ SELECT tg from TaskGroupEntity tg
+ LEFT JOIN FETCH tg.tasks
+ WHERE tg.id = :id
+ """)
+ Optional findByIdWithTasks(Long id);
}
diff --git a/src/main/java/com/jonassavas/spring_task_api/repositories/TaskRepository.java b/src/main/java/com/jonassavas/spring_task_api/repositories/TaskRepository.java
index 60af341..e38e564 100644
--- a/src/main/java/com/jonassavas/spring_task_api/repositories/TaskRepository.java
+++ b/src/main/java/com/jonassavas/spring_task_api/repositories/TaskRepository.java
@@ -1,5 +1,6 @@
package com.jonassavas.spring_task_api.repositories;
+import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@@ -10,6 +11,6 @@
which is used to indicate that the class provides the mechanism for storage,
retrieval, update, delete, and search operation on objects.*/
@Repository
-public interface TaskRepository extends CrudRepository {
+public interface TaskRepository extends JpaRepository {
}
diff --git a/src/main/java/com/jonassavas/spring_task_api/services/TaskGroupService.java b/src/main/java/com/jonassavas/spring_task_api/services/TaskGroupService.java
index 1acd3f0..ad3372e 100644
--- a/src/main/java/com/jonassavas/spring_task_api/services/TaskGroupService.java
+++ b/src/main/java/com/jonassavas/spring_task_api/services/TaskGroupService.java
@@ -2,10 +2,23 @@
import java.util.List;
+import com.jonassavas.spring_task_api.domain.dto.TaskGroupRequestDto;
import com.jonassavas.spring_task_api.domain.entities.TaskGroupEntity;
public interface TaskGroupService {
TaskGroupEntity save(TaskGroupEntity taskGroupEntity);
List findAll();
+
+ List findAllWithTasks();
+
+ TaskGroupEntity findByIdWithTasks(Long id);
+
+ boolean isExist(Long id);
+
+ void delete(Long id);
+
+ void deleteAllTasks(Long id);
+
+ TaskGroupEntity update(Long id, TaskGroupRequestDto dto);
}
diff --git a/src/main/java/com/jonassavas/spring_task_api/services/TaskService.java b/src/main/java/com/jonassavas/spring_task_api/services/TaskService.java
index f02e280..f1e09e4 100644
--- a/src/main/java/com/jonassavas/spring_task_api/services/TaskService.java
+++ b/src/main/java/com/jonassavas/spring_task_api/services/TaskService.java
@@ -1,9 +1,18 @@
package com.jonassavas.spring_task_api.services;
+import java.util.List;
+
+import com.jonassavas.spring_task_api.domain.dto.TaskRequestDto;
import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
public interface TaskService {
TaskEntity createTask(Long groupId, TaskEntity taskEntity);
- void deleteTask(Long id);
+ void delete(Long id);
+
+ boolean isExist(Long id);
+
+ TaskEntity update(Long id, TaskRequestDto dto);
+
+ List findAll();
}
diff --git a/src/main/java/com/jonassavas/spring_task_api/services/impl/TaskGroupServiceImpl.java b/src/main/java/com/jonassavas/spring_task_api/services/impl/TaskGroupServiceImpl.java
index 2b8a2cd..a340e76 100644
--- a/src/main/java/com/jonassavas/spring_task_api/services/impl/TaskGroupServiceImpl.java
+++ b/src/main/java/com/jonassavas/spring_task_api/services/impl/TaskGroupServiceImpl.java
@@ -6,11 +6,16 @@
import org.springframework.stereotype.Service;
+import com.jonassavas.spring_task_api.domain.dto.TaskGroupRequestDto;
import com.jonassavas.spring_task_api.domain.entities.TaskGroupEntity;
import com.jonassavas.spring_task_api.repositories.TaskGroupRepository;
import com.jonassavas.spring_task_api.services.TaskGroupService;
+import jakarta.persistence.EntityNotFoundException;
+import jakarta.transaction.Transactional;
+
@Service
+@Transactional
public class TaskGroupServiceImpl implements TaskGroupService{
private TaskGroupRepository taskGroupRepository;
@@ -31,4 +36,48 @@ public List findAll(){
.spliterator(), false)
.collect(Collectors.toList());
}
+
+ @Override
+ public List findAllWithTasks(){
+ return taskGroupRepository.findAllWithTasks();
+ }
+
+ @Override
+ public TaskGroupEntity findByIdWithTasks(Long id){
+ return taskGroupRepository.findByIdWithTasks(id)
+ .orElseThrow(() -> new EntityNotFoundException(
+ "TaskGroup not found with id " + id));
+ }
+
+ @Override
+ public boolean isExist(Long id){
+ return taskGroupRepository.existsById(id);
+ }
+
+ @Override
+ public void delete(Long id){
+ taskGroupRepository.deleteById(id);
+ }
+
+ @Override
+ public void deleteAllTasks(Long id){
+ TaskGroupEntity taskGroup = taskGroupRepository.findById(id)
+ .orElseThrow(() -> new EntityNotFoundException(
+ "TaskGroup not found with id " + id));
+
+ taskGroup.getTasks().clear();
+ }
+
+ @Override
+ public TaskGroupEntity update(Long id, TaskGroupRequestDto dto){
+ TaskGroupEntity taskGroup = taskGroupRepository.findById(id)
+ .orElseThrow(() -> new EntityNotFoundException(
+ "TaskGroup not found with it: " + id));
+
+ if(dto.getTaskGroupName() != null){
+ taskGroup.setTaskGroupName(dto.getTaskGroupName());
+ }
+
+ return taskGroup;
+ }
}
diff --git a/src/main/java/com/jonassavas/spring_task_api/services/impl/TaskServiceImpl.java b/src/main/java/com/jonassavas/spring_task_api/services/impl/TaskServiceImpl.java
index 9124068..4ca6c9d 100644
--- a/src/main/java/com/jonassavas/spring_task_api/services/impl/TaskServiceImpl.java
+++ b/src/main/java/com/jonassavas/spring_task_api/services/impl/TaskServiceImpl.java
@@ -1,7 +1,12 @@
package com.jonassavas.spring_task_api.services.impl;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
import org.springframework.stereotype.Service;
+import com.jonassavas.spring_task_api.domain.dto.TaskRequestDto;
import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
import com.jonassavas.spring_task_api.domain.entities.TaskGroupEntity;
import com.jonassavas.spring_task_api.repositories.TaskGroupRepository;
@@ -9,8 +14,10 @@
import com.jonassavas.spring_task_api.services.TaskService;
import jakarta.persistence.EntityNotFoundException;
+import jakarta.transaction.Transactional;
@Service
+@Transactional
public class TaskServiceImpl implements TaskService{
private final TaskRepository taskRepository;
private final TaskGroupRepository taskGroupRepository;
@@ -29,19 +36,61 @@ public TaskEntity createTask(Long groupId, TaskEntity taskEntity) {
taskGroup.addTask(taskEntity); // Cascade saves task automatically
- taskRepository.save(taskEntity);
-
- return taskEntity;
+ return taskRepository.save(taskEntity);
}
@Override
- public void deleteTask(Long id){
+ public void delete(Long id){
TaskEntity task = taskRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Task not found with id " + id));
TaskGroupEntity group = task.getTaskGroup();
group.removeTask(task); // Triggers orphanRemoval
+
+ taskRepository.delete(task);
+ }
+
+ @Override
+ public boolean isExist(Long id){
+ return taskRepository.existsById(id);
+ }
+
+ @Override
+ public List findAll(){
+ return StreamSupport.stream(taskRepository
+ .findAll()
+ .spliterator(), false)
+ .collect(Collectors.toList());
+ }
+
+
+ @Override
+ public TaskEntity update(Long id, TaskRequestDto dto){
+ TaskEntity task = taskRepository.findById(id)
+ .orElseThrow(() -> new EntityNotFoundException(
+ "Task not found with id " + id));
+
+ // Update task name
+ if(dto.getTaskName() != null){
+ task.setTaskName(dto.getTaskName());
+ }
+
+ // Move task to another group (if requested)
+ if(dto.getTaskGroupId() != null &&
+ !dto.getTaskGroupId().equals(task.getTaskGroup().getId())){
+ TaskGroupEntity oldGroup = task.getTaskGroup();
+
+ TaskGroupEntity newGroup = taskGroupRepository
+ .findById(dto.getTaskGroupId())
+ .orElseThrow(() -> new EntityNotFoundException(
+ "TaskGroup not found with id " + dto.getTaskGroupId()));
+
+ oldGroup.removeTask(task);
+ newGroup.addTask(task);
+ }
+
+ return task;
}
}
diff --git a/src/test/java/com/jonassavas/spring_task_api/TestDataUtil.java b/src/test/java/com/jonassavas/spring_task_api/TestDataUtil.java
index 23edb79..535895a 100644
--- a/src/test/java/com/jonassavas/spring_task_api/TestDataUtil.java
+++ b/src/test/java/com/jonassavas/spring_task_api/TestDataUtil.java
@@ -1,11 +1,19 @@
package com.jonassavas.spring_task_api;
+import com.jonassavas.spring_task_api.domain.dto.TaskRequestDto;
+import com.jonassavas.spring_task_api.domain.dto.TaskGroupRequestDto;
import com.jonassavas.spring_task_api.domain.dto.TaskDto;
import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
import com.jonassavas.spring_task_api.domain.entities.TaskGroupEntity;
public class TestDataUtil {
+ public static TaskRequestDto createTestCreateTaskDto(){
+ return TaskRequestDto.builder()
+ .taskName("Create Task Dto")
+ .build();
+ }
+
public static TaskDto createTestTaskDtoA(){
return TaskDto.builder()
.taskGroupId(null)
@@ -51,4 +59,22 @@ public static TaskGroupEntity createTaskGroupEntityC(){
.taskGroupName("Task Group C")
.build();
}
+
+ public static TaskGroupRequestDto createTaskGroupDtoA(){
+ return TaskGroupRequestDto.builder()
+ .taskGroupName("Task Group A")
+ .build();
+ }
+
+ public static TaskGroupRequestDto createTaskGroupDtoB(){
+ return TaskGroupRequestDto.builder()
+ .taskGroupName("Task Group B")
+ .build();
+ }
+
+ public static TaskGroupRequestDto createTaskGroupDtoC(){
+ return TaskGroupRequestDto.builder()
+ .taskGroupName("Task Group C")
+ .build();
+ }
}
diff --git a/src/test/java/com/jonassavas/spring_task_api/controllers/TaskControllerIntegrationTests.java b/src/test/java/com/jonassavas/spring_task_api/controllers/TaskControllerIntegrationTests.java
index 95ee239..16aeabd 100644
--- a/src/test/java/com/jonassavas/spring_task_api/controllers/TaskControllerIntegrationTests.java
+++ b/src/test/java/com/jonassavas/spring_task_api/controllers/TaskControllerIntegrationTests.java
@@ -1,5 +1,9 @@
package com.jonassavas.spring_task_api.controllers;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@@ -12,13 +16,13 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jonassavas.spring_task_api.TestDataUtil;
+import com.jonassavas.spring_task_api.domain.dto.TaskRequestDto;
import com.jonassavas.spring_task_api.domain.dto.TaskDto;
import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
import com.jonassavas.spring_task_api.domain.entities.TaskGroupEntity;
import com.jonassavas.spring_task_api.services.TaskGroupService;
import com.jonassavas.spring_task_api.services.TaskService;
-import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@@ -86,50 +90,164 @@ public void testThatCreateTaskReturnsSavedTask() throws Exception{
);
}
- // TODO
@Test
public void testThatCreateTaskWithoutValidTaskGroupReturns404() throws Exception{
// TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
// taskGroupService.save(testTaskGroupEntityA);
- // TaskDto testTaskDtoA = TestDataUtil.createTestTaskDtoA();
+ TaskDto testTaskDtoA = TestDataUtil.createTestTaskDtoA();
- // testTaskDtoA.setTaskGroupId(testTaskGroupEntityA.getId());
+ testTaskDtoA.setTaskGroupId(99L);
- // String taskJson = objectMapper.writeValueAsString(testTaskDtoA);
+ String taskJson = objectMapper.writeValueAsString(testTaskDtoA);
- // mockMvc.perform(
- // MockMvcRequestBuilders.post("/taskgroups/" + testTaskGroupEntityA.getId() + "/tasks")
- // .contentType(MediaType.APPLICATION_JSON)
- // .content(taskJson)
- // ).andExpect(
- // MockMvcResultMatchers.jsonPath("$.taskGroupId").isNumber()
- // ).andExpect(
- // MockMvcResultMatchers.jsonPath("$.id").isNumber()
- // ).andExpect(
- // MockMvcResultMatchers.jsonPath("$.taskName").value("Task A")
- // );
+ mockMvc.perform(
+ MockMvcRequestBuilders.post("/taskgroups/" + 99 + "/tasks")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(taskJson)
+ ).andExpect(
+ MockMvcResultMatchers.status().isNotFound()
+ );
}
- // TODO
+
@Test
public void testThatDeleteTaskReturnsHttp204() throws Exception{
- // TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
- // taskGroupService.save(testTaskGroupEntityA);
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+
+ TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
+
+ assertThat(taskGroupService
+ .findByIdWithTasks(testTaskGroupEntityA.getId())
+ .getTasks().size())
+ .isEqualTo(1);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.delete("/tasks/" + testTaskEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ ).andExpect(
+ MockMvcResultMatchers.status().isNoContent());
+
+ assertThat(taskGroupService
+ .findByIdWithTasks(testTaskGroupEntityA.getId())
+ .getTasks().size())
+ .isEqualTo(0);
+ }
+
+ @Test
+ public void testThatDeleteTaskDeletesCorrectTask() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+
+ TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
+
+ TaskEntity testTaskEntityB = TestDataUtil.createTestTaskEntityB();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityB);
+
+ assertThat(taskGroupService
+ .findByIdWithTasks(testTaskGroupEntityA.getId())
+ .getTasks().size())
+ .isEqualTo(2);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.delete("/tasks/" + testTaskEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ ).andExpect(
+ MockMvcResultMatchers.status().isNoContent());
+
+ List result = taskGroupService
+ .findByIdWithTasks(testTaskGroupEntityA.getId())
+ .getTasks();
+
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result)
+ .extracting(TaskEntity::getId)
+ .containsExactly(testTaskEntityB.getId());
+
+ }
+
+
+ @Test
+ public void testUpdateTaskName() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
- // TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
- // taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
+ TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
- // assertThat(testTaskGroupEntityA.getTasks()).hasSize(1);
+ TaskRequestDto testCreateTaskDto = TestDataUtil.createTestCreateTaskDto();
+ testCreateTaskDto.setTaskName("UPDATED");
- // mockMvc.perform(
- // MockMvcRequestBuilders.delete("/tasks/" + testTaskEntityA.getId())
- // .contentType(MediaType.APPLICATION_JSON)
- // ).andExpect(
- // MockMvcResultMatchers.status().isNoContent());
+ String taskJson = objectMapper.writeValueAsString(testCreateTaskDto);
- // assertThat(testTaskGroupEntityA.getTasks()).isEmpty();
+ mockMvc.perform(
+ MockMvcRequestBuilders.patch("/tasks/" + testTaskEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(taskJson)
+ ).andExpect(
+ MockMvcResultMatchers.status().isOk()
+ ).andExpect(
+ MockMvcResultMatchers.jsonPath("$.taskName").value("UPDATED")
+ );
}
+ @Test
+ public void testUpdateTaskGroupId() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+
+ TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
+
+ TaskGroupEntity testTaskGroupEntityB = TestDataUtil.createTaskGroupEntityB();
+ taskGroupService.save(testTaskGroupEntityB);
+
+ TaskRequestDto testCreateTaskDto = TestDataUtil.createTestCreateTaskDto();
+ testCreateTaskDto.setTaskGroupId(testTaskGroupEntityB.getId());
+
+ String taskJson = objectMapper.writeValueAsString(testCreateTaskDto);
+ mockMvc.perform(
+ MockMvcRequestBuilders.patch("/tasks/" + testTaskEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(taskJson)
+ ).andExpect(
+ MockMvcResultMatchers.status().isOk()
+ ).andExpect(
+ MockMvcResultMatchers.jsonPath("$.taskGroupId").value(testTaskGroupEntityB.getId())
+ );
+ }
+
+ @Test
+ public void testUpdateBothTaskGroupIdAndTaskName() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+
+ TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
+
+ TaskGroupEntity testTaskGroupEntityB = TestDataUtil.createTaskGroupEntityB();
+ taskGroupService.save(testTaskGroupEntityB);
+
+ TaskRequestDto testCreateTaskDto = TestDataUtil.createTestCreateTaskDto();
+ testCreateTaskDto.setTaskGroupId(testTaskGroupEntityB.getId());
+ testCreateTaskDto.setTaskName("UPDATED");
+
+ String taskJson = objectMapper.writeValueAsString(testCreateTaskDto);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.patch("/tasks/" + testTaskEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(taskJson)
+ ).andExpect(
+ MockMvcResultMatchers.status().isOk()
+ ).andExpect(
+ MockMvcResultMatchers.jsonPath("$.taskGroupId").value(testTaskGroupEntityB.getId())
+ ).andExpect(
+ MockMvcResultMatchers.jsonPath("$.taskName").value("UPDATED")
+ );
+ }
}
diff --git a/src/test/java/com/jonassavas/spring_task_api/controllers/TaskGroupControllerIntegrationTests.java b/src/test/java/com/jonassavas/spring_task_api/controllers/TaskGroupControllerIntegrationTests.java
index fc6bdf2..293bec2 100644
--- a/src/test/java/com/jonassavas/spring_task_api/controllers/TaskGroupControllerIntegrationTests.java
+++ b/src/test/java/com/jonassavas/spring_task_api/controllers/TaskGroupControllerIntegrationTests.java
@@ -10,10 +10,18 @@
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jonassavas.spring_task_api.TestDataUtil;
+import com.jonassavas.spring_task_api.domain.dto.TaskGroupRequestDto;
+import com.jonassavas.spring_task_api.domain.entities.TaskEntity;
import com.jonassavas.spring_task_api.domain.entities.TaskGroupEntity;
import com.jonassavas.spring_task_api.services.TaskGroupService;
+import com.jonassavas.spring_task_api.services.TaskService;
+
@SpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@@ -21,14 +29,19 @@
public class TaskGroupControllerIntegrationTests {
private TaskGroupService taskGroupService;
+ private TaskService taskService;
private MockMvc mockMvc;
private ObjectMapper objectMapper;
@Autowired
- public TaskGroupControllerIntegrationTests(MockMvc mockMvc, TaskGroupService taskGroupService, ObjectMapper objectMapper){
+ public TaskGroupControllerIntegrationTests(MockMvc mockMvc,
+ TaskGroupService taskGroupService,
+ TaskService taskService,
+ ObjectMapper objectMapper){
this.mockMvc = mockMvc;
this.taskGroupService = taskGroupService;
+ this.taskService = taskService;
this.objectMapper = objectMapper;
}
@@ -57,8 +70,6 @@ public void testThatCreateTaskGroupReturnsSavedTaskGroup() throws Exception{
MockMvcRequestBuilders.post("/taskgroups")
.contentType(MediaType.APPLICATION_JSON)
.content(taskGroupJson)
- ).andExpect(
- MockMvcResultMatchers.jsonPath("$.id").isNumber()
).andExpect(
MockMvcResultMatchers.jsonPath("$.taskGroupName").value("Task Group A")
);
@@ -88,4 +99,213 @@ public void testThatListTaskGroupsReturnsListOfTaskGroups() throws Exception{
MockMvcResultMatchers.jsonPath("$[0].taskGroupName").value("Task Group A")
);
}
+
+
+ @Test
+ public void testThatDeleteTaskGroupReturnsHttp204() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+
+ assertThat(taskGroupService.findAll().size()).isEqualTo(1);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.delete("/taskgroups/" + testTaskGroupEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ ).andExpect(
+ MockMvcResultMatchers.status().isNoContent()
+ );
+
+ assertThat(taskGroupService.findAll().size()).isEqualTo(0);
+ }
+
+
+ @Test
+ public void testThatDeleteTaskGroupDeletesCorrectGroup() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+ TaskGroupEntity testTaskGroupEntityB = TestDataUtil.createTaskGroupEntityB();
+ taskGroupService.save(testTaskGroupEntityB);
+
+
+ assertThat(taskGroupService.findAll().size()).isEqualTo(2);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.delete("/taskgroups/" + testTaskGroupEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ ).andExpect(
+ MockMvcResultMatchers.status().isNoContent()
+ );
+
+ List result = taskGroupService.findAll();
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result)
+ .extracting(TaskGroupEntity::getId)
+ .containsExactly(testTaskGroupEntityB.getId());
+ }
+
+ @Test
+ public void testThatDeleteTaskGroupDeletesTasks() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+
+ TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
+ TaskEntity testTaskEntityB = TestDataUtil.createTestTaskEntityB();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityB);
+ TaskEntity testTaskEntityC = TestDataUtil.createTestTaskEntityC();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityC);
+
+ List result = taskGroupService.findAllWithTasks();
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result.getFirst().getTasks())
+ .extracting(TaskEntity::getId)
+ .containsExactly(testTaskEntityA.getId(),
+ testTaskEntityB.getId(),
+ testTaskEntityC.getId());
+ assertThat(taskService.findAll())
+ .extracting(TaskEntity::getId)
+ .containsExactly(testTaskEntityA.getId(),
+ testTaskEntityB.getId(),
+ testTaskEntityC.getId());
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.delete("/taskgroups/" + testTaskGroupEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ ).andExpect(
+ MockMvcResultMatchers.status().isNoContent()
+ );
+
+ assertThat(taskGroupService.findAllWithTasks().size()).isEqualTo(0);
+ assertThat(taskService.findAll().size()).isEqualTo(0);
+ }
+
+
+ @Test
+ public void testThatDeleteTaskGroupOnlyDeletesOwnTasks() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+
+ TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
+
+ TaskGroupEntity testTaskGroupEntityB = TestDataUtil.createTaskGroupEntityB();
+ taskGroupService.save(testTaskGroupEntityB);
+
+ TaskEntity testTaskEntityB = TestDataUtil.createTestTaskEntityB();
+ taskService.createTask(testTaskGroupEntityB.getId(), testTaskEntityB);
+ TaskEntity testTaskEntityC = TestDataUtil.createTestTaskEntityC();
+ taskService.createTask(testTaskGroupEntityB.getId(), testTaskEntityC);
+
+ List result = taskGroupService.findAllWithTasks();
+ assertThat(result.size()).isEqualTo(2);
+ assertThat(result.get(0).getTasks())
+ .extracting(TaskEntity::getId)
+ .containsExactly(testTaskEntityA.getId());
+ assertThat(result.get(1).getTasks())
+ .extracting(TaskEntity::getId)
+ .containsExactly(testTaskEntityB.getId(),
+ testTaskEntityC.getId());
+ assertThat(taskService.findAll())
+ .extracting(TaskEntity::getId)
+ .containsExactly(testTaskEntityA.getId(),
+ testTaskEntityB.getId(),
+ testTaskEntityC.getId());
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.delete("/taskgroups/" + testTaskGroupEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ ).andExpect(
+ MockMvcResultMatchers.status().isNoContent()
+ );
+
+ result = taskGroupService.findAllWithTasks();
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result)
+ .extracting(TaskGroupEntity::getId)
+ .containsExactly(testTaskGroupEntityB.getId());
+ assertThat(result.get(0).getTasks())
+ .extracting(TaskEntity::getId)
+ .containsExactly(testTaskEntityB.getId(),
+ testTaskEntityC.getId());
+ }
+
+
+ @Test
+ public void testThatUpdateTaskGroupReturnsHttp200() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+
+ TaskGroupRequestDto testTaskGroupDtoA = TestDataUtil.createTaskGroupDtoA();
+ testTaskGroupDtoA.setTaskGroupName("UPDATED");
+ String taskGroupJson = objectMapper.writeValueAsString(testTaskGroupDtoA);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.patch("/taskgroups/" + testTaskGroupEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(taskGroupJson)
+ ).andExpect(
+ MockMvcResultMatchers.status().isOk()
+ ).andExpect(
+ MockMvcResultMatchers.jsonPath("$.taskGroupName").value("UPDATED")
+ );
+ }
+
+
+ @Test
+ public void testThatUpdateTaskGroupKeepsItsTasks() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+
+ TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
+
+ assertThat(taskGroupService.findByIdWithTasks(testTaskGroupEntityA.getId()).getTasks())
+ .extracting(TaskEntity::getId)
+ .containsExactly(testTaskEntityA.getId());
+
+ TaskGroupRequestDto testTaskGroupDtoA = TestDataUtil.createTaskGroupDtoA();
+ testTaskGroupDtoA.setTaskGroupName("UPDATED");
+ String taskGroupJson = objectMapper.writeValueAsString(testTaskGroupDtoA);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.patch("/taskgroups/" + testTaskGroupEntityA.getId())
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(taskGroupJson)
+ ).andExpect(
+ MockMvcResultMatchers.status().isOk()
+ ).andExpect(
+ MockMvcResultMatchers.jsonPath("$.taskGroupName").value("UPDATED")
+ );
+
+ assertThat(taskGroupService.findByIdWithTasks(testTaskGroupEntityA.getId()).getTasks())
+ .extracting(TaskEntity::getId)
+ .containsExactly(testTaskEntityA.getId());
+ }
+
+
+ @Test
+ public void testThatDeleteAllTasksDeletesCorrespondingTasks() throws Exception{
+ TaskGroupEntity testTaskGroupEntityA = TestDataUtil.createTaskGroupEntityA();
+ taskGroupService.save(testTaskGroupEntityA);
+ TaskEntity testTaskEntityA = TestDataUtil.createTestTaskEntityA();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityA);
+ TaskEntity testTaskEntityB = TestDataUtil.createTestTaskEntityB();
+ taskService.createTask(testTaskGroupEntityA.getId(), testTaskEntityB);
+
+
+ TaskGroupEntity testTaskGroupEntityB = TestDataUtil.createTaskGroupEntityB();
+ taskGroupService.save(testTaskGroupEntityB);
+ TaskEntity testTaskEntityC = TestDataUtil.createTestTaskEntityB();
+ taskService.createTask(testTaskGroupEntityB.getId(), testTaskEntityC);
+
+ mockMvc.perform(
+ MockMvcRequestBuilders.delete("/taskgroups/" + testTaskGroupEntityA.getId() + "/tasks")
+ .contentType(MediaType.APPLICATION_JSON)
+ ).andExpect(
+ MockMvcResultMatchers.status().isNoContent()
+ );
+
+ List result = taskService.findAll();
+ assertThat(result).extracting(TaskEntity::getId).containsExactly(testTaskEntityC.getId());
+ }
}