feat: add task deletion
This commit is contained in:
@ -4,6 +4,7 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
@ -65,4 +66,10 @@ public class TaskController {
|
||||
request.parsedStatus(),
|
||||
request.parsedActiveUserId().value());
|
||||
}
|
||||
|
||||
@DeleteMapping("/{taskId}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void delete(@PathVariable UUID taskId) {
|
||||
taskService.delete(taskId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,6 +104,13 @@ class TaskService {
|
||||
return TaskResponse.from(task);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
void delete(UUID taskId) {
|
||||
Task task = taskRepository.findById(taskId)
|
||||
.orElseThrow(TaskNotFoundException::new);
|
||||
taskRepository.delete(task);
|
||||
}
|
||||
|
||||
private User findAssignee(UUID requestedAssigneeId) {
|
||||
if (requestedAssigneeId == null) {
|
||||
return null;
|
||||
|
||||
@ -0,0 +1,128 @@
|
||||
package se.rubble.hemhub.task;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import se.rubble.hemhub.user.User;
|
||||
import se.rubble.hemhub.user.UserRepository;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest
|
||||
class TaskDeletionApiTest {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
@Autowired
|
||||
private TaskRepository taskRepository;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
taskRepository.deleteAll();
|
||||
userRepository.deleteAll();
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(TaskStatus.class)
|
||||
void deletesTaskInEveryStatus(TaskStatus statusValue) throws Exception {
|
||||
User assignee = createUser();
|
||||
Task task = saveTask(statusValue, assignee);
|
||||
|
||||
mockMvc.perform(delete("/api/tasks/{taskId}", task.getId()))
|
||||
.andExpect(status().isNoContent())
|
||||
.andExpect(content().string(""));
|
||||
|
||||
mockMvc.perform(get("/api/tasks"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$").isEmpty());
|
||||
org.junit.jupiter.api.Assertions.assertTrue(userRepository.existsById(assignee.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deletesOnlyRequestedTask() throws Exception {
|
||||
User assignee = createUser();
|
||||
Task deleted = saveTask(TaskStatus.WAITING, assignee);
|
||||
Task remaining = saveTask(TaskStatus.COMPLETED, null);
|
||||
|
||||
mockMvc.perform(delete("/api/tasks/{taskId}", deleted.getId()))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
mockMvc.perform(get("/api/tasks"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.length()").value(1))
|
||||
.andExpect(jsonPath("$[0].id").value(remaining.getId().toString()))
|
||||
.andExpect(jsonPath("$[0].status").value("COMPLETED"));
|
||||
org.junit.jupiter.api.Assertions.assertTrue(userRepository.existsById(assignee.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsNotFoundForUnknownAndAlreadyDeletedTask() throws Exception {
|
||||
Task task = saveTask(TaskStatus.WAITING, null);
|
||||
|
||||
mockMvc.perform(delete("/api/tasks/{taskId}", task.getId()))
|
||||
.andExpect(status().isNoContent());
|
||||
mockMvc.perform(delete("/api/tasks/{taskId}", task.getId()))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(jsonPath("$.code").value("TASK_NOT_FOUND"));
|
||||
mockMvc.perform(delete(
|
||||
"/api/tasks/{taskId}",
|
||||
"00000000-0000-0000-0000-000000000099"))
|
||||
.andExpect(status().isNotFound())
|
||||
.andExpect(jsonPath("$.code").value("TASK_NOT_FOUND"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void keepsExistingBadRequestForInvalidUuid() throws Exception {
|
||||
mockMvc.perform(delete("/api/tasks/{taskId}", "inte-ett-uuid"))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.code").value("INVALID_TASK_ASSIGNMENT"));
|
||||
}
|
||||
|
||||
private User createUser() throws Exception {
|
||||
String response = mockMvc.perform(post("/api/users")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{"name": "Urban"}
|
||||
"""))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getContentAsString();
|
||||
String id = com.jayway.jsonpath.JsonPath.read(response, "$.id");
|
||||
return userRepository.findById(UUID.fromString(id)).orElseThrow();
|
||||
}
|
||||
|
||||
private Task saveTask(TaskStatus statusValue, User assignee) {
|
||||
return taskRepository.save(new Task(
|
||||
UUID.randomUUID(),
|
||||
"Dammsuga",
|
||||
"Bottenvåningen",
|
||||
statusValue,
|
||||
7,
|
||||
assignee,
|
||||
Instant.parse("2026-07-28T09:00:00Z")));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user